tor-browser

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

pathsub.c (3917B)


      1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 /*
      6 ** Pathname subroutines.
      7 **
      8 ** Brendan Eich, 8/29/95
      9 */
     10 #include <assert.h>
     11 #include <sys/types.h>
     12 #include <dirent.h>
     13 #include <errno.h>
     14 #include <stdarg.h>
     15 #include <stdio.h>
     16 #include <stdlib.h>
     17 #include <string.h>
     18 #include <unistd.h>
     19 #include <sys/stat.h>
     20 #include "pathsub.h"
     21 
     22 #ifdef USE_REENTRANT_LIBC
     23 #  include <libc_r.h>
     24 #endif
     25 
     26 #ifdef SUNOS4
     27 #  include "sunos4.h"
     28 #endif
     29 
     30 char* program;
     31 
     32 void fail(const char* format, ...) {
     33  int error;
     34  va_list ap;
     35 
     36 #ifdef USE_REENTRANT_LIBC
     37  R_STRERROR_INIT_R();
     38 #endif
     39 
     40  error = errno;
     41  fprintf(stderr, "%s: ", program);
     42  va_start(ap, format);
     43  vfprintf(stderr, format, ap);
     44  va_end(ap);
     45  if (error) {
     46 #ifdef USE_REENTRANT_LIBC
     47    R_STRERROR_R(errno);
     48    fprintf(stderr, ": %s", r_strerror_r);
     49 #else
     50    fprintf(stderr, ": %s", strerror(errno));
     51 #endif
     52  }
     53 
     54  putc('\n', stderr);
     55  exit(1);
     56 }
     57 
     58 char* getcomponent(char* path, char* name) {
     59  if (*path == '\0') return 0;
     60  if (*path == '/') {
     61    *name++ = '/';
     62  } else {
     63    do {
     64      *name++ = *path++;
     65    } while (*path != '/' && *path != '\0');
     66  }
     67  *name = '\0';
     68  while (*path == '/') path++;
     69  return path;
     70 }
     71 
     72 #ifdef LAME_READDIR
     73 #  include <sys/param.h>
     74 /*
     75 ** The static buffer in Unixware's readdir is too small.
     76 */
     77 struct dirent* readdir(DIR* d) {
     78  static struct dirent* buf = NULL;
     79 
     80  if (buf == NULL)
     81    buf = (struct dirent*)malloc(sizeof(struct dirent) + MAXPATHLEN);
     82  return (readdir_r(d, buf));
     83 }
     84 #endif
     85 
     86 char* ino2name(ino_t ino) {
     87  DIR* dp;
     88  struct dirent* ep;
     89  char* name;
     90 
     91  dp = opendir("..");
     92  if (!dp) fail("cannot read parent directory");
     93  for (;;) {
     94    if (!(ep = readdir(dp))) fail("cannot find current directory");
     95    if (ep->d_ino == ino) break;
     96  }
     97  name = xstrdup(ep->d_name);
     98  closedir(dp);
     99  return name;
    100 }
    101 
    102 void* xmalloc(size_t size) {
    103  void* p = malloc(size);
    104  if (!p) fail("cannot allocate %u bytes", size);
    105  return p;
    106 }
    107 
    108 char* xstrdup(char* s) { return strcpy(xmalloc(strlen(s) + 1), s); }
    109 
    110 char* xbasename(char* path) {
    111  char* cp;
    112 
    113  while ((cp = strrchr(path, '/')) && cp[1] == '\0') *cp = '\0';
    114  if (!cp) return path;
    115  return cp + 1;
    116 }
    117 
    118 void xchdir(const char* dir) {
    119  if (chdir(dir) < 0) fail("cannot change directory to %s", dir);
    120 }
    121 
    122 int relatepaths(char* from, char* to, char* outpath) {
    123  char *cp, *cp2;
    124  int len;
    125  char buf[NAME_MAX];
    126 
    127  assert(*from == '/' && *to == '/');
    128  for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++)
    129    if (*cp == '\0') break;
    130  while (cp[-1] != '/') cp--, cp2--;
    131  if (cp - 1 == to) {
    132    /* closest common ancestor is /, so use full pathname */
    133    len = strlen(strcpy(outpath, to));
    134    if (outpath[len] != '/') {
    135      outpath[len++] = '/';
    136      outpath[len] = '\0';
    137    }
    138  } else {
    139    len = 0;
    140    while ((cp2 = getcomponent(cp2, buf)) != 0) {
    141      strcpy(outpath + len, "../");
    142      len += 3;
    143    }
    144    while ((cp = getcomponent(cp, buf)) != 0) {
    145      sprintf(outpath + len, "%s/", buf);
    146      len += strlen(outpath + len);
    147    }
    148  }
    149  return len;
    150 }
    151 
    152 void reversepath(char* inpath, char* name, int len, char* outpath) {
    153  char *cp, *cp2;
    154  char buf[NAME_MAX];
    155  struct stat sb;
    156 
    157  cp = strcpy(outpath + PATH_MAX - (len + 1), name);
    158  cp2 = inpath;
    159  while ((cp2 = getcomponent(cp2, buf)) != 0) {
    160    if (strcmp(buf, ".") == 0) continue;
    161    if (strcmp(buf, "..") == 0) {
    162      if (stat(".", &sb) < 0) fail("cannot stat current directory");
    163      name = ino2name(sb.st_ino);
    164      len = strlen(name);
    165      cp -= len + 1;
    166      strcpy(cp, name);
    167      cp[len] = '/';
    168      free(name);
    169      xchdir("..");
    170    } else {
    171      cp -= 3;
    172      strncpy(cp, "../", 3);
    173      xchdir(buf);
    174    }
    175  }
    176  strcpy(outpath, cp);
    177 }