1 /* Return the canonical absolute name of a given file.
2 Copyright (C) 1996 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA. */
27 /* Return the canonical absolute name of file NAME. The last file name
28 component need not exist, and may be a symlink to a nonexistent file.
29 If RESOLVED is null, the result is malloc'd; otherwise, if the canonical
30 name is PATH_MAX chars or more, returns null with `errno' set to
31 ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, returns the
35 canonicalize (const char *name
, char *resolved
)
40 char *result
, *dir
, *end
;
50 path_max
= pathconf (name
, _PC_PATH_MAX
);
56 p
= strrchr (name
, '/');
68 dir
= __alloca (p
- name
);
69 memcpy (dir
, name
, p
- name
- 1);
74 result
= __canonicalize_directory_name_internal (dir
, resolved
, path_max
);
78 /* Reconstruct the file name in the canonicalized directory. */
79 namelen
= strlen (name
);
80 end
= strchr (result
, '\0');
83 /* Make sure the name is not too long. */
84 if (end
- result
+ namelen
> path_max
)
92 /* The name is dynamically allocated. Extend it. */
93 char *new = realloc (result
, end
- result
+ namelen
+ 1);
99 end
= new + (end
- result
);
102 memcpy (end
, name
, namelen
+ 1);
104 while (__lstat (result
, &st
) == 0 && S_ISLNK (st
.st_mode
))
106 /* The file is a symlink. Read its contents. */
109 n
= readlink (result
, end
,
110 resolved
? result
+ path_max
- end
: namelen
+ 1);
112 /* Error reading the link contents. */
117 /* Absolute symlink. */
118 if (resolved
? (end
+ n
< result
+ path_max
) : (n
< namelen
+ 1))
120 /* It fit in our buffer, so we have the whole thing. */
121 memcpy (result
, end
, n
);
126 /* It didn't fit in the remainder of the buffer. Either it
127 fits in the entire buffer, or it doesn't. Copy back the
128 unresolved name onto the canonical directory and try once
130 memcpy (end
, name
, namelen
+ 1);
131 n
= readlink (result
, result
, path_max
);
136 errno
= ENAMETOOLONG
;
142 /* Try again with a bigger buffer. */
145 /* Check the resolved name for being a symlink too. */
151 if (end
+ n
== result
+ path_max
)
153 /* The link contents we read fill the buffer completely.
154 There may be even more to read, and there is certainly no
155 space for the null terminator. */
156 errno
= ENAMETOOLONG
;
160 else if (n
== namelen
+ 1)
163 /* The name buffer is dynamically allocated. Extend it. */
166 /* Copy back the unresolved name onto the canonical directory. */
167 memcpy (end
, name
, namelen
+ 1);
169 /* Make more space for readlink. */
171 new = realloc (result
, end
- result
+ namelen
+ 1);
177 end
= new + (end
- result
);
180 goto read_link_contents
;
183 /* Terminate the string; readlink does not. */
190 weak_alias (canonicalize
, realpath
)
193 canonicalize_file_name (const char *name
)
195 return canonicalize (name
, NULL
);