123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539 |
- #include "../nde.h"
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include "Vfs.h"
- #ifndef EOF
- #define EOF -1
- #endif
- VFILE *Vfnew(const char *fl, const char *mode, int Cached)
- {
- if (!fl) return NULL;
- VFILE *f = (VFILE *)malloc(sizeof(VFILE));
- if (!f)
- return NULL;
- memset(f, 0, sizeof(VFILE));
- #ifdef NDE_ALLOW_NONCACHED
- f->cached = Cached;
- #else
- f->cached = 1;
- #endif
- if (!strchr(mode, '+'))
- {
- if (strchr(mode, 'r'))
- f->mode = VFS_READ | VFS_MUSTEXIST;
- if (strchr(mode, 'w'))
- f->mode = VFS_WRITE | VFS_CREATE | VFS_NEWCONTENT;
- if (strchr(mode, 'a'))
- f->mode = VFS_WRITE | VFS_CREATE | VFS_SEEKEOF;
- }
- else
- {
- if (strstr(mode, "r+"))
- f->mode = VFS_WRITE | VFS_MUSTEXIST;
- if (strstr(mode, "w+"))
- f->mode = VFS_WRITE | VFS_CREATE | VFS_NEWCONTENT;
- if (strstr(mode, "a+"))
- f->mode = VFS_WRITE | VFS_CREATE | VFS_SEEKEOF;
- }
- if (f->mode == 0 || ((f->mode & VFS_READ) && (f->mode & VFS_WRITE)))
- {
- free(f);
- return NULL;
- }
- snprintf(f->lockname, sizeof(f->lockname), "%s.lock", fl);
- return f;
- }
- VFILE *Vfopen(VFILE *f, const char *fl, const char *mode, int Cached)
- {
- if (!f)
- {
- f = Vfnew(fl, mode, Cached);
- if (!f)
- return 0;
- }
- if (!f && !fl) return NULL;
- #ifdef NDE_ALLOW_NONCACHED
- if (!f->cached)
- {
- f->rfile = fopen(fl, mode);
- if (f->rfile)
- f->filename = _strdup(fl);
- }
- else
- {
- free(f);
- return NULL;
- }
- return f;
- }
- #endif
- if (f->mode & VFS_MUSTEXIST)
- {
- if (access(fl, 0) != 0)
- {
- free(f);
- return NULL;
- }
- }
- if (!(f->mode & VFS_NEWCONTENT))
- {
- FILE *pf;
- pf = fopen(fl, "rb");
- if (!pf)
- {
- f->data = (unsigned char *)calloc(VFILE_INC, 1);
- if (f->data == NULL)
- {
- free(f);
- return NULL;
- }
- f->filesize = 0;
- f->maxsize = VFILE_INC;
- }
- else
- {
- fseek(pf, 0, SEEK_END);
- f->filesize = ftell(pf);
- fseek(pf, 0, SEEK_SET);
- f->data = (unsigned char *)calloc(f->filesize, 1);
- if (f->data == NULL)
- {
- free(f);
- return NULL;
- }
- f->maxsize = f->filesize;
- fread(f->data, f->filesize, 1, pf);
- fclose(pf);
- }
- }
- if (f->mode & VFS_SEEKEOF)
- f->ptr = f->filesize;
- f->filename = strdup(fl);
- return f;
- }
- void Vfclose(VFILE *f)
- {
- if (!f) return;
- #ifdef NDE_ALLOW_NONCACHED
- if (!f->cached)
- {
- free(f->filename);
- if (f->rfile)
- fclose(f->rfile);
- f->rfile=0;
- return;
- }
- #endif
- if (!(f->mode & VFS_WRITE))
- {
- free(f->filename);
- free(f->data);
-
- return;
- }
- Vsync(f);
- while (f->locks)
- Vfunlock(f, 1);
- free(f->filename);
- free(f->data);
-
- }
- size_t Vfread(void *ptr, size_t size, VFILE *f)
- {
- if (!ptr || !f) return 0;
- #ifdef NDE_ALLOW_NONCACHED
- if (!f->cached)
- {
- return fread(ptr, 1, size, f->rfile);
- }
- #endif
- size_t s = size;
- if (!s) return 0;
- if (s + f->ptr > f->filesize)
- {
-
- if (!(f->ptr < f->filesize))
- {
-
-
-
-
-
- return 0;
- }
- s = f->filesize - f->ptr;
- }
- memcpy(ptr, f->data+f->ptr, s);
- f->ptr += s;
- return (s/size);
- }
- void Vfwrite(const void *ptr, size_t size, VFILE *f)
- {
- if (!ptr || !f) return;
- #ifdef NDE_ALLOW_NONCACHED
- if (!f->cached)
- {
- fwrite(ptr, size*n, f->rfile);
- return;
- }
- #endif
- f->dirty=1;
- if (size + f->ptr > f->maxsize)
- {
-
-
- size_t newsize=(size + f->ptr + VFILE_INC-1)&~(VFILE_INC-1);
- f->data=(unsigned char *)realloc(f->data,newsize);
- if (f->data == NULL) return;
- memset(f->data+f->maxsize,0,newsize-f->maxsize);
- f->maxsize=newsize;
- }
- memcpy(f->data + f->ptr, ptr, size);
- f->ptr += size;
- if (f->ptr > f->filesize)
- f->filesize = f->ptr;
- }
- void Vgrow(VFILE *f)
- {
- if (!f) return;
- #ifdef NDE_ALLOW_NONCACHED
- if (!f->cached) return;
- #endif
- f->data = (unsigned char *)realloc(f->data, f->maxsize + VFILE_INC);
- f->maxsize += VFILE_INC;
- }
- void Vfputs(char *str, VFILE *f)
- {
- if (!f) return;
- #ifdef NDE_ALLOW_NONCACHED
- if (!f->cached)
- {
- fputs(str, f->rfile);
- return;
- }
- #endif
- Vfwrite(str, strlen(str), f);
- }
- void Vfputc(char c, VFILE *f)
- {
- if (!f) return;
- #ifdef NDE_ALLOW_NONCACHED
- if (!f->cached)
- {
- fputc(c, f->rfile);
- return;
- }
- #endif
- Vfwrite(&c, 1, f);
- }
- unsigned long Vftell(VFILE *f)
- {
- if (!f) return (unsigned)-1;
- #ifdef NDE_ALLOW_NONCACHED
- if (!f->cached)
- {
- return ftell(f->rfile);
- }
- #endif
- return f->ptr;
- }
- void Vfseek(VFILE *f, long i, int whence)
- {
- if (!f) return;
- #ifdef NDE_ALLOW_NONCACHED
- if (!f->cached)
- {
- fseek(f->rfile, i, whence);
- return;
- }
- #endif
- switch (whence)
- {
- case SEEK_SET:
- f->ptr = i;
- break;
- case SEEK_CUR:
- f->ptr += i;
- break;
- case SEEK_END:
- f->ptr = f->filesize+i;
- break;
- }
- }
- int Vfeof(VFILE *f)
- {
- if (!f) return -1;
- #ifdef NDE_ALLOW_NONCACHED
- if (!f->cached)
- {
- return feof(f->rfile);
- }
- #endif
- return (f->ptr >= f->filesize);
- }
- int Vsync(VFILE *f)
- {
- if (!f) return 0;
- if (!f->dirty) return 0;
- if (f->mode & VFS_WRITE)
- {
- #ifdef NDE_ALLOW_NONCACHED
- if (!f->cached)
- {
- int p=ftell(f->rfile);
- fclose(f->rfile);
- f->rfile = fopen(f->filename, "r+b");
- if (!f->rfile)
- return 1;
- fseek(f->rfile, p, SEEK_SET);
- return 0;
- }
- #endif
- char newfn[1024], oldfn[1024];
- DWORD mypid=getpid();
- snprintf(newfn,sizeof(newfn), "%s.n3w%08X",f->filename,mypid);
- snprintf(oldfn,sizeof(oldfn), "%s.o1d%08X",f->filename,mypid);
- unlink(newfn);
- unlink(oldfn);
- tryagain:
- FILE *pf = fopen(newfn, "wb");
- if (!pf || fwrite(f->data, f->filesize, 1, pf) != 1)
- {
- if (pf) fclose(pf);
- printf("Error flushing DB to disk (is your drive full?)\n\nHit (R)etry to try again (recommended), or (C)ancel to abort (NOT recommended, and may leave the DB in an unuseable state)");
- fflush(stdout);
- char c;
- while (1)
- {
- scanf("%c", &c);
- c = toupper(c);
- if (c == 'R') goto tryagain;
- else if (c == 'C') break;
- }
- unlink(newfn);
- return 1;
- }
- fclose(pf);
- rename(f->filename,oldfn);
- int rv=0;
- tryagain2:
- if (rename(newfn,f->filename))
- {
- printf("Error updating DB file on disk. This should never really happen\n\nHit (R)etry to try again (recommended), or (C)ancel to abort (NOT recommended, and may leave the DB in an unuseable state)");
- fflush(stdout);
- char c;
- while (1)
- {
- scanf("%c", &c);
- c = toupper(c);
- if (c == 'R') goto tryagain2;
- else if (c == 'C') break;
- }
- rename(oldfn,f->filename);
- rv=1;
- }
-
- unlink(oldfn);
- unlink(newfn);
-
-
- return rv;
- }
- f->dirty=0;
- return 0;
- }
- void Vfdestroy(VFILE *f)
- {
-
- if (f)
- {
- Vfclose(f);
-
- while (f->locks)
- Vfunlock(f, 1);
-
- free(f);
- }
- }
- int Vflock(VFILE *fl, bool is_sync)
- {
- #ifndef NO_TABLE_WIN32_LOCKING
- if (!fl) return 0;
- if (!is_sync && fl->cached)
- return 1;
- if (fl->locks++ == 0)
- {
- int retry_cnt=0;
- FILE *fFile;
- do
- {
- fFile = fopen(fl->lockname, "wb");
- if (fFile == 0) Sleep(100);
- }
- while (fFile == 0 && retry_cnt++ < 100);
- if (fFile == INVALID_HANDLE_VALUE) return 0;
- fl->lockFile = fFile;
- }
- #endif
- return 1;
- }
- void Vfunlock(VFILE *fl, bool is_sync)
- {
- #ifndef NO_TABLE_WIN32_LOCKING
- if (!is_sync && fl->cached)
- return;
- if (--fl->locks == 0)
- {
- if (fl && fl->lockFile && fl->lockFile != INVALID_HANDLE_VALUE)
- {
- fclose(fl->lockFile);
- unlink(fl->lockname);
- }
- }
- #endif
- }
|