1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
27 * in-place path name canonicalization -- preserves the logical view
28 * pointer to trailing 0 in path returned
30 * remove redundant .'s and /'s
31 * move ..'s to the front
32 * /.. preserved (for pdu and newcastle hacks)
34 * if (flags&PATH_PHYSICAL) then symlinks resolved at each component
35 * if (flags&PATH_DOTDOT) then each .. checked for access
36 * if (flags&PATH_EXISTS) then path must exist at each component
37 * if (flags&PATH_VERIFIED(n)) then first n chars of path exist
39 * longer pathname possible if (flags&PATH_PHYSICAL) or FS_3D ... involved
40 * 0 returned on error and if (flags&(PATH_DOTDOT|PATH_EXISTS)) then path
41 * will contain the components following the failure point
50 pathcanon(char* path
, int flags
)
68 v
= path
+ ((flags
>> 5) & 01777);
71 if (*(path
+ 1) == '/' && *astconf("PATH_LEADING_SLASHES", NiL
, NiL
) == '1')
72 do path
++; while (*path
== '/' && *(path
+ 1) == '/');
77 for (;;) switch (*t
++ = *s
++)
86 while (*s
== '/') s
++;
93 if ((flags
& (PATH_DOTDOT
|PATH_EXISTS
)) == PATH_DOTDOT
&& (t
- 2) >= v
)
105 #if PRESERVE_TRAILING_SLASH
106 if (t
- 5 < r
) r
= t
;
110 if (t
- 4 == r
) t
= r
+ 1;
114 else for (t
-= 5; t
> r
&& *(t
- 1) != '/'; t
--);
124 if ((t
-= 5) <= path
) t
= path
+ 1;
127 if (x
= pathnext(phys
, s
- (*s
!= 0), &visits
))
130 if (t
== r
+ 1) x
= r
;
144 if ((flags
& PATH_PHYSICAL
) && loop
< 32 && (t
- 1) > path
)
151 dots
= pathgetlink(phys
, buf
, sizeof(buf
));
156 strcpy(buf
+ dots
, s
- (*s
!= 0));
157 if (*buf
== '/') p
= r
= path
;
161 else if (dots
< 0 && errno
== ENOENT
)
163 if (flags
& PATH_EXISTS
)
168 flags
&= ~(PATH_PHYSICAL
|PATH_DOTDOT
);
174 if (dots
>= 4 && (flags
& PATH_EXISTS
) && (t
- 1) >= v
&& (t
> path
+ 1 || t
> path
&& *(t
- 1) && *(t
- 1) != '/'))
185 if (*s
) *(t
- 1) = '/';
189 if (t
> path
&& !*(t
- 1)) t
--;
190 if (t
== path
) *t
++ = '.';
191 #if DONT_PRESERVE_TRAILING_SLASH
192 else if (t
> path
+ 1 && *(t
- 1) == '/') t
--;
194 else if ((s
<= path
|| *(s
- 1) != '/') && t
> path
+ 1 && *(t
- 1) == '/') t
--;