OpenCoverage

pathcanon.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/bash/src/lib/sh/pathcanon.c
Source codeSwitch to Preprocessed file
LineSourceCount
1/* pathcanon.c -- canonicalize and manipulate pathnames. */-
2-
3/* Copyright (C) 2000 Free Software Foundation, Inc.-
4-
5 This file is part of GNU Bash, the Bourne Again SHell.-
6-
7 Bash is free software: you can redistribute it and/or modify-
8 it under the terms of the GNU General Public License as published by-
9 the Free Software Foundation, either version 3 of the License, or-
10 (at your option) any later version.-
11-
12 Bash is distributed in the hope that it will be useful,-
13 but WITHOUT ANY WARRANTY; without even the implied warranty of-
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the-
15 GNU General Public License for more details.-
16-
17 You should have received a copy of the GNU General Public License-
18 along with Bash. If not, see <http://www.gnu.org/licenses/>.-
19*/-
20-
21#include <config.h>-
22-
23#include <bashtypes.h>-
24#if defined (HAVE_SYS_PARAM_H)-
25# include <sys/param.h>-
26#endif-
27#include <posixstat.h>-
28-
29#if defined (HAVE_UNISTD_H)-
30# include <unistd.h>-
31#endif-
32-
33#include <filecntl.h>-
34#include <bashansi.h>-
35#include <stdio.h>-
36#include <chartypes.h>-
37#include <errno.h>-
38-
39#include "shell.h"-
40-
41#if !defined (errno)-
42extern int errno;-
43#endif-
44-
45#if defined (__CYGWIN__)-
46#include <sys/cygwin.h>-
47-
48static int-
49_is_cygdrive (path)-
50 char *path;-
51{-
52 static char user[MAXPATHLEN];-
53 static char system[MAXPATHLEN];-
54 static int first_time = 1;-
55-
56 /* If the path is the first part of a network path, treat it as-
57 existing. */-
58 if (path[0] == '/' && path[1] == '/' && !strchr (path + 2, '/'))-
59 return 1; -
60 /* Otherwise check for /cygdrive prefix. */-
61 if (first_time)-
62 {-
63 char user_flags[MAXPATHLEN];-
64 char system_flags[MAXPATHLEN];-
65 /* Get the cygdrive info */-
66 cygwin_internal (CW_GET_CYGDRIVE_INFO, user, system, user_flags, system_flags);-
67 first_time = 0;-
68 }-
69 return !strcasecmp (path, user) || !strcasecmp (path, system);-
70}-
71#endif /* __CYGWIN__ */ -
72-
73/* Return 1 if PATH corresponds to a directory. A function for debugging. */-
74static int-
75_path_isdir (path)-
76 char *path;-
77{-
78 int l;-
79 struct stat sb;-
80-
81 /* This should leave errno set to the correct value. */-
82 errno = 0;-
83 l = stat (path, &sb) == 0 && S_ISDIR (sb.st_mode);
stat (path, &sb) == 0Description
TRUEevaluated 38354 times by 1 test
Evaluated by:
  • Self test
FALSEevaluated 5 times by 1 test
Evaluated by:
  • Self test
(((( sb.st_mod... == (0040000))Description
TRUEevaluated 38353 times by 1 test
Evaluated by:
  • Self test
FALSEevaluated 1 time by 1 test
Evaluated by:
  • Self test
1-38354
84#if defined (__CYGWIN__)-
85 if (l == 0)-
86 l = _is_cygdrive (path);-
87#endif-
88 return l;
executed 38359 times by 1 test: return l;
Executed by:
  • Self test
38359
89}-
90-
91/* Canonicalize PATH, and return a new path. The new path differs from PATH-
92 in that:-
93 Multple `/'s are collapsed to a single `/'.-
94 Leading `./'s and trailing `/.'s are removed.-
95 Trailing `/'s are removed.-
96 Non-leading `../'s and trailing `..'s are handled by removing-
97 portions of the path. */-
98-
99/* Look for ROOTEDPATH, PATHSEP, DIRSEP, and ISDIRSEP in ../../general.h */-
100-
101#define DOUBLE_SLASH(p) ((p[0] == '/') && (p[1] == '/') && p[2] != '/')-
102-
103char *-
104sh_canonpath (path, flags)-
105 char *path;-
106 int flags;-
107{-
108 char stub_char;-
109 char *result, *p, *q, *base, *dotdot;-
110 int rooted, double_slash_path;-
111-
112 /* The result cannot be larger than the input PATH. */-
113 result = (flags & PATH_NOALLOC) ? path : savestring (path);
(flags & 0x0008)Description
TRUEnever evaluated
FALSEevaluated 5515 times by 1 test
Evaluated by:
  • Self test
0-5515
114-
115 /* POSIX.2 says to leave a leading `//' alone. On cygwin, we skip over any-
116 leading `x:' (dos drive name). */-
117 if (rooted = ROOTEDPATH(path))
rooted = (((path)[0] == '/'))Description
TRUEevaluated 5515 times by 1 test
Evaluated by:
  • Self test
FALSEnever evaluated
0-5515
118 {-
119 stub_char = DIRSEP;-
120#if defined (__CYGWIN__)-
121 base = (ISALPHA((unsigned char)result[0]) && result[1] == ':') ? result + 3 : result + 1;-
122#else-
123 base = result + 1;-
124#endif-
125 double_slash_path = DOUBLE_SLASH (path);
(path[0] == '/')Description
TRUEevaluated 5515 times by 1 test
Evaluated by:
  • Self test
FALSEnever evaluated
(path[1] == '/')Description
TRUEnever evaluated
FALSEevaluated 5515 times by 1 test
Evaluated by:
  • Self test
path[2] != '/'Description
TRUEnever evaluated
FALSEnever evaluated
0-5515
126 base += double_slash_path;-
127 }
executed 5515 times by 1 test: end of block
Executed by:
  • Self test
5515
128 else-
129 {-
130 stub_char = '.';-
131#if defined (__CYGWIN__)-
132 base = (ISALPHA((unsigned char)result[0]) && result[1] == ':') ? result + 2 : result;-
133#else-
134 base = result;-
135#endif-
136 double_slash_path = 0;-
137 }
never executed: end of block
0
138-
139 /*-
140 * invariants:-
141 * base points to the portion of the path we want to modify-
142 * p points at beginning of path element we're considering.-
143 * q points just past the last path element we wrote (no slash).-
144 * dotdot points just past the point where .. cannot backtrack-
145 * any further (no slash).-
146 */-
147 p = q = dotdot = base;-
148-
149 while (*p)
*pDescription
TRUEevaluated 71210 times by 1 test
Evaluated by:
  • Self test
FALSEevaluated 5509 times by 1 test
Evaluated by:
  • Self test
5509-71210
150 {-
151 if (ISDIRSEP(p[0])) /* null element */
((p[0]) == '/')Description
TRUEevaluated 32850 times by 1 test
Evaluated by:
  • Self test
FALSEevaluated 38360 times by 1 test
Evaluated by:
  • Self test
32850-38360
152 p++;
executed 32850 times by 1 test: p++;
Executed by:
  • Self test
32850
153 else if(p[0] == '.' && PATHSEP(p[1])) /* . and ./ */
p[0] == '.'Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • Self test
FALSEevaluated 38359 times by 1 test
Evaluated by:
  • Self test
((p[1]) == '/')Description
TRUEevaluated 1 time by 1 test
Evaluated by:
  • Self test
FALSEnever evaluated
(p[1]) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0-38359
154 p += 1; /* don't count the separator in case it is nul */
executed 1 time by 1 test: p += 1;
Executed by:
  • Self test
1
155 else if (p[0] == '.' && p[1] == '.' && PATHSEP(p[2])) /* .. and ../ */
p[0] == '.'Description
TRUEnever evaluated
FALSEevaluated 38359 times by 1 test
Evaluated by:
  • Self test
p[1] == '.'Description
TRUEnever evaluated
FALSEnever evaluated
((p[2]) == '/')Description
TRUEnever evaluated
FALSEnever evaluated
(p[2]) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0-38359
156 {-
157 p += 2; /* skip `..' */-
158 if (q > dotdot) /* can backtrack */
q > dotdotDescription
TRUEnever evaluated
FALSEnever evaluated
0
159 {-
160 if (flags & PATH_CHECKDOTDOT)
flags & 0x0001Description
TRUEnever evaluated
FALSEnever evaluated
0
161 {-
162 char c;-
163-
164 /* Make sure what we have so far corresponds to a valid-
165 path before we chop some of it off. */-
166 c = *q;-
167 *q = '\0';-
168 if (_path_isdir (result) == 0)
_path_isdir (result) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
169 {-
170 if ((flags & PATH_NOALLOC) == 0)
(flags & 0x0008) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
171 free (result);
never executed: sh_xfree((result), "pathcanon.c", 171);
0
172 return ((char *)NULL);
never executed: return ((char *) ((void *)0) );
0
173 }-
174 *q = c;-
175 }
never executed: end of block
0
176-
177 while (--q > dotdot && ISDIRSEP(*q) == 0)
--q > dotdotDescription
TRUEnever evaluated
FALSEnever evaluated
((*q) == '/') == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
178 ;
never executed: ;
0
179 }
never executed: end of block
0
180 else if (rooted == 0)
rooted == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
181 {-
182 /* /.. is / but ./../ is .. */-
183 if (q != base)
q != baseDescription
TRUEnever evaluated
FALSEnever evaluated
0
184 *q++ = DIRSEP;
never executed: *q++ = '/';
0
185 *q++ = '.';-
186 *q++ = '.';-
187 dotdot = q;-
188 }
never executed: end of block
0
189 }
never executed: end of block
0
190 else /* real path element */-
191 {-
192 /* add separator if not at start of work portion of result */-
193 if (q != base)
q != baseDescription
TRUEevaluated 32849 times by 1 test
Evaluated by:
  • Self test
FALSEevaluated 5510 times by 1 test
Evaluated by:
  • Self test
5510-32849
194 *q++ = DIRSEP;
executed 32849 times by 1 test: *q++ = '/';
Executed by:
  • Self test
32849
195 while (*p && (ISDIRSEP(*p) == 0))
*pDescription
TRUEevaluated 323202 times by 1 test
Evaluated by:
  • Self test
FALSEevaluated 5510 times by 1 test
Evaluated by:
  • Self test
(((*p) == '/') == 0)Description
TRUEevaluated 290353 times by 1 test
Evaluated by:
  • Self test
FALSEevaluated 32849 times by 1 test
Evaluated by:
  • Self test
5510-323202
196 *q++ = *p++;
executed 290353 times by 1 test: *q++ = *p++;
Executed by:
  • Self test
290353
197 /* Check here for a valid directory with _path_isdir. */-
198 if (flags & PATH_CHECKEXISTS)
flags & 0x0002Description
TRUEevaluated 38359 times by 1 test
Evaluated by:
  • Self test
FALSEnever evaluated
0-38359
199 {-
200 char c;-
201-
202 /* Make sure what we have so far corresponds to a valid-
203 path before we chop some of it off. */-
204 c = *q;-
205 *q = '\0';-
206 if (_path_isdir (result) == 0)
_path_isdir (result) == 0Description
TRUEevaluated 6 times by 1 test
Evaluated by:
  • Self test
FALSEevaluated 38353 times by 1 test
Evaluated by:
  • Self test
6-38353
207 {-
208 if ((flags & PATH_NOALLOC) == 0)
(flags & 0x0008) == 0Description
TRUEevaluated 6 times by 1 test
Evaluated by:
  • Self test
FALSEnever evaluated
0-6
209 free (result);
executed 6 times by 1 test: sh_xfree((result), "pathcanon.c", 209);
Executed by:
  • Self test
6
210 return ((char *)NULL);
executed 6 times by 1 test: return ((char *) ((void *)0) );
Executed by:
  • Self test
6
211 }-
212 *q = c;-
213 }
executed 38353 times by 1 test: end of block
Executed by:
  • Self test
38353
214 }
executed 38353 times by 1 test: end of block
Executed by:
  • Self test
38353
215 }-
216-
217 /* Empty string is really ``.'' or `/', depending on what we started with. */-
218 if (q == result)
q == resultDescription
TRUEnever evaluated
FALSEevaluated 5509 times by 1 test
Evaluated by:
  • Self test
0-5509
219 *q++ = stub_char;
never executed: *q++ = stub_char;
0
220 *q = '\0';-
221-
222 /* If the result starts with `//', but the original path does not, we-
223 can turn the // into /. Because of how we set `base', this should never-
224 be true, but it's a sanity check. */-
225 if (DOUBLE_SLASH(result) && double_slash_path == 0)
(result[0] == '/')Description
TRUEevaluated 5509 times by 1 test
Evaluated by:
  • Self test
FALSEnever evaluated
(result[1] == '/')Description
TRUEnever evaluated
FALSEevaluated 5509 times by 1 test
Evaluated by:
  • Self test
result[2] != '/'Description
TRUEnever evaluated
FALSEnever evaluated
double_slash_path == 0Description
TRUEnever evaluated
FALSEnever evaluated
0-5509
226 {-
227 if (result[2] == '\0') /* short-circuit for bare `//' */
result[2] == '\0'Description
TRUEnever evaluated
FALSEnever evaluated
0
228 result[1] = '\0';
never executed: result[1] = '\0';
0
229 else-
230 strcpy (result, result + 1);
never executed: strcpy (result, result + 1);
0
231 }-
232-
233 return (result);
executed 5509 times by 1 test: return (result);
Executed by:
  • Self test
5509
234}-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.1.2