1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*b30d1939SAndy Fiddaman * Copyright (c) 1985-2011 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6*b30d1939SAndy Fiddaman * Eclipse Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10*b30d1939SAndy Fiddaman * http://www.eclipse.org/org/documents/epl-v10.html *
11*b30d1939SAndy Fiddaman * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> *
18da2e3ebdSchin * David Korn <dgk@research.att.com> *
19da2e3ebdSchin * Phong Vo <kpv@research.att.com> *
20da2e3ebdSchin * *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #pragma prototyped
23da2e3ebdSchin /*
24da2e3ebdSchin * Glenn Fowler
25da2e3ebdSchin * AT&T Research
26da2e3ebdSchin *
27da2e3ebdSchin * in-place path name canonicalization -- preserves the logical view
28da2e3ebdSchin * pointer to trailing 0 in path returned
29da2e3ebdSchin *
30da2e3ebdSchin * remove redundant .'s and /'s
31da2e3ebdSchin * move ..'s to the front
32da2e3ebdSchin * /.. preserved (for pdu and newcastle hacks)
33da2e3ebdSchin * FS_3D handles ...
34da2e3ebdSchin * if (flags&PATH_PHYSICAL) then symlinks resolved at each component
35da2e3ebdSchin * if (flags&PATH_DOTDOT) then each .. checked for access
36da2e3ebdSchin * if (flags&PATH_EXISTS) then path must exist at each component
37da2e3ebdSchin * if (flags&PATH_VERIFIED(n)) then first n chars of path exist
38da2e3ebdSchin *
39da2e3ebdSchin * longer pathname possible if (flags&PATH_PHYSICAL) or FS_3D ... involved
40da2e3ebdSchin * 0 returned on error and if (flags&(PATH_DOTDOT|PATH_EXISTS)) then path
41da2e3ebdSchin * will contain the components following the failure point
42da2e3ebdSchin */
43da2e3ebdSchin
44*b30d1939SAndy Fiddaman #define _AST_API_H 1
45*b30d1939SAndy Fiddaman
46da2e3ebdSchin #include <ast.h>
47da2e3ebdSchin #include <ls.h>
48da2e3ebdSchin #include <fs3d.h>
49da2e3ebdSchin #include <error.h>
50da2e3ebdSchin
51da2e3ebdSchin char*
pathcanon(char * path,int flags)52da2e3ebdSchin pathcanon(char* path, int flags)
53*b30d1939SAndy Fiddaman {
54*b30d1939SAndy Fiddaman return pathcanon_20100601(path, PATH_MAX, flags);
55*b30d1939SAndy Fiddaman }
56*b30d1939SAndy Fiddaman
57*b30d1939SAndy Fiddaman #undef _AST_API_H
58*b30d1939SAndy Fiddaman
59*b30d1939SAndy Fiddaman #include <ast_api.h>
60*b30d1939SAndy Fiddaman
61*b30d1939SAndy Fiddaman char*
pathcanon_20100601(char * path,size_t size,int flags)62*b30d1939SAndy Fiddaman pathcanon_20100601(char* path, size_t size, int flags)
63da2e3ebdSchin {
64da2e3ebdSchin register char* p;
65da2e3ebdSchin register char* r;
66da2e3ebdSchin register char* s;
67da2e3ebdSchin register char* t;
68da2e3ebdSchin register int dots;
69da2e3ebdSchin char* phys;
70da2e3ebdSchin char* v;
71da2e3ebdSchin int loop;
72da2e3ebdSchin int oerrno;
73da2e3ebdSchin #if defined(FS_3D)
74da2e3ebdSchin long visits = 0;
75da2e3ebdSchin #endif
76da2e3ebdSchin
77da2e3ebdSchin oerrno = errno;
78da2e3ebdSchin dots = loop = 0;
79da2e3ebdSchin phys = path;
80da2e3ebdSchin v = path + ((flags >> 5) & 01777);
81*b30d1939SAndy Fiddaman if (!size)
82*b30d1939SAndy Fiddaman size = strlen(path) + 1;
837c2fbfb3SApril Chin if (*path == '/')
847c2fbfb3SApril Chin {
857c2fbfb3SApril Chin if (*(path + 1) == '/' && *astconf("PATH_LEADING_SLASHES", NiL, NiL) == '1')
867c2fbfb3SApril Chin do path++; while (*path == '/' && *(path + 1) == '/');
877c2fbfb3SApril Chin if (!*(path + 1))
887c2fbfb3SApril Chin return path + 1;
897c2fbfb3SApril Chin }
90da2e3ebdSchin p = r = s = t = path;
91*b30d1939SAndy Fiddaman for (;;)
92*b30d1939SAndy Fiddaman switch (*t++ = *s++)
93da2e3ebdSchin {
94*b30d1939SAndy Fiddaman case '.':
95*b30d1939SAndy Fiddaman dots++;
96da2e3ebdSchin break;
97*b30d1939SAndy Fiddaman case 0:
98*b30d1939SAndy Fiddaman s--;
99*b30d1939SAndy Fiddaman /*FALLTHROUGH*/
100*b30d1939SAndy Fiddaman case '/':
101*b30d1939SAndy Fiddaman while (*s == '/') s++;
102*b30d1939SAndy Fiddaman switch (dots)
103da2e3ebdSchin {
104*b30d1939SAndy Fiddaman case 1:
105*b30d1939SAndy Fiddaman t -= 2;
106*b30d1939SAndy Fiddaman break;
107*b30d1939SAndy Fiddaman case 2:
108*b30d1939SAndy Fiddaman if ((flags & (PATH_DOTDOT|PATH_EXISTS)) == PATH_DOTDOT && (t - 2) >= v)
109da2e3ebdSchin {
110*b30d1939SAndy Fiddaman struct stat st;
111*b30d1939SAndy Fiddaman
112*b30d1939SAndy Fiddaman *(t - 2) = 0;
113*b30d1939SAndy Fiddaman if (stat(phys, &st))
114*b30d1939SAndy Fiddaman {
115*b30d1939SAndy Fiddaman strcpy(path, s);
116*b30d1939SAndy Fiddaman return 0;
117*b30d1939SAndy Fiddaman }
118*b30d1939SAndy Fiddaman *(t - 2) = '.';
119da2e3ebdSchin }
120da2e3ebdSchin #if PRESERVE_TRAILING_SLASH
121*b30d1939SAndy Fiddaman if (t - 5 < r) r = t;
122da2e3ebdSchin #else
123*b30d1939SAndy Fiddaman if (t - 5 < r)
124*b30d1939SAndy Fiddaman {
125*b30d1939SAndy Fiddaman if (t - 4 == r) t = r + 1;
126*b30d1939SAndy Fiddaman else r = t;
127*b30d1939SAndy Fiddaman }
128da2e3ebdSchin #endif
129*b30d1939SAndy Fiddaman else for (t -= 5; t > r && *(t - 1) != '/'; t--);
130*b30d1939SAndy Fiddaman break;
131*b30d1939SAndy Fiddaman case 3:
132da2e3ebdSchin #if defined(FS_3D)
133da2e3ebdSchin {
134*b30d1939SAndy Fiddaman char* x;
135*b30d1939SAndy Fiddaman char* o;
136*b30d1939SAndy Fiddaman int c;
137*b30d1939SAndy Fiddaman
138*b30d1939SAndy Fiddaman o = t;
139*b30d1939SAndy Fiddaman if ((t -= 5) <= path) t = path + 1;
140*b30d1939SAndy Fiddaman c = *t;
141*b30d1939SAndy Fiddaman *t = 0;
142*b30d1939SAndy Fiddaman if (x = pathnext(phys, s - (*s != 0), &visits))
143*b30d1939SAndy Fiddaman {
144*b30d1939SAndy Fiddaman r = path;
145*b30d1939SAndy Fiddaman if (t == r + 1) x = r;
146*b30d1939SAndy Fiddaman v = s = t = x;
147*b30d1939SAndy Fiddaman }
148*b30d1939SAndy Fiddaman else
149*b30d1939SAndy Fiddaman {
150*b30d1939SAndy Fiddaman *t = c;
151*b30d1939SAndy Fiddaman t = o;
152*b30d1939SAndy Fiddaman }
153da2e3ebdSchin }
154*b30d1939SAndy Fiddaman #else
155*b30d1939SAndy Fiddaman r = t;
156*b30d1939SAndy Fiddaman #endif
157*b30d1939SAndy Fiddaman break;
158*b30d1939SAndy Fiddaman default:
159*b30d1939SAndy Fiddaman if ((flags & PATH_PHYSICAL) && loop < 32 && (t - 1) > path)
160da2e3ebdSchin {
161*b30d1939SAndy Fiddaman int c;
162*b30d1939SAndy Fiddaman char buf[PATH_MAX];
163*b30d1939SAndy Fiddaman
164*b30d1939SAndy Fiddaman c = *(t - 1);
165*b30d1939SAndy Fiddaman *(t - 1) = 0;
166*b30d1939SAndy Fiddaman dots = pathgetlink(phys, buf, sizeof(buf));
167*b30d1939SAndy Fiddaman *(t - 1) = c;
168*b30d1939SAndy Fiddaman if (dots > 0)
169*b30d1939SAndy Fiddaman {
170*b30d1939SAndy Fiddaman loop++;
171*b30d1939SAndy Fiddaman strcpy(buf + dots, s - (*s != 0));
172*b30d1939SAndy Fiddaman if (*buf == '/') p = r = path;
173*b30d1939SAndy Fiddaman v = s = t = p;
174*b30d1939SAndy Fiddaman strcpy(p, buf);
175*b30d1939SAndy Fiddaman }
176*b30d1939SAndy Fiddaman else if (dots < 0 && errno == ENOENT)
177*b30d1939SAndy Fiddaman {
178*b30d1939SAndy Fiddaman if (flags & PATH_EXISTS)
179*b30d1939SAndy Fiddaman {
180*b30d1939SAndy Fiddaman strcpy(path, s);
181*b30d1939SAndy Fiddaman return 0;
182*b30d1939SAndy Fiddaman }
183*b30d1939SAndy Fiddaman flags &= ~(PATH_PHYSICAL|PATH_DOTDOT);
184*b30d1939SAndy Fiddaman }
185*b30d1939SAndy Fiddaman dots = 4;
186da2e3ebdSchin }
187*b30d1939SAndy Fiddaman break;
188da2e3ebdSchin }
189*b30d1939SAndy Fiddaman if (dots >= 4 && (flags & PATH_EXISTS) && (t - 1) >= v && (t > path + 1 || t > path && *(t - 1) && *(t - 1) != '/'))
190da2e3ebdSchin {
191*b30d1939SAndy Fiddaman struct stat st;
192da2e3ebdSchin
193da2e3ebdSchin *(t - 1) = 0;
194*b30d1939SAndy Fiddaman if (stat(phys, &st))
195da2e3ebdSchin {
196*b30d1939SAndy Fiddaman strcpy(path, s);
197*b30d1939SAndy Fiddaman return 0;
198da2e3ebdSchin }
199*b30d1939SAndy Fiddaman v = t;
200*b30d1939SAndy Fiddaman if (*s) *(t - 1) = '/';
201da2e3ebdSchin }
202*b30d1939SAndy Fiddaman if (!*s)
203da2e3ebdSchin {
204*b30d1939SAndy Fiddaman if (t > path && !*(t - 1)) t--;
205*b30d1939SAndy Fiddaman if (t == path) *t++ = '.';
206da2e3ebdSchin #if DONT_PRESERVE_TRAILING_SLASH
207*b30d1939SAndy Fiddaman else if (t > path + 1 && *(t - 1) == '/') t--;
208da2e3ebdSchin #else
209*b30d1939SAndy Fiddaman else if ((s <= path || *(s - 1) != '/') && t > path + 1 && *(t - 1) == '/') t--;
210da2e3ebdSchin #endif
211*b30d1939SAndy Fiddaman *t = 0;
212*b30d1939SAndy Fiddaman errno = oerrno;
213*b30d1939SAndy Fiddaman return t;
214*b30d1939SAndy Fiddaman }
215*b30d1939SAndy Fiddaman dots = 0;
216*b30d1939SAndy Fiddaman p = t;
217*b30d1939SAndy Fiddaman break;
218*b30d1939SAndy Fiddaman default:
219*b30d1939SAndy Fiddaman dots = 4;
220*b30d1939SAndy Fiddaman break;
221da2e3ebdSchin }
222da2e3ebdSchin }
223