str *_resolve_link(str *path) { /** Internal helper function. Takes a path and follows symlinks until we either arrive at something that isn't a symlink, or encounter a path we've seen before (meaning that there's a loop). */ list<str *> *paths_seen; str *dir, *resolved; paths_seen = (new list<str *>()); while(islink(path)) { if (paths_seen->__contains__(path)) { return 0; } paths_seen->append(path); resolved = __os__::readlink(path); if ((!isabs(resolved))) { dir = dirname(path); path = normpath(join(2, dir, resolved)); } else { path = normpath(resolved); } } return path; }
static char * relpath(char *from, char *to) { int up; char *p = to, *rel; assert(from[0] == '/'); assert(to[0] == '/'); normpath(from); normpath(to); for (; *from == *to && *to; from++, to++) { if (*to == '/') p = to; } for (up = -1, from--; from && *from; from = strchr(from + 1, '/'), up++); rel = calloc(3 * up + strlen(p), sizeof(char)); while (up--) strcat(rel, "../"); if (*p) strcat(rel, p+1); return rel; }
static std::string pathcat(std::string path, std::string label) { if (path.empty()) return normpath(label); else if (label.empty()) return normpath(path); else return normpath(path+"/"+label); }
// Normalize a file path. // remove relative path component (..\ and .\), // replace slashes by backslashes, // convert to long form. // // Returns a pointer to a memory allocated block containing the normalized string. // The caller is responsible for freeing the block. // Returns NULL if the file does not exist or if a memory allocation fails. // // Precondition: the file must exist on the file system. // // Note: // - the case of the root component is preserved // - the case of rest is set to the way it is stored on the file system // // e.g. suppose the a file "C:\foo\Bar.Pdf" exists on the file system then // "c:\foo\bar.pdf" becomes "c:\foo\Bar.Pdf" // "C:\foo\BAR.PDF" becomes "C:\foo\Bar.Pdf" WCHAR *Normalize(const WCHAR *path) { // convert to absolute path, change slashes into backslashes DWORD cch = GetFullPathName(path, 0, NULL, NULL); if (!cch) return str::Dup(path); ScopedMem<WCHAR> fullpath(AllocArray<WCHAR>(cch)); GetFullPathName(path, cch, fullpath, NULL); // convert to long form cch = GetLongPathName(fullpath, NULL, 0); if (!cch) return fullpath.StealData(); ScopedMem<WCHAR> normpath(AllocArray<WCHAR>(cch)); GetLongPathName(fullpath, normpath, cch); if (cch <= MAX_PATH) return normpath.StealData(); // handle overlong paths: first, try to shorten the path cch = GetShortPathName(fullpath, NULL, 0); if (cch && cch <= MAX_PATH) { ScopedMem<WCHAR> shortpath(AllocArray<WCHAR>(cch)); GetShortPathName(fullpath, shortpath, cch); if (str::Len(path::GetBaseName(normpath)) + path::GetBaseName(shortpath) - shortpath < MAX_PATH) { // keep the long filename if possible *(WCHAR *)path::GetBaseName(shortpath) = '\0'; return str::Join(shortpath, path::GetBaseName(normpath)); } return shortpath.StealData(); } // else mark the path as overlong if (str::StartsWith(normpath.Get(), L"\\\\?\\")) return normpath.StealData(); return str::Join(L"\\\\?\\", normpath); }
//prepends cwd, normpathifys, etc static int prepare_path(const unsigned char *pathin, unsigned char *pathout, int outsize) { if (pathin[0] == '/') { //do nothing? strncpy(pathout, pathin, outsize); return 0; } Process *p = process_get_current(0); if (!p) { strncpy(pathout, pathin, outsize); pathout[outsize-1] = 0; return -1; } pathout[0] = 0; strcat(pathout, p->working_path); int len = strlen(pathout); if (len == 0 && pathin[0] != '/') { strcat(pathout, "/"); } else if (len != 0 && pathin[0] == '/' && pathout[len-1] == '/') { pathout[len-1] = 0; } strcat(pathout, (unsigned char*)pathin); normpath(pathout, outsize); return 0; }
// Normalizes the file path and the converts it into a short form that // can be used for interaction with non-UNICODE aware applications WCHAR *ShortPath(const WCHAR *path) { ScopedMem<WCHAR> normpath(Normalize(path)); DWORD cch = GetShortPathName(normpath, NULL, 0); if (!cch) return normpath.StealData(); WCHAR *shortpath = AllocArray<WCHAR>(cch); GetShortPathName(normpath, shortpath, cch); return shortpath; }
gchar * get_full_path(const gchar * location, const gchar * path) { gchar *dir; dir = g_path_get_dirname(location); setptr(dir, g_build_filename(dir, path, NULL)); setptr(dir, normpath(dir)); return dir; }
str *abspath(str *path) { /** Return an absolute path. */ if ((!isabs(path))) { path = join(2, __os__::getcwd(), path); } return normpath(path); }
gchar * get_relative_path(const gchar * location, const gchar * path) { gchar *dir; gchar *pth; gchar *ret = NULL; gint plen; gint dlen; if (!g_path_is_absolute(path)) { return g_strdup(path); } dir = normpath(location); pth = normpath(path); plen = strlen(pth); dlen = strlen(dir); if (strstr(pth, dir) == pth) { if (plen > dlen) { ret = g_strdup(path + strlen(dir) + 1); } else if (plen == dlen) { ret = g_strdup("."); } } g_free(dir); g_free(pth); return ret; }
static const char * normpath(char *path) { char *seg, *p; for (p = path, seg = NULL; *p; p++) { if (strncmp(p, "/../", 4) == 0 || strncmp(p, "/..", 4) == 0) { memmove(seg ? seg : p, p+3, strlen(p+3) + 1); return normpath(path); } else if (strncmp(p, "/./", 3) == 0 || strncmp(p, "/.", 3) == 0) { memmove(p, p+2, strlen(p+2) + 1); } else if (strncmp(p, "//", 2) == 0 || strncmp(p, "/", 2) == 0) { memmove(p, p+1, strlen(p+1) + 1); } if (*p == '/') seg = p; } return path; }
char *win_realpath(const char *path, char *resolved_path) { return normpath(path, resolved_path); }
std::string abspath(const std::string & path) { std::string p = path; if(!isabs(p)) p = join(getcwd(), p); return normpath(p); }
/* Open a zip-compatible archive and extract all files * into the specified directory (which is assumed to exist) */ BOOL unzip_archive(SCHEME *scheme, char *dirname, char *data, DWORD size, NOTIFYPROC notify) { int n; char pathname[MAX_PATH]; char *new_part; /* read the end of central directory record */ struct eof_cdir *pe = (struct eof_cdir *)&data[size - sizeof (struct eof_cdir)]; int arc_start = size - sizeof (struct eof_cdir) - pe->nBytesCDir - pe->ofsCDir; /* set position to start of central directory */ int pos = arc_start + pe->ofsCDir; /* make sure this is a zip file */ if (pe->tag != 0x06054b50) return FALSE; /* Loop through the central directory, reading all entries */ for (n = 0; n < pe->nTotalCDir; ++n) { int i; char *fname; char *pcomp; char *dst; struct cdir *pcdir; struct fhdr *pfhdr; pcdir = (struct cdir *)&data[pos]; pfhdr = (struct fhdr *)&data[pcdir->ofs_local_header + arc_start]; if (pcdir->tag != 0x02014b50) return FALSE; if (pfhdr->tag != 0x04034b50) return FALSE; pos += sizeof(struct cdir); fname = (char *)&data[pos]; /* This is not null terminated! */ pos += pcdir->fname_length + pcdir->extra_length + pcdir->comment_length; pcomp = &data[pcdir->ofs_local_header + sizeof(struct fhdr) + arc_start + pfhdr->fname_length + pfhdr->extra_length]; /* dirname is the Python home directory (prefix) */ strcpy(pathname, dirname); if (pathname[strlen(pathname)-1] != '\\') strcat(pathname, "\\"); new_part = &pathname[lstrlen(pathname)]; /* we must now match the first part of the pathname * in the archive to a component in the installation * scheme (PURELIB, PLATLIB, HEADERS, SCRIPTS, or DATA) * and replace this part by the one in the scheme to use */ for (i = 0; scheme[i].name; ++i) { if (0 == strnicmp(scheme[i].name, fname, strlen(scheme[i].name))) { char *rest; int len; /* length of the replaced part */ int namelen = strlen(scheme[i].name); strcat(pathname, scheme[i].prefix); rest = fname + namelen; len = pfhdr->fname_length - namelen; if ((pathname[strlen(pathname)-1] != '\\') && (pathname[strlen(pathname)-1] != '/')) strcat(pathname, "\\"); /* Now that pathname ends with a separator, * we must make sure rest does not start with * an additional one. */ if ((rest[0] == '\\') || (rest[0] == '/')) { ++rest; --len; } strncat(pathname, rest, len); goto Done; } } /* no prefix to replace found, go unchanged */ strncat(pathname, fname, pfhdr->fname_length); Done: normpath(pathname); if (pathname[strlen(pathname)-1] != '\\') { /* * The local file header (pfhdr) does not always * contain the compressed and uncompressed sizes of * the data depending on bit 3 of the flags field. So * it seems better to use the data from the central * directory (pcdir). */ dst = map_new_file(0, pathname, new_part, pcdir->uncomp_size, pcdir->last_mod_file_date, pcdir->last_mod_file_time, notify); if (dst) { if (!extract_file(dst, pcomp, pfhdr->method, pcdir->comp_size, pcdir->uncomp_size, notify)) return FALSE; } /* else ??? */ } if (notify) notify(NUM_FILES, new_part, (int)pe->nTotalCDir, (int)n+1); } return TRUE; }
std::string path::expand(const std::string &path) { return normpath(expandvars(expanduser(path))); }