/* * Wrap all zlib calls in this, so the physfs error state is set appropriately. */ static int zlib_err(int rc) { const char *str = zlib_error_string(rc); if (str != NULL) __PHYSFS_setError(str); return(rc); } /* zlib_err */
static int mvl_open(const char *filename, int forWriting, void **fh, PHYSFS_uint32 *count) { PHYSFS_uint8 buf[4]; *fh = NULL; BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0); *fh = __PHYSFS_platformOpenRead(filename); BAIL_IF_MACRO(*fh == NULL, NULL, 0); if (__PHYSFS_platformRead(*fh, buf, 4, 1) != 1) goto openMvl_failed; if (memcmp(buf, "DMVL", 4) != 0) { __PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE); goto openMvl_failed; } /* if */ if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1) goto openMvl_failed; *count = PHYSFS_swapULE32(*count); return 1; openMvl_failed: if (*fh != NULL) __PHYSFS_platformClose(*fh); *count = -1; *fh = NULL; return 0; } /* mvl_open */
static DirHandle *HOG_openArchive(const char *name, int forWriting) { HOGinfo *info; DirHandle *retval = malloc(sizeof (DirHandle)); PHYSFS_sint64 modtime = __PHYSFS_platformGetLastModTime(name); BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); info = retval->opaque = malloc(sizeof (HOGinfo)); if (info == NULL) { __PHYSFS_setError(ERR_OUT_OF_MEMORY); goto HOG_openArchive_failed; } /* if */ memset(info, '\0', sizeof (HOGinfo)); info->filename = (char *) malloc(strlen(name) + 1); if (info->filename == NULL) { __PHYSFS_setError(ERR_OUT_OF_MEMORY); goto HOG_openArchive_failed; } /* if */ if (!hog_load_entries(name, forWriting, info)) goto HOG_openArchive_failed; strcpy(info->filename, name); info->last_mod_time = modtime; retval->funcs = &__PHYSFS_DirFunctions_HOG; return(retval); HOG_openArchive_failed: if (retval != NULL) { if (retval->opaque != NULL) { if (info->filename != NULL) free(info->filename); if (info->entries != NULL) free(info->entries); free(info); } /* if */ free(retval); } /* if */ return(NULL); } /* HOG_openArchive */
static int hog_open(const char *filename, int forWriting, void **fh, PHYSFS_uint32 *count) { PHYSFS_uint8 buf[13]; PHYSFS_uint32 size; PHYSFS_sint64 pos; *count = 0; *fh = NULL; BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0); *fh = __PHYSFS_platformOpenRead(filename); BAIL_IF_MACRO(*fh == NULL, NULL, 0); if (__PHYSFS_platformRead(*fh, buf, 3, 1) != 1) goto openHog_failed; if (memcmp(buf, "DHF", 3) != 0) { __PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE); goto openHog_failed; } /* if */ while( 1 ) { if (__PHYSFS_platformRead(*fh, buf, 13, 1) != 1) break; //eof here is ok if (__PHYSFS_platformRead(*fh, &size, 4, 1) != 1) goto openHog_failed; size = PHYSFS_swapULE32(size); (*count)++; // Skip over entry pos = __PHYSFS_platformTell(*fh); if (pos == -1) goto openHog_failed; if (!__PHYSFS_platformSeek(*fh, pos + size)) goto openHog_failed; } // Rewind to start of entries if (!__PHYSFS_platformSeek(*fh, 3)) goto openHog_failed; return(1); openHog_failed: if (*fh != NULL) __PHYSFS_platformClose(*fh); *count = -1; *fh = NULL; return(0); } /* hog_open */
/* * Wrap all 7z calls in this, so the physfs error state is set appropriately. */ static int lzma_err(SZ_RESULT rc) { switch (rc) { case SZ_OK: /* Same as LZMA_RESULT_OK */ break; case SZE_DATA_ERROR: /* Same as LZMA_RESULT_DATA_ERROR */ __PHYSFS_setError(PHYSFS_ERR_CORRUPT); /*!!!FIXME: was "PHYSFS_ERR_DATA_ERROR" */ break; case SZE_OUTOFMEMORY: __PHYSFS_setError(PHYSFS_ERR_OUT_OF_MEMORY); break; case SZE_CRC_ERROR: __PHYSFS_setError(PHYSFS_ERR_CORRUPT); break; case SZE_NOTIMPL: __PHYSFS_setError(PHYSFS_ERR_UNSUPPORTED); break; case SZE_FAIL: __PHYSFS_setError(PHYSFS_ERR_OTHER_ERROR); /* !!! FIXME: right? */ break; case SZE_ARCHIVE_ERROR: __PHYSFS_setError(PHYSFS_ERR_CORRUPT); /* !!! FIXME: right? */ break; default: __PHYSFS_setError(PHYSFS_ERR_OTHER_ERROR); } /* switch */ return rc; } /* lzma_err */
static char *getExePath(void) { DWORD buflen = 64; LPWSTR modpath = NULL; char *retval = NULL; while (1) { DWORD rc; void *ptr; if ( !(ptr = allocator.Realloc(modpath, buflen*sizeof(WCHAR))) ) { allocator.Free(modpath); BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL); } /* if */ modpath = (LPWSTR) ptr; rc = pGetModuleFileNameW(NULL, modpath, buflen); if (rc == 0) { allocator.Free(modpath); BAIL_MACRO(winApiStrError(), NULL); } /* if */ if (rc < buflen) { buflen = rc; break; } /* if */ buflen *= 2; } /* while */ if (buflen > 0) /* just in case... */ { WCHAR *ptr = (modpath + buflen) - 1; while (ptr != modpath) { if (*ptr == '\\') break; ptr--; } /* while */ if ((ptr == modpath) && (*ptr != '\\')) __PHYSFS_setError(ERR_GETMODFN_NO_DIR); else { *(ptr + 1) = '\0'; /* chop off filename. */ retval = unicodeToUtf8Heap(modpath); } /* else */ } /* else */ allocator.Free(modpath); return(retval); /* w00t. */ } /* getExePath */
char *__PHYSFS_platformCalcBaseDir(const char *argv0) { DWORD buflen = 64; LPWSTR modpath = NULL; char *retval = NULL; while (1) { DWORD rc; void *ptr; if ( (ptr = allocator.Realloc(modpath, buflen*sizeof(WCHAR))) == NULL ) { allocator.Free(modpath); BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL); } /* if */ modpath = (LPWSTR) ptr; rc = GetModuleFileNameW(NULL, modpath, buflen); if (rc == 0) { allocator.Free(modpath); BAIL_MACRO(errcodeFromWinApi(), NULL); } /* if */ if (rc < buflen) { buflen = rc; break; } /* if */ buflen *= 2; } /* while */ if (buflen > 0) /* just in case... */ { WCHAR *ptr = (modpath + buflen) - 1; while (ptr != modpath) { if (*ptr == '\\') break; ptr--; } /* while */ if ((ptr == modpath) && (*ptr != '\\')) __PHYSFS_setError(PHYSFS_ERR_OTHER_ERROR); /* oh well. */ else { *(ptr+1) = '\0'; /* chop off filename. */ retval = unicodeToUtf8Heap(modpath); } /* else */ } /* else */ allocator.Free(modpath); return retval; /* w00t. */ } /* __PHYSFS_platformCalcBaseDir */
static OSErr oserr(OSErr retval) { char buf[sizeof (ERR_MACOS_GENERIC) + 32]; const char *errstr = get_macos_error_string(retval); if (strcmp(errstr, ERR_MACOS_GENERIC) == 0) { sprintf(buf, ERR_MACOS_GENERIC, (int) retval); errstr = buf; } /* if */ if (errstr != NULL) __PHYSFS_setError(errstr); return(retval); } /* oserr */
static APIRET os2err(APIRET retval) { char buf[128]; const char *err = get_os2_error_string(retval); if (err == ERR_OS2_GENERIC) { snprintf(buf, ERR_OS2_GENERIC, (int) retval); err = buf; } /* if */ if (err != NULL) __PHYSFS_setError(err); return(err); } /* os2err */
static char *codepageToUtf8Heap(const char *cpstr) { char *retval = NULL; if (cpstr != NULL) { const int len = (int)(strlen(cpstr) + 1); WCHAR *wbuf = (WCHAR *)__PHYSFS_smallAlloc(len * sizeof(WCHAR)); BAIL_IF_MACRO(wbuf == NULL, ERR_OUT_OF_MEMORY, NULL); MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, cpstr, len, wbuf, len); retval = (char *)allocator.Malloc(len * 4); if (retval == NULL) __PHYSFS_setError(ERR_OUT_OF_MEMORY); else PHYSFS_utf8FromUcs2((const PHYSFS_uint16*)wbuf, retval, len * 4); __PHYSFS_smallFree(wbuf); } /* if */ return(retval); } /* codepageToUtf8Heap */
char *__PHYSFS_platformGetUserName(void) { DWORD bufsize = 0; char *retval = NULL; if (pGetUserNameW(NULL, &bufsize) == 0) /* This SHOULD fail. */ { LPWSTR wbuf = (LPWSTR)__PHYSFS_smallAlloc(bufsize * sizeof(WCHAR)); BAIL_IF_MACRO(wbuf == NULL, ERR_OUT_OF_MEMORY, NULL); if (pGetUserNameW(wbuf, &bufsize) == 0) /* ?! */ __PHYSFS_setError(winApiStrError()); else retval = unicodeToUtf8Heap(wbuf); __PHYSFS_smallFree(wbuf); } /* if */ return(retval); } /* __PHYSFS_platformGetUserName */
char *__PHYSFS_platformGetUserName(void) { DWORD bufsize = 0; LPTSTR retval = NULL; if (GetUserName(NULL, &bufsize) == 0) /* This SHOULD fail. */ { retval = (LPTSTR) malloc(bufsize); BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); if (GetUserName(retval, &bufsize) == 0) /* ?! */ { __PHYSFS_setError(win32strerror()); free(retval); retval = NULL; } /* if */ } /* if */ return((char *) retval); } /* __PHYSFS_platformGetUserName */
static int hha_open(const char *filename, int forWriting, void **fh, PHYSFS_uint32 *filenameSize, PHYSFS_uint32 *count) { PHYSFS_uint32 magic[2]; *fh = NULL; BAIL_IF_MACRO(forWriting, ERR_ARC_IS_READ_ONLY, 0); *fh = __PHYSFS_platformOpenRead(filename); BAIL_IF_MACRO(*fh == NULL, NULL, 0); if (__PHYSFS_platformRead(*fh, magic, sizeof(PHYSFS_uint32), 2) != 2) goto openHHA_failed; magic[0] = PHYSFS_swapULE32(magic[0]); magic[1] = PHYSFS_swapULE32(magic[1]); if (!(magic[0] == HHA_FILE_MAGIC && magic[1] == HHA_FILE_VERSION)) { __PHYSFS_setError(ERR_UNSUPPORTED_ARCHIVE); goto openHHA_failed; } /* if */ if (__PHYSFS_platformRead(*fh, filenameSize, sizeof (PHYSFS_uint32), 1) != 1) goto openHHA_failed; *filenameSize = PHYSFS_swapULE32(*filenameSize); if (__PHYSFS_platformRead(*fh, count, sizeof (PHYSFS_uint32), 1) != 1) goto openHHA_failed; *count = PHYSFS_swapULE32(*count); return(1); openHHA_failed: if (*fh != NULL) __PHYSFS_platformClose(*fh); *filenameSize = -1; *count = -1; *fh = NULL; return(0); } /* HHA_open */
static PHYSFS_sint64 HHA_read(fvoid *opaque, void *buffer, PHYSFS_uint32 objSize, PHYSFS_uint32 objCount) { HHAfileinfo *finfo = (HHAfileinfo *) opaque; HHAentry *entry = finfo->entry; PHYSFS_sint64 retval = 0; PHYSFS_sint64 maxread = ((PHYSFS_sint64) objSize) * objCount; PHYSFS_sint64 avail = entry->uncompressed_size - finfo->uncompressed_position; BAIL_IF_MACRO(maxread == 0, NULL, 0); /* quick rejection. */ if (avail < maxread) { maxread = avail - (avail % objSize); objCount = (PHYSFS_uint32) (maxread / objSize); BAIL_IF_MACRO(objCount == 0, ERR_PAST_EOF, 0); /* quick rejection. */ __PHYSFS_setError(ERR_PAST_EOF); /* this is always true here. */ } /* if */ if (entry->compress == HHA_COMPRESS_NONE) { retval = __PHYSFS_platformRead(finfo->handle, buffer, objSize, objCount); } else if (entry->compress == HHA_COMPRESS_ZLIB) { finfo->zlib_stream.next_out = buffer; finfo->zlib_stream.avail_out = objSize * objCount; while (retval < maxread) { PHYSFS_uint32 before = finfo->zlib_stream.total_out; int rc; if (finfo->zlib_stream.avail_in == 0) { PHYSFS_sint64 br; br = entry->compressed_size - finfo->compressed_position; if (br > 0) { if (br > ZIP_READBUFSIZE) br = ZIP_READBUFSIZE; br = __PHYSFS_platformRead(finfo->handle, finfo->buffer, 1, (PHYSFS_uint32) br); if (br <= 0) break; finfo->compressed_position += (PHYSFS_uint32) br; finfo->zlib_stream.next_in = finfo->buffer; finfo->zlib_stream.avail_in = (PHYSFS_uint32) br; } /* if */ } /* if */ rc = zlib_err(inflate(&finfo->zlib_stream, Z_SYNC_FLUSH)); retval += (finfo->zlib_stream.total_out - before); if (rc != Z_OK) break; } /* while */ retval /= objSize; } if (retval > 0) finfo->uncompressed_position += (PHYSFS_uint32) (retval * objSize); return(retval); } /* HHA_read */
static char *getExePath(const char *argv0) { DWORD buflen; int success = 0; char *ptr = NULL; char *retval = (char *) malloc(sizeof (TCHAR) * (MAX_PATH + 1)); BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); retval[0] = '\0'; buflen = GetModuleFileName(NULL, retval, MAX_PATH + 1); if (buflen <= 0) __PHYSFS_setError(win32strerror()); else { retval[buflen] = '\0'; /* does API always null-terminate this? */ /* make sure the string was not truncated. */ if (__PHYSFS_platformStricmp(&retval[buflen - 4], ".exe") != 0) __PHYSFS_setError(ERR_GETMODFN_TRUNC); else { ptr = strrchr(retval, '\\'); if (ptr == NULL) __PHYSFS_setError(ERR_GETMODFN_NO_DIR); else { *(ptr + 1) = '\0'; /* chop off filename. */ success = 1; } /* else */ } /* else */ } /* else */ /* if any part of the previous approach failed, try SearchPath()... */ if (!success) { if (argv0 == NULL) __PHYSFS_setError(ERR_ARGV0_IS_NULL); else { buflen = SearchPath(NULL, argv0, NULL, MAX_PATH+1, retval, &ptr); if (buflen == 0) __PHYSFS_setError(win32strerror()); else if (buflen > MAX_PATH) __PHYSFS_setError(ERR_SEARCHPATH_TRUNC); else success = 1; } /* else */ } /* if */ if (!success) { free(retval); return(NULL); /* physfs error message will be set, above. */ } /* if */ /* free up the bytes we didn't actually use. */ ptr = (char *) realloc(retval, strlen(retval) + 1); if (ptr != NULL) retval = ptr; return(retval); /* w00t. */ } /* getExePath */
static PHYSFS_sint64 ZIP_read(fvoid *opaque, void *buf, PHYSFS_uint32 objSize, PHYSFS_uint32 objCount) { int total, i = 0; ZIPfileinfo *finfo = (ZIPfileinfo *) opaque; ZIPentry *entry = finfo->entry; PHYSFS_sint64 retval = 0; PHYSFS_sint64 maxread = ((PHYSFS_sint64) objSize) * objCount; PHYSFS_sint64 avail = entry->uncompressed_size - finfo->uncompressed_position; BAIL_IF_MACRO(maxread == 0, NULL, 0); /* quick rejection. */ if (avail < maxread) { maxread = avail - (avail % objSize); objCount = (PHYSFS_uint32) (maxread / objSize); BAIL_IF_MACRO(objCount == 0, ERR_PAST_EOF, 0); /* quick rejection. */ __PHYSFS_setError(ERR_PAST_EOF); /* this is always true here. */ } /* if */ if (entry->compression_method == COMPMETH_NONE) { if (entry->encrypted == AES_ENCRYPTED) { retval = __PHYSFS_platformRead(finfo->handle, buf, objSize, objCount); total = maxread; while (total > 16) { fcrypt_decrypt(((char*)buf) + i, 16, &finfo->zctx); i += 16; total -= 16; } if (total > 0) { fcrypt_decrypt(((char*)buf) + i, total, &finfo->zctx); } } else { retval = __PHYSFS_platformRead(finfo->handle, buf, objSize, objCount); } } /* if */ else { finfo->stream.next_out = buf; finfo->stream.avail_out = objSize * objCount; while (retval < maxread) { PHYSFS_uint32 before = finfo->stream.total_out; int rc; if (finfo->stream.avail_in == 0) { PHYSFS_sint64 br; br = entry->compressed_size - finfo->compressed_position; if (br > 0) { if (br > ZIP_READBUFSIZE) br = ZIP_READBUFSIZE; br = __PHYSFS_platformRead(finfo->handle, finfo->buffer, 1, (PHYSFS_uint32) br); if (br <= 0) { break; } if (entry->encrypted == AES_ENCRYPTED) { total = br; i = 0; while (total > 16) { fcrypt_decrypt(finfo->buffer + i, 16, &finfo->zctx); i += 16; total -= 16; } if (total > 0) { fcrypt_decrypt(finfo->buffer + i, total, &finfo->zctx); } } finfo->compressed_position += (PHYSFS_uint32) br; finfo->stream.next_in = finfo->buffer; finfo->stream.avail_in = (PHYSFS_uint32) br; } /* if */ } /* if */ rc = zlib_err(inflate(&finfo->stream, Z_SYNC_FLUSH)); retval += (finfo->stream.total_out - before); if (rc != Z_OK) break; } /* while */ retval /= objSize; } /* else */ if (retval > 0) finfo->uncompressed_position += (PHYSFS_uint32) (retval * objSize); return(retval); } /* ZIP_read */
static PHYSFS_sint64 LZMA_read(fvoid *opaque, void *outBuffer, PHYSFS_uint32 objSize, PHYSFS_uint32 objCount) { LZMAentry *entry = (LZMAentry *) opaque; PHYSFS_sint64 wantedSize = objSize*objCount; PHYSFS_sint64 remainingSize = entry->file->Size - entry->position; size_t fileSize; ISzAlloc allocImp; ISzAlloc allocTempImp; BAIL_IF_MACRO(wantedSize == 0, NULL, 0); /* quick rejection. */ BAIL_IF_MACRO(remainingSize == 0, ERR_PAST_EOF, 0); if (remainingSize < wantedSize) { wantedSize = remainingSize - (remainingSize % objSize); objCount = (PHYSFS_uint32) (remainingSize / objSize); BAIL_IF_MACRO(objCount == 0, ERR_PAST_EOF, 0); /* quick rejection. */ __PHYSFS_setError(ERR_PAST_EOF); /* this is always true here. */ } /* if */ /* Prepare callbacks for 7z */ allocImp.Alloc = SzAllocPhysicsFS; allocImp.Free = SzFreePhysicsFS; allocTempImp.Alloc = SzAllocPhysicsFS; allocTempImp.Free = SzFreePhysicsFS; /* Only decompress the folder if it is not allready cached */ if (entry->archive->folder[entry->folderIndex].cache == NULL) { size_t tmpsize = entry->archive->folder[entry->folderIndex].size; int rc = lzma_err(SzExtract( &entry->archive->stream.InStream, /* compressed data */ &entry->archive->db, entry->fileIndex, /* Index of cached folder, will be changed by SzExtract */ &entry->archive->folder[entry->folderIndex].index, /* Cache for decompressed folder, allocated/freed by SzExtract */ &entry->archive->folder[entry->folderIndex].cache, /* Size of cache, will be changed by SzExtract */ &tmpsize, /* Offset of this file inside the cache, set by SzExtract */ &entry->offset, &fileSize, /* Size of this file */ &allocImp, &allocTempImp)); entry->archive->folder[entry->folderIndex].size = tmpsize; if (rc != SZ_OK) return -1; } /* if */ /* Copy wanted bytes over from cache to outBuffer */ /* !!! FIXME: strncpy for non-string data? */ strncpy(outBuffer, (void*) (entry->archive->folder[entry->folderIndex].cache + entry->offset + entry->position), (size_t) wantedSize); entry->position += wantedSize; return objCount; } /* LZMA_read */