Import from 1.9a8 tarball
[mozilla-nss.git] / security / coreconf / nsinstall / pathsub.c
blobd8ac93e61afd1664c8339da894bdfcc948617db5
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
38 ** Pathname subroutines.
40 #include <assert.h>
41 #if defined(FREEBSD) || defined(BSDI) || defined(DARWIN)
42 #include <sys/types.h>
43 #endif /* FREEBSD */
44 #include <dirent.h>
45 #include <errno.h>
46 #include <stdarg.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <unistd.h>
51 #include <sys/types.h>
52 #include <sys/stat.h>
53 #include "pathsub.h"
54 #ifdef USE_REENTRANT_LIBC
55 #include "libc_r.h"
56 #endif /* USE_REENTRANT_LIBC */
58 char *program;
60 void
61 fail(char *format, ...)
63 int error;
64 va_list ap;
66 #ifdef USE_REENTRANT_LIBC
67 R_STRERROR_INIT_R();
68 #endif
70 error = errno;
71 fprintf(stderr, "%s: ", program);
72 va_start(ap, format);
73 vfprintf(stderr, format, ap);
74 va_end(ap);
75 if (error) {
77 #ifdef USE_REENTRANT_LIBC
78 R_STRERROR_R(errno);
79 fprintf(stderr, ": %s", r_strerror_r);
80 #else
81 fprintf(stderr, ": %s", strerror(errno));
82 #endif
85 putc('\n', stderr);
86 abort();
87 exit(1);
90 char *
91 getcomponent(char *path, char *name)
93 if (*path == '\0')
94 return 0;
95 if (*path == '/') {
96 *name++ = '/';
97 } else {
98 do {
99 *name++ = *path++;
100 } while (*path != '/' && *path != '\0');
102 *name = '\0';
103 while (*path == '/')
104 path++;
105 return path;
108 #ifdef UNIXWARE
109 /* The static buffer in Unixware's readdir is too small. */
110 struct dirent * readdir(DIR *d)
112 static struct dirent *buf = NULL;
113 #define MAX_PATH_LEN 1024
115 if (buf == NULL)
116 buf = (struct dirent *)xmalloc(sizeof(struct dirent) + MAX_PATH_LEN) ;
117 return readdir_r(d, buf);
119 #endif
121 /* APPARENT BUG - ignores argument "dir", uses ".." instead. */
122 char *
123 ino2name(ino_t ino, char *dir)
125 DIR *dp;
126 struct dirent *ep;
127 char *name;
129 dp = opendir(".."); /* XXX */
130 if (!dp)
131 fail("cannot read parent directory");
132 for (;;) {
133 if (!(ep = readdir(dp)))
134 fail("cannot find current directory");
135 if (ep->d_ino == ino)
136 break;
138 name = xstrdup(ep->d_name);
139 closedir(dp);
140 return name;
143 void *
144 xmalloc(size_t size)
146 void *p;
148 if (size <= 0)
149 fail("attempted to allocate %u bytes", size);
150 p = malloc(size);
151 if (!p)
152 fail("cannot allocate %u bytes", size);
153 return p;
156 char *
157 xstrdup(char *s)
159 if (!s || !s[0])
160 fail("Null pointer or empty string passed to xstrdup()");
161 return strcpy((char*)xmalloc(strlen(s) + 1), s);
164 char *
165 xbasename(char *path)
167 char *cp;
169 if (!path || !path[0])
170 fail("Null pointer or empty string passed to xbasename()");
171 while ((cp = strrchr(path, '/')) && cp[1] == '\0')
172 *cp = '\0';
173 if (!cp) return path;
174 return cp + 1;
177 void
178 xchdir(char *dir)
180 if (!dir || !dir[0])
181 fail("Null pointer or empty string passed to xchdir()");
182 if (chdir(dir) < 0)
183 fail("cannot change directory to %s", dir);
187 relatepaths(char *from, char *to, char *outpath)
189 char *cp, *cp2;
190 int len;
191 char buf[NAME_MAX];
193 assert(*from == '/' && *to == '/');
194 if (!from || *from != '/')
195 fail("relatepaths: from path does not start with /");
196 if (!to || *to != '/')
197 fail("relatepaths: to path does not start with /");
199 for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++)
200 if (*cp == '\0')
201 break;
202 while (cp[-1] != '/')
203 cp--, cp2--;
204 if (cp - 1 == to) {
205 /* closest common ancestor is /, so use full pathname */
206 len = strlen(strcpy(outpath, to));
207 if (outpath[len] != '/') {
208 outpath[len++] = '/';
209 outpath[len] = '\0';
211 } else {
212 len = 0;
213 while ((cp2 = getcomponent(cp2, buf)) != 0) {
214 strcpy(outpath + len, "../");
215 len += 3;
217 while ((cp = getcomponent(cp, buf)) != 0) {
218 sprintf(outpath + len, "%s/", buf);
219 len += strlen(outpath + len);
222 return len;
225 void
226 reversepath(char *inpath, char *name, int len, char *outpath)
228 char *cp, *cp2;
229 char buf[NAME_MAX];
230 struct stat sb;
232 cp = strcpy(outpath + PATH_MAX - (len + 1), name);
233 cp2 = inpath;
234 while ((cp2 = getcomponent(cp2, buf)) != 0) {
235 if (strcmp(buf, ".") == 0)
236 continue;
237 if (strcmp(buf, "..") == 0) {
238 if (stat(".", &sb) < 0)
239 fail("cannot stat current directory");
240 name = ino2name(sb.st_ino, "..");
241 len = strlen(name);
242 cp -= len + 1;
243 strcpy(cp, name);
244 cp[len] = '/';
245 free(name);
246 xchdir("..");
247 } else {
248 cp -= 3;
249 strncpy(cp, "../", 3);
250 xchdir(buf);
253 strcpy(outpath, cp);
256 void
257 diagnosePath(const char * path)
259 char * myPath;
260 char * slash;
261 int rv;
262 struct stat sb;
263 char buf[BUFSIZ];
265 if (!path || !path[0])
266 fail("Null pointer or empty string passed to mkdirs()");
267 myPath = strdup(path);
268 if (!myPath)
269 fail("strdup() failed!");
270 do {
271 rv = lstat(myPath, &sb);
272 if (rv < 0) {
273 perror(myPath);
274 } else if (S_ISLNK(sb.st_mode)) {
275 rv = readlink(myPath, buf, sizeof buf);
276 if (rv < 0) {
277 perror("readlink");
278 buf[0] = 0;
279 } else {
280 buf[rv] = 0;
282 fprintf(stderr, "%s is a link to %s\n", myPath, buf);
283 } else if (S_ISDIR(sb.st_mode)) {
284 fprintf(stderr, "%s is a directory\n", myPath);
285 rv = access(myPath, X_OK);
286 if (rv < 0) {
287 fprintf(stderr, "%s: no search permission\n", myPath);
289 } else {
290 fprintf(stderr, "%s is a file !?!\n", myPath);
291 rv = access(myPath, F_OK);
292 if (rv < 0) {
293 fprintf(stderr, "%s does not exist\n", myPath);
297 /* chop path off one level. */
298 slash = strrchr(myPath, '/');
299 if (!slash)
300 slash = strrchr(myPath, '\\');
301 if (!slash)
302 slash = myPath;
303 *slash = 0;
304 } while (myPath[0]);
305 free(myPath);