1
1
/* Return the canonical absolute name of a given file.
2
- Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
2
+ Copyright (C) 1996-2020 Free Software Foundation, Inc.
3
3
This file is part of the GNU C Library.
4
4
5
5
The GNU C Library is free software; you can redistribute it and/or
6
- modify it under the terms of the GNU Library General Public License as
7
- published by the Free Software Foundation; either version 2 of the
8
- License, or (at your option) any later version.
6
+ modify it under the terms of the GNU Lesser General Public
7
+ License as published by the Free Software Foundation; either
8
+ version 2.1 of the License, or (at your option) any later version.
9
9
10
10
The GNU C Library is distributed in the hope that it will be useful,
11
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
18
19
19
/* Modified by Guido Flohr <guido@freemint.de> for MiNTLib. */
20
20
21
- #include <errno.h>
22
- #include <limits.h>
23
21
#include <stdlib.h>
24
22
#include <string.h>
25
23
#include <unistd.h>
24
+ #include <limits.h>
26
25
#include <sys/param.h>
27
26
#include <sys/stat.h>
27
+ #include <errno.h>
28
28
29
29
#ifdef __MINT__
30
30
# define __lxstat (version , file , buf ) __lstat(file, buf)
31
31
# define _STAT_VER
32
32
#endif
33
33
34
- #if __GNUC_PREREQ (12 ,0 )
35
- /*
36
- * we don't return a local addr;
37
- * rpath is either == resolved, or malloced
38
- */
39
- #pragma GCC diagnostic ignored "-Wreturn-local-addr"
40
- #endif
41
-
42
34
/* Return the canonical absolute name of file NAME. A canonical name
43
35
does not contain any `.', `..' components nor any repeated path
44
36
separators ('/') or symlinks. All path components must exist. If
50
42
that cannot be resolved. If the path can be resolved, RESOLVED
51
43
holds the same value as the value returned. */
52
44
53
- static char *
54
- canonicalize (const char * name , char * resolved )
45
+ __typeof__ (realpath ) __realpath ;
46
+
47
+ char *
48
+ __realpath (const char * name , char * resolved )
55
49
{
56
50
char * rpath , * dest , * extra_buf = NULL ;
57
51
const char * start , * end , * rpath_limit ;
@@ -84,13 +78,23 @@ canonicalize (const char *name, char *resolved)
84
78
path_max = 1024 ;
85
79
#endif
86
80
87
- rpath = resolved ? alloca (path_max ) : malloc (path_max );
81
+ if (resolved == NULL )
82
+ {
83
+ rpath = malloc (path_max );
84
+ if (rpath == NULL )
85
+ return NULL ;
86
+ }
87
+ else
88
+ rpath = resolved ;
88
89
rpath_limit = rpath + path_max ;
89
90
90
91
if (name [0 ] != '/' || name [0 ] == '\\' )
91
92
{
92
93
if (!__getcwd (rpath , path_max ))
94
+ {
95
+ rpath [0 ] = '\0' ;
93
96
goto error ;
97
+ }
94
98
dest = strchr (rpath , '\0' );
95
99
}
96
100
else
@@ -132,21 +136,26 @@ canonicalize (const char *name, char *resolved)
132
136
if (dest + (end - start ) >= rpath_limit )
133
137
{
134
138
long dest_offset = dest - rpath ;
139
+ char * new_rpath ;
135
140
136
141
if (resolved )
137
142
{
138
143
__set_errno (ENAMETOOLONG );
144
+ if (dest > rpath + 1 )
145
+ dest -- ;
146
+ * dest = '\0' ;
139
147
goto error ;
140
148
}
141
149
new_size = rpath_limit - rpath ;
142
150
if (end - start + 1 > path_max )
143
151
new_size += end - start + 1 ;
144
152
else
145
153
new_size += path_max ;
146
- rpath = realloc (rpath , new_size );
154
+ new_rpath = (char * )realloc (rpath , new_size );
155
+ if (new_rpath == NULL )
156
+ goto error ;
157
+ rpath = new_rpath ;
147
158
rpath_limit = rpath + new_size ;
148
- if (rpath == NULL )
149
- return NULL ;
150
159
151
160
dest = rpath + dest_offset ;
152
161
}
@@ -173,7 +182,7 @@ canonicalize (const char *name, char *resolved)
173
182
goto error ;
174
183
}
175
184
176
- n = __readlink (rpath , buf , path_max );
185
+ n = __readlink (rpath , buf , path_max - 1 );
177
186
if (n < 0 )
178
187
goto error ;
179
188
buf [n ] = '\0' ;
@@ -199,43 +208,31 @@ canonicalize (const char *name, char *resolved)
199
208
if (dest > rpath + 1 )
200
209
while ((-- dest )[-1 ] != '/' && dest [-1 ] != '\\' );
201
210
}
211
+ else if (!S_ISDIR (st .st_mode ) && * end != '\0' )
212
+ {
213
+ __set_errno (ENOTDIR );
214
+ goto error ;
215
+ }
202
216
}
203
217
}
204
218
if (dest > rpath + 1 && (dest [-1 ] == '/' || dest [-1 ] == '\\' ))
205
219
-- dest ;
206
220
* dest = '\0' ;
207
221
208
- return resolved ? memcpy ( resolved , rpath , dest - rpath + 1 ) : rpath ;
222
+ return rpath ;
209
223
210
224
error :
211
- if (resolved )
212
- strcpy (resolved , rpath );
213
- else
225
+ if (resolved == NULL )
214
226
free (rpath );
215
227
return NULL ;
216
228
}
217
-
218
-
219
- __typeof__ (realpath ) __realpath ;
220
-
221
- char *
222
- __realpath (const char * name , char * resolved )
223
- {
224
- if (resolved == NULL )
225
- {
226
- __set_errno (EINVAL );
227
- return NULL ;
228
- }
229
-
230
- return canonicalize (name , resolved );
231
- }
232
229
weak_alias (__realpath , realpath )
233
230
234
231
__typeof__ (canonicalize_file_name ) __canonicalize_file_name ;
235
232
236
233
char *
237
234
__canonicalize_file_name (const char * name )
238
235
{
239
- return canonicalize (name , NULL );
236
+ return __realpath (name , NULL );
240
237
}
241
238
weak_alias (__canonicalize_file_name , canonicalize_file_name )
0 commit comments