1 /*
2 NETWIB
3 Network library
4 Copyright(c) 1999-2010 Laurent Constantin
5 -----
6
7 Main server : http://www.laurentconstantin.com/
8 Backup server : http://laurentconstantin.free.fr/
9 [my current email address is on the web servers]
10
11 -----
12 This file is part of Netwib.
13
14 Netwib is free software: you can redistribute it and/or modify
15 it under the terms of the GNU General Public License version 3
16 as published by the Free Software Foundation.
17
18 Netwib is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details (http://www.gnu.org/).
22
23 ------------------------------------------------------------------------
24 */
25
26 #include <netwib/inc/maininc.h>
27
28 /*-------------------------------------------------------------*/
netwib_priv_path_info_smb(netwib_constdata data,netwib_uint32 datasize,netwib_buf * pbufbegin,netwib_bufext * pbufthen)29 static netwib_err netwib_priv_path_info_smb(netwib_constdata data,
30 netwib_uint32 datasize,
31 netwib_buf *pbufbegin,
32 netwib_bufext *pbufthen)
33 {
34 netwib_constdata dataori;
35 netwib_buf buf;
36
37 /* data should contain "[\/][\/]server[\/]share[\/]*.*" */
38
39 /* leading // or \\ was detected before calling this function. */
40 data += 2;
41 datasize -= 2;
42
43 /* search the server */
44 dataori = data;
45 while (NETWIB_TRUE) {
46 if (datasize == 0) {
47 return(NETWIB_ERR_PAPATHNOTCANON);
48 }
49 if (*data == '/' || *data == '\\') {
50 break;
51 }
52 data++;
53 datasize--;
54 }
55 if (data - dataori == 0) {
56 return(NETWIB_ERR_PAPATHNOTCANON);
57 }
58 if (pbufbegin != NULL) {
59 netwib_er(netwib_buf_append_byte('/', pbufbegin));
60 netwib_er(netwib_buf_append_byte('/', pbufbegin));
61 netwib_er(netwib_buf_init_ext_arrayfilled(dataori, data - dataori, &buf));
62 netwib_er(netwib_buf_encode(&buf, NETWIB_ENCODETYPE_LOWERCASE, pbufbegin));
63 netwib_er(netwib_buf_append_byte('/', pbufbegin));
64 }
65 data++;
66 datasize--;
67
68 /* now search the share */
69 dataori = data;
70 while (NETWIB_TRUE) {
71 if (datasize == 0 || *data == '/' || *data == '\\') {
72 break;
73 }
74 data++;
75 datasize--;
76 }
77 if (data - dataori == 0) {
78 /* path is invalid because there is no share name */
79 return(NETWIB_ERR_PAPATHNOTCANON);
80 }
81 if (pbufbegin != NULL) {
82 netwib_er(netwib_buf_init_ext_arrayfilled(dataori, data - dataori, &buf));
83 netwib_er(netwib_buf_encode(&buf, NETWIB_ENCODETYPE_LOWERCASE, pbufbegin));
84 netwib_er(netwib_buf_append_byte('/', pbufbegin));
85 }
86
87 if (datasize == 0) {
88 netwib_er(netwib_buf_init_ext_string("/", pbufthen));/* MT safe */
89 } else {
90 netwib_er(netwib_buf_init_ext_arrayfilled(data, datasize, pbufthen));
91 }
92
93 return(NETWIB_ERR_OK);
94 }
95 /* warning: output parameters are not consistent :
96 - pbufbegin : data is canonized and appended
97 - pbufthen : data is external pointing in ppathname (so not canonized)
98 pbufthen is similar to core, but not canonized
99 */
netwib_priv_path_info(netwib_constbuf * ppathname,netwib_pathtype * ppathtype,netwib_buf * pbufbegin,netwib_bufext * pbufthen)100 static netwib_err netwib_priv_path_info(netwib_constbuf *ppathname,
101 netwib_pathtype *ppathtype,
102 netwib_buf *pbufbegin,
103 netwib_bufext *pbufthen)
104 {
105 netwib_data data;
106 netwib_uint32 datasize;
107 netwib_char c1, c2, c3;
108 netwib_err ret;
109
110 datasize = netwib__buf_ref_data_size(ppathname);
111 if (datasize == 0) {
112 return(NETWIB_ERR_PAPATHNOTCANON);
113 }
114 data = netwib__buf_ref_data_ptr(ppathname);
115
116 c1 = data[0];
117 c2 = (netwib_char)((datasize > 1)?data[1]:'\0');
118 c3 = (netwib_char)((datasize > 2)?data[2]:'\0');
119 if (ppathtype != NULL) {
120 *ppathtype = 0;
121 }
122 if (c1 == '.') {
123 if (ppathtype != NULL) {
124 *ppathtype = NETWIB_PATHTYPE_UNIX;
125 }
126 if (pbufbegin != NULL) {
127 netwib_er(netwib_buf_append_byte('.', pbufbegin));
128 }
129 if (pbufthen != NULL) {
130 netwib_er(netwib_buf_init_ext_arrayfilled(data, datasize, pbufthen));
131 }
132 } else if (c1 == '/' || c1 == '\\') {
133 netwib_bool issmb;
134 issmb = NETWIB_FALSE;
135 if (c2 == '/' || c2 == '\\') {
136 netwib_uint32 bufbeginsize;
137 netwib_buf bufthen;
138 bufbeginsize = netwib__buf_ref_data_sizenull(pbufbegin);
139 if (pbufthen == NULL) {
140 pbufthen = &bufthen;
141 }
142 ret = netwib_priv_path_info_smb(data, datasize, pbufbegin, pbufthen);
143 if (ret == NETWIB_ERR_OK) {
144 if (ppathtype != NULL) {
145 *ppathtype = NETWIB_PATHTYPE_WINSHARE | NETWIB_PATHTYPE_ABSOLUTE;
146 data = netwib__buf_ref_data_ptr(pbufthen);
147 datasize = netwib__buf_ref_data_size(pbufthen);
148 if (datasize == 1 && (data[0] == '/' || data[0] == '\\')) {
149 *ppathtype |= NETWIB_PATHTYPE_ROOT;
150 }
151 }
152 issmb = NETWIB_TRUE;
153 } else {
154 /* error, so suppose it's absolute (skip leading /) */
155 if (pbufbegin != NULL) {
156 pbufbegin->endoffset = pbufbegin->beginoffset + bufbeginsize;
157 }
158 data++;
159 datasize--;
160 }
161 }
162 if (!issmb) {
163 /* absolute path */
164 if (ppathtype != NULL) {
165 *ppathtype = NETWIB_PATHTYPE_UNIX | NETWIB_PATHTYPE_ABSOLUTE;
166 if (datasize == 1) *ppathtype |= NETWIB_PATHTYPE_ROOT;
167 }
168 if (pbufbegin != NULL) {
169 netwib_er(netwib_buf_append_byte('/', pbufbegin));
170 }
171 if (pbufthen != NULL) {
172 netwib_er(netwib_buf_init_ext_arrayfilled(data, datasize, pbufthen));
173 }
174 }
175 } else if (netwib_c2_isalpha(c1) && c2 == ':') {
176 if (ppathtype != NULL) {
177 *ppathtype = NETWIB_PATHTYPE_WINDRIVE;
178 }
179 if (pbufbegin != NULL) {
180 netwib_er(netwib_buf_append_byte((netwib_char)(netwib_c2_lc(c1)), pbufbegin));
181 netwib_er(netwib_buf_append_byte(':', pbufbegin));
182 }
183 if (c3 == '/' || c3 == '\\') {
184 if (ppathtype != NULL) {
185 *ppathtype |= NETWIB_PATHTYPE_ABSOLUTE;
186 if (datasize == 3) *ppathtype |= NETWIB_PATHTYPE_ROOT;
187 }
188 if (pbufbegin != NULL) {
189 netwib_er(netwib_buf_append_byte('/', pbufbegin));
190 }
191 if (pbufthen != NULL) {
192 netwib_er(netwib_buf_init_ext_arrayfilled(data+2, datasize-2,
193 pbufthen));
194 }
195 } else if (c3 == '\0') {
196 if (pbufthen != NULL) {
197 netwib_er(netwib_buf_init_ext_string(".", pbufthen));/* MT safe */
198 }
199 } else {
200 if (pbufthen != NULL) {
201 netwib_er(netwib_buf_init_ext_arrayfilled(data+2, datasize-2,
202 pbufthen));
203 }
204 }
205 } else {
206 /* suppose it's a relative path */
207 if (ppathtype != NULL) {
208 *ppathtype = NETWIB_PATHTYPE_UNIX;
209 }
210 if (pbufbegin != NULL) {
211 netwib_er(netwib_buf_append_byte('.', pbufbegin));
212 }
213 if (pbufthen != NULL) {
214 netwib_er(netwib_buf_init_ext_arrayfilled(data, datasize, pbufthen));
215 }
216 }
217
218 return(NETWIB_ERR_OK);
219 }
220
221 /*-------------------------------------------------------------*/
222 #define NETWIB_PRIV_PATH_CANON_LASTWAS_PATH 0
223 #define NETWIB_PRIV_PATH_CANON_LASTWAS_SLASH 1
224 #define NETWIB_PRIV_PATH_CANON_LASTWAS_DOT 2
netwib_priv_path_canon_goup(netwib_buf * pout,netwib_uint32 outinitsize,netwib_uint32 * plastwas)225 static netwib_err netwib_priv_path_canon_goup(netwib_buf *pout,
226 netwib_uint32 outinitsize,
227 netwib_uint32 *plastwas)
228 {
229 netwib_data data, pc;
230 netwib_uint32 datasize;
231
232 /* convert :
233 / to NETWIB_ERR_PAPATHROOTDOTDOT [/..]
234 . to .. [./..]
235 .. to ../.. [../..]
236 x/.. to x/../.. [x/../..]
237 x/aa/bb to x/aa [x/aa/bb/..]
238 x/aa to x [x/aa/..]
239 x to . [x/..]
240 /x to / [/x/..]
241 */
242
243 data = netwib__buf_ref_data_ptr(pout) + outinitsize;
244 datasize = netwib__buf_ref_data_size(pout) - outinitsize;
245
246 if (datasize == 1) {
247 if (data[0] == '/' || data[0] == '\\') {
248 return(NETWIB_ERR_PAPATHROOTDOTDOT);
249 }
250 if (data[0] == '.') {
251 /* "." to ".." */
252 netwib_er(netwib_buf_append_byte('.', pout));
253 *plastwas = NETWIB_PRIV_PATH_CANON_LASTWAS_PATH;
254 return(NETWIB_ERR_OK);
255 }
256 }
257
258 if (datasize == 2) {
259 if (data[0] == '.' && data[1] == '.') {
260 /* ".." to "../.." */
261 netwib_er(netwib_buf_append_string("/..", pout));
262 *plastwas = NETWIB_PRIV_PATH_CANON_LASTWAS_PATH;
263 return(NETWIB_ERR_OK);
264 }
265 }
266
267 if (datasize >= 3) {
268 pc = data + datasize - 3;
269 if (*pc == '/' || *pc == '\\') {
270 pc++;
271 if (*pc++ == '.') {
272 if (*pc == '.') {
273 /* "x/.." to "x/../.." */
274 netwib_er(netwib_buf_append_string("/..", pout));
275 *plastwas = NETWIB_PRIV_PATH_CANON_LASTWAS_PATH;
276 return(NETWIB_ERR_OK);
277 }
278 }
279 }
280 }
281
282 pc = data + datasize - 1;
283 while (NETWIB_TRUE) {
284 if (*pc == '/' || *pc == '\\') {
285 break;
286 }
287 pc--;
288 if (pc < data) {
289 /* no '/' found, so : "x" to "." */
290 pout->endoffset = pout->beginoffset + outinitsize;
291 netwib_er(netwib_buf_append_string(".", pout));
292 *plastwas = NETWIB_PRIV_PATH_CANON_LASTWAS_DOT;
293 return(NETWIB_ERR_OK);
294 }
295 }
296 if (pc == data) {
297 /* "/x" to "/" */
298 pout->endoffset = pout->beginoffset + outinitsize + 1;
299 *plastwas = NETWIB_PRIV_PATH_CANON_LASTWAS_SLASH;
300 } else {
301 /* "x/aa/bb" to "x/aa" */
302 pout->endoffset = pout->beginoffset + outinitsize + pc - data;
303 *plastwas = NETWIB_PRIV_PATH_CANON_LASTWAS_PATH;
304 }
305
306 return(NETWIB_ERR_OK);
307 }
308 /* works only on a NETWIB_PATHTYPE_UNIX path */
netwib_priv_path_canon(netwib_constbuf * ppathname,netwib_buf * pout)309 static netwib_err netwib_priv_path_canon(netwib_constbuf *ppathname,
310 netwib_buf *pout)
311 {
312 netwib_data data, dataori;
313 netwib_uint32 datasize, lastwas, outinitsize;
314
315 datasize = netwib__buf_ref_data_size(ppathname);
316 if (datasize == 0) {
317 /* forbids empty filenames */
318 return(NETWIB_ERR_PAPATHNOTCANON);
319 }
320 data = netwib__buf_ref_data_ptr(ppathname);
321 outinitsize = netwib__buf_ref_data_size(pout);
322
323 /* set root */
324 lastwas = NETWIB_PRIV_PATH_CANON_LASTWAS_PATH;
325 if (data[0] == '/' || data[0] == '\\') {
326 netwib_er(netwib_buf_append_byte('/', pout));
327 lastwas = NETWIB_PRIV_PATH_CANON_LASTWAS_SLASH;
328 } else {
329 netwib_er(netwib_buf_append_byte('.', pout));
330 lastwas = NETWIB_PRIV_PATH_CANON_LASTWAS_DOT;
331 }
332
333 /* main loop treating each directory */
334 while (NETWIB_TRUE) {
335 /* ensures data points to the begin of directory */
336 while (NETWIB_TRUE) {
337 if (datasize == 0) {
338 /* normal end */
339 return(NETWIB_ERR_OK);
340 }
341 if (*data != '/' && *data != '\\') {
342 break;
343 }
344 data++;
345 datasize--;
346 }
347 /* obtain the directory end */
348 dataori = data;
349 while (NETWIB_TRUE) {
350 if (datasize == 0 || *data == '/' || *data == '\\') {
351 break;
352 }
353 data++;
354 datasize--;
355 }
356 /* now, the directory name is between dataori and data */
357 if ((data-dataori == 1) && (dataori[0] == '.')) {
358 /* add nothing */
359 } else if ((data-dataori == 2) && (dataori[0] == '.')
360 && (dataori[1] == '.')) {
361 /* go up */
362 netwib_er(netwib_priv_path_canon_goup(pout, outinitsize, &lastwas));
363 } else {
364 /* add directory */
365 if (lastwas == NETWIB_PRIV_PATH_CANON_LASTWAS_DOT) {
366 pout->endoffset--; /* remove dot */
367 } else if (lastwas != NETWIB_PRIV_PATH_CANON_LASTWAS_SLASH) {
368 netwib_er(netwib_buf_append_byte('/', pout));
369 }
370 netwib_er(netwib_buf_append_data(dataori, data-dataori, pout));
371 lastwas = NETWIB_PRIV_PATH_CANON_LASTWAS_PATH;
372 }
373 }
374
375 return(NETWIB_ERR_LOINTERNALERROR);
376 }
377
378 /*-------------------------------------------------------------*/
379 /* pcanonizedpathname must contain "begin canonized" */
netwib_priv_path_append_then(netwib_pathtype beginpathtype,netwib_constbuf * pthen,netwib_buf * pcanonizedpathname)380 static netwib_err netwib_priv_path_append_then(netwib_pathtype beginpathtype,
381 netwib_constbuf *pthen,
382 netwib_buf *pcanonizedpathname)
383 {
384 netwib_data data;
385 netwib_uint32 size;
386
387 if (beginpathtype & NETWIB_PATHTYPE_UNIX) {
388 pcanonizedpathname->endoffset--; /* suppress last / or . of begin */
389 netwib_er(netwib_priv_path_canon(pthen, pcanonizedpathname));
390 } else if (beginpathtype & NETWIB_PATHTYPE_WINDRIVE) {
391 if (beginpathtype & NETWIB_PATHTYPE_ABSOLUTE) {
392 pcanonizedpathname->endoffset--; /* suppress last / of begin */
393 netwib_er(netwib_priv_path_canon(pthen, pcanonizedpathname));
394 } else {
395 size = netwib__buf_ref_data_size(pcanonizedpathname);
396 netwib_er(netwib_priv_path_canon(pthen, pcanonizedpathname));
397 /* suppress last '.' in 'c:.' */
398 if (netwib__buf_ref_data_size(pcanonizedpathname) - size == 1) {
399 data = netwib__buf_ref_data_ptr(pcanonizedpathname);
400 if (data[size] == '.') {
401 pcanonizedpathname->endoffset--; /* suppress . of then */
402 }
403 }
404 }
405 } else if (beginpathtype & NETWIB_PATHTYPE_WINSHARE) {
406 pcanonizedpathname->endoffset--; /* suppress last / of begin */
407 netwib_er(netwib_priv_path_canon(pthen, pcanonizedpathname));
408 } else {
409 return(NETWIB_ERR_LOINTERNALERROR);
410 }
411
412 return(NETWIB_ERR_OK);
413 }
414
415 /*-------------------------------------------------------------*/
netwib_path_canon(netwib_constbuf * ppathname,netwib_buf * pcanonizedpathname)416 netwib_err netwib_path_canon(netwib_constbuf *ppathname,
417 netwib_buf *pcanonizedpathname)
418 {
419 netwib_buf then;
420 netwib_pathtype pathtype;
421
422 /* directly store begin in pcanonizedpathname */
423 netwib_er(netwib_priv_path_info(ppathname, &pathtype, pcanonizedpathname,
424 &then));
425
426 /* append then */
427 netwib_er(netwib_priv_path_append_then(pathtype, &then,
428 pcanonizedpathname));
429
430 return(NETWIB_ERR_OK);
431 }
432
433 /*-------------------------------------------------------------*/
netwib_pathtype_init(netwib_constbuf * ppathname,netwib_pathtype * ppathtype)434 netwib_err netwib_pathtype_init(netwib_constbuf *ppathname,
435 netwib_pathtype *ppathtype)
436 {
437 netwib_er(netwib_priv_path_info(ppathname, ppathtype, NULL, NULL));
438 return(NETWIB_ERR_OK);
439 }
440
441 /*-------------------------------------------------------------*/
netwib_path_decode(netwib_constbuf * ppathname,netwib_path_decodetype type,netwib_buf * pout)442 netwib_err netwib_path_decode(netwib_constbuf *ppathname,
443 netwib_path_decodetype type,
444 netwib_buf *pout)
445 {
446 netwib_pathtype pathtype;
447 netwib_byte buftmparray[512];
448 netwib_buf buftmp, then;
449 netwib_data data;
450 netwib_uint32 datasize;
451 netwib_err ret;
452
453 if (netwib__buf_ref_data_sizenull(ppathname) == 0) {
454 return(NETWIB_ERR_PAPATHNOTCANON);
455 }
456
457 switch(type) {
458 case NETWIB_PATH_DECODETYPE_BEGIN :
459 netwib_er(netwib_priv_path_info(ppathname, NULL, pout, NULL));
460 break;
461 case NETWIB_PATH_DECODETYPE_CORE :
462 netwib_er(netwib_priv_path_info(ppathname, NULL, NULL, &then));
463 netwib_er(netwib_priv_path_canon(&then, pout));
464 break;
465 case NETWIB_PATH_DECODETYPE_PARENT :
466 /* We could simply convert "a/b" to "a", but there are cases such
467 as "a/.." to "a/../.." which are not so easy. So, use buftmp. */
468 netwib_er(netwib_priv_path_info(ppathname, &pathtype, pout, &then));
469 netwib_er(netwib_buf_init_ext_storagearraysizeof(buftmparray, &buftmp));
470 netwib_er(netwib_buf_append_buf(&then, &buftmp));
471 netwib_er(netwib_buf_append_string("/..", &buftmp));
472 ret = netwib_priv_path_append_then(pathtype, &buftmp, pout);
473 netwib_er(netwib_buf_close(&buftmp));
474 netwib_er(ret);
475 break;
476 case NETWIB_PATH_DECODETYPE_CHILD :
477 /* We could use last part, but there are cases such as "a/" or "a/."
478 which are not so easy. So, use buftmp, and canonize it. */
479 netwib_er(netwib_priv_path_info(ppathname, NULL, NULL, &then));
480 netwib_er(netwib_buf_init_ext_storagearraysizeof(buftmparray, &buftmp));
481 ret = netwib_priv_path_canon(&then, &buftmp);
482 if (ret == NETWIB_ERR_OK) {
483 datasize = netwib__buf_ref_data_size(&buftmp);
484 if (datasize == 0) {
485 return(NETWIB_ERR_LOINTERNALERROR);
486 }
487 data = netwib__buf_ref_data_ptr(&buftmp);
488 if (datasize == 1 && data[0] == '/') {
489 netwib_er(netwib_buf_append_byte('/', pout));
490 } else {
491 data += datasize;
492 while (datasize--) {
493 data--;
494 if (*data == '/') {
495 data++;
496 break;
497 }
498 }
499 netwib_er(netwib_buf_append_data(data, netwib__buf_ref_data_size(&buftmp) - datasize - 1, pout));
500 }
501 }
502 netwib_er(netwib_buf_close(&buftmp));
503 netwib_er(ret);
504 break;
505 case NETWIB_PATH_DECODETYPE_EXTENSION :
506 datasize = netwib__buf_ref_data_size(ppathname);
507 data = netwib__buf_ref_data_ptr(ppathname);
508 data += datasize;
509 while (NETWIB_TRUE) {
510 if (datasize == 0) { /* no extension */
511 netwib_er(netwib_buf_init_ext_empty(pout));
512 return(NETWIB_ERR_OK);
513 }
514 datasize--;
515 data--;
516 if (*data == '.') {
517 data++;
518 break;
519 }
520 if (*data == '/' || *data == '\\') { /* no extension */
521 netwib_er(netwib_buf_init_ext_empty(pout));
522 return(NETWIB_ERR_OK);
523 }
524 }
525 netwib_er(netwib_buf_init_ext_arrayfilled(data, netwib__buf_ref_data_size(ppathname) - datasize - 1, pout));
526 break;
527 default :
528 return(NETWIB_ERR_PAINVALIDTYPE);
529 break;
530 }
531
532 return(NETWIB_ERR_OK);
533 }
534
535 /*-------------------------------------------------------------*/
netwib_priv_path_begin_cmp(netwib_constbuf * pbegin1,netwib_pathtype pathtype1,netwib_constbuf * pbegin2,netwib_pathtype pathtype2,netwib_bool ignoreroot)536 static netwib_err netwib_priv_path_begin_cmp(netwib_constbuf *pbegin1,
537 netwib_pathtype pathtype1,
538 netwib_constbuf *pbegin2,
539 netwib_pathtype pathtype2,
540 netwib_bool ignoreroot)
541 {
542 netwib_buf begin1, begin2;
543 netwib_cmp cmp;
544
545 if (pathtype1 & NETWIB_PATHTYPE_UNIX) {
546 if (!(pathtype2 & NETWIB_PATHTYPE_UNIX)) {
547 return(NETWIB_ERR_PAPATHCANTINIT);
548 }
549 if (!ignoreroot) {
550 netwib_er(netwib_buf_cmp(pbegin1, pbegin2, &cmp));
551 if (cmp != NETWIB_CMP_EQ) {
552 return(NETWIB_ERR_PAPATHCANTINIT);
553 }
554 }
555 } else if (pathtype1 & NETWIB_PATHTYPE_WINSHARE) {
556 if (!(pathtype2 & NETWIB_PATHTYPE_WINSHARE)) {
557 return(NETWIB_ERR_PAPATHCANTINIT);
558 }
559 netwib_er(netwib_buf_cmp(pbegin1, pbegin2, &cmp));
560 if (cmp != NETWIB_CMP_EQ) {
561 return(NETWIB_ERR_PAPATHCANTINIT);
562 }
563 } else if (pathtype1 & NETWIB_PATHTYPE_WINDRIVE) {
564 if (!(pathtype2 & NETWIB_PATHTYPE_WINDRIVE)) {
565 return(NETWIB_ERR_PAPATHCANTINIT);
566 }
567 begin1 = *pbegin1;
568 begin2 = *pbegin2;
569 if (ignoreroot) {
570 if (pathtype1 & NETWIB_PATHTYPE_ABSOLUTE) {
571 begin1.endoffset--; /* ignore "c:'/'" for comparing */
572 }
573 if (pathtype2 & NETWIB_PATHTYPE_ABSOLUTE) {
574 begin2.endoffset--; /* ignore "c:'/'" for comparing */
575 }
576 }
577 netwib_er(netwib_buf_cmp(&begin1, &begin2, &cmp));
578 if (cmp != NETWIB_CMP_EQ) {
579 return(NETWIB_ERR_PAPATHCANTINIT);
580 }
581 } else {
582 return(NETWIB_ERR_LOINTERNALERROR);
583 }
584
585 return(NETWIB_ERR_OK);
586 }
587
588 /*-------------------------------------------------------------*/
netwib_priv_path_init_concat(netwib_constbuf * pdirname1,netwib_constbuf * ppathname2,netwib_buf * pout)589 static netwib_err netwib_priv_path_init_concat(netwib_constbuf *pdirname1,
590 netwib_constbuf *ppathname2,
591 netwib_buf *pout)
592 {
593 netwib_byte buftmp1array[512], buftmp2array[512];
594 netwib_buf buftmp1, buftmp2, then1, then2;
595 netwib_pathtype pathtype1, pathtype2;
596 netwib_err ret=NETWIB_ERR_OK;
597
598 /* initialize buffers */
599 netwib_er(netwib_buf_init_ext_storagearraysizeof(buftmp1array, &buftmp1));
600 netwib_er(netwib_buf_init_ext_storagearraysizeof(buftmp2array, &buftmp2));
601
602 /* obtain information */
603 netwib_eg(netwib_priv_path_info(pdirname1, &pathtype1, &buftmp1, &then1));
604 netwib_eg(netwib_priv_path_info(ppathname2, &pathtype2, &buftmp2, &then2));
605
606 /* check parameters */
607 if (pathtype2 & NETWIB_PATHTYPE_ABSOLUTE) {
608 if (!(pathtype1 & NETWIB_PATHTYPE_ROOT)) {
609 /* if ppathname2 is absolute, pdirname1 must be a root */
610 netwib_eg(NETWIB_ERR_PAPATHCANTINIT);
611 }
612 /* if ppathname2 is absolute, pdirname1 must be the same root */
613 if (!(pathtype2 & NETWIB_PATHTYPE_UNIX)) {
614 netwib_eg(netwib_priv_path_begin_cmp(&buftmp1, pathtype1, &buftmp2,
615 pathtype2, NETWIB_FALSE));
616 }
617 } else {
618 /* the root must be the same */
619 if (!(pathtype2 & NETWIB_PATHTYPE_UNIX)) {
620 netwib_eg(netwib_priv_path_begin_cmp(&buftmp1, pathtype1, &buftmp2,
621 pathtype2, NETWIB_TRUE));
622 }
623 }
624
625 /* create path */
626 netwib__buf_reinit(&buftmp2);
627 netwib_eg(netwib_buf_append_buf(&then1, &buftmp2));
628 netwib_eg(netwib_buf_append_byte('/', &buftmp2));
629 netwib_eg(netwib_buf_append_buf(&then2, &buftmp2));
630 netwib_eg(netwib_priv_path_append_then(pathtype1, &buftmp2, &buftmp1));
631 netwib_eg(netwib_buf_append_buf(&buftmp1, pout));
632
633 /* close */
634 netwib_gotolabel:
635 netwib_er(netwib_buf_close(&buftmp2));
636 netwib_er(netwib_buf_close(&buftmp1));
637 return(ret);
638 }
639
640 /*-------------------------------------------------------------*/
netwib_priv_path_init_jail(netwib_constbuf * pdirname1,netwib_constbuf * ppathname2,netwib_buf * pout)641 static netwib_err netwib_priv_path_init_jail(netwib_constbuf *pdirname1,
642 netwib_constbuf *ppathname2,
643 netwib_buf *pout)
644 {
645 netwib_byte buftmp2array[512], buftmp3array[512];
646 netwib_buf buftmp2, buftmp3, then1, then2;
647 netwib_pathtype pathtype1, pathtype2;
648 netwib_err ret=NETWIB_ERR_OK;
649
650 /* initialize buffers */
651 netwib_er(netwib_buf_init_ext_storagearraysizeof(buftmp2array, &buftmp2));
652 netwib_er(netwib_buf_init_ext_storagearraysizeof(buftmp3array, &buftmp3));
653
654 /* obtain information */
655 netwib_eg(netwib_priv_path_info(pdirname1, &pathtype1, pout, &then1));
656 netwib_eg(netwib_priv_path_info(ppathname2, &pathtype2, NULL, &then2));
657
658 /* check parameters */
659 if (pathtype2 & NETWIB_PATHTYPE_WINDRIVE) {
660 /* for security reasons, this should not be allowed */
661 netwib_goto(NETWIB_ERR_PAPATHCANTINIT);
662 }
663 if (pathtype2 & NETWIB_PATHTYPE_WINSHARE) {
664 /* for security reasons, this should not be allowed */
665 netwib_goto(NETWIB_ERR_PAPATHCANTINIT);
666 }
667
668 /* create path */
669 netwib_eg(netwib_buf_append_buf(&then1, &buftmp2));
670 netwib_eg(netwib_buf_append_byte('/', &buftmp3));
671 netwib_eg(netwib_buf_append_buf(&then2, &buftmp3));
672 netwib_eg(netwib_priv_path_canon(&buftmp3, &buftmp2));
673 netwib_eg(netwib_priv_path_append_then(pathtype1, &buftmp2, pout));
674
675 /* close */
676 netwib_gotolabel:
677 netwib_er(netwib_buf_close(&buftmp3));
678 netwib_er(netwib_buf_close(&buftmp2));
679 return(ret);
680 }
681
682 /*-------------------------------------------------------------*/
netwib_priv_path_init_abs(netwib_constbuf * pdirname1,netwib_constbuf * ppathname2,netwib_buf * pout)683 static netwib_err netwib_priv_path_init_abs(netwib_constbuf *pdirname1,
684 netwib_constbuf *ppathname2,
685 netwib_buf *pout)
686 {
687 netwib_byte buftmp1array[512], buftmp2array[512];
688 netwib_buf buftmp1, buftmp2, then1, then2;
689 netwib_pathtype pathtype1, pathtype2;
690 netwib_err ret=NETWIB_ERR_OK;
691
692 /* initialize buffers */
693 netwib_er(netwib_buf_init_ext_storagearraysizeof(buftmp1array, &buftmp1));
694 netwib_er(netwib_buf_init_ext_storagearraysizeof(buftmp2array, &buftmp2));
695
696 /* check parameters */
697 netwib_eg(netwib_priv_path_info(ppathname2, &pathtype2, &buftmp2, &then2));
698 if (pathtype2 & NETWIB_PATHTYPE_ABSOLUTE) {
699 netwib_eg(netwib_buf_append_buf(ppathname2, pout));
700 netwib_goto(NETWIB_ERR_OK);
701 }
702 netwib_eg(netwib_priv_path_info(pdirname1, &pathtype1, &buftmp1, &then1));
703 if (!(pathtype1 & NETWIB_PATHTYPE_ABSOLUTE)) {
704 netwib_eg(NETWIB_ERR_PAPATHCANTINIT);
705 }
706
707 /* check parameters */
708 if (!(pathtype2 & NETWIB_PATHTYPE_UNIX)) {
709 netwib_eg(netwib_priv_path_begin_cmp(&buftmp1, pathtype1, &buftmp2,
710 pathtype2, NETWIB_TRUE));
711 }
712
713 /* create path */
714 netwib__buf_reinit(&buftmp2);
715 netwib_eg(netwib_buf_append_buf(&then1, &buftmp2));
716 netwib_eg(netwib_buf_append_byte('/', &buftmp2));
717 netwib_eg(netwib_buf_append_buf(&then2, &buftmp2));
718 netwib_eg(netwib_priv_path_append_then(pathtype1, &buftmp2, &buftmp1));
719 netwib_eg(netwib_buf_append_buf(&buftmp1, pout));
720
721 /* close */
722 netwib_gotolabel:
723 netwib_er(netwib_buf_close(&buftmp2));
724 netwib_er(netwib_buf_close(&buftmp1));
725 return(ret);
726 }
727
728 /*-------------------------------------------------------------*/
netwib_priv_path_init_rel(netwib_constbuf * ppathname1,netwib_constbuf * ppathname2,netwib_buf * pout)729 static netwib_err netwib_priv_path_init_rel(netwib_constbuf *ppathname1,
730 netwib_constbuf *ppathname2,
731 netwib_buf *pout)
732 {
733 netwib_byte buftmp1array[512], buftmp2array[512], buftmp3array[512];
734 netwib_buf buftmp1, buftmp2, buftmp3;
735 netwib_string pc1, pc2, pitem1, pitem2;
736 netwib_err ret=NETWIB_ERR_OK;
737
738 /* initialize buffers */
739 netwib_er(netwib_buf_init_ext_storagearraysizeof(buftmp1array, &buftmp1));
740 netwib_er(netwib_buf_init_ext_storagearraysizeof(buftmp2array, &buftmp2));
741 netwib_er(netwib_buf_init_ext_storagearraysizeof(buftmp3array, &buftmp3));
742
743 /* first, canonize */
744 netwib_eg(netwib_priv_path_canon(ppathname1, &buftmp1));
745 netwib_eg(netwib_priv_path_canon(ppathname2, &buftmp2));
746 netwib_eg(netwib_buf_ref_string(&buftmp1, &pc1));
747 netwib_eg(netwib_buf_ref_string(&buftmp2, &pc2));
748
749 /* find the common part */
750 pitem1 = pc1;
751 pitem2 = pc2;
752 while (NETWIB_TRUE) {
753 if (*pc1 != *pc2) {
754 if (*pc1 == '\0' && *pc2 == '/') {
755 pitem1 = NULL; /* means end */
756 pitem2 = pc2+1; /* char after '/'*/
757 }
758 if (*pc1 == '/' && *pc2 == '\0') {
759 pitem1 = pc1+1; /* char after '/'*/
760 pitem2 = NULL; /* means end */
761 }
762 break;
763 }
764 if (*pc1 == '\0' /* comparing pc2 is not needed because *pc1 == *pc2 */) {
765 pitem1 = NULL; /* means end */
766 pitem2 = NULL; /* means end */
767 break;
768 }
769 if (*pc1 == '/' /* comparing pc2 is not needed because *pc1 == *pc2 */) {
770 pitem1 = pc1+1; /* char after '/'*/
771 pitem2 = pc2+1; /* char after '/'*/
772 }
773 pc1++;
774 pc2++;
775 }
776 /* now, cases "pci+1" (to go char after '/') have to be converted to NULL */
777 if (pitem1 != NULL && *pitem1 == '\0') pitem1 = NULL;
778 if (pitem2 != NULL && *pitem2 == '\0') pitem2 = NULL;
779
780 if (pitem1 != NULL) {
781 /* if pitem1 points to "../xyz", we cannot determine */
782 if (pitem1[0] == '.' && pitem1[1] == '.' && pitem1[2] == '/') {
783 netwib_eg(NETWIB_ERR_PAPATHCANTINIT);
784 }
785 /* loop till the end of pc1 to create "../../../" */
786 pc1 = pitem1;
787 while (*pc1 != '\0') {
788 if (*pc1 == '/') {
789 netwib_eg(netwib_buf_append_string("../", pout));
790 }
791 pc1++;
792 }
793 netwib_eg(netwib_buf_append_string("..", pout));
794 if (pitem2 != NULL) {
795 netwib_eg(netwib_buf_append_string("/", pout));
796 /* pitem2 is already canonized, so use it */
797 netwib_eg(netwib_buf_append_string(pitem2, pout));
798 }
799 } else {
800 /* if pitem1 is NULL, there is no "../../../" to create */
801 if (pitem2 != NULL) {
802 /* pitem2 is already canonized, so use it */
803 netwib_eg(netwib_buf_append_string(pitem2, pout));
804 } else {
805 netwib_eg(netwib_buf_append_string(".", pout));
806 }
807 }
808
809 /* close */
810 netwib_gotolabel:
811 netwib_er(netwib_buf_close(&buftmp3));
812 netwib_er(netwib_buf_close(&buftmp2));
813 netwib_er(netwib_buf_close(&buftmp1));
814 return(ret);
815 }
816
817 /*-------------------------------------------------------------*/
netwib_priv_path_init_rela(netwib_constbuf * pdirname1,netwib_constbuf * ppathname2,netwib_buf * pout)818 static netwib_err netwib_priv_path_init_rela(netwib_constbuf *pdirname1,
819 netwib_constbuf *ppathname2,
820 netwib_buf *pout)
821 {
822 netwib_byte buftmp1array[512], buftmp2array[512];
823 netwib_buf buftmp1, buftmp2, then1, then2;
824 netwib_pathtype pathtype1, pathtype2;
825 netwib_err ret=NETWIB_ERR_OK;
826
827 /* initialize buffers */
828 netwib_er(netwib_buf_init_ext_storagearraysizeof(buftmp1array, &buftmp1));
829 netwib_er(netwib_buf_init_ext_storagearraysizeof(buftmp2array, &buftmp2));
830
831 /* obtain information */
832 netwib_eg(netwib_priv_path_info(pdirname1, &pathtype1, &buftmp1, &then1));
833 netwib_eg(netwib_priv_path_info(ppathname2, &pathtype2, &buftmp2, &then2));
834
835 /* check parameters */
836 if (pathtype2 & NETWIB_PATHTYPE_ABSOLUTE) {
837 if (!(pathtype1 & NETWIB_PATHTYPE_ABSOLUTE)) {
838 netwib_eg(NETWIB_ERR_PAPATHCANTINIT);
839 }
840 if (!(pathtype2 & NETWIB_PATHTYPE_UNIX)) {
841 netwib_eg(netwib_priv_path_begin_cmp(&buftmp1, pathtype1, &buftmp2,
842 pathtype2, NETWIB_TRUE));
843 }
844 netwib_eg(netwib_priv_path_init_rel(&then1, &then2, pout));
845 } else {
846 /* ensure root is the same */
847 if (!(pathtype2 & NETWIB_PATHTYPE_UNIX)) {
848 netwib_eg(netwib_priv_path_begin_cmp(&buftmp1, pathtype1, &buftmp2,
849 pathtype2, NETWIB_TRUE));
850 }
851 /* if ppathname2 is relative, use it */
852 netwib_eg(netwib_priv_path_canon(ppathname2, pout));
853 }
854
855 /* close */
856 netwib_gotolabel:
857 netwib_er(netwib_buf_close(&buftmp2));
858 netwib_er(netwib_buf_close(&buftmp1));
859 return(ret);
860 }
861
862 /*-------------------------------------------------------------*/
netwib_priv_path_init_relb(netwib_constbuf * pdirname1,netwib_constbuf * ppathname2,netwib_buf * pout)863 static netwib_err netwib_priv_path_init_relb(netwib_constbuf *pdirname1,
864 netwib_constbuf *ppathname2,
865 netwib_buf *pout)
866 {
867 netwib_byte buftmp1array[512], buftmp2array[512];
868 netwib_buf buftmp1, buftmp2, then1, then2;
869 netwib_pathtype pathtype1, pathtype2;
870 netwib_err ret=NETWIB_ERR_OK;
871
872 /* initialize buffers */
873 netwib_er(netwib_buf_init_ext_storagearraysizeof(buftmp1array, &buftmp1));
874 netwib_er(netwib_buf_init_ext_storagearraysizeof(buftmp2array, &buftmp2));
875
876 /* obtain information */
877 netwib_eg(netwib_priv_path_info(pdirname1, &pathtype1, &buftmp1, &then1));
878 netwib_eg(netwib_priv_path_info(ppathname2, &pathtype2, &buftmp2, &then2));
879
880 /* check parameters */
881 netwib_eg(netwib_priv_path_begin_cmp(&buftmp1, pathtype1, &buftmp2,
882 pathtype2, NETWIB_FALSE));
883
884 /* create path */
885 netwib_eg(netwib_priv_path_init_rel(&then1, &then2, pout));
886
887 /* close */
888 netwib_gotolabel:
889 netwib_er(netwib_buf_close(&buftmp2));
890 netwib_er(netwib_buf_close(&buftmp1));
891 return(ret);
892 }
893
894 /*-------------------------------------------------------------*/
netwib_path_init(netwib_constbuf * pdirname1,netwib_constbuf * ppathname2,netwib_path_inittype type,netwib_buf * pout)895 netwib_err netwib_path_init(netwib_constbuf *pdirname1,
896 netwib_constbuf *ppathname2,
897 netwib_path_inittype type,
898 netwib_buf *pout)
899 {
900 netwib_err ret=NETWIB_ERR_OK;
901
902 if (netwib__buf_ref_data_sizenull(pdirname1) == 0 ||
903 netwib__buf_ref_data_sizenull(ppathname2) == 0) {
904 return(NETWIB_ERR_PAPATHNOTCANON);
905 }
906
907 switch(type) {
908 case NETWIB_PATH_INITTYPE_CONCAT :
909 ret = netwib_priv_path_init_concat(pdirname1, ppathname2, pout);
910 break;
911 case NETWIB_PATH_INITTYPE_JAIL :
912 ret = netwib_priv_path_init_jail(pdirname1, ppathname2, pout);
913 break;
914 case NETWIB_PATH_INITTYPE_ABS :
915 ret = netwib_priv_path_init_abs(pdirname1, ppathname2, pout);
916 break;
917 case NETWIB_PATH_INITTYPE_RELA :
918 ret = netwib_priv_path_init_rela(pdirname1, ppathname2, pout);
919 break;
920 case NETWIB_PATH_INITTYPE_RELB :
921 ret = netwib_priv_path_init_relb(pdirname1, ppathname2, pout);
922 break;
923 }
924
925 if (ret == NETWIB_ERR_PAPATHROOTDOTDOT || ret == NETWIB_ERR_PAPATHNOTCANON) {
926 ret = NETWIB_ERR_PAPATHCANTINIT;
927 }
928
929 return(ret);
930 }
931