char * base_name (char const *name) { char const *base = name + FILESYSTEM_PREFIX_LEN (name); char const *p; for (p = base; *p; p++) { if (ISSLASH (*p)) { /* Treat multiple adjacent slashes like a single slash. */ do p++; while (ISSLASH (*p)); /* If the file name ends in slash, use the trailing slash as the basename if no non-slashes have been found. */ if (! *p) { if (ISSLASH (*base)) base = p - 1; break; } /* *P is a non-slash preceded by a slash. */ base = p; } } return (char *) base; }
char *base_name(char const *name) { char const *base = name + FILESYSTEM_PREFIX_LEN(name); char const *p; // kill drive letter, if present (on Win32) /* GGRIII */ if((p = strchr(base, ':'))) { // drive letter is present base = p + 1; } for(p = base; *p; p++) { if(ISSLASH(*p)) { /* Treat multiple adjacent slashes like a single slash. */ do p++; while (ISSLASH(*p)); /* If the file name ends in slash, use the trailing slash as the basename if no non-slashes have been found. */ if(!*p) { if(ISSLASH(*base)) base = p - 1; break; } /* *P is a non-slash preceded by a slash. */ base = p; } } return (char *)base; }
/* Concatenate a directory pathname, a relative pathname and an optional suffix. The directory may end with the directory separator. The second argument may not start with the directory separator (it is relative). Return a freshly allocated pathname. */ char * concatenated_pathname (const char *directory, const char *filename, const char *suffix) { char *result; char *p; if (strcmp (directory, ".") == 0) { /* No need to prepend the directory. */ result = (char *) xmalloc (strlen (filename) + (suffix != NULL ? strlen (suffix) : 0) + 1); p = result; } else { size_t directory_len = strlen (directory); int need_slash = (directory_len > FILESYSTEM_PREFIX_LEN (directory) && !ISSLASH (directory[directory_len - 1])); result = (char *) xmalloc (directory_len + need_slash + strlen (filename) + (suffix != NULL ? strlen (suffix) : 0) + 1); memcpy (result, directory, directory_len); p = result + directory_len; if (need_slash) *p++ = '/'; } p = stpcpy (p, filename); if (suffix != NULL) stpcpy (p, suffix); return result; }
char * path_concat (const char *dir, const char *base, char **base_in_result) { char *p; char *p_concat; size_t baselen; size_t dirlen; if (!dir) { p_concat = strdup (base); if (base_in_result) *base_in_result = p_concat; return p_concat; } /* DIR is not empty. */ baselen = base_len (base); dirlen = strlen (dir); p_concat = malloc (dirlen + baselen + 2); if (!p_concat) return 0; p = mempcpy (p_concat, dir, dirlen); if (FILESYSTEM_PREFIX_LEN (dir) < dirlen) { if (ISSLASH (*(p - 1)) && ISSLASH (*base)) --p; else if (!ISSLASH (*(p - 1)) && !ISSLASH (*base)) *p++ = DIRECTORY_SEPARATOR; } if (base_in_result) *base_in_result = p; memcpy (p, base, baselen); p[baselen] = '\0'; return p_concat; }
char * base_name (char const *name) { char const *base = name += FILESYSTEM_PREFIX_LEN (name); int all_slashes = 1; char const *p; for (p = name; *p; p++) { if (ISSLASH (*p)) base = p + 1; else all_slashes = 0; } /* If NAME is all slashes, arrange to return `/'. */ if (*base == '\0' && ISSLASH (*name) && all_slashes) --base; return (char *) base; }
/* Strip directory and suffix from filenames */ char * ft_basename (char const *fpath) { char const *base = fpath += FILESYSTEM_PREFIX_LEN (fpath); int all_slashes = 1; char const *p; for (p = fpath; *p; p++) { if (ISSLASH (*p)) { base = p + 1; } else { all_slashes = 0; } } /* If NAME is all slashes, arrange to return `/'. */ if (*base == '\0' && ISSLASH (*fpath) && all_slashes) { --base; } return (char *) base; }
/* Replace '/' with '\0' in FILENAME if it marks a place that needs testing for the existence of directory. Return the address of the last location replaced, or 0 if none were replaced. */ static char * replace_slashes (char *filename) { char *f; char *last_location_replaced = 0; char const *component_start; for (f = filename + FILESYSTEM_PREFIX_LEN (filename); ISSLASH (*f); f++) continue; component_start = f; for (; *f; f++) if (ISSLASH (*f)) { char *slash = f; /* Treat multiple slashes as if they were one slash. */ while (ISSLASH (f[1])) f++; /* Ignore slashes at the end of the path. */ if (! f[1]) break; /* "." and ".." need not be tested. */ if (! (slash - component_start <= 2 && component_start[0] == '.' && slash[-1] == '.')) { *slash = '\0'; last_location_replaced = slash; } component_start = f + 1; } return last_location_replaced; }
char *basename(char const *name) { char const *base = name += FILESYSTEM_PREFIX_LEN(name); int all_slashes = 1; char const *p; for (p = name; *p; p++) { if (ISSLASH(*p)) base = p + 1; else all_slashes = 0; } /* If NAME is all slashes, arrange to return `/'. */ if (*base == '\0' && ISSLASH(*name) && all_slashes) --base; /* Make sure the last byte is not a slash. */ //assert(all_slashes || !ISSLASH(*(p - 1))); return (char *)base; }
void move_file (char const *from, int volatile *from_needs_removal, char *to, mode_t mode, int backup) { struct stat to_st; int to_errno = ! backup ? -1 : stat (to, &to_st) == 0 ? 0 : errno; if (backup) { int try_makedirs_errno = 0; char *bakname; if (origprae || origbase) { char const *p = origprae ? origprae : ""; char const *b = origbase ? origbase : ""; char const *o = base_name (to); size_t plen = strlen (p); size_t tlen = o - to; size_t blen = strlen (b); size_t osize = strlen (o) + 1; bakname = xmalloc (plen + tlen + blen + osize); memcpy (bakname, p, plen); memcpy (bakname + plen, to, tlen); memcpy (bakname + plen + tlen, b, blen); memcpy (bakname + plen + tlen + blen, o, osize); for (p += FILESYSTEM_PREFIX_LEN (p); *p; p++) if (ISSLASH (*p)) { try_makedirs_errno = ENOENT; break; } } else { bakname = find_backup_file_name (to, backup_type); if (!bakname) memory_fatal (); } if (to_errno) { int fd; if (debug & 4) say ("Creating empty unreadable file %s\n", quotearg (bakname)); try_makedirs_errno = ENOENT; unlink (bakname); while ((fd = creat (bakname, 0)) < 0) { if (errno != try_makedirs_errno) pfatal ("Can't create file %s", quotearg (bakname)); makedirs (bakname); try_makedirs_errno = 0; } if (close (fd) != 0) pfatal ("Can't close file %s", quotearg (bakname)); } else { if (debug & 4) say ("Renaming file %s to %s\n", quotearg_n (0, to), quotearg_n (1, bakname)); while (rename (to, bakname) != 0) { if (errno != try_makedirs_errno) pfatal ("Can't rename file %s to %s", quotearg_n (0, to), quotearg_n (1, bakname)); makedirs (bakname); try_makedirs_errno = 0; } } free (bakname); } if (from) { if (debug & 4) say ("Renaming file %s to %s\n", quotearg_n (0, from), quotearg_n (1, to)); if (rename (from, to) == 0) *from_needs_removal = 0; else { int to_dir_known_to_exist = 0; if (errno == ENOENT && (to_errno == -1 || to_errno == ENOENT)) { makedirs (to); to_dir_known_to_exist = 1; if (rename (from, to) == 0) { *from_needs_removal = 0; return; } } if (errno == EXDEV) { if (! backup) { if (unlink (to) == 0) to_dir_known_to_exist = 1; else if (errno != ENOENT) pfatal ("Can't remove file %s", quotearg (to)); } if (! to_dir_known_to_exist) makedirs (to); copy_file (from, to, 0, mode); return; } pfatal ("Can't rename file %s to %s", quotearg_n (0, from), quotearg_n (1, to)); } } else if (! backup) { if (debug & 4) say ("Removing file %s\n", quotearg (to)); if (unlink (to) != 0) pfatal ("Can't remove file %s", quotearg (to)); } }
static #endif const char * compute_curr_prefix (const char *orig_installprefix, const char *orig_installdir, const char *curr_pathname) { const char *curr_installdir; const char *rel_installdir; if (curr_pathname == NULL) return NULL; if (strncmp (orig_installprefix, orig_installdir, strlen (orig_installprefix)) != 0) return NULL; rel_installdir = orig_installdir + strlen (orig_installprefix); { const char *p_base = curr_pathname + FILESYSTEM_PREFIX_LEN (curr_pathname); const char *p = curr_pathname + strlen (curr_pathname); char *q; while (p > p_base) { p--; if (ISSLASH (*p)) break; } q = (char *) xmalloc (p - curr_pathname + 1); #ifdef NO_XMALLOC if (q == NULL) return NULL; #endif memcpy (q, curr_pathname, p - curr_pathname); q[p - curr_pathname] = '\0'; curr_installdir = q; } { const char *rp = rel_installdir + strlen (rel_installdir); const char *cp = curr_installdir + strlen (curr_installdir); const char *cp_base = curr_installdir + FILESYSTEM_PREFIX_LEN (curr_installdir); while (rp > rel_installdir && cp > cp_base) { bool same = false; const char *rpi = rp; const char *cpi = cp; while (rpi > rel_installdir && cpi > cp_base) { rpi--; cpi--; if (ISSLASH (*rpi) || ISSLASH (*cpi)) { if (ISSLASH (*rpi) && ISSLASH (*cpi)) same = true; break; } #if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi) != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi)) break; #else if (*rpi != *cpi) break; #endif } if (!same) break; rp = rpi; cp = cpi; } if (rp > rel_installdir) return NULL; { size_t curr_prefix_len = cp - curr_installdir; char *curr_prefix; curr_prefix = (char *) xmalloc (curr_prefix_len + 1); #ifdef NO_XMALLOC if (curr_prefix == NULL) return NULL; #endif memcpy (curr_prefix, curr_installdir, curr_prefix_len); curr_prefix[curr_prefix_len] = '\0'; return curr_prefix; } } }
static #endif const char * compute_curr_prefix (const char *orig_installprefix, const char *orig_installdir, const char *curr_pathname) { const char *curr_installdir; const char *rel_installdir; if (curr_pathname == NULL) return NULL; /* Determine the relative installation directory, relative to the prefix. This is simply the difference between orig_installprefix and orig_installdir. */ if (strncmp (orig_installprefix, orig_installdir, strlen (orig_installprefix)) != 0) /* Shouldn't happen - nothing should be installed outside $(prefix). */ return NULL; rel_installdir = orig_installdir + strlen (orig_installprefix); /* Determine the current installation directory. */ { const char *p_base = curr_pathname + FILESYSTEM_PREFIX_LEN (curr_pathname); const char *p = curr_pathname + strlen (curr_pathname); char *q; while (p > p_base) { p--; if (ISSLASH (*p)) break; } q = (char *) xmalloc (p - curr_pathname + 1); #ifdef NO_XMALLOC if (q == NULL) return NULL; #endif memcpy (q, curr_pathname, p - curr_pathname); q[p - curr_pathname] = '\0'; curr_installdir = q; } /* Compute the current installation prefix by removing the trailing rel_installdir from it. */ { const char *rp = rel_installdir + strlen (rel_installdir); const char *cp = curr_installdir + strlen (curr_installdir); const char *cp_base = curr_installdir + FILESYSTEM_PREFIX_LEN (curr_installdir); while (rp > rel_installdir && cp > cp_base) { bool same = false; const char *rpi = rp; const char *cpi = cp; while (rpi > rel_installdir && cpi > cp_base) { rpi--; cpi--; if (ISSLASH (*rpi) || ISSLASH (*cpi)) { if (ISSLASH (*rpi) && ISSLASH (*cpi)) same = true; break; } #if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ /* Win32, OS/2, DOS - case insignificant filesystem */ if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi) != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi)) break; #else if (*rpi != *cpi) break; #endif } if (!same) break; /* The last pathname component was the same. opi and cpi now point to the slash before it. */ rp = rpi; cp = cpi; } if (rp > rel_installdir) /* Unexpected: The curr_installdir does not end with rel_installdir. */ return NULL; { size_t curr_prefix_len = cp - curr_installdir; char *curr_prefix; curr_prefix = (char *) xmalloc (curr_prefix_len + 1); #ifdef NO_XMALLOC if (curr_prefix == NULL) return NULL; #endif memcpy (curr_prefix, curr_installdir, curr_prefix_len); curr_prefix[curr_prefix_len] = '\0'; return curr_prefix; } } }