/[path-sandbox]/tags/sandbox_1_2_13/canonicalize.c
Gentoo

Contents of /tags/sandbox_1_2_13/canonicalize.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide annotations) (download) (as text)
Fri Nov 19 22:03:42 2004 UTC (10 years, 7 months ago) by ferringb
Original Path: trunk/canonicalize.c
File MIME type: text/x-csrc
File size: 4718 byte(s)
Initial revision

1 ferringb 2 /* Return the canonical absolute name of a given file.
2     Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc.
3     This file is part of the GNU C Library.
4    
5     The GNU C Library is free software; you can redistribute it and/or
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    
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     Lesser General Public License for more details.
14    
15     You should have received a copy of the GNU Lesser General Public
16     License along with the GNU C Library; if not, write to the Free
17     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18     02111-1307 USA. */
19    
20     /*
21     * $Header$
22     */
23    
24     #include <stdlib.h>
25     #include <string.h>
26     #include <unistd.h>
27     #include <limits.h>
28     #include <sys/param.h>
29     #include <sys/stat.h>
30     #include <errno.h>
31     #include <stddef.h>
32    
33     #ifndef __set_errno
34     # define __set_errno(val) errno = (val)
35     #endif
36    
37     /* Return the canonical absolute name of file NAME. A canonical name
38     does not contain any `.', `..' components nor any repeated path
39     separators ('/') or symlinks. All path components must exist. If
40     RESOLVED is null, the result is malloc'd; otherwise, if the
41     canonical name is SB_PATH_MAX chars or more, returns null with `errno'
42     set to ENAMETOOLONG; if the name fits in fewer than SB_PATH_MAX chars,
43     returns the name in RESOLVED. If the name cannot be resolved and
44     RESOLVED is non-NULL, it contains the path of the first component
45     that cannot be resolved. If the path can be resolved, RESOLVED
46     holds the same value as the value returned. */
47    
48     /* Modified: 19 Aug 2002; Martin Schlemmer <azarah@gentoo.org>
49     *
50     * Cleaned up unneeded stuff, and change so that it will not
51     * resolve symlinks. Also prepended a 'e' to functions that
52     * I did not rip out.
53     *
54     */
55    
56     char *
57     erealpath(const char *name, char *resolved)
58     {
59     char *rpath, *dest;
60     const char *start, *end, *rpath_limit;
61     long int path_max;
62    
63     if (name == NULL) {
64     /* As per Single Unix Specification V2 we must return an error if
65     either parameter is a null pointer. We extend this to allow
66     the RESOLVED parameter to be NULL in case the we are expected to
67     allocate the room for the return value. */
68     __set_errno(EINVAL);
69     return NULL;
70     }
71    
72     if (name[0] == '\0') {
73     /* As per Single Unix Specification V2 we must return an error if
74     the name argument points to an empty string. */
75     __set_errno(ENOENT);
76     return NULL;
77     }
78     #ifdef SB_PATH_MAX
79     path_max = SB_PATH_MAX;
80     #else
81     path_max = pathconf(name, _PC_PATH_MAX);
82     if (path_max <= 0)
83     path_max = 1024;
84     #endif
85    
86     if (resolved == NULL) {
87     rpath = malloc(path_max);
88     if (rpath == NULL)
89     return NULL;
90     } else
91     rpath = resolved;
92     rpath_limit = rpath + path_max;
93    
94     if (name[0] != '/') {
95     if (!egetcwd(rpath, path_max)) {
96     rpath[0] = '\0';
97     goto error;
98     }
99     dest = strchr(rpath, '\0');
100     } else {
101     rpath[0] = '/';
102     dest = rpath + 1;
103     }
104    
105     for (start = end = name; *start; start = end) {
106     /* Skip sequence of multiple path-separators. */
107     while (*start == '/')
108     ++start;
109    
110     /* Find end of path component. */
111     for (end = start; *end && *end != '/'; ++end)
112     /* Nothing. */ ;
113    
114     if (end - start == 0)
115     break;
116     else if (end - start == 1 && start[0] == '.')
117     /* nothing */ ;
118     else if (end - start == 2 && start[0] == '.' && start[1] == '.') {
119     /* Back up to previous component, ignore if at root already. */
120     if (dest > rpath + 1)
121     while ((--dest)[-1] != '/') ;
122     } else {
123     size_t new_size;
124    
125     if (dest[-1] != '/')
126     *dest++ = '/';
127    
128     if (dest + (end - start) >= rpath_limit) {
129     ptrdiff_t dest_offset = dest - rpath;
130     char *new_rpath;
131    
132     if (resolved) {
133     __set_errno(ENAMETOOLONG);
134     if (dest > rpath + 1)
135     dest--;
136     *dest = '\0';
137     goto error;
138     }
139     new_size = rpath_limit - rpath;
140     if (end - start + 1 > path_max)
141     new_size += end - start + 1;
142     else
143     new_size += path_max;
144     new_rpath = (char *) realloc(rpath, new_size);
145     if (new_rpath == NULL)
146     goto error;
147     rpath = new_rpath;
148     rpath_limit = rpath + new_size;
149    
150     dest = rpath + dest_offset;
151     }
152    
153     dest = __mempcpy(dest, start, end - start);
154     *dest = '\0';
155     }
156     }
157     #if 1
158     if (dest > rpath + 1 && dest[-1] == '/')
159     --dest;
160     #endif
161     *dest = '\0';
162    
163     return resolved ? memcpy(resolved, rpath, dest - rpath + 1) : rpath;
164    
165     error:
166     if (resolved)
167     strcpy(resolved, rpath);
168     else
169     free(rpath);
170     return NULL;
171     }
172    
173     // vim:expandtab noai:cindent ai

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.20