security/nss/coreconf/nsinstall/pathsub.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial