char *Bgetappdir(void) { char *dir = NULL; #ifdef _WIN32 TCHAR appdir[MAX_PATH]; if (GetModuleFileName(NULL, appdir, MAX_PATH) > 0) { // trim off the filename char *slash = Bstrrchr(appdir, '\\'); if (slash) slash[0] = 0; dir = Bstrdup(appdir); } #elif defined EDUKE32_OSX dir = osx_getappdir(); #elif defined __FreeBSD__ // the sysctl should also work when /proc/ is not mounted (which seems to // be common on FreeBSD), so use it.. char buf[PATH_MAX] = {0}; int name[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; size_t len = sizeof(buf)-1; int ret = sysctl(name, sizeof(name)/sizeof(name[0]), buf, &len, NULL, 0); if(ret == 0 && buf[0] != '\0') { // again, remove executable name with dirname() // on FreeBSD dirname() seems to use some internal buffer dir = strdup(dirname(buf)); } #elif defined __linux || defined EDUKE32_BSD char buf[PATH_MAX] = {0}; char buf2[PATH_MAX] = {0}; # ifdef __linux Bsnprintf(buf, sizeof(buf), "/proc/%d/exe", getpid()); # else // the BSDs.. except for FreeBSD which has a sysctl Bsnprintf(buf, sizeof(buf), "/proc/%d/file", getpid()); # endif int len = readlink(buf, buf2, sizeof(buf2)); if (len != -1) { // remove executable name with dirname(3) // on Linux, dirname() will modify buf2 (cutting off executable name) and return it // on FreeBSD it seems to use some internal buffer instead.. anyway, just strdup() dir = Bstrdup(dirname(buf2)); } #endif return dir; }
int32_t Bcanonicalisefilename(char *filename, int32_t removefn) { char cwd[BMAX_PATH]; char *fnp = filename; #ifdef _WIN32 int drv = 0; if (filename[0] && filename[1] == ':') { // filename is prefixed with a drive drv = toupper(filename[0]) - 'A' + 1; fnp += 2; } if (!_getdcwd(drv, cwd, sizeof(cwd))) return -1; for (char *p = cwd; *p; p++) if (*p == '\\') *p = '/'; #else if (!getcwd(cwd, sizeof(cwd))) return -1; #endif char *p = Bstrrchr(cwd, '/'); if (!p || p[1]) Bstrcat(cwd, "/"); char fn[BMAX_PATH]; Bstrcpy(fn, fnp); #ifdef _WIN32 for (p = fn; *p; p++) if (*p == '\\') *p = '/'; #endif if (fn[0] != '/') { // we are dealing with a path relative to the current directory Bstrcpy(filename, cwd); Bstrcat(filename, fn); } else { #ifdef _WIN32 filename[0] = cwd[0]; filename[1] = ':'; filename[2] = 0; Bstrcat(filename, fn); #else Bstrcpy(filename, fn); #endif } fnp = filename; #ifdef _WIN32 fnp += 2; // skip the drive #endif UNREFERENCED_PARAMETER(removefn); // change the call below to use removefn instead of 1? return Bcorrectfilename(fnp, 1); }
int Bcorrectfilename(char *filename, int removefn) { #ifdef _WIN32 int r, trailslash=0; #endif char path[256]="", fn[64]="", scratch[256], *ptr, *ptr2, ch; char cwd[256], *cwdp = cwd; char *tokarr[64]; int ntok=0, i, j; int grpmode = 0; if (!Bstrncasecmp(filename,"GRP:",4)) { grpmode = 1; for (ptr=filename; *ptr; ptr++) if (*ptr == '\\') *ptr = '/'; } #ifdef _WIN32 if (!grpmode) { // Windows uses backslashes so translate all unix-like forwardslashes for (ptr=filename; *ptr; ptr++) if (*ptr == '/') *ptr = '\\'; if (*(ptr-1) == '\\') trailslash = 1; r = GetFullPathName(filename, 256, path, &ptr); if (r > 256) return -1; if (r == 0) return -1; if (!trailslash && removefn && ptr) *ptr=0; if (trailslash) { if (path[ strlen(path) - 1 ] != '\\') strcat(path, "\\"); } for (ptr=path; *ptr; ptr++) if (*ptr == '\\') *ptr = '/'; strcpy(filename,path); } else { #endif #ifndef _WIN32 if (!grpmode) { Bgetcwd(cwd, 256); Bstrcat(cwd, "/"); } else { #endif cwd[0] = '/'; cwd[1] = 0; #ifndef _WIN32 } #endif ptr2 = filename; if (grpmode) { ptr2 += 3; if (ptr2[1] != '/') *ptr2 = '/'; else ptr2++; } if (removefn) { ptr = Bstrrchr(ptr2, '/'); if (ptr) ptr[1] = 0; else if (!grpmode) ptr2[0] = 0; } // now we have all the bits and pieces, clean it all up scratch[0] = 0; if (ptr2[0] != '/') { // relative path, which means prepend the current dir to the path Bstrcat(scratch, cwdp); } Bstrcat(scratch, ptr2); ptr2 = scratch; while ((ptr = Bstrtoken(ptr2==scratch?scratch:NULL,"/",&ptr2,1)) != NULL) { if (!Bstrcmp(ptr,".")) continue; else if (!Bstrcmp(ptr,"..")) { if (ntok>0) ntok--; } else { tokarr[ntok++] = ptr; } } ptr2 = filename; if (grpmode) { Bstrcpy(filename,"GRP:"); ptr2 += 4; } else filename[0] = 0; *(ptr2++) = '/'; for (i=0; i<ntok; i++) { ptr = tokarr[i]; if (i>0) *(ptr2++) = '/'; while (*ptr) *(ptr2++) = *(ptr++); } if (removefn) if (*(ptr2-1) != '/') *(ptr2++) = '/'; *(ptr2) = 0; #ifdef _WIN32 } #endif return 0; }