1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
---|
2 | /* ***** BEGIN LICENSE BLOCK ***** |
---|
3 | * Version: NPL 1.1/GPL 2.0/LGPL 2.1 |
---|
4 | * |
---|
5 | * The contents of this file are subject to the Netscape Public License |
---|
6 | * Version 1.1 (the "License"); you may not use this file except in |
---|
7 | * compliance with the License. You may obtain a copy of the License at |
---|
8 | * http://www.mozilla.org/NPL/ |
---|
9 | * |
---|
10 | * Software distributed under the License is distributed on an "AS IS" basis, |
---|
11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
---|
12 | * for the specific language governing rights and limitations under the |
---|
13 | * License. |
---|
14 | * |
---|
15 | * The Original Code is mozilla.org code. |
---|
16 | * |
---|
17 | * The Initial Developer of the Original Code is |
---|
18 | * Netscape Communications Corporation. |
---|
19 | * Portions created by the Initial Developer are Copyright (C) 1998 |
---|
20 | * the Initial Developer. All Rights Reserved. |
---|
21 | * |
---|
22 | * Contributor(s): |
---|
23 | * |
---|
24 | * |
---|
25 | * Alternatively, the contents of this file may be used under the terms of |
---|
26 | * either the GNU General Public License Version 2 or later (the "GPL"), or |
---|
27 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
---|
28 | * in which case the provisions of the GPL or the LGPL are applicable instead |
---|
29 | * of those above. If you wish to allow use of your version of this file only |
---|
30 | * under the terms of either the GPL or the LGPL, and not to allow others to |
---|
31 | * use your version of this file under the terms of the NPL, indicate your |
---|
32 | * decision by deleting the provisions above and replace them with the notice |
---|
33 | * and other provisions required by the GPL or the LGPL. If you do not delete |
---|
34 | * the provisions above, a recipient may use your version of this file under |
---|
35 | * the terms of any one of the NPL, the GPL or the LGPL. |
---|
36 | * |
---|
37 | * ***** END LICENSE BLOCK ***** */ |
---|
38 | /* |
---|
39 | ** Pathname subroutines. |
---|
40 | ** |
---|
41 | ** Brendan Eich, 8/29/95 |
---|
42 | */ |
---|
43 | #include <assert.h> |
---|
44 | #include <sys/types.h> |
---|
45 | #include <dirent.h> |
---|
46 | #include <errno.h> |
---|
47 | #include <stdarg.h> |
---|
48 | #include <stdio.h> |
---|
49 | #include <stdlib.h> |
---|
50 | #include <string.h> |
---|
51 | #include <unistd.h> |
---|
52 | #include <sys/stat.h> |
---|
53 | #include "pathsub.h" |
---|
54 | |
---|
55 | #ifdef USE_REENTRANT_LIBC |
---|
56 | #include <libc_r.h> |
---|
57 | #endif |
---|
58 | |
---|
59 | #ifdef SUNOS4 |
---|
60 | #include "sunos4.h" |
---|
61 | #endif |
---|
62 | |
---|
63 | #ifndef D_INO |
---|
64 | #define D_INO d_ino |
---|
65 | #endif |
---|
66 | |
---|
67 | char *program; |
---|
68 | |
---|
69 | void |
---|
70 | fail(char *format, ...) |
---|
71 | { |
---|
72 | int error; |
---|
73 | va_list ap; |
---|
74 | |
---|
75 | #ifdef USE_REENTRANT_LIBC |
---|
76 | R_STRERROR_INIT_R(); |
---|
77 | #endif |
---|
78 | |
---|
79 | error = errno; |
---|
80 | fprintf(stderr, "%s: ", program); |
---|
81 | va_start(ap, format); |
---|
82 | vfprintf(stderr, format, ap); |
---|
83 | va_end(ap); |
---|
84 | if (error) { |
---|
85 | |
---|
86 | #ifdef USE_REENTRANT_LIBC |
---|
87 | R_STRERROR_R(errno); |
---|
88 | fprintf(stderr, ": %s", r_strerror_r); |
---|
89 | #else |
---|
90 | fprintf(stderr, ": %s", strerror(errno)); |
---|
91 | #endif |
---|
92 | } |
---|
93 | |
---|
94 | putc('\n', stderr); |
---|
95 | exit(1); |
---|
96 | } |
---|
97 | |
---|
98 | char * |
---|
99 | getcomponent(char *path, char *name) |
---|
100 | { |
---|
101 | if (*path == '\0') |
---|
102 | return 0; |
---|
103 | if (*path == '/') { |
---|
104 | *name++ = '/'; |
---|
105 | } else { |
---|
106 | do { |
---|
107 | *name++ = *path++; |
---|
108 | } while (*path != '/' && *path != '\0'); |
---|
109 | } |
---|
110 | *name = '\0'; |
---|
111 | while (*path == '/') |
---|
112 | path++; |
---|
113 | return path; |
---|
114 | } |
---|
115 | |
---|
116 | #ifdef LAME_READDIR |
---|
117 | #include <sys/param.h> |
---|
118 | /* |
---|
119 | ** The static buffer in Unixware's readdir is too small. |
---|
120 | */ |
---|
121 | struct dirent *readdir(DIR *d) |
---|
122 | { |
---|
123 | static struct dirent *buf = NULL; |
---|
124 | |
---|
125 | if(buf == NULL) |
---|
126 | buf = (struct dirent *) malloc(sizeof(struct dirent) + MAXPATHLEN); |
---|
127 | return(readdir_r(d, buf)); |
---|
128 | } |
---|
129 | #endif |
---|
130 | |
---|
131 | char * |
---|
132 | ino2name(ino_t ino, char *dir) |
---|
133 | { |
---|
134 | DIR *dp; |
---|
135 | struct dirent *ep; |
---|
136 | char *name; |
---|
137 | |
---|
138 | dp = opendir(".."); |
---|
139 | if (!dp) |
---|
140 | fail("cannot read parent directory"); |
---|
141 | for (;;) { |
---|
142 | if (!(ep = readdir(dp))) |
---|
143 | fail("cannot find current directory"); |
---|
144 | if (ep->D_INO == ino) |
---|
145 | break; |
---|
146 | } |
---|
147 | name = xstrdup(ep->d_name); |
---|
148 | closedir(dp); |
---|
149 | return name; |
---|
150 | } |
---|
151 | |
---|
152 | void * |
---|
153 | xmalloc(size_t size) |
---|
154 | { |
---|
155 | void *p = malloc(size); |
---|
156 | if (!p) |
---|
157 | fail("cannot allocate %u bytes", size); |
---|
158 | return p; |
---|
159 | } |
---|
160 | |
---|
161 | char * |
---|
162 | xstrdup(char *s) |
---|
163 | { |
---|
164 | return strcpy(xmalloc(strlen(s) + 1), s); |
---|
165 | } |
---|
166 | |
---|
167 | char * |
---|
168 | xbasename(char *path) |
---|
169 | { |
---|
170 | char *cp; |
---|
171 | |
---|
172 | while ((cp = strrchr(path, '/')) && cp[1] == '\0') |
---|
173 | *cp = '\0'; |
---|
174 | if (!cp) return path; |
---|
175 | return cp + 1; |
---|
176 | } |
---|
177 | |
---|
178 | void |
---|
179 | xchdir(char *dir) |
---|
180 | { |
---|
181 | if (chdir(dir) < 0) |
---|
182 | fail("cannot change directory to %s", dir); |
---|
183 | } |
---|
184 | |
---|
185 | int |
---|
186 | relatepaths(char *from, char *to, char *outpath) |
---|
187 | { |
---|
188 | char *cp, *cp2; |
---|
189 | int len; |
---|
190 | char buf[NAME_MAX]; |
---|
191 | |
---|
192 | assert(*from == '/' && *to == '/'); |
---|
193 | for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++) |
---|
194 | if (*cp == '\0') |
---|
195 | break; |
---|
196 | while (cp[-1] != '/') |
---|
197 | cp--, cp2--; |
---|
198 | if (cp - 1 == to) { |
---|
199 | /* closest common ancestor is /, so use full pathname */ |
---|
200 | len = strlen(strcpy(outpath, to)); |
---|
201 | if (outpath[len] != '/') { |
---|
202 | outpath[len++] = '/'; |
---|
203 | outpath[len] = '\0'; |
---|
204 | } |
---|
205 | } else { |
---|
206 | len = 0; |
---|
207 | while ((cp2 = getcomponent(cp2, buf)) != 0) { |
---|
208 | strcpy(outpath + len, "../"); |
---|
209 | len += 3; |
---|
210 | } |
---|
211 | while ((cp = getcomponent(cp, buf)) != 0) { |
---|
212 | sprintf(outpath + len, "%s/", buf); |
---|
213 | len += strlen(outpath + len); |
---|
214 | } |
---|
215 | } |
---|
216 | return len; |
---|
217 | } |
---|
218 | |
---|
219 | void |
---|
220 | reversepath(char *inpath, char *name, int len, char *outpath) |
---|
221 | { |
---|
222 | char *cp, *cp2; |
---|
223 | char buf[NAME_MAX]; |
---|
224 | struct stat sb; |
---|
225 | |
---|
226 | cp = strcpy(outpath + PATH_MAX - (len + 1), name); |
---|
227 | cp2 = inpath; |
---|
228 | while ((cp2 = getcomponent(cp2, buf)) != 0) { |
---|
229 | if (strcmp(buf, ".") == 0) |
---|
230 | continue; |
---|
231 | if (strcmp(buf, "..") == 0) { |
---|
232 | if (stat(".", &sb) < 0) |
---|
233 | fail("cannot stat current directory"); |
---|
234 | name = ino2name(sb.st_ino, ".."); |
---|
235 | len = strlen(name); |
---|
236 | cp -= len + 1; |
---|
237 | strcpy(cp, name); |
---|
238 | cp[len] = '/'; |
---|
239 | free(name); |
---|
240 | xchdir(".."); |
---|
241 | } else { |
---|
242 | cp -= 3; |
---|
243 | strncpy(cp, "../", 3); |
---|
244 | xchdir(buf); |
---|
245 | } |
---|
246 | } |
---|
247 | strcpy(outpath, cp); |
---|
248 | } |
---|