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 */
/* (be gentle, this function isn't very robust.) */ static void cvt_path_to_correct_case(char *buf) { char *fname = buf + 3; /* point to first element. */ char *ptr = strchr(fname, '\\'); /* find end of first element. */ buf[0] = toupper(buf[0]); /* capitalize drive letter. */ /* * Go through each path element, and enumerate its parent dir until * a case-insensitive match is found. If one is (and it SHOULD be) * then overwrite the original element with the correct case. * If there's an error, or the path has vanished for some reason, it * won't hurt to have the original case, so we just keep going. */ while (fname != NULL) { char spec[CCHMAXPATH]; FILEFINDBUF3 fb; HDIR hdir = HDIR_CREATE; ULONG count = 1; APIRET rc; *(fname - 1) = '\0'; /* isolate parent dir string. */ strcpy(spec, buf); /* copy isolated parent dir... */ strcat(spec, "\\*.*"); /* ...and add wildcard search spec. */ if (ptr != NULL) /* isolate element to find (fname is the start). */ *ptr = '\0'; rc = DosFindFirst(spec, &hdir, FILE_DIRECTORY, &fb, sizeof (fb), &count, FIL_STANDARD); if (rc == NO_ERROR) { while (count == 1) /* while still entries to enumerate... */ { if (__PHYSFS_platformStricmp(fb.achName, fname) == 0) { strcpy(fname, fb.achName); break; /* there it is. Overwrite and stop searching. */ } /* if */ DosFindNext(hdir, &fb, sizeof (fb), &count); } /* while */ DosFindClose(hdir); } /* if */ *(fname - 1) = '\\'; /* unisolate parent dir. */ fname = ptr; /* point to next element. */ if (ptr != NULL) { *ptr = '\\'; /* unisolate element. */ ptr = strchr(++fname, '\\'); /* find next element. */ } /* if */ } /* while */ } /* cvt_file_to_correct_case */
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 */