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 }