OpenCoverage

pathphys.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/bash/src/lib/sh/pathphys.c
Source codeSwitch to Preprocessed file
LineSourceCount
1/* pathphys.c -- return pathname with all symlinks expanded. */-
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 (MAXSYMLINKS)-
42# define MAXSYMLINKS 32-
43#endif-
44-
45#if !defined (errno)-
46extern int errno;-
47#endif /* !errno */-
48-
49extern char *get_working_directory __P((char *));-
50-
51static int-
52_path_readlink (path, buf, bufsiz)-
53 char *path;-
54 char *buf;-
55 int bufsiz;-
56{-
57#ifdef HAVE_READLINK-
58 return readlink (path, buf, bufsiz);
executed 7 times by 1 test: return readlink (path, buf, bufsiz);
Executed by:
  • Self test
7
59#else-
60 errno = EINVAL;-
61 return -1;-
62#endif-
63}-
64-
65/* Look for ROOTEDPATH, PATHSEP, DIRSEP, and ISDIRSEP in ../../general.h */-
66-
67#define DOUBLE_SLASH(p) ((p[0] == '/') && (p[1] == '/') && p[2] != '/')-
68-
69/*-
70 * Return PATH with all symlinks expanded in newly-allocated memory.-
71 * This always gets an absolute pathname.-
72 */-
73-
74char *-
75sh_physpath (path, flags)-
76 char *path;-
77 int flags;-
78{-
79 char tbuf[PATH_MAX+1], linkbuf[PATH_MAX+1];-
80 char *result, *p, *q, *qsave, *qbase, *workpath;-
81 int double_slash_path, linklen, nlink;-
82-
83 linklen = strlen (path);-
84-
85#if 0-
86 /* First sanity check -- punt immediately if the name is too long. */-
87 if (linklen >= PATH_MAX)-
88 return (savestring (path));-
89#endif-
90-
91 nlink = 0;-
92 q = result = (char *)xmalloc (PATH_MAX + 1);-
93-
94 /* Even if we get something longer than PATH_MAX, we might be able to-
95 shorten it, so we try. */-
96 if (linklen >= PATH_MAX)
linklen >= 4096Description
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • Self test
0-4
97 workpath = savestring (path);
never executed: workpath = (char *)strcpy (sh_xmalloc((1 + strlen (path)), "pathphys.c", 97), (path));
0
98 else-
99 {-
100 workpath = (char *)xmalloc (PATH_MAX + 1);-
101 strcpy (workpath, path);-
102 }
executed 4 times by 1 test: end of block
Executed by:
  • Self test
4
103-
104 /* This always gets an absolute pathname. */-
105-
106 /* POSIX.2 says to leave a leading `//' alone. On cygwin, we skip over any-
107 leading `x:' (dos drive name). */-
108#if defined (__CYGWIN__)-
109 qbase = (ISALPHA((unsigned char)workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1;-
110#else-
111 qbase = workpath + 1;-
112#endif-
113 double_slash_path = DOUBLE_SLASH (workpath);
(workpath[0] == '/')Description
TRUEevaluated 4 times by 1 test
Evaluated by:
  • Self test
FALSEnever evaluated
(workpath[1] == '/')Description
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • Self test
workpath[2] != '/'Description
TRUEnever evaluated
FALSEnever evaluated
0-4
114 qbase += double_slash_path;-
115-
116 for (p = workpath; p < qbase; )
p < qbaseDescription
TRUEevaluated 4 times by 1 test
Evaluated by:
  • Self test
FALSEevaluated 4 times by 1 test
Evaluated by:
  • Self test
4
117 *q++ = *p++;
executed 4 times by 1 test: *q++ = *p++;
Executed by:
  • Self test
4
118 qbase = q;-
119-
120 /*-
121 * invariants:-
122 * qbase points to the portion of the result path we want to modify-
123 * p points at beginning of path element we're considering.-
124 * q points just past the last path element we wrote (no slash).-
125 *-
126 * XXX -- need to fix error checking for too-long pathnames-
127 */-
128-
129 while (*p)
*pDescription
TRUEevaluated 13 times by 1 test
Evaluated by:
  • Self test
FALSEevaluated 4 times by 1 test
Evaluated by:
  • Self test
4-13
130 {-
131 if (ISDIRSEP(p[0])) /* null element */
((p[0]) == '/')Description
TRUEevaluated 6 times by 1 test
Evaluated by:
  • Self test
FALSEevaluated 7 times by 1 test
Evaluated by:
  • Self test
6-7
132 p++;
executed 6 times by 1 test: p++;
Executed by:
  • Self test
6
133 else if(p[0] == '.' && PATHSEP(p[1])) /* . and ./ */
p[0] == '.'Description
TRUEnever evaluated
FALSEevaluated 7 times by 1 test
Evaluated by:
  • Self test
((p[1]) == '/')Description
TRUEnever evaluated
FALSEnever evaluated
(p[1]) == 0Description
TRUEnever evaluated
FALSEnever evaluated
0-7
134 p += 1; /* don't count the separator in case it is nul */
never executed: p += 1;
0
135 else if (p[0] == '.' && p[1] == '.' && PATHSEP(p[2])) /* .. and ../ */
p[0] == '.'Description
TRUEnever evaluated
FALSEevaluated 7 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-7
136 {-
137 p += 2; /* skip `..' */-
138 if (q > qbase)
q > qbaseDescription
TRUEnever evaluated
FALSEnever evaluated
0
139 {-
140 while (--q > qbase && ISDIRSEP(*q) == 0)
--q > qbaseDescription
TRUEnever evaluated
FALSEnever evaluated
((*q) == '/') == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
141 ;
never executed: ;
0
142 }
never executed: end of block
0
143 }
never executed: end of block
0
144 else /* real path element */-
145 {-
146 /* add separator if not at start of work portion of result */-
147 qsave = q;-
148 if (q != qbase)
q != qbaseDescription
TRUEevaluated 6 times by 1 test
Evaluated by:
  • Self test
FALSEevaluated 1 time by 1 test
Evaluated by:
  • Self test
1-6
149 *q++ = DIRSEP;
executed 6 times by 1 test: *q++ = '/';
Executed by:
  • Self test
6
150 while (*p && (ISDIRSEP(*p) == 0))
*pDescription
TRUEevaluated 59 times by 1 test
Evaluated by:
  • Self test
FALSEevaluated 1 time by 1 test
Evaluated by:
  • Self test
(((*p) == '/') == 0)Description
TRUEevaluated 53 times by 1 test
Evaluated by:
  • Self test
FALSEevaluated 6 times by 1 test
Evaluated by:
  • Self test
1-59
151 {-
152 if (q - result >= PATH_MAX)
q - result >= 4096Description
TRUEnever evaluated
FALSEevaluated 53 times by 1 test
Evaluated by:
  • Self test
0-53
153 {-
154#ifdef ENAMETOOLONG-
155 errno = ENAMETOOLONG;-
156#else-
157 errno = EINVAL;-
158#endif-
159 goto error;
never executed: goto error;
0
160 }-
161 -
162 *q++ = *p++;-
163 }
executed 53 times by 1 test: end of block
Executed by:
  • Self test
53
164-
165 *q = '\0';-
166-
167 linklen = _path_readlink (result, linkbuf, PATH_MAX);-
168 if (linklen < 0) /* if errno == EINVAL, it's not a symlink */
linklen < 0Description
TRUEevaluated 7 times by 1 test
Evaluated by:
  • Self test
FALSEnever evaluated
0-7
169 {-
170 if (errno != EINVAL)
(*__errno_location ()) != 22Description
TRUEnever evaluated
FALSEevaluated 7 times by 1 test
Evaluated by:
  • Self test
0-7
171 goto error;
never executed: goto error;
0
172 continue;
executed 7 times by 1 test: continue;
Executed by:
  • Self test
7
173 }-
174-
175 /* It's a symlink, and the value is in LINKBUF. */-
176 nlink++;-
177 if (nlink > MAXSYMLINKS)
nlink > 20Description
TRUEnever evaluated
FALSEnever evaluated
0
178 {-
179#ifdef ELOOP-
180 errno = ELOOP;-
181#else-
182 errno = EINVAL;-
183#endif-
184error:
code before this statement never executed: error:
0
185 free (result);-
186 free (workpath);-
187 return ((char *)NULL);
never executed: return ((char *) ((void *)0) );
0
188 }-
189-
190 linkbuf[linklen] = '\0';-
191-
192 /* If the new path length would overrun PATH_MAX, punt now. */-
193 if ((strlen (p) + linklen + 2) >= PATH_MAX)
(strlen (p) + ...n + 2) >= 4096Description
TRUEnever evaluated
FALSEnever evaluated
0
194 {-
195#ifdef ENAMETOOLONG-
196 errno = ENAMETOOLONG;-
197#else-
198 errno = EINVAL;-
199#endif-
200 goto error;
never executed: goto error;
0
201 }-
202-
203 /* Form the new pathname by copying the link value to a temporary-
204 buffer and appending the rest of `workpath'. Reset p to point-
205 to the start of the rest of the path. If the link value is an-
206 absolute pathname, reset p, q, and qbase. If not, reset p-
207 and q. */-
208 strcpy (tbuf, linkbuf);-
209 tbuf[linklen] = '/';-
210 strcpy (tbuf + linklen, p);-
211 strcpy (workpath, tbuf);-
212-
213 if (ABSPATH(linkbuf))
((linkbuf)[0] == '/')Description
TRUEnever evaluated
FALSEnever evaluated
0
214 {-
215 q = result;-
216 /* Duplicating some code here... */-
217#if defined (__CYGWIN__)-
218 qbase = (ISALPHA((unsigned char)workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1;-
219#else-
220 qbase = workpath + 1;-
221#endif-
222 double_slash_path = DOUBLE_SLASH (workpath);
(workpath[0] == '/')Description
TRUEnever evaluated
FALSEnever evaluated
(workpath[1] == '/')Description
TRUEnever evaluated
FALSEnever evaluated
workpath[2] != '/'Description
TRUEnever evaluated
FALSEnever evaluated
0
223 qbase += double_slash_path;-
224 -
225 for (p = workpath; p < qbase; )
p < qbaseDescription
TRUEnever evaluated
FALSEnever evaluated
0
226 *q++ = *p++;
never executed: *q++ = *p++;
0
227 qbase = q;-
228 }
never executed: end of block
0
229 else-
230 {-
231 p = workpath;-
232 q = qsave;-
233 }
never executed: end of block
0
234 }-
235 }-
236-
237 *q = '\0';-
238 free (workpath);-
239-
240 /* If the result starts with `//', but the original path does not, we-
241 can turn the // into /. Because of how we set `qbase', this should never-
242 be true, but it's a sanity check. */-
243 if (DOUBLE_SLASH(result) && double_slash_path == 0)
(result[0] == '/')Description
TRUEevaluated 4 times by 1 test
Evaluated by:
  • Self test
FALSEnever evaluated
(result[1] == '/')Description
TRUEnever evaluated
FALSEevaluated 4 times by 1 test
Evaluated by:
  • Self test
result[2] != '/'Description
TRUEnever evaluated
FALSEnever evaluated
double_slash_path == 0Description
TRUEnever evaluated
FALSEnever evaluated
0-4
244 {-
245 if (result[2] == '\0') /* short-circuit for bare `//' */
result[2] == '\0'Description
TRUEnever evaluated
FALSEnever evaluated
0
246 result[1] = '\0';
never executed: result[1] = '\0';
0
247 else-
248 strcpy (result, result + 1);
never executed: strcpy (result, result + 1);
0
249 }-
250-
251 return (result);
executed 4 times by 1 test: return (result);
Executed by:
  • Self test
4
252}-
253-
254char *-
255sh_realpath (pathname, resolved)-
256 const char *pathname;-
257 char *resolved;-
258{-
259 char *tdir, *wd;-
260-
261 if (pathname == 0 || *pathname == '\0')
pathname == 0Description
TRUEnever evaluated
FALSEnever evaluated
*pathname == '\0'Description
TRUEnever evaluated
FALSEnever evaluated
0
262 {-
263 errno = (pathname == 0) ? EINVAL : ENOENT;-
264 return ((char *)NULL);
never executed: return ((char *) ((void *)0) );
0
265 }-
266-
267 if (ABSPATH (pathname) == 0)
((pathname)[0] == '/') == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
268 {-
269 wd = get_working_directory ("sh_realpath");-
270 if (wd == 0)
wd == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
271 return ((char *)NULL);
never executed: return ((char *) ((void *)0) );
0
272 tdir = sh_makepath (wd, (char *)pathname, 0);-
273 free (wd);-
274 }
never executed: end of block
0
275 else-
276 tdir = savestring (pathname);
never executed: tdir = (char *)strcpy (sh_xmalloc((1 + strlen (pathname)), "pathphys.c", 276), (pathname));
0
277-
278 wd = sh_physpath (tdir, 0);-
279 free (tdir);-
280-
281 if (resolved == 0)
resolved == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
282 return (wd);
never executed: return (wd);
0
283-
284 if (wd)
wdDescription
TRUEnever evaluated
FALSEnever evaluated
0
285 {-
286 strncpy (resolved, wd, PATH_MAX - 1);-
287 resolved[PATH_MAX - 1] = '\0';-
288 free (wd);-
289 return resolved;
never executed: return resolved;
0
290 }-
291 else-
292 {-
293 resolved[0] = '\0';-
294 return wd;
never executed: return wd;
0
295 }-
296}-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.1.2