4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Copyright (c) 1988 AT&T */
27 /* All Rights Reserved */
30 #include <sys/types.h>
32 #include <sys/param.h>
40 * Canonicalize the path given in file_name, resolving away all symbolic link
41 * components. Store the result into the buffer named by resolved_name, which
42 * must be long enough (PATH_MAX bytes will suffice). Returns NULL
43 * on failure and resolved_name on success. On failure, to maintain
44 * compatibility with the past, the contents of file_name will be copied
48 realpath_impl(const char *file_name
, char *resolved_name
)
53 if (file_name
== NULL
) {
59 * Call resolvepath() to resolve all the symlinks in file_name,
60 * eliminate embedded "." components, and collapse embedded ".."
61 * components. We may be left with leading ".." components.
63 if ((len
= resolvepath(file_name
, resolved_name
, PATH_MAX
)) < 0) {
64 (void) strlcpy(resolved_name
, file_name
, PATH_MAX
);
65 return (NULL
); /* errno set by resolvepath() */
68 if (len
>= PATH_MAX
) /* "can't happen" */
70 resolved_name
[len
] = '\0';
72 if (*resolved_name
== '/') /* nothing more to do */
73 return (resolved_name
);
76 * Prepend the current working directory to the relative path.
77 * If the relative path is not empty (or "."), collapse all of the
78 * resulting embedded ".." components with trailing cwd components.
79 * We know that getcwd() returns a path name free of symlinks.
81 if (getcwd(cwd
, sizeof (cwd
)) == NULL
) {
82 (void) strlcpy(resolved_name
, file_name
, PATH_MAX
);
83 return (NULL
); /* errno set by getcwd() */
86 if (len
!= 0 && strcmp(resolved_name
, ".") != 0) {
87 char *relpath
= resolved_name
;
88 char *endcwd
= cwd
+ strlen(cwd
);
91 * Eliminate ".." components from the relative path
92 * left-to-right, components from cwd right-to-left.
95 while (len
>= 3 && strncmp(relpath
, "../", 3) == 0) {
98 while (*--endcwd
!= '/')
102 /* the relative path was all ".." components */
105 /* there are non-null components on both sides */
106 relpath
[--len
] = '\0';
108 if (endcwd
+ len
>= cwd
+ PATH_MAX
) {
109 (void) strlcpy(resolved_name
,
110 file_name
, PATH_MAX
);
111 errno
= ENAMETOOLONG
;
114 (void) strcpy(endcwd
, relpath
);
118 (void) strcpy(resolved_name
, cwd
);
119 return (resolved_name
);
123 * Canonicalize the path given in file_name, resolving away all symbolic link
124 * components. If resolved_name is a null pointer, return a malloc()d
125 * buffer containing the result, else store the result into resolved_name
126 * and return resolved_name. Return NULL on failure.
129 realpath(const char *file_name
, char *resolved_name
)
131 char buffer
[PATH_MAX
];
133 if (resolved_name
!= NULL
)
134 return (realpath_impl(file_name
, resolved_name
));
136 if (realpath_impl(file_name
, buffer
) != NULL
)
137 return (strdup(buffer
));
146 canonicalize_file_name(const char *path
)
148 return (realpath(path
, NULL
));