OpenCoverage

realpath.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/openssh/src/openbsd-compat/realpath.c
Source codeSwitch to Preprocessed file
LineSourceCount
1/* $OpenBSD: realpath.c,v 1.20 2015/10/13 20:55:37 millert Exp $ */-
2/*-
3 * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>-
4 *-
5 * Redistribution and use in source and binary forms, with or without-
6 * modification, are permitted provided that the following conditions-
7 * are met:-
8 * 1. Redistributions of source code must retain the above copyright-
9 * notice, this list of conditions and the following disclaimer.-
10 * 2. Redistributions in binary form must reproduce the above copyright-
11 * notice, this list of conditions and the following disclaimer in the-
12 * documentation and/or other materials provided with the distribution.-
13 * 3. The names of the authors may not be used to endorse or promote-
14 * products derived from this software without specific prior written-
15 * permission.-
16 *-
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND-
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE-
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE-
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE-
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL-
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS-
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)-
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT-
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY-
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF-
27 * SUCH DAMAGE.-
28 */-
29-
30/* OPENBSD ORIGINAL: lib/libc/stdlib/realpath.c */-
31-
32#include "includes.h"-
33-
34#if !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH)-
35-
36#include <sys/types.h>-
37#include <sys/param.h>-
38#include <sys/stat.h>-
39-
40#include <errno.h>-
41#include <stdlib.h>-
42#include <stddef.h>-
43#include <string.h>-
44#include <unistd.h>-
45#include <limits.h>-
46-
47#ifndef SYMLOOP_MAX-
48# define SYMLOOP_MAX 32-
49#endif-
50-
51/* A slightly modified copy of this file exists in libexec/ld.so */-
52-
53/*-
54 * char *realpath(const char *path, char resolved[PATH_MAX]);-
55 *-
56 * Find the real name of path, by removing all ".", ".." and symlink-
57 * components. Returns (resolved) on success, or (NULL) on failure,-
58 * in which case the path which caused trouble is left in (resolved).-
59 */-
60char *-
61realpath(const char *path, char *resolved)-
62{-
63 struct stat sb;-
64 char *p, *q, *s;-
65 size_t left_len, resolved_len;-
66 unsigned symlinks;-
67 int serrno, slen, mem_allocated;-
68 char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];-
69-
70 if (path[0] == '\0') {
path[0] == '\0'Description
TRUEnever evaluated
FALSEnever evaluated
0
71 errno = ENOENT;-
72 return (NULL);
never executed: return ( ((void *)0) );
0
73 }-
74-
75 serrno = errno;-
76-
77 if (resolved == NULL) {
resolved == ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
78 resolved = malloc(PATH_MAX);-
79 if (resolved == NULL)
resolved == ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
80 return (NULL);
never executed: return ( ((void *)0) );
0
81 mem_allocated = 1;-
82 } else
never executed: end of block
0
83 mem_allocated = 0;
never executed: mem_allocated = 0;
0
84-
85 symlinks = 0;-
86 if (path[0] == '/') {
path[0] == '/'Description
TRUEnever evaluated
FALSEnever evaluated
0
87 resolved[0] = '/';-
88 resolved[1] = '\0';-
89 if (path[1] == '\0')
path[1] == '\0'Description
TRUEnever evaluated
FALSEnever evaluated
0
90 return (resolved);
never executed: return (resolved);
0
91 resolved_len = 1;-
92 left_len = strlcpy(left, path + 1, sizeof(left));-
93 } else {
never executed: end of block
0
94 if (getcwd(resolved, PATH_MAX) == NULL) {
getcwd(resolve...== ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
95 if (mem_allocated)
mem_allocatedDescription
TRUEnever evaluated
FALSEnever evaluated
0
96 free(resolved);
never executed: free(resolved);
0
97 else-
98 strlcpy(resolved, ".", PATH_MAX);
never executed: strlcpy(resolved, ".", 4096 );
0
99 return (NULL);
never executed: return ( ((void *)0) );
0
100 }-
101 resolved_len = strlen(resolved);-
102 left_len = strlcpy(left, path, sizeof(left));-
103 }
never executed: end of block
0
104 if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
left_len >= sizeof(left)Description
TRUEnever evaluated
FALSEnever evaluated
resolved_len >= 4096Description
TRUEnever evaluated
FALSEnever evaluated
0
105 errno = ENAMETOOLONG;-
106 goto err;
never executed: goto err;
0
107 }-
108-
109 /*-
110 * Iterate over path components in `left'.-
111 */-
112 while (left_len != 0) {
left_len != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
113 /*-
114 * Extract the next path component and adjust `left'-
115 * and its length.-
116 */-
117 p = strchr(left, '/');
__builtin_constant_p ( '/' )Description
TRUEnever evaluated
FALSEnever evaluated
!__builtin_constant_p ( left )Description
TRUEnever evaluated
FALSEnever evaluated
( '/' ) == '\0'Description
TRUEnever evaluated
FALSEnever evaluated
0
118 s = p ? p : left + left_len;
pDescription
TRUEnever evaluated
FALSEnever evaluated
0
119 if (s - left >= (ptrdiff_t)sizeof(next_token)) {
s - left >= (p...of(next_token)Description
TRUEnever evaluated
FALSEnever evaluated
0
120 errno = ENAMETOOLONG;-
121 goto err;
never executed: goto err;
0
122 }-
123 memcpy(next_token, left, s - left);-
124 next_token[s - left] = '\0';-
125 left_len -= s - left;-
126 if (p != NULL)
p != ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
127 memmove(left, s + 1, left_len + 1);
never executed: memmove(left, s + 1, left_len + 1);
0
128 if (resolved[resolved_len - 1] != '/') {
resolved[resol...en - 1] != '/'Description
TRUEnever evaluated
FALSEnever evaluated
0
129 if (resolved_len + 1 >= PATH_MAX) {
resolved_len + 1 >= 4096Description
TRUEnever evaluated
FALSEnever evaluated
0
130 errno = ENAMETOOLONG;-
131 goto err;
never executed: goto err;
0
132 }-
133 resolved[resolved_len++] = '/';-
134 resolved[resolved_len] = '\0';-
135 }
never executed: end of block
0
136 if (next_token[0] == '\0')
next_token[0] == '\0'Description
TRUEnever evaluated
FALSEnever evaluated
0
137 continue;
never executed: continue;
0
138 else if (strcmp(next_token, ".") == 0)
never executed: __result = (((const unsigned char *) (const char *) ( next_token ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
never executed: __result = (((const unsigned char *) (const char *) ( "." ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
__extension__ ... )))); }) == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 0Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 0Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
139 continue;
never executed: continue;
0
140 else if (strcmp(next_token, "..") == 0) {
never executed: __result = (((const unsigned char *) (const char *) ( next_token ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
never executed: __result = (((const unsigned char *) (const char *) ( ".." ))[3] - __s2[3]);
never executed: end of block
never executed: end of block
__extension__ ... )))); }) == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 0Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s1_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 0Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
__s2_len > 2Description
TRUEnever evaluated
FALSEnever evaluated
__result == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
141 /*-
142 * Strip the last path component except when we have-
143 * single "/"-
144 */-
145 if (resolved_len > 1) {
resolved_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
146 resolved[resolved_len - 1] = '\0';-
147 q = strrchr(resolved, '/') + 1;-
148 *q = '\0';-
149 resolved_len = q - resolved;-
150 }
never executed: end of block
0
151 continue;
never executed: continue;
0
152 }-
153-
154 /*-
155 * Append the next path component and lstat() it. If-
156 * lstat() fails we still can return successfully if-
157 * there are no more path components left.-
158 */-
159 resolved_len = strlcat(resolved, next_token, PATH_MAX);-
160 if (resolved_len >= PATH_MAX) {
resolved_len >= 4096Description
TRUEnever evaluated
FALSEnever evaluated
0
161 errno = ENAMETOOLONG;-
162 goto err;
never executed: goto err;
0
163 }-
164 if (lstat(resolved, &sb) != 0) {
lstat(resolved, &sb) != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
165 if (errno == ENOENT && p == NULL) {
(*__errno_location ()) == 2Description
TRUEnever evaluated
FALSEnever evaluated
p == ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
166 errno = serrno;-
167 return (resolved);
never executed: return (resolved);
0
168 }-
169 goto err;
never executed: goto err;
0
170 }-
171 if (S_ISLNK(sb.st_mode)) {
(((( sb.st_mod... == (0120000))Description
TRUEnever evaluated
FALSEnever evaluated
0
172 if (symlinks++ > SYMLOOP_MAX) {
symlinks++ > 32Description
TRUEnever evaluated
FALSEnever evaluated
0
173 errno = ELOOP;-
174 goto err;
never executed: goto err;
0
175 }-
176 slen = readlink(resolved, symlink, sizeof(symlink) - 1);-
177 if (slen < 0)
slen < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
178 goto err;
never executed: goto err;
0
179 symlink[slen] = '\0';-
180 if (symlink[0] == '/') {
symlink[0] == '/'Description
TRUEnever evaluated
FALSEnever evaluated
0
181 resolved[1] = 0;-
182 resolved_len = 1;-
183 } else if (resolved_len > 1) {
never executed: end of block
resolved_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
184 /* Strip the last path component. */-
185 resolved[resolved_len - 1] = '\0';-
186 q = strrchr(resolved, '/') + 1;-
187 *q = '\0';-
188 resolved_len = q - resolved;-
189 }
never executed: end of block
0
190-
191 /*-
192 * If there are any path components left, then-
193 * append them to symlink. The result is placed-
194 * in `left'.-
195 */-
196 if (p != NULL) {
p != ((void *)0)Description
TRUEnever evaluated
FALSEnever evaluated
0
197 if (symlink[slen - 1] != '/') {
symlink[slen - 1] != '/'Description
TRUEnever evaluated
FALSEnever evaluated
0
198 if (slen + 1 >=
slen + 1 >= (p...izeof(symlink)Description
TRUEnever evaluated
FALSEnever evaluated
0
199 (ptrdiff_t)sizeof(symlink)) {
slen + 1 >= (p...izeof(symlink)Description
TRUEnever evaluated
FALSEnever evaluated
0
200 errno = ENAMETOOLONG;-
201 goto err;
never executed: goto err;
0
202 }-
203 symlink[slen] = '/';-
204 symlink[slen + 1] = 0;-
205 }
never executed: end of block
0
206 left_len = strlcat(symlink, left, sizeof(symlink));-
207 if (left_len >= sizeof(symlink)) {
left_len >= sizeof(symlink)Description
TRUEnever evaluated
FALSEnever evaluated
0
208 errno = ENAMETOOLONG;-
209 goto err;
never executed: goto err;
0
210 }-
211 }
never executed: end of block
0
212 left_len = strlcpy(left, symlink, sizeof(left));-
213 }
never executed: end of block
0
214 }
never executed: end of block
0
215-
216 /*-
217 * Remove trailing slash except when the resolved pathname-
218 * is a single "/".-
219 */-
220 if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
resolved_len > 1Description
TRUEnever evaluated
FALSEnever evaluated
resolved[resol...en - 1] == '/'Description
TRUEnever evaluated
FALSEnever evaluated
0
221 resolved[resolved_len - 1] = '\0';
never executed: resolved[resolved_len - 1] = '\0';
0
222 return (resolved);
never executed: return (resolved);
0
223-
224err:-
225 if (mem_allocated)
mem_allocatedDescription
TRUEnever evaluated
FALSEnever evaluated
0
226 free(resolved);
never executed: free(resolved);
0
227 return (NULL);
never executed: return ( ((void *)0) );
0
228}-
229#endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.2.2