char *__PHYSFS_platformCalcBaseDir(const char *argv0) { char *retval = NULL; char *envr = NULL; /* fast path: default behaviour can handle this. */ if ( (argv0 != NULL) && (strchr(argv0, '/') != NULL) ) return(NULL); /* higher level will parse out real path from argv0. */ /* * Try to avoid using argv0 unless forced to. If there's a Linux-like * /proc filesystem, you can get the full path to the current process from * the /proc/self/exe symlink. */ retval = readSymLink("/proc/self/exe"); if (retval == NULL) { /* older kernels don't have /proc/self ... try PID version... */ const unsigned long long pid = (unsigned long long) getpid(); char path[64]; const int rc = (int) snprintf(path,sizeof(path),"/proc/%llu/exe",pid); if ( (rc > 0) && (rc < sizeof(path)) ) retval = readSymLink(path); } /* if */ if (retval != NULL) /* chop off filename. */ { char *ptr = strrchr(retval, '/'); if (ptr != NULL) *ptr = '\0'; } /* if */ if ((retval == NULL) && (argv0 != NULL)) { /* If there's no dirsep on argv0, then look through $PATH for it. */ envr = __PHYSFS_platformCopyEnvironmentVariable("PATH"); BAIL_IF_MACRO(!envr, NULL, NULL); retval = findBinaryInPath(argv0, envr); allocator.Free(envr); } /* if */ if (retval != NULL) { /* try to shrink buffer... */ char *ptr = (char *) allocator.Realloc(retval, strlen(retval) + 1); if (ptr != NULL) retval = ptr; /* oh well if it failed. */ } /* if */ return(retval); } /* __PHYSFS_platformCalcBaseDir */
char *__PHYSFS_platformCalcBaseDir(const char *argv0) { char *retval = NULL; const char *envr = NULL; /* Try to avoid using argv0 unless forced to. Try system-specific stuff. */ #if PHYSFS_PLATFORM_FREEBSD { char fullpath[PATH_MAX]; size_t buflen = sizeof (fullpath); int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; if (sysctl(mib, 4, fullpath, &buflen, NULL, 0) != -1) retval = __PHYSFS_strdup(fullpath); } #elif PHYSFS_PLATFORM_SOLARIS { const char *path = getexecname(); if ((path != NULL) && (path[0] == '/')) /* must be absolute path... */ retval = __PHYSFS_strdup(path); } #endif if (retval) return retval; /* already got it. */ /* If there's a Linux-like /proc filesystem, you can get the full path to * the current process from a symlink in there. */ if (access("/proc", F_OK) == 0) { retval = readSymLink("/proc/self/exe"); if (!retval) retval = readSymLink("/proc/curproc/file"); if (!retval) retval = readSymLink("/proc/curproc/exe"); if (retval == NULL) { /* older kernels don't have /proc/self ... try PID version... */ const unsigned long long pid = (unsigned long long) getpid(); char path[64]; const int rc = (int) snprintf(path,sizeof(path),"/proc/%llu/exe",pid); if ( (rc > 0) && (rc < sizeof(path)) ) retval = readSymLink(path); } /* if */ } /* if */ if (retval != NULL) /* chop off filename. */ { char *ptr = strrchr(retval, '/'); if (ptr != NULL) *(ptr+1) = '\0'; else /* shouldn't happen, but just in case... */ { physfs_alloc.Free(retval); retval = NULL; } /* else */ } /* if */ /* No /proc/self/exe, etc, but we have an argv[0] we can parse? */ if ((retval == NULL) && (argv0 != NULL)) { /* fast path: default behaviour can handle this. */ if (strchr(argv0, '/') != NULL) return NULL; /* higher level parses out real path from argv0. */ /* If there's no dirsep on argv0, then look through $PATH for it. */ envr = getenv("PATH"); if (envr != NULL) { char *path = (char *) __PHYSFS_smallAlloc(strlen(envr) + 1); BAIL_IF_MACRO(!path, PHYSFS_ERR_OUT_OF_MEMORY, NULL); strcpy(path, envr); retval = findBinaryInPath(argv0, path); __PHYSFS_smallFree(path); } /* if */ } /* if */ if (retval != NULL) { /* try to shrink buffer... */ char *ptr = (char *) physfs_alloc.Realloc(retval, strlen(retval) + 1); if (ptr != NULL) retval = ptr; /* oh well if it failed. */ } /* if */ return retval; } /* __PHYSFS_platformCalcBaseDir */