Mercurial > notdcc
comparison dcclib/fnm2path.c @ 0:c7f6b056b673
First import of vendor version
author | Peter Gervai <grin@grin.hu> |
---|---|
date | Tue, 10 Mar 2009 13:49:58 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c7f6b056b673 |
---|---|
1 /* Distributed Checksum Clearinghouse | |
2 * | |
3 * Copyright (c) 2008 by Rhyolite Software, LLC | |
4 * | |
5 * This agreement is not applicable to any entity which sells anti-spam | |
6 * solutions to others or provides an anti-spam solution as part of a | |
7 * security solution sold to other entities, or to a private network | |
8 * which employs the DCC or uses data provided by operation of the DCC | |
9 * but does not provide corresponding data to other users. | |
10 * | |
11 * Permission to use, copy, modify, and distribute this software without | |
12 * changes for any purpose with or without fee is hereby granted, provided | |
13 * that the above copyright notice and this permission notice appear in all | |
14 * copies and any distributed versions or copies are either unchanged | |
15 * or not called anything similar to "DCC" or "Distributed Checksum | |
16 * Clearinghouse". | |
17 * | |
18 * Parties not eligible to receive a license under this agreement can | |
19 * obtain a commercial license to use DCC by contacting Rhyolite Software | |
20 * at sales@rhyolite.com. | |
21 * | |
22 * A commercial license would be for Distributed Checksum and Reputation | |
23 * Clearinghouse software. That software includes additional features. This | |
24 * free license for Distributed ChecksumClearinghouse Software does not in any | |
25 * way grant permision to use Distributed Checksum and Reputation Clearinghouse | |
26 * software | |
27 * | |
28 * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL | |
29 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES | |
30 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC | |
31 * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES | |
32 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
33 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |
34 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | |
35 * SOFTWARE. | |
36 * | |
37 * Rhyolite Software DCC 1.3.103-1.26 $Revision$ | |
38 */ | |
39 | |
40 #include "dcc_defs.h" | |
41 #ifdef DCC_WIN32 | |
42 #include <direct.h> | |
43 #endif | |
44 | |
45 DCC_PATH dcc_homedir; | |
46 int dcc_homedir_len = 2; /* (ensure comparisons fail) */ | |
47 | |
48 | |
49 #ifndef DCC_WIN32 | |
50 static u_char | |
51 trimpath(DCC_PATH path, const DCC_PATH tmp) | |
52 { | |
53 const char *s; | |
54 char c, *t, *p; | |
55 | |
56 | |
57 /* trim "//", "/./", "../", "/../", or trailing "/" */ | |
58 s = tmp; | |
59 if (s[0] == '.' && s[1] == '/') | |
60 s += 2; | |
61 t = path; | |
62 for (;;) { | |
63 c = *s++; | |
64 if (c != '/') { | |
65 *t = c; | |
66 if (c == '\0') | |
67 break; | |
68 ++t; | |
69 continue; | |
70 } | |
71 | |
72 /* check character after '/' */ | |
73 c = *s; | |
74 if (c == '/') /* discard first '/' in "//" */ | |
75 continue; | |
76 if (c == '\0' /* discard trailing '/' */ | |
77 && t != path) | |
78 continue; | |
79 | |
80 if (c != '.') { | |
81 *t++ = '/'; | |
82 continue; | |
83 } | |
84 | |
85 /* we have seen "/." */ | |
86 c = *++s; | |
87 if (c == '/') /* discard "/." in "/./" */ | |
88 continue; | |
89 | |
90 /* trim trailing "/." */ | |
91 if (c == '\0') | |
92 continue; | |
93 | |
94 if (c != '.' | |
95 || (*(s+1) != '/' && *(s+1) != '\0')) { | |
96 *t++ = '/'; | |
97 *t++ = '.'; | |
98 continue; | |
99 } | |
100 | |
101 /* we have "/../" or "/..\0", so remove last name in target */ | |
102 *t = '\0'; | |
103 p = strrchr(path, '/'); | |
104 if (p) { | |
105 t = p; | |
106 if (t == path) /* convert "/.." to "/" */ | |
107 ++t; | |
108 } else { | |
109 t = path; | |
110 } | |
111 ++s; /* advance to '\0' or 2nd '/' */ | |
112 } | |
113 if (path[0] == '\0') { | |
114 path[0] = tmp[0] == '/' ? '/' : '.'; | |
115 path[1] = '\0'; | |
116 } | |
117 | |
118 return 1; | |
119 } | |
120 #endif | |
121 | |
122 | |
123 | |
124 /* make a relative pathname from a file name and an optional suffix */ | |
125 u_char /* 0=too long */ | |
126 fnm2rel(DCC_PATH new_path, const char *nm, const char *suffix) | |
127 { | |
128 #ifdef DCC_WIN32 | |
129 return fnm2abs(new_path, nm, suffix); | |
130 #else | |
131 DCC_PATH tmp; | |
132 int i; | |
133 const char *p, *p1; | |
134 | |
135 /* the answer is the input pathname if it is null */ | |
136 if (!nm || *nm == '\0') { | |
137 new_path[0] = '\0'; | |
138 return 0; | |
139 } | |
140 | |
141 if (suffix) { | |
142 p = tmp; | |
143 i = snprintf(tmp, sizeof(tmp), "%s%s", nm, suffix); | |
144 } else { | |
145 p = nm; | |
146 i = strlen(p); | |
147 } | |
148 if (i >= ISZ(tmp)) { | |
149 /* too long */ | |
150 new_path[0] = '\0'; | |
151 return 0; | |
152 } | |
153 if (p[dcc_homedir_len] == '/' | |
154 && !strncmp(p, dcc_homedir, dcc_homedir_len)) { | |
155 p1 = p + dcc_homedir_len; | |
156 do { | |
157 ++p1; | |
158 } while (*p1 == '/'); | |
159 if (*p1 != '\0') | |
160 p = p1; | |
161 } | |
162 | |
163 return trimpath(new_path, p); | |
164 #endif | |
165 } | |
166 | |
167 | |
168 | |
169 /* make pathname from an optional suffix and a file name relative to | |
170 * a path or the home directory */ | |
171 u_char /* 0=too long */ | |
172 fnm2abs(DCC_PATH path, /* put it here */ | |
173 const char *nm, const char *suffix) | |
174 { | |
175 DCC_PATH tmp; | |
176 int i; | |
177 #ifdef DCC_WIN32 | |
178 char *p; | |
179 DWORD lasterror; | |
180 #endif | |
181 | |
182 /* the answer is the input pathname if it is null */ | |
183 if (!nm || *nm == '\0') { | |
184 path[0] = '\0'; | |
185 return 0; | |
186 } | |
187 | |
188 if (!suffix) | |
189 suffix = ""; | |
190 | |
191 #ifdef DCC_WIN32 | |
192 i = snprintf(tmp, sizeof(DCC_PATH), "%s%s", nm, suffix); | |
193 if (i >= ISZ(DCC_PATH)) { | |
194 path[0] = '\0'; | |
195 return 0; | |
196 } | |
197 lasterror = GetLastError(); | |
198 GetFullPathName(tmp, sizeof(DCC_PATH), path, &p); | |
199 SetLastError(lasterror); | |
200 return 1; | |
201 #else | |
202 if (nm[0] == '/' || dcc_homedir[0] == '\0') { | |
203 i = snprintf(tmp, sizeof(tmp), "%s%s", nm, suffix); | |
204 } else { | |
205 i = snprintf(tmp, sizeof(tmp), "%s/%s%s", | |
206 dcc_homedir, nm, suffix); | |
207 } | |
208 if (i >= ISZ(tmp)) { | |
209 /* too long */ | |
210 path[0] = '\0'; | |
211 return 0; | |
212 } | |
213 | |
214 return trimpath(path, tmp); | |
215 #endif | |
216 } | |
217 | |
218 | |
219 | |
220 /* make an absolute pathname from a file name for printing */ | |
221 const char * | |
222 fnm2abs_err(DCC_PATH path, const char *nm) | |
223 { | |
224 static DCC_PATH pathbuf; | |
225 | |
226 if (!path) /* obviously not thread safe */ | |
227 path = pathbuf; | |
228 | |
229 return fnm2abs(path, nm, 0) ? path : nm; | |
230 } | |
231 | |
232 | |
233 | |
234 /* make a relative pathname from a file name that must be good */ | |
235 void | |
236 fnm2rel_good(DCC_PATH path, const char *nm, const char* suffix) | |
237 { | |
238 if (!fnm2rel(path, nm, suffix)) | |
239 dcc_logbad(EX_SOFTWARE, "\"%s%s\" is too long", | |
240 nm, suffix ? suffix : ""); | |
241 } | |
242 | |
243 | |
244 | |
245 /* remove initial substring of the home directory */ | |
246 const char * | |
247 path2fnm(const char *path) | |
248 { | |
249 const char *p; | |
250 | |
251 if (path[dcc_homedir_len] != '/' | |
252 || strncmp(path, dcc_homedir, dcc_homedir_len)) | |
253 return path; | |
254 | |
255 p = path+dcc_homedir_len; | |
256 do { | |
257 ++p; | |
258 } while (*p == '/'); | |
259 if (*p == '\0') | |
260 return path; | |
261 return p; | |
262 } | |
263 | |
264 | |
265 | |
266 /* change to the DCC home directory */ | |
267 u_char /* 0=failed 1=ok */ | |
268 dcc_cdhome(DCC_EMSG emsg, const char *newdir, u_char rdonly) | |
269 { | |
270 DCC_PATH tmp; | |
271 u_char result; | |
272 | |
273 result = 1; | |
274 if (!newdir) | |
275 newdir = DCC_HOMEDIR; | |
276 | |
277 if (*newdir == '\0') { | |
278 dcc_pemsg(EX_NOINPUT, emsg, | |
279 "invalid null DCC home directory"); | |
280 newdir = DCC_HOMEDIR; | |
281 result = 0; | |
282 } | |
283 | |
284 if (!fnm2abs(tmp, newdir, 0)) { | |
285 dcc_pemsg(EX_NOINPUT, emsg, | |
286 "bad DCC home directory \"%s\"", newdir); | |
287 result = 0; | |
288 } | |
289 #ifdef DCC_WIN32 | |
290 if (!SetCurrentDirectory(tmp)) { | |
291 dcc_pemsg(EX_NOINPUT, emsg, "SetCurrentDirectory(%s): %s" , | |
292 tmp, ERROR_STR()); | |
293 return 0; | |
294 } | |
295 if (!getcwd(dcc_homedir, sizeof(dcc_homedir))) { | |
296 BUFCPY(dcc_homedir, tmp); | |
297 dcc_homedir_len = strlen(dcc_homedir); | |
298 } | |
299 #else | |
300 if (0 > chdir(tmp)) { | |
301 dcc_pemsg(EX_NOINPUT, emsg, "chdir(%s): %s", | |
302 tmp, ERROR_STR()); | |
303 result = 0; | |
304 } else if (tmp[0] == '/' | |
305 || !getcwd(dcc_homedir, sizeof(dcc_homedir))) { | |
306 BUFCPY(dcc_homedir, tmp); | |
307 dcc_homedir_len = strlen(dcc_homedir); | |
308 } | |
309 | |
310 if (!rdonly && 0 > access(dcc_homedir, W_OK)) { | |
311 if ((errno == EACCES || errno == EPERM) | |
312 && dcc_real_uid != dcc_effective_uid) { | |
313 #ifdef HAVE_EACCESS | |
314 dcc_get_priv(); | |
315 if (0 > eaccess(dcc_homedir, W_OK)) { | |
316 dcc_pemsg(EX_NOINPUT, emsg, "%s: %s", | |
317 dcc_homedir, ERROR_STR()); | |
318 result = 0; | |
319 } | |
320 dcc_rel_priv(); | |
321 #endif | |
322 } else { | |
323 dcc_pemsg(EX_NOINPUT, emsg, "%s: %s", | |
324 dcc_homedir, ERROR_STR()); | |
325 result = 0; | |
326 } | |
327 } | |
328 #endif /* !DCC_WIN32 */ | |
329 | |
330 return result; | |
331 } |