config/pathsub.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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"
    22 #ifdef USE_REENTRANT_LIBC
    23 #include <libc_r.h>
    24 #endif
    26 #ifdef SUNOS4
    27 #include "sunos4.h"
    28 #endif
    30 #ifndef D_INO
    31 #define D_INO	d_ino
    32 #endif
    34 char *program;
    36 void
    37 fail(char *format, ...)
    38 {
    39     int error;
    40     va_list ap;
    42 #ifdef USE_REENTRANT_LIBC
    43     R_STRERROR_INIT_R();
    44 #endif
    46     error = errno;
    47     fprintf(stderr, "%s: ", program);
    48     va_start(ap, format);
    49     vfprintf(stderr, format, ap);
    50     va_end(ap);
    51     if (error) {
    53 #ifdef USE_REENTRANT_LIBC
    54     R_STRERROR_R(errno);
    55 	fprintf(stderr, ": %s", r_strerror_r);
    56 #else
    57 	fprintf(stderr, ": %s", strerror(errno));
    58 #endif
    59     }
    61     putc('\n', stderr);
    62     exit(1);
    63 }
    65 char *
    66 getcomponent(char *path, char *name)
    67 {
    68     if (*path == '\0')
    69 	return 0;
    70     if (*path == '/') {
    71 	*name++ = '/';
    72     } else {
    73 	do {
    74 	    *name++ = *path++;
    75 	} while (*path != '/' && *path != '\0');
    76     }
    77     *name = '\0';
    78     while (*path == '/')
    79 	path++;
    80     return path;
    81 }
    83 #ifdef LAME_READDIR
    84 #include <sys/param.h>
    85 /*
    86 ** The static buffer in Unixware's readdir is too small.
    87 */
    88 struct dirent *readdir(DIR *d)
    89 {
    90         static struct dirent *buf = NULL;
    92         if(buf == NULL)
    93                 buf = (struct dirent *) malloc(sizeof(struct dirent) + MAXPATHLEN);
    94         return(readdir_r(d, buf));
    95 }
    96 #endif
    98 char *
    99 ino2name(ino_t ino)
   100 {
   101     DIR *dp;
   102     struct dirent *ep;
   103     char *name;
   105     dp = opendir("..");
   106     if (!dp)
   107 	fail("cannot read parent directory");
   108     for (;;) {
   109 	if (!(ep = readdir(dp)))
   110 	    fail("cannot find current directory");
   111 	if (ep->D_INO == ino)
   112 	    break;
   113     }
   114     name = xstrdup(ep->d_name);
   115     closedir(dp);
   116     return name;
   117 }
   119 void *
   120 xmalloc(size_t size)
   121 {
   122     void *p = malloc(size);
   123     if (!p)
   124 	fail("cannot allocate %u bytes", size);
   125     return p;
   126 }
   128 char *
   129 xstrdup(char *s)
   130 {
   131     return strcpy(xmalloc(strlen(s) + 1), s);
   132 }
   134 char *
   135 xbasename(char *path)
   136 {
   137     char *cp;
   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 (chdir(dir) < 0)
   149 	fail("cannot change directory to %s", dir);
   150 }
   152 int
   153 relatepaths(char *from, char *to, char *outpath)
   154 {
   155     char *cp, *cp2;
   156     int len;
   157     char buf[NAME_MAX];
   159     assert(*from == '/' && *to == '/');
   160     for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++)
   161 	if (*cp == '\0')
   162 	    break;
   163     while (cp[-1] != '/')
   164 	cp--, cp2--;
   165     if (cp - 1 == to) {
   166 	/* closest common ancestor is /, so use full pathname */
   167 	len = strlen(strcpy(outpath, to));
   168 	if (outpath[len] != '/') {
   169 	    outpath[len++] = '/';
   170 	    outpath[len] = '\0';
   171 	}
   172     } else {
   173 	len = 0;
   174 	while ((cp2 = getcomponent(cp2, buf)) != 0) {
   175 	    strcpy(outpath + len, "../");
   176 	    len += 3;
   177 	}
   178 	while ((cp = getcomponent(cp, buf)) != 0) {
   179 	    sprintf(outpath + len, "%s/", buf);
   180 	    len += strlen(outpath + len);
   181 	}
   182     }
   183     return len;
   184 }
   186 void
   187 reversepath(char *inpath, char *name, int len, char *outpath)
   188 {
   189     char *cp, *cp2;
   190     char buf[NAME_MAX];
   191     struct stat sb;
   193     cp = strcpy(outpath + PATH_MAX - (len + 1), name);
   194     cp2 = inpath;
   195     while ((cp2 = getcomponent(cp2, buf)) != 0) {
   196 	if (strcmp(buf, ".") == 0)
   197 	    continue;
   198 	if (strcmp(buf, "..") == 0) {
   199 	    if (stat(".", &sb) < 0)
   200 		fail("cannot stat current directory");
   201 	    name = ino2name(sb.st_ino);
   202 	    len = strlen(name);
   203 	    cp -= len + 1;
   204 	    strcpy(cp, name);
   205 	    cp[len] = '/';
   206 	    free(name);
   207 	    xchdir("..");
   208 	} else {
   209 	    cp -= 3;
   210 	    strncpy(cp, "../", 3);
   211 	    xchdir(buf);
   212 	}
   213     }
   214     strcpy(outpath, cp);
   215 }

mercurial