Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtksh / ksh93 / src / lib / libast / path / pathcanon.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: pathcanon.c /main/2 1996/05/08 19:52:14 drk $ */
24 /***************************************************************
25 *                                                              *
26 *                      AT&T - PROPRIETARY                      *
27 *                                                              *
28 *         THIS IS PROPRIETARY SOURCE CODE LICENSED BY          *
29 *                          AT&T CORP.                          *
30 *                                                              *
31 *                Copyright (c) 1995 AT&T Corp.                 *
32 *                     All Rights Reserved                      *
33 *                                                              *
34 *           This software is licensed by AT&T Corp.            *
35 *       under the terms and conditions of the license in       *
36 *       http://www.research.att.com/orgs/ssr/book/reuse        *
37 *                                                              *
38 *               This software was created by the               *
39 *           Software Engineering Research Department           *
40 *                    AT&T Bell Laboratories                    *
41 *                                                              *
42 *               For further information contact                *
43 *                     gsf@research.att.com                     *
44 *                                                              *
45 ***************************************************************/
46
47 /* : : generated by proto : : */
48
49 #if !defined(__PROTO__)
50 #if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)
51 #if defined(__cplusplus)
52 #define __MANGLE__      "C"
53 #else
54 #define __MANGLE__
55 #endif
56 #define __STDARG__
57 #define __PROTO__(x)    x
58 #define __OTORP__(x)
59 #define __PARAM__(n,o)  n
60 #if !defined(__STDC__) && !defined(__cplusplus)
61 #if !defined(c_plusplus)
62 #define const
63 #endif
64 #define signed
65 #define void            int
66 #define volatile
67 #define __V_            char
68 #else
69 #define __V_            void
70 #endif
71 #else
72 #define __PROTO__(x)    ()
73 #define __OTORP__(x)    x
74 #define __PARAM__(n,o)  o
75 #define __MANGLE__
76 #define __V_            char
77 #define const
78 #define signed
79 #define void            int
80 #define volatile
81 #endif
82 #if defined(__cplusplus) || defined(c_plusplus)
83 #define __VARARG__      ...
84 #else
85 #define __VARARG__
86 #endif
87 #if defined(__STDARG__)
88 #define __VA_START__(p,a)       va_start(p,a)
89 #else
90 #define __VA_START__(p,a)       va_start(p)
91 #endif
92 #endif
93 #include <ast.h>
94 #include <ls.h>
95 #include <fs3d.h>
96 #include <error.h>
97
98 char*
99 pathcanon __PARAM__((char* path, int flags), (path, flags)) __OTORP__(char* path; int flags;){
100         register char*  p;
101         register char*  r;
102         register char*  s;
103         register char*  t;
104         register int    dots;
105         int             loop;
106         int             oerrno;
107 #if defined(FS_3D)
108         long            visits = 0;
109 #endif
110
111         oerrno = errno;
112         dots = loop = 0;
113         p = r = s = t = path;
114         for (;;) switch (*t++ = *s++)
115         {
116         case '.':
117                 dots++;
118                 break;
119         case 0:
120                 s--;
121                 /*FALLTHROUGH*/
122         case '/':
123                 while (*s == '/') s++;
124                 switch (dots)
125                 {
126                 case 1:
127                         t -= 2;
128                         break;
129                 case 2:
130                         if ((flags & (PATH_DOTDOT|PATH_EXISTS)) == PATH_DOTDOT)
131                         {
132                                 struct stat     st;
133
134                                 *(t - 2) = 0;
135                                 if (stat(path, &st))
136                                 {
137                                         strcpy(path, s);
138                                         return(0);
139                                 }
140                                 *(t - 2) = '.';
141                         }
142 #if PRESERVE_TRAILING_SLASH
143                         if (t - 5 < r) r = t;
144 #else
145                         if (t - 5 < r)
146                         {
147                                 if (t - 4 == r) t = r + 1;
148                                 else r = t;
149                         }
150 #endif
151                         else for (t -= 5; t > r && *(t - 1) != '/'; t--);
152                         break;
153                 case 3:
154 #if defined(FS_3D)
155                         {
156                                 char*           x;
157                                 char*           o;
158                                 int             c;
159
160                                 o = t;
161                                 if ((t -= 5) <= path) t = path + 1;
162                                 c = *t;
163                                 *t = 0;
164                                 if (x = pathnext(path, s - (*s != 0), &visits))
165                                 {
166                                         r = path;
167                                         if (t == r + 1) x = r;
168                                         s = t = x;
169                                 }
170                                 else
171                                 {
172                                         *t = c;
173                                         t = o;
174                                 }
175                         }
176 #else
177                         r = t;
178 #endif
179                         break;
180                 default:
181                         if ((flags & PATH_PHYSICAL) && loop < 32 && (t - 1) > path)
182                         {
183                                 int     c;
184                                 char    buf[PATH_MAX];
185
186                                 c = *(t - 1);
187                                 *(t - 1) = 0;
188                                 dots = pathgetlink(path, buf, sizeof(buf));
189                                 *(t - 1) = c;
190                                 if (dots > 0)
191                                 {
192                                         loop++;
193                                         strcpy(buf + dots, s - (*s != 0));
194                                         if (*buf == '/') p = r = path;
195                                         s = t = p;
196                                         strcpy(p, buf);
197                                 }
198                                 else if (dots < 0 && errno == ENOENT)
199                                 {
200                                         if (flags & PATH_EXISTS)
201                                         {
202                                                 strcpy(path, s);
203                                                 return(0);
204                                         }
205                                         flags &= ~(PATH_PHYSICAL|PATH_DOTDOT);
206                                 }
207                                 dots = 4;
208                         }
209                         break;
210                 }
211                 if (dots >= 4 && (flags & PATH_EXISTS) && (t > path + 1 || t > path && *(t - 1) && *(t - 1) != '/'))
212                 {
213                         struct stat     st;
214
215                         *(t - 1) = 0;
216                         if (stat(path, &st))
217                         {
218                                 strcpy(path, s);
219                                 return(0);
220                         }
221                         if (*s) *(t - 1) = '/';
222                 }
223                 if (!*s)
224                 {
225                         if (t > path && !*(t - 1)) t--;
226                         if (t == path) *t++ = '.';
227 #if DONT_PRESERVE_TRAILING_SLASH
228                         else if (t > path + 1 && *(t - 1) == '/') t--;
229 #else
230                         else if ((s <= path || *(s - 1) != '/') && t > path + 1 && *(t - 1) == '/') t--;
231 #endif
232                         *t = 0;
233                         errno = oerrno;
234                         return(t);
235                 }
236                 dots = 0;
237                 p = t;
238                 break;
239         default:
240                 dots = 4;
241                 break;
242         }
243 }