tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pathsub.c (5404B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 /*
      6 ** Pathname subroutines.
      7 */
      8 #if defined(FREEBSD) || defined(BSDI) || defined(DARWIN)
      9 #include <sys/types.h>
     10 #endif /* FREEBSD */
     11 #include <dirent.h>
     12 #include <errno.h>
     13 #include <stdarg.h>
     14 #include <stdio.h>
     15 #include <stdlib.h>
     16 #include <string.h>
     17 #include <unistd.h>
     18 #include <sys/types.h>
     19 #include <sys/stat.h>
     20 #include "pathsub.h"
     21 #ifdef USE_REENTRANT_LIBC
     22 #include "libc_r.h"
     23 #endif /* USE_REENTRANT_LIBC */
     24 
     25 char *program;
     26 
     27 void
     28 fail(char *format, ...)
     29 {
     30    int error;
     31    va_list ap;
     32 
     33 #ifdef USE_REENTRANT_LIBC
     34    R_STRERROR_INIT_R();
     35 #endif
     36 
     37    error = errno;
     38    fprintf(stderr, "%s: ", program);
     39    va_start(ap, format);
     40    vfprintf(stderr, format, ap);
     41    va_end(ap);
     42    if (error) {
     43 
     44 #ifdef USE_REENTRANT_LIBC
     45    R_STRERROR_R(errno);
     46 fprintf(stderr, ": %s", r_strerror_r);
     47 #else
     48 fprintf(stderr, ": %s", strerror(errno));
     49 #endif
     50    }
     51 
     52    putc('\n', stderr);
     53    abort();
     54    exit(1);
     55 }
     56 
     57 char *
     58 getcomponent(char *path, char *name)
     59 {
     60    if (*path == '\0')
     61 return 0;
     62    if (*path == '/') {
     63 *name++ = '/';
     64    } else {
     65 do {
     66     *name++ = *path++;
     67 } while (*path != '/' && *path != '\0');
     68    }
     69    *name = '\0';
     70    while (*path == '/')
     71 path++;
     72    return path;
     73 }
     74 
     75 /* APPARENT BUG - ignores argument "dir", uses ".." instead. */
     76 char *
     77 ino2name(ino_t ino, char *dir)
     78 {
     79    DIR *dp;
     80    struct dirent *ep;
     81    char *name;
     82 
     83    dp = opendir("..");		/* XXX */
     84    if (!dp)
     85 fail("cannot read parent directory");
     86    for (;;) {
     87 if (!(ep = readdir(dp)))
     88     fail("cannot find current directory");
     89 if (ep->d_ino == ino)
     90     break;
     91    }
     92    name = xstrdup(ep->d_name);
     93    closedir(dp);
     94    return name;
     95 }
     96 
     97 void *
     98 xmalloc(size_t size)
     99 {
    100    void *p;
    101 
    102    if (size <= 0)
    103 fail("attempted to allocate %u bytes", size);
    104    p = malloc(size);
    105    if (!p)
    106 fail("cannot allocate %u bytes", size);
    107    return p;
    108 }
    109 
    110 char *
    111 xstrdup(char *s)
    112 {
    113    if (!s || !s[0])
    114 fail("Null pointer or empty string passed to xstrdup()");
    115    return strcpy((char*)xmalloc(strlen(s) + 1), s);
    116 }
    117 
    118 char *
    119 xbasename(char *path)
    120 {
    121    char *cp;
    122 
    123    if (!path || !path[0])
    124 fail("Null pointer or empty string passed to xbasename()");
    125    while ((cp = strrchr(path, '/')) && cp[1] == '\0')
    126 *cp = '\0';
    127    if (!cp) return path;
    128    return cp + 1;
    129 }
    130 
    131 void
    132 xchdir(char *dir)
    133 {
    134    if (!dir || !dir[0])
    135 fail("Null pointer or empty string passed to xchdir()");
    136    if (chdir(dir) < 0)
    137 fail("cannot change directory to %s", dir);
    138 }
    139 
    140 int
    141 relatepaths(char *from, char *to, char *outpath)
    142 {
    143    char *cp, *cp2;
    144    int len;
    145    char buf[NAME_MAX];
    146 
    147    if (!from || *from != '/')
    148 fail("relatepaths: from path does not start with /");
    149    if (!to || *to != '/')
    150 fail("relatepaths: to   path does not start with /");
    151 
    152    for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++)
    153 if (*cp == '\0')
    154     break;
    155    while (cp[-1] != '/')
    156 cp--, cp2--;
    157    if (cp - 1 == to) {
    158 /* closest common ancestor is /, so use full pathname */
    159 len = strlen(strcpy(outpath, to));
    160 if (outpath[len] != '/') {
    161     outpath[len++] = '/';
    162     outpath[len] = '\0';
    163 }
    164    } else {
    165 len = 0;
    166 while ((cp2 = getcomponent(cp2, buf)) != 0) {
    167     strcpy(outpath + len, "../");
    168     len += 3;
    169 }
    170 while ((cp = getcomponent(cp, buf)) != 0) {
    171     snprintf(outpath + len, PATH_MAX - len, "%s/", buf);
    172     len += strlen(outpath + len);
    173 }
    174    }
    175    return len;
    176 }
    177 
    178 void
    179 reversepath(char *inpath, char *name, int len, char *outpath)
    180 {
    181    char *cp, *cp2;
    182    char buf[NAME_MAX];
    183    struct stat sb;
    184 
    185    cp = strcpy(outpath + PATH_MAX - (len + 1), name);
    186    cp2 = inpath;
    187    while ((cp2 = getcomponent(cp2, buf)) != 0) {
    188 if (strcmp(buf, ".") == 0)
    189     continue;
    190 if (strcmp(buf, "..") == 0) {
    191     if (stat(".", &sb) < 0)
    192 	fail("cannot stat current directory");
    193     name = ino2name(sb.st_ino, "..");
    194     len = strlen(name);
    195     cp -= len + 1;
    196     strcpy(cp, name);
    197     cp[len] = '/';
    198     free(name);
    199     xchdir("..");
    200 } else {
    201     cp -= 3;
    202     memcpy(cp, "../", 3);
    203     xchdir(buf);
    204 }
    205    }
    206    strcpy(outpath, cp);
    207 }
    208 
    209 void
    210 diagnosePath(const char * path)
    211 {
    212    char *	myPath;
    213    char *      slash;
    214    int		rv;
    215    struct stat sb;
    216    char 	buf[BUFSIZ];
    217 
    218    if (!path || !path[0])
    219 fail("Null pointer or empty string passed to mkdirs()");
    220    myPath = strdup(path);
    221    if (!myPath)
    222 fail("strdup() failed!");
    223    do {
    224    	rv = lstat(myPath, &sb);
    225 if (rv < 0) {
    226     perror(myPath);
    227 } else if (S_ISLNK(sb.st_mode)) {
    228     rv = readlink(myPath, buf, sizeof(buf) - 1);
    229     if (rv < 0) {
    230     	perror("readlink");
    231 	buf[0] = 0;
    232     } else {
    233     	buf[rv] = 0;
    234     }
    235     fprintf(stderr, "%s is a link to %s\n", myPath, buf);
    236 } else if (S_ISDIR(sb.st_mode)) {
    237     fprintf(stderr, "%s is a directory\n", myPath);
    238     rv = access(myPath, X_OK);
    239     if (rv < 0) {
    240     	fprintf(stderr, "%s: no search permission\n", myPath);
    241     }
    242 } else {
    243     fprintf(stderr, "%s is a file !?!\n", myPath);
    244     rv = access(myPath, F_OK);
    245     if (rv < 0) {
    246     	fprintf(stderr, "%s does not exist\n", myPath);
    247     }
    248 }
    249 
    250 /* chop path off one level. */
    251 slash = strrchr(myPath, '/');
    252 if (!slash)
    253     slash = strrchr(myPath, '\\');
    254 if (!slash)
    255     slash = myPath;
    256 *slash = 0;
    257    } while (myPath[0]);
    258    free(myPath);
    259 }