static void *doOpen(const char *filename, int mode) { const int appending = (mode & O_APPEND); int fd; int *retval; errno = 0; /* O_APPEND doesn't actually behave as we'd like. */ mode &= ~O_APPEND; fd = open(filename, mode, S_IRUSR | S_IWUSR); BAIL_IF_MACRO(fd < 0, errcodeFromErrno(), NULL); if (appending) { if (lseek(fd, 0, SEEK_END) < 0) { const int err = errno; close(fd); BAIL_MACRO(errcodeFromErrnoError(err), NULL); } /* if */ } /* if */ retval = (int *) allocator.Malloc(sizeof (int)); if (!retval) { close(fd); BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL); } /* if */ *retval = fd; return ((void *) retval); } /* doOpen */
char *__PHYSFS_platformCurrentDir(void) { int allocSize = 0; char *retval = NULL; char *ptr; do { allocSize += 100; ptr = (char *) realloc(retval, allocSize); if (ptr == NULL) { if (retval != NULL) free(retval); BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL); } /* if */ retval = ptr; ptr = getcwd(retval, allocSize); } while (ptr == NULL && errno == ERANGE); if (ptr == NULL && errno) { /* * getcwd() failed for some reason, for example current * directory not existing. */ if (retval != NULL) free(retval); BAIL_MACRO(ERR_NO_SUCH_FILE, NULL); } /* if */ return(retval); } /* __PHYSFS_platformCurrentDir */
char *__PHYSFS_platformCalcPrefDir(const char *org, const char *app) { /* * Vista and later has a new API for this, but SHGetFolderPath works there, * and apparently just wraps the new API. This is the new way to do it: * * SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_CREATE, * NULL, &wszPath); */ WCHAR path[MAX_PATH]; char *utf8 = NULL; size_t len = 0; char *retval = NULL; if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) BAIL_MACRO(PHYSFS_ERR_OS_ERROR, NULL); utf8 = unicodeToUtf8Heap(path); BAIL_IF_MACRO(!utf8, ERRPASS, NULL); len = strlen(utf8) + strlen(org) + strlen(app) + 4; retval = allocator.Malloc(len); if (!retval) { allocator.Free(utf8); BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL); } /* if */ sprintf(retval, "%s\\%s\\%s\\", utf8, org, app); return retval; } /* __PHYSFS_platformCalcPrefDir */
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 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 */
static int HHA_load_entries(const char *name, int forWriting, HHAinfo *info) { void *fh = NULL; PHYSFS_uint32 fileNameSize; PHYSFS_uint32 fileCount; HHAentry *entry; PHYSFS_uint32 buf[6]; BAIL_IF_MACRO(!hha_open(name, forWriting, &fh, &fileNameSize, &fileCount), NULL, 0); info->entryCount = fileCount; info->filenames = (char *) allocator.Malloc(fileNameSize); if (info->filenames == NULL) { __PHYSFS_platformClose(fh); BAIL_MACRO(ERR_OUT_OF_MEMORY, 0); } /* if */ info->entries = (HHAentry *) allocator.Malloc(sizeof(HHAentry)*fileCount); if (info->entries == NULL) { __PHYSFS_platformClose(fh); BAIL_MACRO(ERR_OUT_OF_MEMORY, 0); } /* if */ if (__PHYSFS_platformRead(fh, info->filenames, 1, fileNameSize) != fileNameSize) { __PHYSFS_platformClose(fh); return(0); } for (entry = info->entries; fileCount > 0; fileCount--, entry++) { if (__PHYSFS_platformRead(fh, buf, sizeof(PHYSFS_uint32), 6) != 6) { __PHYSFS_platformClose(fh); return(0); } /* if */ entry->dir = info->filenames + PHYSFS_swapULE32(buf[0]); entry->name = info->filenames + PHYSFS_swapULE32(buf[1]); entry->compress = PHYSFS_swapULE32(buf[2]); entry->offset = PHYSFS_swapULE32(buf[3]); entry->uncompressed_size = PHYSFS_swapULE32(buf[4]); entry->compressed_size = PHYSFS_swapULE32(buf[5]); } /* for */ __PHYSFS_platformClose(fh); __PHYSFS_sort(info->entries, info->entryCount, HHA_entry_cmp, HHA_entry_swap); return(1); } /* HHA_load_entries */
static PHYSFS_sint64 LZMA_getLastModTime(dvoid *opaque, const char *name, int *fileExists) { /* !!! FIXME: Lacking support in the LZMA C SDK. */ BAIL_MACRO(ERR_NOT_IMPLEMENTED, -1); } /* LZMA_getLastModTime */
static void *doOpen(const char *fname, DWORD mode, DWORD creation, int rdonly) { HANDLE fileHandle; WinApiFile *retval; WCHAR *wfname; UTF8_TO_UNICODE_STACK_MACRO(wfname, fname); BAIL_IF_MACRO(wfname == NULL, ERR_OUT_OF_MEMORY, NULL); fileHandle = pCreateFileW(wfname, mode, FILE_SHARE_READ, NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL); __PHYSFS_smallFree(wfname); BAIL_IF_MACRO ( fileHandle == INVALID_HANDLE_VALUE, winApiStrError(), NULL ); retval = (WinApiFile *) allocator.Malloc(sizeof (WinApiFile)); if (retval == NULL) { CloseHandle(fileHandle); BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL); } /* if */ retval->readonly = rdonly; retval->handle = fileHandle; return(retval); } /* doOpen */
char *__PHYSFS_platformGetUserName(void) { char *retval = NULL; StringHandle strHandle; short origResourceFile = CurResFile(); /* use the System resource file. */ UseResFile(0); /* apparently, -16096 specifies the username. */ strHandle = GetString(-16096); UseResFile(origResourceFile); BAIL_IF_MACRO(strHandle == NULL, NULL, NULL); HLock((Handle) strHandle); retval = (char *) malloc((*strHandle)[0] + 1); if (retval == NULL) { HUnlock((Handle) strHandle); BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL); } /* if */ memcpy(retval, &(*strHandle)[1], (*strHandle)[0]); retval[(*strHandle)[0]] = '\0'; /* null-terminate it. */ HUnlock((Handle) strHandle); return(retval); } /* __PHYSFS_platformGetUserName */
static DirHandle *DIR_openArchive(const char *name, int forWriting) { const char *dirsep = PHYSFS_getDirSeparator(); DirHandle *retval = NULL; size_t namelen = strlen(name); size_t seplen = strlen(dirsep); BAIL_IF_MACRO(!DIR_isArchive(name, forWriting), ERR_UNSUPPORTED_ARCHIVE, NULL); retval = (DirHandle *) malloc(sizeof (DirHandle)); BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL); retval->opaque = malloc(namelen + seplen + 1); if (retval->opaque == NULL) { free(retval); BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL); } /* if */ /* make sure there's a dir separator at the end of the string */ strcpy((char *) (retval->opaque), name); if (strcmp((name + namelen) - seplen, dirsep) != 0) strcat((char *) (retval->opaque), dirsep); retval->funcs = &__PHYSFS_DirFunctions_DIR; return(retval); } /* DIR_openArchive */
static void *QPAK_openArchive(PHYSFS_Io *io, const char *name, int forWriting) { UNPKentry *entries = NULL; PHYSFS_uint32 val = 0; PHYSFS_uint32 pos = 0; PHYSFS_uint32 count = 0; assert(io != NULL); /* shouldn't ever happen. */ BAIL_IF_MACRO(forWriting, PHYSFS_ERR_READ_ONLY, NULL); BAIL_IF_MACRO(!__PHYSFS_readAll(io, &val, 4), ERRPASS, NULL); if (PHYSFS_swapULE32(val) != QPAK_SIG) BAIL_MACRO(PHYSFS_ERR_UNSUPPORTED, NULL); BAIL_IF_MACRO(!__PHYSFS_readAll(io, &val, 4), ERRPASS, NULL); pos = PHYSFS_swapULE32(val); /* directory table offset. */ BAIL_IF_MACRO(!__PHYSFS_readAll(io, &val, 4), ERRPASS, NULL); count = PHYSFS_swapULE32(val); /* corrupted archive? */ BAIL_IF_MACRO((count % 64) != 0, PHYSFS_ERR_CORRUPT, NULL); count /= 64; BAIL_IF_MACRO(!io->seek(io, pos), ERRPASS, NULL); entries = qpakLoadEntries(io, count); BAIL_IF_MACRO(!entries, ERRPASS, NULL); return UNPK_openArchive(io, entries, count); } /* QPAK_openArchive */
static void *doOpen(const char *fname, DWORD mode, DWORD creation, int rdonly) { HANDLE fileHandle; win32file *retval; fileHandle = CreateFile(fname, mode, FILE_SHARE_READ, NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL); BAIL_IF_MACRO ( fileHandle == INVALID_HANDLE_VALUE, win32strerror(), NULL ); retval = malloc(sizeof (win32file)); if (retval == NULL) { CloseHandle(fileHandle); BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL); } /* if */ retval->readonly = rdonly; retval->handle = fileHandle; return(retval); } /* doOpen */
static SInt16 *macDoOpen(const char *fname, SInt8 perm, int createIfMissing) { int created = 0; SInt16 *retval = NULL; FSSpec spec; OSErr err = fnameToFSSpec(fname, &spec); BAIL_IF_MACRO((err != noErr) && (err != fnfErr), NULL, NULL); if (err == fnfErr) { BAIL_IF_MACRO(!createIfMissing, ERR_NO_SUCH_FILE, NULL); err = HCreate(spec.vRefNum, spec.parID, spec.name, procInfo.processSignature, 'BINA'); BAIL_IF_MACRO(oserr(err) != noErr, NULL, NULL); created = 1; } /* if */ retval = (SInt16 *) malloc(sizeof (SInt16)); if (retval == NULL) { if (created) HDelete(spec.vRefNum, spec.parID, spec.name); BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL); } /* if */ err = HOpenDF(spec.vRefNum, spec.parID, spec.name, perm, retval); if (oserr(err) != noErr) { free(retval); if (created) HDelete(spec.vRefNum, spec.parID, spec.name); return(NULL); } /* if */ return(retval); } /* macDoOpen */
static HOGentry *hog_find_entry(HOGinfo *info, const char *name) { char *ptr = strchr(name, '.'); HOGentry *a = info->entries; PHYSFS_sint32 lo = 0; PHYSFS_sint32 hi = (PHYSFS_sint32) (info->entryCount - 1); PHYSFS_sint32 middle; int rc; /* * Rule out filenames to avoid unneeded processing...no dirs, * big filenames, or extensions > 3 chars. */ BAIL_IF_MACRO((ptr) && (strlen(ptr) > 4), ERR_NO_SUCH_FILE, NULL); BAIL_IF_MACRO(strlen(name) > 12, ERR_NO_SUCH_FILE, NULL); BAIL_IF_MACRO(strchr(name, '/') != NULL, ERR_NO_SUCH_FILE, NULL); while (lo <= hi) { middle = lo + ((hi - lo) / 2); rc = __PHYSFS_platformStricmp(name, a[middle].name); if (rc == 0) /* found it! */ return(&a[middle]); else if (rc > 0) lo = middle + 1; else hi = middle - 1; } /* while */ BAIL_MACRO(ERR_NO_SUCH_FILE, NULL); } /* hog_find_entry */
int __PHYSFS_platformSeek(void *opaque, PHYSFS_uint64 pos) { HANDLE Handle = ((WinApiFile *) opaque)->handle; LONG HighOrderPos; PLONG pHighOrderPos; DWORD rc; /* Get the high order 32-bits of the position */ HighOrderPos = HIGHORDER_UINT64(pos); /* * MSDN: "If you do not need the high-order 32 bits, this * pointer must be set to NULL." */ pHighOrderPos = (HighOrderPos) ? &HighOrderPos : NULL; /* Move pointer "pos" count from start of file */ rc = SetFilePointer(Handle, LOWORDER_UINT64(pos), pHighOrderPos, FILE_BEGIN); if ( (rc == PHYSFS_INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR) ) { BAIL_MACRO(errcodeFromWinApi(), 0); } /* if */ return 1; /* No error occured */ } /* __PHYSFS_platformSeek */
static void *doOpen(const char *fname, DWORD mode, DWORD creation, int rdonly) { HANDLE fileh; WinApiFile *retval; WCHAR *wfname; UTF8_TO_UNICODE_STACK_MACRO(wfname, fname); BAIL_IF_MACRO(!wfname, PHYSFS_ERR_OUT_OF_MEMORY, NULL); //fileh = CreateFileW(wfname, mode, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, creation, FILE_ATTRIBUTE_NORMAL, NULL); fileh = CreateFile2(wfname, mode, FILE_SHARE_READ | FILE_SHARE_WRITE, creation, NULL); __PHYSFS_smallFree(wfname); BAIL_IF_MACRO(fileh == INVALID_HANDLE_VALUE, errcodeFromWinApi(), NULL); retval = (WinApiFile *)allocator.Malloc(sizeof(WinApiFile)); if (!retval) { CloseHandle(fileh); BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL); } /* if */ retval->readonly = rdonly; retval->handle = fileh; return retval; } /* doOpen */
LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname, int omitSymLinks) { LinkedStringList *ret = NULL, *p = NULL; UInt16 i; UInt16 max; FSSpec spec; CInfoPBRec infoPB; Str255 str255; long dirID; BAIL_IF_MACRO(fnameToFSSpec(dirname, &spec) != noErr, NULL, 0); /* get the dir ID of what we want to enumerate... */ memset(&infoPB, '\0', sizeof (CInfoPBRec)); infoPB.dirInfo.ioNamePtr = spec.name; /* name of dir to enum. */ infoPB.dirInfo.ioVRefNum = spec.vRefNum; /* ID of file's volume. */ infoPB.dirInfo.ioDrDirID = spec.parID; /* ID of dir. */ infoPB.dirInfo.ioFDirIndex = 0; /* file (not parent) info. */ BAIL_IF_MACRO(oserr(PBGetCatInfoSync(&infoPB)) != noErr, NULL, NULL); if ((infoPB.dirInfo.ioFlAttrib & kioFlAttribDirMask) == 0) BAIL_MACRO(ERR_NOT_A_DIR, NULL); dirID = infoPB.dirInfo.ioDrDirID; max = infoPB.dirInfo.ioDrNmFls; for (i = 1; i <= max; i++) { FSSpec aliasspec; Boolean alias = 0; Boolean folder = 0; memset(&infoPB, '\0', sizeof (CInfoPBRec)); str255[0] = 0; infoPB.dirInfo.ioNamePtr = str255; /* store name in here. */ infoPB.dirInfo.ioVRefNum = spec.vRefNum; /* ID of dir's volume. */ infoPB.dirInfo.ioDrDirID = dirID; /* ID of dir. */ infoPB.dirInfo.ioFDirIndex = i; /* next file's info. */ if (PBGetCatInfoSync(&infoPB) != noErr) continue; /* skip this file. Oh well. */ if (FSMakeFSSpec(spec.vRefNum, dirID, str255, &aliasspec) != noErr) continue; /* skip it. */ if (IsAliasFile(&aliasspec, &alias, &folder) != noErr) continue; /* skip it. */ if ((alias) && (omitSymLinks)) continue; /* still here? Add it to the list. */ ret = __PHYSFS_addToLinkedStringList(ret, &p, (const char *) &str255[1], str255[0]); } /* for */ return(ret); } /* __PHYSFS_platformEnumerateFiles */
static PHYSFS_sint64 FileTimeToPhysfsTime(const FILETIME *ft) { SYSTEMTIME st_utc; SYSTEMTIME st_localtz; TIME_ZONE_INFORMATION tzi; DWORD tzid; PHYSFS_sint64 retval; struct tm tm; BAIL_IF_MACRO(!FileTimeToSystemTime(ft, &st_utc), winApiStrError(), -1); tzid = GetTimeZoneInformation(&tzi); BAIL_IF_MACRO(tzid == TIME_ZONE_ID_INVALID, winApiStrError(), -1); /* (This API is unsupported and fails on non-NT systems. */ if (!SystemTimeToTzSpecificLocalTime(&tzi, &st_utc, &st_localtz)) { /* do it by hand. Grumble... */ ULARGE_INTEGER ui64; FILETIME new_ft; ui64.LowPart = ft->dwLowDateTime; ui64.HighPart = ft->dwHighDateTime; if (tzid == TIME_ZONE_ID_STANDARD) tzi.Bias += tzi.StandardBias; else if (tzid == TIME_ZONE_ID_DAYLIGHT) tzi.Bias += tzi.DaylightBias; /* convert from minutes to 100-nanosecond increments... */ ui64.QuadPart -= (((LONGLONG)tzi.Bias) * (600000000)); /* Move it back into a FILETIME structure... */ new_ft.dwLowDateTime = ui64.LowPart; new_ft.dwHighDateTime = ui64.HighPart; /* Convert to something human-readable... */ if (!FileTimeToSystemTime(&new_ft, &st_localtz)) BAIL_MACRO(winApiStrError(), -1); } /* if */ /* Convert to a format that mktime() can grok... */ tm.tm_sec = st_localtz.wSecond; tm.tm_min = st_localtz.wMinute; tm.tm_hour = st_localtz.wHour; tm.tm_mday = st_localtz.wDay; tm.tm_mon = st_localtz.wMonth - 1; tm.tm_year = st_localtz.wYear - 1900; tm.tm_wday = -1 /*st_localtz.wDayOfWeek*/; tm.tm_yday = -1; tm.tm_isdst = -1; /* Convert to a format PhysicsFS can grok... */ retval = (PHYSFS_sint64)mktime(&tm); BAIL_IF_MACRO(retval == -1, strerror(errno), -1); return(retval); } /* FileTimeToPhysfsTime */
static char *convFSSpecToPath(FSSpec *spec, int includeFile) { char *ptr; char *retval = NULL; UInt32 retLength = 0; CInfoPBRec infoPB; Str255 str255; str255[0] = spec->name[0]; memcpy(&str255[1], &spec->name[1], str255[0]); memset(&infoPB, '\0', sizeof (CInfoPBRec)); infoPB.dirInfo.ioNamePtr = str255; /* put name in here. */ infoPB.dirInfo.ioVRefNum = spec->vRefNum; /* ID of bin's volume. */ infoPB.dirInfo.ioDrParID = spec->parID; /* ID of bin's dir. */ infoPB.dirInfo.ioFDirIndex = (includeFile) ? 0 : -1; /* walk the tree back to the root dir (volume), building path string... */ do { /* check parent dir of what we last looked at... */ infoPB.dirInfo.ioDrDirID = infoPB.dirInfo.ioDrParID; if (oserr(PBGetCatInfoSync(&infoPB)) != noErr) { if (retval != NULL) free(retval); return(NULL); } /* if */ infoPB.dirInfo.ioFDirIndex = -1; /* look at parent dir next time. */ /* allocate more space for the retval... */ retLength += str255[0] + 1; /* + 1 for a ':' or null char... */ ptr = (char *) malloc(retLength); if (ptr == NULL) { if (retval != NULL) free(retval); BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL); } /* if */ /* prepend new dir to retval and cleanup... */ memcpy(ptr, &str255[1], str255[0]); ptr[str255[0]] = '\0'; /* null terminate it. */ if (retval != NULL) { strcat(ptr, ":"); strcat(ptr, retval); free(retval); } /* if */ retval = ptr; } while (infoPB.dirInfo.ioDrDirID != fsRtDirID); return(retval); } /* convFSSpecToPath */
/* * See where program (bin) resides in the $PATH specified by (envr). * returns a copy of the first element in envr that contains it, or NULL * if it doesn't exist or there were other problems. PHYSFS_SetError() is * called if we have a problem. * * (envr) will be scribbled over, and you are expected to physfs_alloc.Free() the * return value when you're done with it. */ static char *findBinaryInPath(const char *bin, char *envr) { size_t alloc_size = 0; char *exe = NULL; char *start = envr; char *ptr; assert(bin != NULL); assert(envr != NULL); do { size_t size; size_t binlen; ptr = strchr(start, ':'); /* find next $PATH separator. */ if (ptr) *ptr = '\0'; binlen = strlen(bin); size = strlen(start) + binlen + 2; if (size >= alloc_size) { char *x = (char *) physfs_alloc.Realloc(exe, size); if (!x) { if (exe != NULL) physfs_alloc.Free(exe); BAIL_MACRO(PHYSFS_ERR_OUT_OF_MEMORY, NULL); } /* if */ alloc_size = size; exe = x; } /* if */ /* build full binary path... */ strcpy(exe, start); if ((exe[0] == '\0') || (exe[strlen(exe) - 1] != '/')) strcat(exe, "/"); strcat(exe, bin); if (access(exe, X_OK) == 0) /* Exists as executable? We're done. */ { exe[(size - binlen) - 1] = '\0'; /* chop off filename, leave '/' */ return exe; } /* if */ start = ptr + 1; /* start points to beginning of next element. */ } while (ptr != NULL); if (exe != NULL) physfs_alloc.Free(exe); return NULL; /* doesn't exist in path. */ } /* findBinaryInPath */
/* * Find entry 'name' in 'archive' and report the 'index' back */ static int lzma_find_entry(LZMAarchive *archive, const char *name, PHYSFS_uint32 *index) { for (*index = 0; *index < archive->db.Database.NumFiles; (*index)++) { if (strcmp(archive->db.Database.Files[*index].Name, name) == 0) return 1; } /* for */ BAIL_MACRO(ERR_NO_SUCH_FILE, 0); } /* lzma_find_entry */
/* * See where program (bin) resides in the $PATH specified by (envr). * returns a copy of the first element in envr that contains it, or NULL * if it doesn't exist or there were other problems. PHYSFS_SetError() is * called if we have a problem. * * (envr) will be scribbled over, and you are expected to allocator.Free() the * return value when you're done with it. */ static char *findBinaryInPath(const char *bin, char *envr) { size_t alloc_size = 0; char *exe = NULL; char *start = envr; char *ptr; BAIL_IF_MACRO(bin == NULL, ERR_INVALID_ARGUMENT, NULL); BAIL_IF_MACRO(envr == NULL, ERR_INVALID_ARGUMENT, NULL); do { size_t size; ptr = strchr(start, ':'); /* find next $PATH separator. */ if (ptr) *ptr = '\0'; size = strlen(start) + strlen(bin) + 2; if (size > alloc_size) { char *x = (char *) allocator.Realloc(exe, size); if (x == NULL) { if (exe != NULL) allocator.Free(exe); BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL); } /* if */ alloc_size = size; exe = x; } /* if */ /* build full binary path... */ strcpy(exe, start); if ((exe[0] == '\0') || (exe[strlen(exe) - 1] != '/')) strcat(exe, "/"); strcat(exe, bin); if (access(exe, X_OK) == 0) /* Exists as executable? We're done. */ { strcpy(exe, start); /* i'm lazy. piss off. */ return(exe); } /* if */ start = ptr + 1; /* start points to beginning of next element. */ } while (ptr != NULL); if (exe != NULL) allocator.Free(exe); return(NULL); /* doesn't exist in path. */ } /* findBinaryInPath */
static int wad_load_entries(const char *name, int forWriting, WADinfo *info) { void *fh = NULL; PHYSFS_uint32 fileCount; PHYSFS_uint32 directoryOffset; WADentry *entry; char lastDirectory[9]; lastDirectory[8] = 0; /* Make sure lastDirectory stays null-terminated. */ BAIL_IF_MACRO(!wad_open(name, forWriting, &fh, &fileCount,&directoryOffset), NULL, 0); info->entryCount = fileCount; info->entries = (WADentry *) allocator.Malloc(sizeof(WADentry)*fileCount); if (info->entries == NULL) { __PHYSFS_platformClose(fh); BAIL_MACRO(ERR_OUT_OF_MEMORY, 0); } /* if */ __PHYSFS_platformSeek(fh,directoryOffset); for (entry = info->entries; fileCount > 0; fileCount--, entry++) { if (__PHYSFS_platformRead(fh, &entry->startPos, 4, 1) != 1) { __PHYSFS_platformClose(fh); return 0; } /* if */ if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1) { __PHYSFS_platformClose(fh); return 0; } /* if */ if (__PHYSFS_platformRead(fh, &entry->name, 8, 1) != 1) { __PHYSFS_platformClose(fh); return 0; } /* if */ entry->name[8] = '\0'; /* name might not be null-terminated in file. */ entry->size = PHYSFS_swapULE32(entry->size); entry->startPos = PHYSFS_swapULE32(entry->startPos); } /* for */ __PHYSFS_platformClose(fh); __PHYSFS_sort(info->entries, info->entryCount, wad_entry_cmp, wad_entry_swap); return 1; } /* wad_load_entries */
char *__PHYSFS_platformCurrentDir(void) { /* * This can't just do platformRealPath("."), since that would eventually * just end up calling back into here. */ int allocSize = 0; char *retval = NULL; char *ptr; do { allocSize += 100; ptr = (char *) allocator.Realloc(retval, allocSize); if (ptr == NULL) { if (retval != NULL) allocator.Free(retval); BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL); } /* if */ retval = ptr; ptr = getcwd(retval, allocSize); } while (ptr == NULL && errno == ERANGE); if (ptr == NULL && errno) { /* * getcwd() failed for some reason, for example current * directory not existing. */ if (retval != NULL) allocator.Free(retval); BAIL_MACRO(ERR_NO_SUCH_FILE, NULL); } /* if */ return(retval); } /* __PHYSFS_platformCurrentDir */
PHYSFS_sint64 __PHYSFS_platformRead(void *opaque, void *buf, PHYSFS_uint64 len) { HANDLE Handle = ((WinApiFile *)opaque)->handle; PHYSFS_sint64 totalRead = 0; if (!__PHYSFS_ui64FitsAddressSpace(len)) BAIL_MACRO(PHYSFS_ERR_INVALID_ARGUMENT, -1); while (len > 0) { const DWORD thislen = (len > 0xFFFFFFFF) ? 0xFFFFFFFF : (DWORD)len; DWORD numRead = 0; if (!ReadFile(Handle, buf, thislen, &numRead, NULL)) BAIL_MACRO(errcodeFromWinApi(), -1); len -= (PHYSFS_uint64)numRead; totalRead += (PHYSFS_sint64)numRead; if (numRead != thislen) break; } /* while */ return totalRead; } /* __PHYSFS_platformRead */
static int hog_load_entries(const char *name, int forWriting, HOGinfo *info) { void *fh = NULL; PHYSFS_uint32 fileCount; HOGentry *entry; BAIL_IF_MACRO(!hog_open(name, forWriting, &fh, &fileCount), NULL, 0); info->entryCount = fileCount; info->entries = (HOGentry *) malloc(sizeof (HOGentry) * fileCount); if (info->entries == NULL) { __PHYSFS_platformClose(fh); BAIL_MACRO(ERR_OUT_OF_MEMORY, 0); } /* if */ for (entry = info->entries; fileCount > 0; fileCount--, entry++) { if (__PHYSFS_platformRead(fh, &entry->name, 13, 1) != 1) { __PHYSFS_platformClose(fh); return(0); } /* if */ if (__PHYSFS_platformRead(fh, &entry->size, 4, 1) != 1) { __PHYSFS_platformClose(fh); return(0); } /* if */ entry->size = PHYSFS_swapULE32(entry->size); entry->startPos = __PHYSFS_platformTell(fh); if (entry->startPos == -1) { __PHYSFS_platformClose(fh); return(0); } // Skip over entry if (!__PHYSFS_platformSeek(fh, entry->startPos + entry->size)) { __PHYSFS_platformClose(fh); return(0); } } /* for */ __PHYSFS_platformClose(fh); __PHYSFS_sort(info->entries, info->entryCount, hog_entry_cmp, hog_entry_swap); return(1); } /* hog_load_entries */
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer, PHYSFS_uint64 len) { HANDLE Handle = ((WinApiFile *)opaque)->handle; PHYSFS_sint64 totalWritten = 0; if (!__PHYSFS_ui64FitsAddressSpace(len)) BAIL_MACRO(PHYSFS_ERR_INVALID_ARGUMENT, -1); while (len > 0) { const DWORD thislen = (len > 0xFFFFFFFF) ? 0xFFFFFFFF : (DWORD)len; DWORD numWritten = 0; if (!WriteFile(Handle, buffer, thislen, &numWritten, NULL)) BAIL_MACRO(errcodeFromWinApi(), -1); len -= (PHYSFS_uint64)numWritten; totalWritten += (PHYSFS_sint64)numWritten; if (numWritten != thislen) break; } /* while */ return totalWritten; } /* __PHYSFS_platformWrite */
PHYSFS_sint64 __PHYSFS_platformWrite(void *opaque, const void *buffer, PHYSFS_uint64 len) { const int fd = *((int *) opaque); ssize_t rc = 0; if (!__PHYSFS_ui64FitsAddressSpace(len)) BAIL_MACRO(PHYSFS_ERR_INVALID_ARGUMENT, -1); rc = write(fd, (void *) buffer, (size_t) len); BAIL_IF_MACRO(rc == -1, errcodeFromErrno(), rc); assert(rc >= 0); assert(rc <= len); return (PHYSFS_sint64) rc; } /* __PHYSFS_platformWrite */
/* Note: I found this tech note: http://developer.apple.com/library/mac/#qa/qa2009/qa1678.html I don't know if this applies to us. So far, I haven't noticed the problem, so I haven't applied any of the techniques. */ static int CoreAudio_seek(Sound_Sample *sample, Uint32 ms) { OSStatus error_result = noErr; Sound_SampleInternal *internal = (Sound_SampleInternal *) sample->opaque; CoreAudioFileContainer* core_audio_file_container = (CoreAudioFileContainer *) internal->decoder_private; SInt64 frame_offset = 0; AudioStreamBasicDescription actual_format; UInt32 format_size; /* I'm confused. The Apple documentation says this: "Seek position is specified in the sample rate and frame count of the file’s audio data format — not your application’s audio data format." My interpretation is that I want to get the "actual format of the file and compute the frame offset. But when I try that, seeking goes to the wrong place. When I use outputFormat, things seem to work correctly. I must be misinterpreting the documentation or doing something wrong. */ #if 0 /* not working */ format_size = sizeof(AudioStreamBasicDescription); error_result = AudioFileGetProperty( *core_audio_file_container->audioFileID, kAudioFilePropertyDataFormat, &format_size, &actual_format ); if(error_result != noErr) { sample->flags |= SOUND_SAMPLEFLAG_ERROR; BAIL_MACRO("Core Audio: Could not GetProperty for kAudioFilePropertyDataFormat.", 0); } /* if */ // packetIndex = (pos * sampleRate) / framesPerPacket // frame_offset = (SInt64)((ms/1000.0 * actual_format.mSampleRate) / actual_format.mFramesPerPacket); #else /* seems to work, but I'm confused */ // packetIndex = (pos * sampleRate) / framesPerPacket frame_offset = (SInt64)((ms/1000.0 * core_audio_file_container->outputFormat->mSampleRate) / core_audio_file_container->outputFormat->mFramesPerPacket); #endif // computed against actual format and not the client format error_result = ExtAudioFileSeek(core_audio_file_container->extAudioFileRef, frame_offset); if(error_result != noErr) { sample->flags |= SOUND_SAMPLEFLAG_ERROR; } return(1); } /* CoreAudio_seek */
void *__PHYSFS_platformCreateMutex(void) { int rc; PthreadMutex *m = (PthreadMutex *) allocator.Malloc(sizeof (PthreadMutex)); BAIL_IF_MACRO(m == NULL, ERR_OUT_OF_MEMORY, NULL); rc = pthread_mutex_init(&m->mutex, NULL); if (rc != 0) { allocator.Free(m); BAIL_MACRO(strerror(rc), NULL); } /* if */ m->count = 0; m->owner = (pthread_t) 0xDEADBEEF; return((void *) m); } /* __PHYSFS_platformCreateMutex */