Example #1
0
int TXTFAM::GetFileLength(PGLOBAL g)
  {
  char    filename[_MAX_PATH];
  int     h;
  int    len;

  PlugSetPath(filename, To_File, Tdbp->GetPath());
  h= global_open(g, MSGID_OPEN_MODE_STRERROR, filename, _O_RDONLY);

  if (trace)
    htrc("GetFileLength: fn=%s h=%d\n", filename, h);

  if (h == -1) {
    if (errno != ENOENT) {
      if (trace)
        htrc("%s\n", g->Message);
      len = -1;
    }
    else
    {
      len = 0;          // File does not exist yet
      g->Message[0]= '\0';
    }
  } else {
    if ((len = _filelength(h)) < 0)
      sprintf(g->Message, MSG(FILELEN_ERROR), "_filelength", filename);

    if (Eof && len)
      len--;              // Do not count the EOF character

    close(h);
  } // endif h

  return len;
  } // end of GetFileLength
Example #2
0
bool DBFFAM::OpenTableFile(PGLOBAL g)
  {
  char    opmode[4], filename[_MAX_PATH];
//int     ftype = Tdbp->GetFtype();
  MODE    mode = Tdbp->GetMode();
  PDBUSER dbuserp = PlgGetUser(g);

  switch (mode) {
    case MODE_READ:
      strcpy(opmode, "rb");
      break;
    case MODE_DELETE:
      if (!Tdbp->GetNext()) {
        // Store the number of deleted lines
        DelRows = -1;      // Means all lines deleted
//      DelRows = Cardinality(g); no good because of soft deleted lines

        // This will erase the entire file
        strcpy(opmode, "w");
        Tdbp->ResetSize();
        Records = 0;
        break;
        } // endif

      // Selective delete, pass thru
    case MODE_UPDATE:
      UseTemp = Tdbp->IsUsingTemp(g);
      strcpy(opmode, (UseTemp) ? "rb" : "r+b");
      break;
    case MODE_INSERT:
      // Must be in text mode to remove an eventual EOF character
      strcpy(opmode, "a+");
      break;
    default:
      sprintf(g->Message, MSG(BAD_OPEN_MODE), mode);
      return true;
    } // endswitch Mode

  // Now open the file stream
  PlugSetPath(filename, To_File, Tdbp->GetPath());

  if (!(Stream = PlugOpenFile(g, filename, opmode))) {
    if (trace)
      htrc("%s\n", g->Message);
    
    return (mode == MODE_READ && errno == ENOENT)
            ? PushWarning(g, Tdbp) : true;
    } // endif Stream

  if (trace)
    htrc("File %s is open in mode %s\n", filename, opmode);

  To_Fb = dbuserp->Openlist;     // Keep track of File block

  /*********************************************************************/
  /*  Allocate the line buffer. For mode Delete a bigger buffer has to */
  /*  be allocated because is it also used to move lines into the file.*/
  /*********************************************************************/
  return AllocateBuffer(g);
  } // end of OpenTableFile
Example #3
0
bool VCTDEF::Erase(char *filename)
  {
  bool    rc = false;

  if (Split) {
    char    fpat[_MAX_PATH];
    int     i;
    PCOLDEF cdp;

    MakeFnPattern(fpat);

    for (i = 1, cdp = To_Cols; cdp; i++, cdp = cdp->GetNext()) {
      sprintf(filename, fpat, i);
//#if defined(WIN32)
//      rc |= !DeleteFile(filename);
//#else    // UNIX
      rc |= remove(filename);
//#endif   // UNIX
      } // endfor cdp

  } else {
    rc = DOSDEF::Erase(filename);

    if (Estimate && Header == 2) {
      PlugSetPath(filename, Fn, GetPath());
      strcat(PlugRemoveType(filename, filename), ".blk");
      rc |= remove(filename);
      } // endif Header

  } // endif Split

  return rc;                                  // Return true if error
  } // end of Erase
Example #4
0
int DBFBASE::ScanHeader(PGLOBAL g, PSZ fname, int lrecl, char *defpath)
  {
  int       rc;
  char      filename[_MAX_PATH];
  DBFHEADER header;
  FILE     *infile;

  /************************************************************************/
  /*  Open the input file.                                                */
  /************************************************************************/
  PlugSetPath(filename, fname, defpath);

  if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "rb")))
    return 0;              // Assume file does not exist

  /************************************************************************/
  /*  Get the first 32 bytes of the header.                               */
  /************************************************************************/
  rc = dbfhead(g, infile, filename, &header);
  fclose(infile);

  if (rc == RC_NF) {
    Records = 0;
    return 0;
  } else if (rc == RC_FX)
    return -1;

  if ((int)header.Reclen != lrecl) {
    sprintf(g->Message, MSG(BAD_LRECL), lrecl, header.Reclen);
    return -1;
    } // endif Lrecl

  Records = (int)header.Records;
  return (int)header.Headlen;
  } // end of ScanHeader
Example #5
0
int VCTDEF::MakeFnPattern(char *fpat)
  {
  char    pat[8];
#if !defined(UNIX)
  char    drive[_MAX_DRIVE];
#else
  char    *drive = NULL;
#endif
  char    direc[_MAX_DIR];
  char    fname[_MAX_FNAME];
  char    ftype[_MAX_EXT];          // File extention
  int     n, m, ncol = 0;
  PCOLDEF cdp;

  for (cdp = To_Cols; cdp; cdp = cdp->GetNext())
    ncol++;

  for (n = 1, m = ncol; m /= 10; n++) ;

  sprintf(pat, "%%0%dd", n);
  _splitpath(Fn, drive, direc, fname, ftype);
  strcat(fname, pat);
  _makepath(fpat, drive, direc, fname, ftype);
  PlugSetPath(fpat, fpat, GetPath());
  return ncol;
  } // end of MakeFnPattern
Example #6
0
void FIDBLK::ReadColumn(PGLOBAL g)
  {
  if (Fn != ((PTDBASE)To_Tdb)->GetFile(g)) {
    char filename[_MAX_PATH];

    Fn = ((PTDBASE)To_Tdb)->GetFile(g);
    PlugSetPath(filename, Fn, ((PTDBASE)To_Tdb)->GetPath());
    Value->SetValue_psz(filename);
    } // endif Fn

  } // end of ReadColumn
Example #7
0
char *PlugReadMessage(PGLOBAL g, int mid, char *m)
  {
  char  msgfile[_MAX_PATH], msgid[32], buff[256];
  char *msg;
  FILE *mfile = NULL;

//GetPrivateProfileString("Message", msglang, "Message\\english.msg",
//                                   msgfile, _MAX_PATH, plgini);
//strcat(strcat(strcpy(msgfile, msg_path), msglang()), ".msg");
  strcat(strcpy(buff, msglang()), ".msg");
  PlugSetPath(msgfile, NULL, buff, msg_path);

  if (!(mfile = fopen(msgfile, "rt"))) {
    sprintf(stmsg, "Fail to open message file %s", msgfile);
    goto err;
    } // endif mfile

  for (;;)
    if (!fgets(buff, 256, mfile)) {
      sprintf(stmsg, "Cannot get message %d %s", mid, SVP(m));
      goto fin;
    } else
      if (atoi(buff) == mid)
        break;

  if (sscanf(buff, " %*d %s \"%[^\"]", msgid, stmsg) < 2) {
    // Old message file
    if (!sscanf(buff, " %*d \"%[^\"]", stmsg)) {
      sprintf(stmsg, "Bad message file for %d %s", mid, SVP(m));
      goto fin;
    } else
      m = NULL;

    } // endif sscanf

  if (m && strcmp(m, msgid)) {
    // Message file is out of date
    strcpy(stmsg, m);
    goto fin;
    } // endif m

 fin:
  fclose(mfile);

 err:
  if (g) {
    // Called by STEP
    msg = (char *)PlugSubAlloc(g, NULL, strlen(stmsg) + 1);
    strcpy(msg, stmsg);
  } else // Called by MSG or PlgGetErrorMsg
    msg =  stmsg;

  return msg;
  } // end of PlugReadMessage
bool INIDEF::DeleteTableFile(PGLOBAL g)
  {
  char    filename[_MAX_PATH];
  bool    rc;

  // Delete the INI table file if not protected
  if (!IsReadOnly()) {
    PlugSetPath(filename, Fn, GetPath());
#if defined(WIN32)
    rc = !DeleteFile(filename);
#else    // UNIX
    rc = remove(filename);
#endif   // UNIX
  } else
    rc =true;

  return rc;                                  // Return true if error
  } // end of DeleteTableFile
Example #9
0
bool DOSFAM::OpenTempFile(PGLOBAL g)
  {
  char tempname[_MAX_PATH];
  bool rc = false;

  /*********************************************************************/
  /*  Open the temporary file, Spos is at the beginning of file.       */
  /*********************************************************************/
  PlugSetPath(tempname, To_File, Tdbp->GetPath());
  strcat(PlugRemoveType(tempname, tempname), ".t");

  if (!(T_Stream = PlugOpenFile(g, tempname, "wb"))) {
    if (trace)
      htrc("%s\n", g->Message);

    rc = true;
  } else
    To_Fbt = PlgGetUser(g)->Openlist;

  return rc;
  } // end of OpenTempFile
bool INIDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
  {
  char   buf[8];

  Fn = GetStringCatInfo(g, "Filename", NULL);
  GetCharCatInfo("Layout", "C", buf, sizeof(buf));
  Layout = toupper(*buf);

  if (Fn) {
    char   *p = (char*)PlugSubAlloc(g, NULL, _MAX_PATH);

    PlugSetPath(p, Fn, GetPath());
    Fn = p;
  } else {
    strcpy(g->Message, MSG(MISSING_FNAME));
    return true;
  } // endif Fn

  Ln = GetSizeCatInfo("Secsize", "8K");
  Desc = Fn;
  return false;
  } // end of DefineAM
Example #11
0
int DOSFAM::RenameTempFile(PGLOBAL g)
  {
  char *tempname, filetemp[_MAX_PATH], filename[_MAX_PATH];
  int   rc;

  if (!To_Fbt)
    return RC_INFO;               // Nothing to do ???

  // This loop is necessary because, in case of join,
  // To_File can have been open several times.
  for (PFBLOCK fb = PlgGetUser(g)->Openlist; fb; fb = fb->Next)
    if (fb == To_Fb || fb == To_Fbt)
      rc = PlugCloseFile(g, fb);

  tempname = (char*)To_Fbt->Fname;
  PlugSetPath(filename, To_File, Tdbp->GetPath());
  strcat(PlugRemoveType(filetemp, filename), ".ttt");
  remove(filetemp);   // May still be there from previous error

  if (rename(filename, filetemp)) {    // Save file for security
    sprintf(g->Message, MSG(RENAME_ERROR),
            filename, filetemp, strerror(errno));
    rc = RC_FX;
  } else if (rename(tempname, filename)) {
    sprintf(g->Message, MSG(RENAME_ERROR),
            tempname, filename, strerror(errno));
    rc = rename(filetemp, filename);   // Restore saved file
    rc = RC_FX;
  } else if (remove(filetemp)) {
    sprintf(g->Message, MSG(REMOVE_ERROR),
            filetemp, strerror(errno));
    rc = RC_INFO;                      // Acceptable
  } else
    rc = RC_OK;

  return rc;
  } // end of RenameTempFile
Example #12
0
bool ZIPFAM::OpenTableFile(PGLOBAL g)
  {
  char    opmode[4], filename[_MAX_PATH];
  MODE    mode = Tdbp->GetMode();

  switch (mode) {
    case MODE_READ:
      strcpy(opmode, "r");
      break;
    case MODE_UPDATE:
      /*****************************************************************/
      /* Updating ZIP files not implemented yet.                       */
      /*****************************************************************/
      strcpy(g->Message, MSG(UPD_ZIP_NOT_IMP));
      return true;
    case MODE_DELETE:
      if (!Tdbp->GetNext()) {
        // Store the number of deleted lines
        DelRows = Cardinality(g);

        // This will erase the entire file
        strcpy(opmode, "w");
//      Block = 0;                // For ZBKFAM
//      Last = Nrec;              // For ZBKFAM
        Tdbp->ResetSize();
      } else {
        sprintf(g->Message, MSG(NO_PART_DEL), "ZIP");
        return true;
      } // endif filter

      break;
    case MODE_INSERT:
      strcpy(opmode, "a+");
      break;
    default:
      sprintf(g->Message, MSG(BAD_OPEN_MODE), mode);
      return true;
    } // endswitch Mode

  /*********************************************************************/
  /*  Open according to logical input/output mode required.            */
  /*  Use specific zlib functions.                                     */
  /*  Treat files as binary.                                           */
  /*********************************************************************/
  strcat(opmode, "b");
  Zfile = gzopen(PlugSetPath(filename, To_File, Tdbp->GetPath()), opmode);

  if (Zfile == NULL) {
    sprintf(g->Message, MSG(GZOPEN_ERROR),
            opmode, (int)errno, filename);
    strcat(strcat(g->Message, ": "), strerror(errno));
    return (mode == MODE_READ && errno == ENOENT)
            ? PushWarning(g, Tdbp) : true;
    } // endif Zfile

  /*********************************************************************/
  /*  Something to be done here. >>>>>>>> NOT DONE <<<<<<<<            */
  /*********************************************************************/
//To_Fb = dbuserp->Openlist;     // Keep track of File block

  /*********************************************************************/
  /*  Allocate the line buffer.                                        */
  /*********************************************************************/
  return AllocateBuffer(g);
  } // end of OpenTableFile
Example #13
0
bool MAPFAM::OpenTableFile(PGLOBAL g)
  {
  char    filename[_MAX_PATH];
  int     len;
  MODE    mode = Tdbp->GetMode();
  PFBLOCK fp;
  PDBUSER dbuserp = (PDBUSER)g->Activityp->Aptr;

#if defined(_DEBUG)
  // Insert mode is no more handled using file mapping
  assert(mode != MODE_INSERT);
#endif   // _DEBUG

  /*********************************************************************/
  /*  We used the file name relative to recorded datapath.             */
  /*********************************************************************/
  PlugSetPath(filename, To_File, Tdbp->GetPath());

  /*********************************************************************/
  /*  Under Win32 the whole file will be mapped so we can use it as    */
  /*  if it were entirely read into virtual memory.                    */
  /*  Firstly we check whether this file have been already mapped.     */
  /*********************************************************************/
  if (mode == MODE_READ) {
    for (fp = dbuserp->Openlist; fp; fp = fp->Next)
      if (fp->Type == TYPE_FB_MAP && !stricmp(fp->Fname, filename)
                     && fp->Count && fp->Mode == mode)
        break;

    if (trace)
      htrc("Mapping file, fp=%p\n", fp);

  } else
    fp = NULL;

  if (fp) {
    /*******************************************************************/
    /*  File already mapped. Just increment use count and get pointer. */
    /*******************************************************************/
    fp->Count++;
    Memory = fp->Memory;
    len = fp->Length;
  } else {
    /*******************************************************************/
    /*  If required, delete the whole file if no filtering is implied. */
    /*******************************************************************/
    bool   del;
    HANDLE hFile;
    MEMMAP mm;

    del = mode == MODE_DELETE && !Tdbp->GetNext();

    if (del)
      DelRows = Cardinality(g);

    /*******************************************************************/
    /*  Create the mapping file object.                                */
    /*******************************************************************/
    hFile = CreateFileMap(g, filename, &mm, mode, del);

    if (hFile == INVALID_HANDLE_VALUE) {
      DWORD rc = GetLastError();

      if (!(*g->Message))
        sprintf(g->Message, MSG(OPEN_MODE_ERROR),
                "map", (int) rc, filename);

      if (trace)
        htrc("CreateFileMap: %s\n", g->Message);

      return (mode == MODE_READ && rc == ENOENT)
              ? PushWarning(g, Tdbp) : true;
      } // endif hFile

    /*******************************************************************/
    /*  Get the file size (assuming file is smaller than 4 GB)         */
    /*******************************************************************/
    len = mm.lenL;
    Memory = (char *)mm.memory;

    if (!len) {              // Empty or deleted file
      CloseFileHandle(hFile);
      Tdbp->ResetSize();
      return false;
      } // endif len

    if (!Memory) {
      CloseFileHandle(hFile);
      sprintf(g->Message, MSG(MAP_VIEW_ERROR),
                          filename, GetLastError());
      return true;
      } // endif Memory

#if defined(WIN32)
    if (mode != MODE_DELETE) {
#else   // !WIN32
    if (mode == MODE_READ) {
#endif  // !WIN32
      CloseFileHandle(hFile);                    // Not used anymore
      hFile = INVALID_HANDLE_VALUE;              // For Fblock
      } // endif Mode

    /*******************************************************************/
    /*  Link a Fblock. This make possible to reuse already opened maps */
    /*  and also to automatically unmap them in case of error g->jump. */
    /*  Note: block can already exist for previously closed file.      */
    /*******************************************************************/
    fp = (PFBLOCK)PlugSubAlloc(g, NULL, sizeof(FBLOCK));
    fp->Type = TYPE_FB_MAP;
    fp->Fname = (char*)PlugSubAlloc(g, NULL, strlen(filename) + 1);
    strcpy((char*)fp->Fname, filename);
    fp->Next = dbuserp->Openlist;
    dbuserp->Openlist = fp;
    fp->Count = 1;
    fp->Length = len;
    fp->Memory = Memory;
    fp->Mode = mode;
    fp->File = NULL;
    fp->Handle = hFile;                // Used for Delete
  } // endif fp

  To_Fb = fp;                               // Useful when closing

  /*********************************************************************/
  /*  The pseudo "buffer" is here the entire file mapping view.        */
  /*********************************************************************/
  Fpos = Mempos = Memory;
  Top = Memory + len;

  if (trace)
    htrc("fp=%p count=%d MapView=%p len=%d Top=%p\n",
          fp, fp->Count, Memory, len, Top);

  return AllocateBuffer(g);          // Useful for DBF files
  } // end of OpenTableFile

/***********************************************************************/
/*  GetRowID: return the RowID of last read record.                    */
/***********************************************************************/
int MAPFAM::GetRowID(void)
  {
  return Rows;
  } // end of GetRowID

/***********************************************************************/
/*  GetPos: return the position of last read record.                   */
/***********************************************************************/
int MAPFAM::GetPos(void)
  {
  return Fpos - Memory;
  } // end of GetPos

/***********************************************************************/
/*  GetNextPos: return the position of next record.                    */
/***********************************************************************/
int MAPFAM::GetNextPos(void)
  {
  return Mempos - Memory;
  } // end of GetNextPos

/***********************************************************************/
/*  SetPos: Replace the table at the specified position.               */
/***********************************************************************/
bool MAPFAM::SetPos(PGLOBAL g, int pos)
  {
  Fpos = Mempos = Memory + pos;

  if (Mempos >= Top || Mempos < Memory) {
    strcpy(g->Message, MSG(INV_MAP_POS));
    return true;
    } // endif Mempos

  Placed = true;
  return false;
  } // end of SetPos
Example #14
0
int DOSFAM::DeleteRecords(PGLOBAL g, int irc)
  {
  bool moved;
  int curpos = ftell(Stream);

  /*********************************************************************/
  /*  There is an alternative here:                                    */
  /*  1 - use a temporary file in which are copied all not deleted     */
  /*      lines, at the end the original file will be deleted and      */
  /*      the temporary file renamed to the original file name.        */
  /*  2 - directly move the not deleted lines inside the original      */
  /*      file, and at the end erase all trailing records.             */
  /*  This will be experimented, but method 1 must be used for Unix as */
  /*  the function needed to erase trailing records is not available.  */
  /*********************************************************************/
  if (trace)
    htrc(
  "DOS DeleteDB: rc=%d UseTemp=%d curpos=%d Fpos=%d Tpos=%d Spos=%d\n",
                irc, UseTemp, curpos, Fpos, Tpos, Spos);

  if (irc != RC_OK) {
    /*******************************************************************/
    /*  EOF: position Fpos at the end-of-file position.                */
    /*******************************************************************/
    fseek(Stream, 0, SEEK_END);
    Fpos = ftell(Stream);

    if (trace)
      htrc("Fpos placed at file end=%d\n", Fpos);

    } // endif irc

  if (Tpos == Spos) {
    /*******************************************************************/
    /*  First line to delete, Open temporary file.                     */
    /*******************************************************************/
    if (UseTemp) {
      if (OpenTempFile(g))
        return RC_FX;

    } else {
      /*****************************************************************/
      /*  Move of eventual preceeding lines is not required here.      */
      /*  Set the target file as being the source file itself.         */
      /*  Set the future Tpos, and give Spos a value to block copying. */
      /*****************************************************************/
      T_Stream = Stream;
      Spos = Tpos = Fpos;
    } // endif UseTemp

    } // endif Tpos == Spos

  /*********************************************************************/
  /*  Move any intermediate lines.                                     */
  /*********************************************************************/
  if (MoveIntermediateLines(g, &moved))
    return RC_FX;

  if (irc == RC_OK) {
    /*******************************************************************/
    /*  Reposition the file pointer and set Spos.                      */
    /*******************************************************************/
    if (!UseTemp || moved)
      if (fseek(Stream, curpos, SEEK_SET)) {
        sprintf(g->Message, MSG(FSETPOS_ERROR), 0);
        return RC_FX;
        } // endif

    Spos = GetNextPos();                     // New start position

    if (trace)
      htrc("after: Tpos=%d Spos=%d\n", Tpos, Spos);

  } else {
    /*******************************************************************/
    /*  Last call after EOF has been reached.                          */
    /*  The UseTemp case is treated in CloseTableFile.                 */
    /*******************************************************************/
    if (!UseTemp) {
      /*****************************************************************/
      /*  Because the chsize functionality is only accessible with a   */
      /*  system call we must close the file and reopen it with the    */
      /*  open function (_fopen for MS ??) this is still to be checked */
      /*  for compatibility with Text files and other OS's.            */
      /*****************************************************************/
      char filename[_MAX_PATH];
      int  h;                           // File handle, return code

      PlugSetPath(filename, To_File, Tdbp->GetPath());
      /*rc=*/ PlugCloseFile(g, To_Fb);

      if ((h= global_open(g, MSGID_OPEN_STRERROR, filename, O_WRONLY)) <= 0)
        return RC_FX;

      /*****************************************************************/
      /*  Remove extra records.                                        */
      /*****************************************************************/
#if defined(UNIX)
      if (ftruncate(h, (off_t)Tpos)) {
        sprintf(g->Message, MSG(TRUNCATE_ERROR), strerror(errno));
        close(h);
        return RC_FX;
        } // endif
#else
      if (chsize(h, Tpos)) {
        sprintf(g->Message, MSG(CHSIZE_ERROR), strerror(errno));
        close(h);
        return RC_FX;
        } // endif
#endif

      close(h);

      if (trace)
        htrc("done, h=%d irc=%d\n", h, irc);

      } // endif !UseTemp

  } // endif irc

  return RC_OK;                                      // All is correct
  } // end of DeleteRecords
Example #15
0
bool DOSFAM::OpenTableFile(PGLOBAL g)
  {
  char    opmode[4], filename[_MAX_PATH];
//int     ftype = Tdbp->GetFtype();
  MODE    mode = Tdbp->Mode;
  PDBUSER dbuserp = PlgGetUser(g);

  // This is required when using Unix files under Windows
  Bin = (Ending == 1);

  switch (mode) {
    case MODE_READ:
      strcpy(opmode, "r");
      break;
    case MODE_DELETE:
      if (!Tdbp->Next) {
        // Store the number of deleted lines
        DelRows = Cardinality(g);

        if (Blocked) {
          // Cardinality must return 0
          Block = 0;
          Last = Nrec;
          } // endif blocked

        // This will erase the entire file
        strcpy(opmode, "w");
        Tdbp->ResetSize();
        break;
        } // endif

      // Selective delete, pass thru
      Bin = true;
    case MODE_UPDATE:
      if ((UseTemp = Tdbp->IsUsingTemp(g))) {
        strcpy(opmode, "r");
        Bin = true;
      } else
        strcpy(opmode, "r+");

      break;
    case MODE_INSERT:
      strcpy(opmode, "a+");
      break;
    default:
      sprintf(g->Message, MSG(BAD_OPEN_MODE), mode);
      return true;
    } // endswitch Mode

  // For blocked I/O or for moving lines, open the table in binary
  strcat(opmode, (Blocked || Bin) ? "b" : "t");

  // Now open the file stream
  PlugSetPath(filename, To_File, Tdbp->GetPath());

  if (!(Stream = PlugOpenFile(g, filename, opmode))) {
    if (trace)
      htrc("%s\n", g->Message);

    return (mode == MODE_READ && errno == ENOENT)
            ? PushWarning(g, Tdbp) : true;
    } // endif Stream

  if (trace)
    htrc("File %s open Stream=%p mode=%s\n", filename, Stream, opmode);

  To_Fb = dbuserp->Openlist;     // Keep track of File block

  /*********************************************************************/
  /*  Allocate the line buffer. For mode Delete a bigger buffer has to */
  /*  be allocated because is it also used to move lines into the file.*/
  /*********************************************************************/
  return AllocateBuffer(g);
  } // end of OpenTableFile
Example #16
0
void DBFFAM::CloseTableFile(PGLOBAL g, bool abort)
  {
  int rc = RC_OK, wrc = RC_OK;
  MODE mode = Tdbp->GetMode();

  Abort = abort;

  // Closing is True if last Write was in error
  if (mode == MODE_INSERT && CurNum && !Closing) {
    // Some more inserted lines remain to be written
    Rbuf = CurNum--;
//  Closing = true;
    wrc = WriteBuffer(g);
  } else if (mode == MODE_UPDATE || mode == MODE_DELETE) {
    if (Modif && !Closing) {
      // Last updated block remains to be written
      Closing = true;
      wrc = WriteModifiedBlock(g);
      } // endif Modif

    if (UseTemp && T_Stream && wrc == RC_OK) {
      if (!Abort) {
        // Copy any remaining lines
        bool b;
    
        Fpos = Tdbp->Cardinality(g);
        Abort = MoveIntermediateLines(g, &b) != RC_OK;
        } // endif Abort

      // Delete the old file and rename the new temp file.
      RenameTempFile(g);
      goto fin;
      } // endif UseTemp

  } // endif's mode

  if (Tdbp->GetMode() == MODE_INSERT) {
    int n = ftell(Stream) - Headlen;

    rc = PlugCloseFile(g, To_Fb);

    if (n >= 0 && !(n % Lrecl)) {
      n /= Lrecl;                       // New number of lines

      if (n > Records) {
        // Update the number of rows in the file header
        char filename[_MAX_PATH];

        PlugSetPath(filename, To_File, Tdbp->GetPath());
        if ((Stream= global_fopen(g, MSGID_OPEN_MODE_STRERROR, filename, "r+b")))
        {
          fseek(Stream, 4, SEEK_SET);     // Get header.Records position
          fwrite(&n, sizeof(int), 1, Stream);
          fclose(Stream);
          Stream= NULL;
          Records= n;                    // Update Records value
        }
      } // endif n

    } // endif n

  } else  // Finally close the file
    rc = PlugCloseFile(g, To_Fb);

 fin:
  if (trace)
    htrc("DBF CloseTableFile: closing %s mode=%d wrc=%d rc=%d\n",
         To_File, mode, wrc, rc);

  Stream = NULL;           // So we can know whether table is open
  } // end of CloseTableFile
Example #17
0
PQRYRES DBFColumns(PGLOBAL g, char *dp, const char *fn, bool info)
  {
  int  buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
                   TYPE_INT,    TYPE_INT,   TYPE_SHORT};
  XFLD fldtyp[] = {FLD_NAME, FLD_TYPE,   FLD_TYPENAME,
                   FLD_PREC, FLD_LENGTH, FLD_SCALE};
  unsigned int length[] = {11, 6, 8, 10, 10, 6};
  char       buf[2], filename[_MAX_PATH];
  int        ncol = sizeof(buftyp) / sizeof(int);
  int        rc, type, len, field, fields;
  bool       bad;
  DBFHEADER  mainhead;
  DESCRIPTOR thisfield;
  FILE      *infile = NULL;
  PQRYRES    qrp;
  PCOLRES    crp;

  if (trace)
    htrc("DBFColumns: File %s\n", SVP(fn));

  if (!info) {
    if (!fn) {
      strcpy(g->Message, MSG(MISSING_FNAME));
      return NULL;
      } // endif fn

    /************************************************************************/
    /*  Open the input file.                                                */
    /************************************************************************/
    PlugSetPath(filename, fn, dp);

    if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "rb")))
      return NULL;

    /************************************************************************/
    /*  Get the first 32 bytes of the header.                               */
    /************************************************************************/
    if ((rc = dbfhead(g, infile, filename, &mainhead)) == RC_FX) {
      fclose(infile);
      return NULL;
      } // endif dbfhead

    /************************************************************************/
    /*  Allocate the structures used to refer to the result set.            */
    /************************************************************************/
    fields = mainhead.Fields;
  } else
    fields = 0;

  qrp = PlgAllocResult(g, ncol, fields, IDS_COLUMNS + 3,
                          buftyp, fldtyp, length, true, false);

  if (info || !qrp) {
  	if (infile)
      fclose(infile);
      
    return qrp;
    } // endif info

  if (trace) {
    htrc("Structure of %s\n", filename);
    htrc("headlen=%hd reclen=%hd degree=%d\n",
          mainhead.Headlen, mainhead.Reclen, fields);
    htrc("flags(iem)=%d,%d,%d cp=%d\n", mainhead.Incompleteflag,
          mainhead.Encryptflag, mainhead.Mdxflag, mainhead.Language);
    htrc("%hd records, last changed %02d/%02d/%d\n",
          mainhead.Records, mainhead.Filedate[1], mainhead.Filedate[2],
          mainhead.Filedate[0] + (mainhead.Filedate[0] <= 30) ? 2000 : 1900);
    htrc("Field    Type  Offset  Len  Dec  Set  Mdx\n");
    } // endif trace

  buf[1] = '\0';

  /**************************************************************************/
  /*  Do it field by field.  We are at byte 32 of file.                     */
  /**************************************************************************/
  for (field = 0; field < fields; field++) {
    bad = FALSE;

    if (fread(&thisfield, HEADLEN, 1, infile) != 1) {
      sprintf(g->Message, MSG(ERR_READING_REC), field+1, fn);
      goto err;
    } else
      len = thisfield.Length;

    if (trace)
      htrc("%-11s %c  %6ld  %3d   %2d  %3d  %3d\n",
           thisfield.Name, thisfield.Type, thisfield.Offset, len,
           thisfield.Decimals, thisfield.Setfield, thisfield.Mdxfield);

    /************************************************************************/
    /*  Now get the results into blocks.                                    */
    /************************************************************************/
    switch (thisfield.Type) {
      case 'C':                      // Characters
      case 'L':                      // Logical 'T' or 'F'
        type = TYPE_STRING;
        break;
      case 'N':
        type = (thisfield.Decimals) ? TYPE_DOUBLE
             : (len > 10) ? TYPE_BIGINT : TYPE_INT;
        break;
      case 'F':
        type = TYPE_DOUBLE;
        break;
      case 'D':
        type = TYPE_DATE;            // Is this correct ???
        break;
      default:
        if (!info) {
          sprintf(g->Message, MSG(BAD_DBF_TYPE), thisfield.Type);
          goto err;
          } // endif info

        type = TYPE_ERROR;
        bad = TRUE;
      } // endswitch Type

    crp = qrp->Colresp;                    // Column Name
    crp->Kdata->SetValue(thisfield.Name, field);
    crp = crp->Next;                       // Data Type
    crp->Kdata->SetValue((int)type, field);
    crp = crp->Next;                       // Type Name

    if (bad) {
      buf[0] = thisfield.Type;
      crp->Kdata->SetValue(buf, field);
    } else
      crp->Kdata->SetValue(GetTypeName(type), field);

    crp = crp->Next;                       // Precision
    crp->Kdata->SetValue((int)thisfield.Length, field);
    crp = crp->Next;                       // Length
    crp->Kdata->SetValue((int)thisfield.Length, field);
    crp = crp->Next;                       // Scale (precision)
    crp->Kdata->SetValue((int)thisfield.Decimals, field);
    } // endfor field

  qrp->Nblin = field;
  fclose(infile);

#if 0
  if (info) {
    /************************************************************************/
    /*  Prepare return message for dbfinfo command.                         */
    /************************************************************************/
    char buf[64];

    sprintf(buf,
      "Ver=%02x ncol=%hu nlin=%u lrecl=%hu headlen=%hu date=%02d/%02d/%02d",
      mainhead.Version, fields, mainhead.Records, mainhead.Reclen,
      mainhead.Headlen, mainhead.Filedate[0], mainhead.Filedate[1],
      mainhead.Filedate[2]);

    strcat(g->Message, buf);
    } // endif info
#endif // 0

  /**************************************************************************/
  /*  Return the result pointer for use by GetData routines.                */
  /**************************************************************************/
  return qrp;

 err:
  fclose(infile);
  return NULL;
  } // end of DBFColumns
Example #18
0
PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q,
                   int hdr, int mxr, bool info)
  {
  static int  buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_STRING,
                          TYPE_INT,   TYPE_INT, TYPE_SHORT};
  static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE,   FLD_TYPENAME,
                          FLD_PREC, FLD_LENGTH, FLD_SCALE};
  static unsigned int length[] = {6, 6, 8, 10, 10, 6};
  char   *p, *colname[MAXCOL], dechar, filename[_MAX_PATH], buf[4096];
  int     i, imax, hmax, n, nerr, phase, blank, digit, dec, type;
  int     ncol = sizeof(buftyp) / sizeof(int);
  int     num_read = 0, num_max = 10000000;     // Statistics
  int     len[MAXCOL], typ[MAXCOL], prc[MAXCOL];
  FILE   *infile;
  PQRYRES qrp;
  PCOLRES crp;

  if (info) {
    imax = hmax = 0;
    length[0] = 128;
    goto skipit;
    } // endif info

//      num_max = atoi(p+1);             // Max num of record to test
#if defined(WIN32)
  if (sep == ',' || strnicmp(setlocale(LC_NUMERIC, NULL), "French", 6))
    dechar = '.';
  else
    dechar = ',';
#else   // !WIN32
  dechar = '.';
#endif  // !WIN32

  if (trace)
    htrc("File %s sep=%c q=%c hdr=%d mxr=%d\n",
          SVP(fn), sep, q, hdr, mxr);

  if (!fn) {
    strcpy(g->Message, MSG(MISSING_FNAME));
    return NULL;
    } // endif fn

  imax = hmax = nerr = 0;
  mxr = MY_MAX(0, mxr);

  for (i = 0; i < MAXCOL; i++) {
    colname[i] = NULL;
    len[i] = 0;
    typ[i] = TYPE_UNKNOWN;
    prc[i] = 0;
    } // endfor i

  /*********************************************************************/
  /*  Open the input file.                                             */
  /*********************************************************************/
  PlugSetPath(filename, fn, PlgGetDataPath(g));

  if (!(infile= global_fopen(g, MSGID_CANNOT_OPEN, filename, "r")))
    return NULL;

  if (hdr) {
    /*******************************************************************/
    /*  Make the column names from the first line.                     */
    /*******************************************************************/
    phase = 0;

    if (fgets(buf, sizeof(buf), infile)) {
      n = strlen(buf) + 1;
      buf[n - 2] = '\0';
#if defined(UNIX)
      // The file can be imported from Windows 
      if (buf[n - 3] == '\r')
        buf[n - 3] = 0;
#endif   // UNIX
      p = (char*)PlugSubAlloc(g, NULL, n);
      memcpy(p, buf, n);

      //skip leading blanks
      for (; *p == ' '; p++) ;

      if (q && *p == q) {
        // Header is quoted
        p++;
        phase = 1;
        } // endif q

      colname[0] = p;
    } else {
      sprintf(g->Message, MSG(FILE_IS_EMPTY), fn);
      goto err;
    } // endif's

    for (i = 1; *p; p++)
      if (phase == 1 && *p == q) {
        *p = '\0';
        phase = 0;
      } else if (*p == sep && !phase) {
        *p = '\0';

        //skip leading blanks
        for (; *(p+1) == ' '; p++) ;

        if (q && *(p+1) == q) {
          // Header is quoted
          p++;
          phase = 1;
          } // endif q

        colname[i++] = p + 1;
        } // endif sep

    num_read++;
    imax = hmax = i;

    for (i = 0; i < hmax; i++)
      length[0] = MY_MAX(length[0], strlen(colname[i]));

    } // endif hdr

  for (num_read++; num_read <= num_max; num_read++) {
    /*******************************************************************/
    /*  Now start the reading process. Read one line.                  */
    /*******************************************************************/
    if (fgets(buf, sizeof(buf), infile)) {
      n = strlen(buf);
      buf[n - 1] = '\0';
#if defined(UNIX)
      // The file can be imported from Windows 
      if (buf[n - 2] == '\r')
        buf[n - 2] = 0;
#endif   // UNIX
    } else if (feof(infile)) {
      sprintf(g->Message, MSG(EOF_AFTER_LINE), num_read -1);
      break;
    } else {
      sprintf(g->Message, MSG(ERR_READING_REC), num_read, fn);
      goto err;
    } // endif's

    /*******************************************************************/
    /*  Make the test for field lengths.                               */
    /*******************************************************************/
    i = n = phase = blank = digit = dec = 0;

    for (p = buf; *p; p++)
      if (*p == sep) {
        if (phase != 1) {
          if (i == MAXCOL - 1) {
            sprintf(g->Message, MSG(TOO_MANY_FIELDS), num_read, fn);
            goto err;
            } // endif i

          if (n) {
            len[i] = MY_MAX(len[i], n);
            type = (digit || (dec && n == 1)) ? TYPE_STRING
                 : (dec) ? TYPE_DOUBLE : TYPE_INT;
            typ[i] = MY_MIN(type, typ[i]);
            prc[i] = MY_MAX((typ[i] == TYPE_DOUBLE) ? (dec - 1) : 0, prc[i]);
            } // endif n

          i++;
          n = phase = blank = digit = dec = 0;
        } else          // phase == 1
          n++;

      } else if (*p == ' ') {
        if (phase < 2)
          n++;

        if (blank)
          digit = 1;

      } else if (*p == q) {
        if (phase == 0) {
          if (blank)
            if (++nerr > mxr) {
              sprintf(g->Message, MSG(MISPLACED_QUOTE), num_read);
              goto err;
            } else
              goto skip;

          n = 0;
          phase = digit = 1;
        } else if (phase == 1) {
          if (*(p+1) == q) {
            // This is currently not implemented for CSV tables
//          if (++nerr > mxr) {
//            sprintf(g->Message, MSG(QUOTE_IN_QUOTE), num_read);
//            goto err;
//          } else
//            goto skip;

            p++;
            n++;
          } else
            phase = 2;

        } else if (++nerr > mxr) {      // phase == 2
          sprintf(g->Message, MSG(MISPLACED_QUOTE), num_read);
          goto err;
        } else
          goto skip;

      } else {
        if (phase == 2)
          if (++nerr > mxr) {
            sprintf(g->Message, MSG(MISPLACED_QUOTE), num_read);
            goto err;
          } else
            goto skip;

        // isdigit cannot be used here because of debug assert
        if (!strchr("0123456789", *p)) {
          if (!digit && *p == dechar)
            dec = 1;                    // Decimal point found
          else if (blank || !(*p == '-' || *p == '+'))
            digit = 1;

        } else if (dec)
          dec++;                        // More decimals

        n++;
        blank = 1;
      } // endif's *p

    if (phase == 1)
      if (++nerr > mxr) {
        sprintf(g->Message, MSG(UNBALANCE_QUOTE), num_read);
        goto err;
      } else
        goto skip;

    if (n) {
      len[i] = MY_MAX(len[i], n);
      type = (digit || n == 0 || (dec && n == 1)) ? TYPE_STRING
           : (dec) ? TYPE_DOUBLE : TYPE_INT;
      typ[i] = MY_MIN(type, typ[i]);
      prc[i]  = MY_MAX((typ[i] == TYPE_DOUBLE) ? (dec - 1) : 0, prc[i]);
      } // endif n

    imax = MY_MAX(imax, i+1);
   skip: ;                  // Skip erroneous line
    } // endfor num_read

  if (trace) {
    htrc("imax=%d Lengths:", imax);

    for (i = 0; i < imax; i++)
      htrc(" %d", len[i]);

    htrc("\n");
  } // endif trace

  fclose(infile);

 skipit:
  if (trace)
    htrc("CSVColumns: imax=%d hmax=%d len=%d\n",
                      imax, hmax, length[0]);

  /*********************************************************************/
  /*  Allocate the structures used to refer to the result set.         */
  /*********************************************************************/
  qrp = PlgAllocResult(g, ncol, imax, IDS_COLUMNS + 3,
                          buftyp, fldtyp, length, false, false);
  if (info || !qrp)
    return qrp;

  qrp->Nblin = imax;

  /*********************************************************************/
  /*  Now get the results into blocks.                                 */
  /*********************************************************************/
  for (i = 0; i < imax; i++) {
    if (i >= hmax) {
      sprintf(buf, "COL%.3d", i+1);
      p = buf;
    } else
      p = colname[i];

    if (typ[i] == TYPE_UNKNOWN)            // Void column
      typ[i] = TYPE_STRING;

    crp = qrp->Colresp;                    // Column Name
    crp->Kdata->SetValue(p, i);
    crp = crp->Next;                       // Data Type
    crp->Kdata->SetValue(typ[i], i);
    crp = crp->Next;                       // Type Name
    crp->Kdata->SetValue(GetTypeName(typ[i]), i);
    crp = crp->Next;                       // Precision
    crp->Kdata->SetValue(len[i], i);
    crp = crp->Next;                       // Length
    crp->Kdata->SetValue(len[i], i);
    crp = crp->Next;                       // Scale (precision)
    crp->Kdata->SetValue(prc[i], i);
    } // endfor i

  /*********************************************************************/
  /*  Return the result pointer for use by GetData routines.           */
  /*********************************************************************/
  return qrp;

 err:
  fclose(infile);
  return NULL;
  } // end of CSVCColumns