Commit 7d596c9f authored by Olivier Bertrand's avatar Olivier Bertrand

- Working on MDEV-10525. Lrecl mismatch on DBF files

  modified:   storage/connect/filamdbf.cpp
  modified:   storage/connect/filamdbf.h
  modified:   storage/connect/reldef.cpp
parent 2140dcf6
...@@ -383,7 +383,7 @@ DBFBASE::DBFBASE(DBFBASE *txfp) ...@@ -383,7 +383,7 @@ DBFBASE::DBFBASE(DBFBASE *txfp)
/* and header length. Set Records, check that Reclen is equal to lrecl and */ /* and header length. Set Records, check that Reclen is equal to lrecl and */
/* return the header length or 0 in case of error. */ /* return the header length or 0 in case of error. */
/****************************************************************************/ /****************************************************************************/
int DBFBASE::ScanHeader(PGLOBAL g, PSZ fname, int lrecl, char *defpath) int DBFBASE::ScanHeader(PGLOBAL g, PSZ fn, int lrecl, int *rln, char *defpath)
{ {
int rc; int rc;
char filename[_MAX_PATH]; char filename[_MAX_PATH];
...@@ -393,7 +393,7 @@ int DBFBASE::ScanHeader(PGLOBAL g, PSZ fname, int lrecl, char *defpath) ...@@ -393,7 +393,7 @@ int DBFBASE::ScanHeader(PGLOBAL g, PSZ fname, int lrecl, char *defpath)
/************************************************************************/ /************************************************************************/
/* Open the input file. */ /* Open the input file. */
/************************************************************************/ /************************************************************************/
PlugSetPath(filename, fname, defpath); PlugSetPath(filename, fn, defpath);
if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "rb"))) if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "rb")))
return 0; // Assume file does not exist return 0; // Assume file does not exist
...@@ -410,11 +410,7 @@ int DBFBASE::ScanHeader(PGLOBAL g, PSZ fname, int lrecl, char *defpath) ...@@ -410,11 +410,7 @@ int DBFBASE::ScanHeader(PGLOBAL g, PSZ fname, int lrecl, char *defpath)
} else if (rc == RC_FX) } else if (rc == RC_FX)
return -1; return -1;
if ((int)header.Reclen() != lrecl) { *rln = (int)header.Reclen();
sprintf(g->Message, MSG(BAD_LRECL), lrecl, header.Reclen());
return -1;
} // endif Lrecl
Records = (int)header.Records(); Records = (int)header.Records();
return (int)header.Headlen(); return (int)header.Headlen();
} // end of ScanHeader } // end of ScanHeader
...@@ -431,9 +427,27 @@ int DBFFAM::Cardinality(PGLOBAL g) ...@@ -431,9 +427,27 @@ int DBFFAM::Cardinality(PGLOBAL g)
if (!g) if (!g)
return 1; return 1;
if (!Headlen) if (!Headlen) {
if ((Headlen = ScanHeader(g, To_File, Lrecl, Tdbp->GetPath())) < 0) int rln = 0; // Record length in the file header
return -1; // Error in ScanHeader
Headlen = ScanHeader(g, To_File, Lrecl, &rln, Tdbp->GetPath());
if (Headlen < 0)
return -1; // Error in ScanHeader
if (rln && Lrecl != rln) {
// This happens always on some Linux platforms
sprintf(g->Message, MSG(BAD_LRECL), Lrecl, rln);
if (Accept) {
Lrecl = rln;
PushWarning(g, Tdbp);
} else
return -1;
} // endif rln
} // endif Headlen
// Set number of blocks for later use // Set number of blocks for later use
Block = (Records > 0) ? (Records + Nrec - 1) / Nrec : 0; Block = (Records > 0) ? (Records + Nrec - 1) / Nrec : 0;
...@@ -565,7 +579,13 @@ bool DBFFAM::AllocateBuffer(PGLOBAL g) ...@@ -565,7 +579,13 @@ bool DBFFAM::AllocateBuffer(PGLOBAL g)
if (Lrecl != reclen) { if (Lrecl != reclen) {
sprintf(g->Message, MSG(BAD_LRECL), Lrecl, reclen); sprintf(g->Message, MSG(BAD_LRECL), Lrecl, reclen);
return true;
if (Accept) {
Lrecl = reclen;
PushWarning(g, Tdbp);
} else
return true;
} // endif Lrecl } // endif Lrecl
hlen = HEADLEN * (n + 1) + 2; hlen = HEADLEN * (n + 1) + 2;
...@@ -641,8 +661,14 @@ bool DBFFAM::AllocateBuffer(PGLOBAL g) ...@@ -641,8 +661,14 @@ bool DBFFAM::AllocateBuffer(PGLOBAL g)
if ((rc = dbfhead(g, Stream, Tdbp->GetFile(g), &header)) == RC_OK) { if ((rc = dbfhead(g, Stream, Tdbp->GetFile(g), &header)) == RC_OK) {
if (Lrecl != (int)header.Reclen()) { if (Lrecl != (int)header.Reclen()) {
sprintf(g->Message, MSG(BAD_LRECL), Lrecl, header.Reclen()); sprintf(g->Message, MSG(BAD_LRECL), Lrecl, header.Reclen());
return true;
} // endif Lrecl if (Accept) {
Lrecl = header.Reclen();
PushWarning(g, Tdbp);
} else
return true;
} // endif Lrecl
Records = (int)header.Records(); Records = (int)header.Records();
Headlen = (int)header.Headlen(); Headlen = (int)header.Headlen();
...@@ -916,9 +942,27 @@ int DBMFAM::Cardinality(PGLOBAL g) ...@@ -916,9 +942,27 @@ int DBMFAM::Cardinality(PGLOBAL g)
if (!g) if (!g)
return 1; return 1;
if (!Headlen) if (!Headlen) {
if ((Headlen = ScanHeader(g, To_File, Lrecl, Tdbp->GetPath())) < 0) int rln = 0; // Record length in the file header
return -1; // Error in ScanHeader
Headlen = ScanHeader(g, To_File, Lrecl, &rln, Tdbp->GetPath());
if (Headlen < 0)
return -1; // Error in ScanHeader
if (rln && Lrecl != rln) {
// This happens always on some Linux platforms
sprintf(g->Message, MSG(BAD_LRECL), Lrecl, rln);
if (Accept) {
Lrecl = rln;
PushWarning(g, Tdbp);
} else
return -1;
} // endif rln
} // endif Headlen
// Set number of blocks for later use // Set number of blocks for later use
Block = (Records > 0) ? (Records + Nrec - 1) / Nrec : 0; Block = (Records > 0) ? (Records + Nrec - 1) / Nrec : 0;
...@@ -961,8 +1005,14 @@ bool DBMFAM::AllocateBuffer(PGLOBAL g) ...@@ -961,8 +1005,14 @@ bool DBMFAM::AllocateBuffer(PGLOBAL g)
if (Lrecl != (int)hp->Reclen()) { if (Lrecl != (int)hp->Reclen()) {
sprintf(g->Message, MSG(BAD_LRECL), Lrecl, hp->Reclen()); sprintf(g->Message, MSG(BAD_LRECL), Lrecl, hp->Reclen());
return true;
} // endif Lrecl if (Accept) {
Lrecl = hp->Reclen();
PushWarning(g, Tdbp);
} else
return true;
} // endif Lrecl
Records = (int)hp->Records(); Records = (int)hp->Records();
Headlen = (int)hp->Headlen(); Headlen = (int)hp->Headlen();
......
...@@ -31,7 +31,7 @@ class DllExport DBFBASE { ...@@ -31,7 +31,7 @@ class DllExport DBFBASE {
DBFBASE(PDBF txfp); DBFBASE(PDBF txfp);
// Implementation // Implementation
int ScanHeader(PGLOBAL g, PSZ fname, int lrecl, char *defpath); int ScanHeader(PGLOBAL g, PSZ fname, int lrecl, int *rlen, char *defpath);
protected: protected:
// Default constructor, not to be used // Default constructor, not to be used
......
...@@ -440,7 +440,11 @@ int TABDEF::GetColCatInfo(PGLOBAL g) ...@@ -440,7 +440,11 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
} // endswitch tc } // endswitch tc
// lrecl must be at least recln to avoid buffer overflow // lrecl must be at least recln to avoid buffer overflow
recln= MY_MAX(recln, Hc->GetIntegerOption("Lrecl")); if (trace)
htrc("Lrecl: Calculated=%d defined=%d\n",
recln, Hc->GetIntegerOption("Lrecl"));
recln = MY_MAX(recln, Hc->GetIntegerOption("Lrecl"));
Hc->SetIntegerOption("Lrecl", recln); Hc->SetIntegerOption("Lrecl", recln);
((PDOSDEF)this)->SetLrecl(recln); ((PDOSDEF)this)->SetLrecl(recln);
} // endif Lrecl } // endif Lrecl
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment