1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/coreconf/nsinstall/pathsub.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,274 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 +** Pathname subroutines. 1.10 +*/ 1.11 +#include <assert.h> 1.12 +#if defined(FREEBSD) || defined(BSDI) || defined(DARWIN) 1.13 +#include <sys/types.h> 1.14 +#endif /* FREEBSD */ 1.15 +#include <dirent.h> 1.16 +#include <errno.h> 1.17 +#include <stdarg.h> 1.18 +#include <stdio.h> 1.19 +#include <stdlib.h> 1.20 +#include <string.h> 1.21 +#include <unistd.h> 1.22 +#include <sys/types.h> 1.23 +#include <sys/stat.h> 1.24 +#include "pathsub.h" 1.25 +#ifdef USE_REENTRANT_LIBC 1.26 +#include "libc_r.h" 1.27 +#endif /* USE_REENTRANT_LIBC */ 1.28 + 1.29 +char *program; 1.30 + 1.31 +void 1.32 +fail(char *format, ...) 1.33 +{ 1.34 + int error; 1.35 + va_list ap; 1.36 + 1.37 +#ifdef USE_REENTRANT_LIBC 1.38 + R_STRERROR_INIT_R(); 1.39 +#endif 1.40 + 1.41 + error = errno; 1.42 + fprintf(stderr, "%s: ", program); 1.43 + va_start(ap, format); 1.44 + vfprintf(stderr, format, ap); 1.45 + va_end(ap); 1.46 + if (error) { 1.47 + 1.48 +#ifdef USE_REENTRANT_LIBC 1.49 + R_STRERROR_R(errno); 1.50 + fprintf(stderr, ": %s", r_strerror_r); 1.51 +#else 1.52 + fprintf(stderr, ": %s", strerror(errno)); 1.53 +#endif 1.54 + } 1.55 + 1.56 + putc('\n', stderr); 1.57 + abort(); 1.58 + exit(1); 1.59 +} 1.60 + 1.61 +char * 1.62 +getcomponent(char *path, char *name) 1.63 +{ 1.64 + if (*path == '\0') 1.65 + return 0; 1.66 + if (*path == '/') { 1.67 + *name++ = '/'; 1.68 + } else { 1.69 + do { 1.70 + *name++ = *path++; 1.71 + } while (*path != '/' && *path != '\0'); 1.72 + } 1.73 + *name = '\0'; 1.74 + while (*path == '/') 1.75 + path++; 1.76 + return path; 1.77 +} 1.78 + 1.79 +#ifdef UNIXWARE 1.80 +/* The static buffer in Unixware's readdir is too small. */ 1.81 +struct dirent * readdir(DIR *d) 1.82 +{ 1.83 + static struct dirent *buf = NULL; 1.84 +#define MAX_PATH_LEN 1024 1.85 + 1.86 + if (buf == NULL) 1.87 + buf = (struct dirent *)xmalloc(sizeof(struct dirent) + MAX_PATH_LEN) ; 1.88 + return readdir_r(d, buf); 1.89 +} 1.90 +#endif 1.91 + 1.92 +/* APPARENT BUG - ignores argument "dir", uses ".." instead. */ 1.93 +char * 1.94 +ino2name(ino_t ino, char *dir) 1.95 +{ 1.96 + DIR *dp; 1.97 + struct dirent *ep; 1.98 + char *name; 1.99 + 1.100 + dp = opendir(".."); /* XXX */ 1.101 + if (!dp) 1.102 + fail("cannot read parent directory"); 1.103 + for (;;) { 1.104 + if (!(ep = readdir(dp))) 1.105 + fail("cannot find current directory"); 1.106 + if (ep->d_ino == ino) 1.107 + break; 1.108 + } 1.109 + name = xstrdup(ep->d_name); 1.110 + closedir(dp); 1.111 + return name; 1.112 +} 1.113 + 1.114 +void * 1.115 +xmalloc(size_t size) 1.116 +{ 1.117 + void *p; 1.118 + 1.119 + if (size <= 0) 1.120 + fail("attempted to allocate %u bytes", size); 1.121 + p = malloc(size); 1.122 + if (!p) 1.123 + fail("cannot allocate %u bytes", size); 1.124 + return p; 1.125 +} 1.126 + 1.127 +char * 1.128 +xstrdup(char *s) 1.129 +{ 1.130 + if (!s || !s[0]) 1.131 + fail("Null pointer or empty string passed to xstrdup()"); 1.132 + return strcpy((char*)xmalloc(strlen(s) + 1), s); 1.133 +} 1.134 + 1.135 +char * 1.136 +xbasename(char *path) 1.137 +{ 1.138 + char *cp; 1.139 + 1.140 + if (!path || !path[0]) 1.141 + fail("Null pointer or empty string passed to xbasename()"); 1.142 + while ((cp = strrchr(path, '/')) && cp[1] == '\0') 1.143 + *cp = '\0'; 1.144 + if (!cp) return path; 1.145 + return cp + 1; 1.146 +} 1.147 + 1.148 +void 1.149 +xchdir(char *dir) 1.150 +{ 1.151 + if (!dir || !dir[0]) 1.152 + fail("Null pointer or empty string passed to xchdir()"); 1.153 + if (chdir(dir) < 0) 1.154 + fail("cannot change directory to %s", dir); 1.155 +} 1.156 + 1.157 +int 1.158 +relatepaths(char *from, char *to, char *outpath) 1.159 +{ 1.160 + char *cp, *cp2; 1.161 + int len; 1.162 + char buf[NAME_MAX]; 1.163 + 1.164 + assert(*from == '/' && *to == '/'); 1.165 + if (!from || *from != '/') 1.166 + fail("relatepaths: from path does not start with /"); 1.167 + if (!to || *to != '/') 1.168 + fail("relatepaths: to path does not start with /"); 1.169 + 1.170 + for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++) 1.171 + if (*cp == '\0') 1.172 + break; 1.173 + while (cp[-1] != '/') 1.174 + cp--, cp2--; 1.175 + if (cp - 1 == to) { 1.176 + /* closest common ancestor is /, so use full pathname */ 1.177 + len = strlen(strcpy(outpath, to)); 1.178 + if (outpath[len] != '/') { 1.179 + outpath[len++] = '/'; 1.180 + outpath[len] = '\0'; 1.181 + } 1.182 + } else { 1.183 + len = 0; 1.184 + while ((cp2 = getcomponent(cp2, buf)) != 0) { 1.185 + strcpy(outpath + len, "../"); 1.186 + len += 3; 1.187 + } 1.188 + while ((cp = getcomponent(cp, buf)) != 0) { 1.189 + sprintf(outpath + len, "%s/", buf); 1.190 + len += strlen(outpath + len); 1.191 + } 1.192 + } 1.193 + return len; 1.194 +} 1.195 + 1.196 +void 1.197 +reversepath(char *inpath, char *name, int len, char *outpath) 1.198 +{ 1.199 + char *cp, *cp2; 1.200 + char buf[NAME_MAX]; 1.201 + struct stat sb; 1.202 + 1.203 + cp = strcpy(outpath + PATH_MAX - (len + 1), name); 1.204 + cp2 = inpath; 1.205 + while ((cp2 = getcomponent(cp2, buf)) != 0) { 1.206 + if (strcmp(buf, ".") == 0) 1.207 + continue; 1.208 + if (strcmp(buf, "..") == 0) { 1.209 + if (stat(".", &sb) < 0) 1.210 + fail("cannot stat current directory"); 1.211 + name = ino2name(sb.st_ino, ".."); 1.212 + len = strlen(name); 1.213 + cp -= len + 1; 1.214 + strcpy(cp, name); 1.215 + cp[len] = '/'; 1.216 + free(name); 1.217 + xchdir(".."); 1.218 + } else { 1.219 + cp -= 3; 1.220 + strncpy(cp, "../", 3); 1.221 + xchdir(buf); 1.222 + } 1.223 + } 1.224 + strcpy(outpath, cp); 1.225 +} 1.226 + 1.227 +void 1.228 +diagnosePath(const char * path) 1.229 +{ 1.230 + char * myPath; 1.231 + char * slash; 1.232 + int rv; 1.233 + struct stat sb; 1.234 + char buf[BUFSIZ]; 1.235 + 1.236 + if (!path || !path[0]) 1.237 + fail("Null pointer or empty string passed to mkdirs()"); 1.238 + myPath = strdup(path); 1.239 + if (!myPath) 1.240 + fail("strdup() failed!"); 1.241 + do { 1.242 + rv = lstat(myPath, &sb); 1.243 + if (rv < 0) { 1.244 + perror(myPath); 1.245 + } else if (S_ISLNK(sb.st_mode)) { 1.246 + rv = readlink(myPath, buf, sizeof(buf) - 1); 1.247 + if (rv < 0) { 1.248 + perror("readlink"); 1.249 + buf[0] = 0; 1.250 + } else { 1.251 + buf[rv] = 0; 1.252 + } 1.253 + fprintf(stderr, "%s is a link to %s\n", myPath, buf); 1.254 + } else if (S_ISDIR(sb.st_mode)) { 1.255 + fprintf(stderr, "%s is a directory\n", myPath); 1.256 + rv = access(myPath, X_OK); 1.257 + if (rv < 0) { 1.258 + fprintf(stderr, "%s: no search permission\n", myPath); 1.259 + } 1.260 + } else { 1.261 + fprintf(stderr, "%s is a file !?!\n", myPath); 1.262 + rv = access(myPath, F_OK); 1.263 + if (rv < 0) { 1.264 + fprintf(stderr, "%s does not exist\n", myPath); 1.265 + } 1.266 + } 1.267 + 1.268 + /* chop path off one level. */ 1.269 + slash = strrchr(myPath, '/'); 1.270 + if (!slash) 1.271 + slash = strrchr(myPath, '\\'); 1.272 + if (!slash) 1.273 + slash = myPath; 1.274 + *slash = 0; 1.275 + } while (myPath[0]); 1.276 + free(myPath); 1.277 +}