1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/config/pathsub.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,215 @@ 1.4 +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 +/* 1.9 +** Pathname subroutines. 1.10 +** 1.11 +** Brendan Eich, 8/29/95 1.12 +*/ 1.13 +#include <assert.h> 1.14 +#include <sys/types.h> 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/stat.h> 1.23 +#include "pathsub.h" 1.24 + 1.25 +#ifdef USE_REENTRANT_LIBC 1.26 +#include <libc_r.h> 1.27 +#endif 1.28 + 1.29 +#ifdef SUNOS4 1.30 +#include "sunos4.h" 1.31 +#endif 1.32 + 1.33 +#ifndef D_INO 1.34 +#define D_INO d_ino 1.35 +#endif 1.36 + 1.37 +char *program; 1.38 + 1.39 +void 1.40 +fail(char *format, ...) 1.41 +{ 1.42 + int error; 1.43 + va_list ap; 1.44 + 1.45 +#ifdef USE_REENTRANT_LIBC 1.46 + R_STRERROR_INIT_R(); 1.47 +#endif 1.48 + 1.49 + error = errno; 1.50 + fprintf(stderr, "%s: ", program); 1.51 + va_start(ap, format); 1.52 + vfprintf(stderr, format, ap); 1.53 + va_end(ap); 1.54 + if (error) { 1.55 + 1.56 +#ifdef USE_REENTRANT_LIBC 1.57 + R_STRERROR_R(errno); 1.58 + fprintf(stderr, ": %s", r_strerror_r); 1.59 +#else 1.60 + fprintf(stderr, ": %s", strerror(errno)); 1.61 +#endif 1.62 + } 1.63 + 1.64 + putc('\n', stderr); 1.65 + exit(1); 1.66 +} 1.67 + 1.68 +char * 1.69 +getcomponent(char *path, char *name) 1.70 +{ 1.71 + if (*path == '\0') 1.72 + return 0; 1.73 + if (*path == '/') { 1.74 + *name++ = '/'; 1.75 + } else { 1.76 + do { 1.77 + *name++ = *path++; 1.78 + } while (*path != '/' && *path != '\0'); 1.79 + } 1.80 + *name = '\0'; 1.81 + while (*path == '/') 1.82 + path++; 1.83 + return path; 1.84 +} 1.85 + 1.86 +#ifdef LAME_READDIR 1.87 +#include <sys/param.h> 1.88 +/* 1.89 +** The static buffer in Unixware's readdir is too small. 1.90 +*/ 1.91 +struct dirent *readdir(DIR *d) 1.92 +{ 1.93 + static struct dirent *buf = NULL; 1.94 + 1.95 + if(buf == NULL) 1.96 + buf = (struct dirent *) malloc(sizeof(struct dirent) + MAXPATHLEN); 1.97 + return(readdir_r(d, buf)); 1.98 +} 1.99 +#endif 1.100 + 1.101 +char * 1.102 +ino2name(ino_t ino) 1.103 +{ 1.104 + DIR *dp; 1.105 + struct dirent *ep; 1.106 + char *name; 1.107 + 1.108 + dp = opendir(".."); 1.109 + if (!dp) 1.110 + fail("cannot read parent directory"); 1.111 + for (;;) { 1.112 + if (!(ep = readdir(dp))) 1.113 + fail("cannot find current directory"); 1.114 + if (ep->D_INO == ino) 1.115 + break; 1.116 + } 1.117 + name = xstrdup(ep->d_name); 1.118 + closedir(dp); 1.119 + return name; 1.120 +} 1.121 + 1.122 +void * 1.123 +xmalloc(size_t size) 1.124 +{ 1.125 + void *p = malloc(size); 1.126 + if (!p) 1.127 + fail("cannot allocate %u bytes", size); 1.128 + return p; 1.129 +} 1.130 + 1.131 +char * 1.132 +xstrdup(char *s) 1.133 +{ 1.134 + return strcpy(xmalloc(strlen(s) + 1), s); 1.135 +} 1.136 + 1.137 +char * 1.138 +xbasename(char *path) 1.139 +{ 1.140 + char *cp; 1.141 + 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 (chdir(dir) < 0) 1.152 + fail("cannot change directory to %s", dir); 1.153 +} 1.154 + 1.155 +int 1.156 +relatepaths(char *from, char *to, char *outpath) 1.157 +{ 1.158 + char *cp, *cp2; 1.159 + int len; 1.160 + char buf[NAME_MAX]; 1.161 + 1.162 + assert(*from == '/' && *to == '/'); 1.163 + for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++) 1.164 + if (*cp == '\0') 1.165 + break; 1.166 + while (cp[-1] != '/') 1.167 + cp--, cp2--; 1.168 + if (cp - 1 == to) { 1.169 + /* closest common ancestor is /, so use full pathname */ 1.170 + len = strlen(strcpy(outpath, to)); 1.171 + if (outpath[len] != '/') { 1.172 + outpath[len++] = '/'; 1.173 + outpath[len] = '\0'; 1.174 + } 1.175 + } else { 1.176 + len = 0; 1.177 + while ((cp2 = getcomponent(cp2, buf)) != 0) { 1.178 + strcpy(outpath + len, "../"); 1.179 + len += 3; 1.180 + } 1.181 + while ((cp = getcomponent(cp, buf)) != 0) { 1.182 + sprintf(outpath + len, "%s/", buf); 1.183 + len += strlen(outpath + len); 1.184 + } 1.185 + } 1.186 + return len; 1.187 +} 1.188 + 1.189 +void 1.190 +reversepath(char *inpath, char *name, int len, char *outpath) 1.191 +{ 1.192 + char *cp, *cp2; 1.193 + char buf[NAME_MAX]; 1.194 + struct stat sb; 1.195 + 1.196 + cp = strcpy(outpath + PATH_MAX - (len + 1), name); 1.197 + cp2 = inpath; 1.198 + while ((cp2 = getcomponent(cp2, buf)) != 0) { 1.199 + if (strcmp(buf, ".") == 0) 1.200 + continue; 1.201 + if (strcmp(buf, "..") == 0) { 1.202 + if (stat(".", &sb) < 0) 1.203 + fail("cannot stat current directory"); 1.204 + name = ino2name(sb.st_ino); 1.205 + len = strlen(name); 1.206 + cp -= len + 1; 1.207 + strcpy(cp, name); 1.208 + cp[len] = '/'; 1.209 + free(name); 1.210 + xchdir(".."); 1.211 + } else { 1.212 + cp -= 3; 1.213 + strncpy(cp, "../", 3); 1.214 + xchdir(buf); 1.215 + } 1.216 + } 1.217 + strcpy(outpath, cp); 1.218 +}