diff options
Diffstat (limited to 'src/common/grfio.c')
-rw-r--r-- | src/common/grfio.c | 151 |
1 files changed, 97 insertions, 54 deletions
diff --git a/src/common/grfio.c b/src/common/grfio.c index 28e6c87f4..d226fb158 100644 --- a/src/common/grfio.c +++ b/src/common/grfio.c @@ -402,51 +402,72 @@ static void grfio_localpath_create(char* buffer, size_t size, const char* filena /// Reads a file into a newly allocated buffer (from grf or data directory). -void* grfio_reads(const char* fname, int* size) +void *grfio_reads(const char *fname, int *size) { - unsigned char* buf2 = NULL; - FILELIST* entry = filelist_find(fname); - if( entry == NULL || entry->gentry <= 0 ) {// LocalFileCheck + if (entry == NULL || entry->gentry <= 0) { + // LocalFileCheck char lfname[256]; - FILE* in; - grfio_localpath_create(lfname, sizeof(lfname), ( entry && entry->fnd ) ? entry->fnd : fname); + FILE *in; + unsigned char *buf = NULL; + grfio_localpath_create(lfname, sizeof(lfname), (entry && entry->fnd) ? entry->fnd : fname); in = fopen(lfname, "rb"); - if( in != NULL ) { + if (in != NULL) { int declen; fseek(in,0,SEEK_END); declen = (int)ftell(in); + if (declen == -1) { + ShowError("An error occurred in fread grfio_reads, fname=%s \n",fname); + fclose(in); + return NULL; + } fseek(in,0,SEEK_SET); - buf2 = (unsigned char *)aMalloc(declen+1); // +1 for resnametable zero-termination - if(fread(buf2, 1, declen, in) != (size_t)declen) ShowError("An error occurred in fread grfio_reads, fname=%s \n",fname); + buf = (unsigned char *)aMalloc(declen+1); // +1 for resnametable zero-termination + buf[declen] = '\0'; + if (fread(buf, 1, declen, in) != (size_t)declen) { + ShowError("An error occurred in fread grfio_reads, fname=%s \n",fname); + aFree(buf); + fclose(in); + return NULL; + } fclose(in); - if( size ) + if (size) *size = declen; - } else { - if (entry != NULL && entry->gentry < 0) { - entry->gentry = -entry->gentry; // local file checked - } else { - ShowError("grfio_reads: %s not found (local file: %s)\n", fname, lfname); - return NULL; - } + return buf; } + + if (entry == NULL || entry->gentry >= 0) { + ShowError("grfio_reads: %s not found (local file: %s)\n", fname, lfname); + return NULL; + } + + entry->gentry = -entry->gentry; // local file checked } - if( entry != NULL && entry->gentry > 0 ) {// Archive[GRF] File Read - char* grfname = gentry_table[entry->gentry - 1]; - FILE* in = fopen(grfname, "rb"); - if( in != NULL ) { + if (entry != NULL && entry->gentry > 0) { + // Archive[GRF] File Read + char *grfname = gentry_table[entry->gentry - 1]; + FILE *in = fopen(grfname, "rb"); + + if (in != NULL) { int fsize = entry->srclen_aligned; unsigned char *buf = (unsigned char *)aMalloc(fsize); - fseek(in, entry->srcpos, 0); - if(fread(buf, 1, fsize, in) != (size_t)fsize) ShowError("An error occurred in fread in grfio_reads, grfname=%s\n",grfname); + unsigned char *buf2 = NULL; + if (fseek(in, entry->srcpos, SEEK_SET) != 0 + || fread(buf, 1, fsize, in) != (size_t)fsize) { + ShowError("An error occurred in fread in grfio_reads, grfname=%s\n",grfname); + aFree(buf); + fclose(in); + return NULL; + } fclose(in); buf2 = (unsigned char *)aMalloc(entry->declen+1); // +1 for resnametable zero-termination - if( entry->type & FILELIST_TYPE_FILE ) - {// file + buf2[entry->declen] = '\0'; + if (entry->type & FILELIST_TYPE_FILE) { + // file uLongf len; grf_decode(buf, fsize, entry->type, entry->srclen); len = entry->declen; @@ -457,21 +478,23 @@ void* grfio_reads(const char* fname, int* size) aFree(buf2); return NULL; } - } else {// directory? + } else { + // directory? memcpy(buf2, buf, entry->declen); } - if( size ) + if (size) *size = entry->declen; aFree(buf); + return buf2; } else { ShowError("grfio_reads: %s not found (GRF file: %s)\n", fname, grfname); return NULL; } } - return buf2; + return NULL; } @@ -506,26 +529,31 @@ static bool isFullEncrypt(const char* fname) /// Loads all entries in the specified grf file into the filelist. /// @param gentry index of the grf file name in the gentry_table -static int grfio_entryread(const char* grfname, int gentry) +static int grfio_entryread(const char *grfname, int gentry) { long grf_size; unsigned char grf_header[0x2e] = { 0 }; int entry,entrys,ofs,grf_version; unsigned char *grf_filelist; - FILE* fp = fopen(grfname, "rb"); + FILE *fp = fopen(grfname, "rb"); if( fp == NULL ) { ShowWarning("GRF data file not found: '%s'\n",grfname); return 1; // 1:not found error - } else + } else { ShowInfo("GRF data file found: '%s'\n",grfname); + } fseek(fp,0,SEEK_END); grf_size = ftell(fp); fseek(fp,0,SEEK_SET); - if(fread(grf_header,1,0x2e,fp) != 0x2e) { ShowError("Couldn't read all grf_header element of %s \n", grfname); } - if( strcmp((const char*)grf_header,"Master of Magic") != 0 || fseek(fp,getlong(grf_header+0x1e),SEEK_CUR) != 0 ) { + if (fread(grf_header,1,0x2e,fp) != 0x2e) { + ShowError("Couldn't read all grf_header element of %s \n", grfname); + fclose(fp); + return 2; // 2:file format error + } + if (strcmp((const char*)grf_header,"Master of Magic") != 0 || fseek(fp,getlong(grf_header+0x1e),SEEK_CUR) != 0) { fclose(fp); ShowError("GRF %s read error\n", grfname); return 2; // 2:file format error @@ -533,32 +561,37 @@ static int grfio_entryread(const char* grfname, int gentry) grf_version = getlong(grf_header+0x2a) >> 8; - if( grf_version == 0x01 ) {// ****** Grf version 01xx ****** + if (grf_version == 0x01) { + // ****** Grf version 01xx ****** long list_size; list_size = grf_size - ftell(fp); - grf_filelist = (unsigned char *) aMalloc(list_size); - if(fread(grf_filelist,1,list_size,fp) != (size_t)list_size) { ShowError("Couldn't read all grf_filelist element of %s \n", grfname); } + grf_filelist = (unsigned char *)aMalloc(list_size); + if (fread(grf_filelist,1,list_size,fp) != (size_t)list_size) { + ShowError("Couldn't read all grf_filelist element of %s \n", grfname); + aFree(grf_filelist); + fclose(fp); + return 2; // 2:file format error + } fclose(fp); entrys = getlong(grf_header+0x26) - getlong(grf_header+0x22) - 7; // Get an entry - for( entry = 0, ofs = 0; entry < entrys; ++entry ) { + for (entry = 0, ofs = 0; entry < entrys; ++entry) { FILELIST aentry; - int ofs2 = ofs+getlong(grf_filelist+ofs)+4; unsigned char type = grf_filelist[ofs2+12]; - if( type & FILELIST_TYPE_FILE ) { - char* fname = decode_filename(grf_filelist+ofs+6, grf_filelist[ofs]-6); + if (type&FILELIST_TYPE_FILE) { + char *fname = decode_filename(grf_filelist+ofs+6, grf_filelist[ofs]-6); int srclen = getlong(grf_filelist+ofs2+0) - getlong(grf_filelist+ofs2+8) - 715; - if( strlen(fname) > sizeof(aentry.fn) - 1 ) { + if (strlen(fname) > sizeof(aentry.fn) - 1) { ShowFatalError("GRF file name %s is too long\n", fname); aFree(grf_filelist); - exit(EXIT_FAILURE); + return 5; // 5: file name too long } - type |= ( isFullEncrypt(fname) ) ? FILELIST_TYPE_ENCRYPT_MIXED : FILELIST_TYPE_ENCRYPT_HEADER; + type |= isFullEncrypt(fname) ? FILELIST_TYPE_ENCRYPT_MIXED : FILELIST_TYPE_ENCRYPT_HEADER; aentry.srclen = srclen; aentry.srclen_aligned = getlong(grf_filelist+ofs2+4)-37579; @@ -579,45 +612,55 @@ static int grfio_entryread(const char* grfname, int gentry) } aFree(grf_filelist); - } else if( grf_version == 0x02 ) {// ****** Grf version 02xx ****** + } else if (grf_version == 0x02) { + // ****** Grf version 02xx ****** unsigned char eheader[8]; unsigned char *rBuf; uLongf rSize, eSize; - if(fread(eheader,1,8,fp) != 8) ShowError("An error occurred in fread while reading header buffer\n"); + if (fread(eheader,1,8,fp) != 8) { + ShowError("An error occurred in fread while reading header buffer\n"); + fclose(fp); + return 4; + } rSize = getlong(eheader); // Read Size eSize = getlong(eheader+4); // Extend Size - if( (long)rSize > grf_size-ftell(fp) ) { + if ((long)rSize > grf_size-ftell(fp)) { fclose(fp); ShowError("Illegal data format: GRF compress entry size\n"); return 4; } rBuf = (unsigned char *)aMalloc(rSize); // Get a Read Size - grf_filelist = (unsigned char *)aMalloc(eSize); // Get a Extend Size - if(fread(rBuf,1,rSize,fp) != rSize) ShowError("An error occurred in fread \n"); + if (fread(rBuf,1,rSize,fp) != rSize) { + ShowError("An error occurred in fread \n"); + fclose(fp); + aFree(rBuf); + return 4; + } fclose(fp); + grf_filelist = (unsigned char *)aMalloc(eSize); // Get a Extend Size decode_zip(grf_filelist, &eSize, rBuf, rSize); // Decode function aFree(rBuf); entrys = getlong(grf_header+0x26) - 7; // Get an entry - for( entry = 0, ofs = 0; entry < entrys; ++entry ) { + for (entry = 0, ofs = 0; entry < entrys; ++entry) { FILELIST aentry; - - char* fname = (char*)(grf_filelist+ofs); + char *fname = (char*)(grf_filelist+ofs); int ofs2 = ofs + (int)strlen(fname)+1; int type = grf_filelist[ofs2+12]; - if( strlen(fname) > sizeof(aentry.fn)-1 ) { + if (strlen(fname) > sizeof(aentry.fn)-1) { ShowFatalError("GRF file name %s is too long\n", fname); aFree(grf_filelist); - exit(EXIT_FAILURE); + return 5; // 5: file name too long } - if( type & FILELIST_TYPE_FILE ) {// file + if (type&FILELIST_TYPE_FILE) { + // file aentry.srclen = getlong(grf_filelist+ofs2+0); aentry.srclen_aligned = getlong(grf_filelist+ofs2+4); aentry.declen = getlong(grf_filelist+ofs2+8); |