const char* FBDirectory::Normalize(const char* path) { static char newpath[MAXPATHLEN+1]; const char* buf; buf = InterpSlashSlash(path); buf = ElimDot(buf); buf = ElimDotDot(buf); buf = InterpTilde(buf); if (*buf == '\0') { strcpy(newpath, "./"); } else if (!DotSlash(buf) && !DotDotSlash(buf) && *buf != '/') { strcpy(newpath, "./"); strcat(newpath, buf); } else if (IsADirectory(buf) && buf[strlen(buf)-1] != '/') { strcpy(newpath, buf); strcat(newpath, "/"); } else { strcpy(newpath, buf); } return newpath; }
const char* Directory::ElimDotDot (const char* path) { static char newpath[MAX_PATH_LENGTH+1]; const char* src; char* dest = newpath; for (src = path; src < &path[strlen(path)]; ++src) { if (DotDotSlash(src) && CollapsedDotDotSlash(newpath, dest)) { src += 2; } else { *dest++ = *src; } } *dest = '\0'; return newpath; }
static boolean CollapsedDotDotSlash(const char* path, const char*& start) { if (path == start || *(start-1) != '/') { return false; } else if (path == start-1 && *path == '/') { return true; } else if (path == start-2) { /* NB: won't handle '//' right */ start = path; return *start != '.'; } else if (path < start-2 && !DotDotSlash(start-3)) { for (start -= 2; path <= start; --start) { if (*start == '/') { ++start; return true; } } start = path; return true; } return false; }