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
HANDLE CreateFileMap(PGLOBAL g, LPCSTR fileName, MEMMAP *mm, MODE mode, bool del) { unsigned int openMode; int protmode; HANDLE fd; size_t filesize; struct stat st; memset(mm, 0, sizeof(MEMMAP)); *g->Message = '\0'; switch (mode) { case MODE_READ: openMode = O_RDONLY; protmode = PROT_READ; break; case MODE_UPDATE: case MODE_DELETE: openMode = (del) ? (O_RDWR | O_TRUNC) : O_RDWR; protmode = PROT_READ | PROT_WRITE; break; case MODE_INSERT: openMode = (O_WRONLY | O_CREAT | O_APPEND); protmode = PROT_WRITE; break; default: sprintf(g->Message, MSG(BAD_FUNC_MODE), "CreateFileMap", mode); return INVALID_HANDLE_VALUE; } // endswitch // Try to open the addressed file. fd= global_open(g, MSGID_NONE, fileName, openMode); if (fd != INVALID_HANDLE_VALUE && mode != MODE_INSERT) { /* We must know about the size of the file. */ if (fstat(fd, &st)) { sprintf(g->Message, MSG(FILE_MAP_ERROR), fileName, errno); close(fd); return INVALID_HANDLE_VALUE; } // endif fstat if ((filesize = st.st_size)) // Now we are ready to load the file. If mmap() is available we try // this first. If not available or it failed we try to load it. mm->memory = mmap(NULL, filesize, protmode, MAP_SHARED, fd, 0); else mm->memory = 0; if (mm->memory != MAP_FAILED) { mm->lenL = (mm->memory != 0) ? filesize : 0; mm->lenH = 0; } else { strcpy(g->Message, "Memory mapping failed"); close(fd); return INVALID_HANDLE_VALUE; } // endif memory } /* endif fd */ // mmap() call was successful. ?????????? return fd; } // end of CreateFileMap
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