annotate src/realpath.c @ 589:37fe04af1590

[xemacs-hg @ 2001-05-31 02:00:29 by wmperry] Regenerated some .c files from their lisp equivalents for GTK bindings. Fix buttons as modifiers code so that text selection works in GTK event loop.
author wmperry
date Thu, 31 May 2001 02:00:31 +0000
parents 0f910da8ca73
children 5fd7ba8b56e7
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
1 /*
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
2 * realpath.c -- canonicalize pathname by removing symlinks
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
3 * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
4 *
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
5
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
6 This file is part of XEmacs.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
7
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
8 XEmacs is free software; you can redistribute it and/or modify it
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
9 under the terms of the GNU General Public License as published by the
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
10 Free Software Foundation; either version 2, or (at your option) any
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
11 later version.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
12
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
16 for more details.
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
17
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
18 You should have received a copy of the GNU General Public License
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
19 along with XEmacs; see the file COPYING. If not, write to
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
21 Boston, MA 02111-1307, USA. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
22
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
23 /* Synched up with: Not in FSF. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
24
572
0f910da8ca73 [xemacs-hg @ 2001-05-25 03:46:45 by martinb]
martinb
parents: 558
diff changeset
25 #define DONT_ENCAPSULATE
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
26 #include <config.h>
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
27 #include "lisp.h"
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
28
558
ed498ef2108b [xemacs-hg @ 2001-05-23 09:59:33 by ben]
ben
parents: 462
diff changeset
29 #include "sysfile.h"
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
30
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
31 /* First char after start of absolute filename. */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
32 #define ABS_START(name) (name + ABS_LENGTH (name))
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
33
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
34 #if defined (WIN32_NATIVE)
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
35 /* Length of start of absolute filename. */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
36 # define ABS_LENGTH(name) (win32_abs_start (name))
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
37 static int win32_abs_start (const char * name);
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
38 /* System dependent version of readlink. */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
39 # define system_readlink win32_readlink
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
40 #else
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
41 # ifdef CYGWIN
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
42 # define ABS_LENGTH(name) (IS_DIRECTORY_SEP (*name) ? \
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
43 (IS_DIRECTORY_SEP (name[1]) ? 2 : 1) : 0)
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
44 # define system_readlink cygwin_readlink
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
45 # else
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
46 # define ABS_LENGTH(name) (IS_DIRECTORY_SEP (*name) ? 1 : 0)
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
47 # define system_readlink readlink
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
48 # endif /* CYGWIN */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
49 #endif /* WIN32_NATIVE */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
50
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
51 #if defined (WIN32_NATIVE) || defined (CYGWIN)
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
52 #include "syswindows.h"
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
53 /* Emulate readlink on win32 - finds real name (i.e. correct case) of
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
54 a file. UNC servers and shares are lower-cased. Directories must be
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
55 given without trailing '/'. One day, this could read Win2K's
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
56 reparse points. */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
57 static int
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
58 win32_readlink (const char * name, char * buf, int size)
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
59 {
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
60 WIN32_FIND_DATA find_data;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
61 HANDLE dir_handle = NULL;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
62 int len = 0;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
63 int err = 0;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
64 const char* lastname;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
65 int count = 0;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
66 const char* tmp;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
67 char* res = NULL;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
68
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
69 assert (*name);
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
70
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
71 /* Sort of check we have a valid filename. */
558
ed498ef2108b [xemacs-hg @ 2001-05-23 09:59:33 by ben]
ben
parents: 462
diff changeset
72 if (strpbrk (name, "*?|<>\"") || strlen (name) >= PATH_MAX)
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
73 {
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
74 errno = EIO;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
75 return -1;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
76 }
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
77
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
78 /* Find start of filename */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
79 lastname = name + strlen (name);
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
80 while (lastname > name && !IS_DIRECTORY_SEP (lastname[-1]))
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
81 --lastname;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
82
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
83 /* Count slashes in unc path */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
84 if (ABS_LENGTH (name) == 2)
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
85 for (tmp = name; *tmp; tmp++)
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
86 if (IS_DIRECTORY_SEP (*tmp))
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
87 count++;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
88
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
89 if (count >= 2 && count < 4)
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
90 {
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
91 /* UNC server or share name: just copy lowercased name. */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
92 res = find_data.cFileName;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
93 for (tmp = lastname; *tmp; tmp++)
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
94 *res++ = tolower (*tmp);
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
95 *res = '\0';
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
96 }
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
97 else
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
98 dir_handle = FindFirstFile (name, &find_data);
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
99
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
100 if (res || dir_handle != INVALID_HANDLE_VALUE)
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
101 {
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
102 if ((len = strlen (find_data.cFileName)) < size)
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
103 {
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
104 if (strcmp (lastname, find_data.cFileName) == 0)
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
105 /* Signal that the name is already OK. */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
106 err = EINVAL;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
107 else
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
108 memcpy (buf, find_data.cFileName, len + 1);
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
109 }
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
110 else
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
111 err = ENAMETOOLONG;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
112 if (!res) FindClose (dir_handle);
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
113 }
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
114 else
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
115 err = ENOENT;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
116
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
117 errno = err;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
118 return err ? -1 : len;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
119 }
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
120 #endif /* WIN32_NATIVE || CYGWIN */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
121
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
122 #ifdef CYGWIN
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
123 /* Call readlink and try to find out the correct case for the file. */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
124 static int
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
125 cygwin_readlink (const char * name, char * buf, int size)
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
126 {
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
127 int n = readlink (name, buf, size);
462
0784d089fdc9 Import from CVS: tag r21-2-46
cvs
parents: 446
diff changeset
128 if (n < 0 && errno == EINVAL)
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
129 {
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
130 /* The file may exist, but isn't a symlink. Try to find the
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
131 right name. */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
132 char* tmp = alloca (cygwin_posix_to_win32_path_list_buf_size (name));
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
133 cygwin_posix_to_win32_path_list (name, tmp);
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
134 n = win32_readlink (tmp, buf, size);
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
135 }
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
136 return n;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
137 }
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
138 #endif /* CYGWIN */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
139
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
140 #ifdef WIN32_NATIVE
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
141 #ifndef ELOOP
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
142 #define ELOOP 10062 /* = WSAELOOP in winsock.h */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
143 #endif
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
144 /* Length of start of absolute filename. */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
145 static int
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
146 win32_abs_start (const char * name)
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
147 {
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
148 if (isalpha (*name) && IS_DEVICE_SEP (name[1])
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
149 && IS_DIRECTORY_SEP (name[2]))
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
150 return 3;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
151 else if (IS_DIRECTORY_SEP (*name))
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
152 return IS_DIRECTORY_SEP (name[1]) ? 2 : 1;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
153 else
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
154 return 0;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
155 }
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
156 #endif /* WIN32_NATIVE */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
157
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
158 #if !defined (HAVE_GETCWD) && defined (HAVE_GETWD)
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
159 #undef getcwd
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
160 #define getcwd(buffer, len) getwd (buffer)
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
161 #endif
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
162
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
163 #ifndef PATH_MAX
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
164 # if defined (_POSIX_PATH_MAX)
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
165 # define PATH_MAX _POSIX_PATH_MAX
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
166 # elif defined (MAXPATHLEN)
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
167 # define PATH_MAX MAXPATHLEN
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
168 # else
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
169 # define PATH_MAX 1024
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
170 # endif
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
171 #endif
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
172
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
173 #define MAX_READLINKS 32
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
174
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
175 char * xrealpath (const char *path, char resolved_path []);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
176 char *
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
177 xrealpath (const char *path, char resolved_path [])
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
178 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
179 char copy_path[PATH_MAX];
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
180 char *new_path = resolved_path;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
181 char *max_path;
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
182 #if defined (S_IFLNK) || defined (WIN32_NATIVE)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
183 int readlinks = 0;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
184 char link_path[PATH_MAX];
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
185 int n;
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
186 int abslen = ABS_LENGTH (path);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
187 #endif
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
188
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
189 /* Make a copy of the source path since we may need to modify it. */
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
190 strcpy (copy_path, path);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
191 path = copy_path;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
192 max_path = copy_path + PATH_MAX - 2;
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
193
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
194 #ifdef WIN32_NATIVE
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
195 /* Check for c:/... or //server/... */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
196 if (abslen == 2 || abslen == 3)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
197 {
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
198 strncpy (new_path, path, abslen);
462
0784d089fdc9 Import from CVS: tag r21-2-46
cvs
parents: 446
diff changeset
199 /* Make sure drive letter is lowercased. */
0784d089fdc9 Import from CVS: tag r21-2-46
cvs
parents: 446
diff changeset
200 if (abslen == 3)
0784d089fdc9 Import from CVS: tag r21-2-46
cvs
parents: 446
diff changeset
201 *new_path = tolower (*new_path);
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
202 new_path += abslen;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
203 path += abslen;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
204 }
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
205 /* No drive letter, but a beginning slash? Prepend drive letter. */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
206 else if (abslen == 1)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
207 {
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
208 getcwd (new_path, PATH_MAX - 1);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
209 new_path += 3;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
210 path++;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
211 }
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
212 /* Just a path name, prepend the current directory */
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
213 else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
214 {
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
215 getcwd (new_path, PATH_MAX - 1);
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
216 new_path += strlen (new_path);
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
217 if (!IS_DIRECTORY_SEP (new_path[-1]))
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
218 *new_path++ = DIRECTORY_SEP;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
219 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
220 #else
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
221 /* If it's a relative pathname use getcwd for starters. */
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
222 if (abslen == 0)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
223 {
440
8de8e3f6228a Import from CVS: tag r21-2-28
cvs
parents: 428
diff changeset
224 getcwd (new_path, PATH_MAX - 1);
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
225 new_path += strlen (new_path);
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
226 if (!IS_DIRECTORY_SEP (new_path[-1]))
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
227 *new_path++ = DIRECTORY_SEP;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
228 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
229 else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
230 {
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
231 /* Copy first directory sep. May have two on cygwin. */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
232 strncpy (new_path, path, abslen);
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
233 new_path += abslen;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
234 path += abslen;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
235 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
236 #endif
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
237 /* Expand each slash-separated pathname component. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
238 while (*path != '\0')
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
239 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
240 /* Ignore stray "/". */
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
241 if (IS_DIRECTORY_SEP (*path))
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
242 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
243 path++;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
244 continue;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
245 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
246
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
247 if (*path == '.')
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
248 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
249 /* Ignore ".". */
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
250 if (path[1] == '\0' || IS_DIRECTORY_SEP (path[1]))
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
251 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
252 path++;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
253 continue;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
254 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
255
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
256 /* Handle ".." */
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
257 if (path[1] == '.' &&
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
258 (path[2] == '\0' || IS_DIRECTORY_SEP (path[2])))
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
259 {
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
260 path += 2;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
261
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
262 /* Ignore ".." at root. */
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
263 if (new_path == ABS_START (resolved_path))
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
264 continue;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
265
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
266 /* Handle ".." by backing up. */
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
267 --new_path;
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
268 while (!IS_DIRECTORY_SEP (new_path[-1]))
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
269 --new_path;
442
abe6d1db359e Import from CVS: tag r21-2-36
cvs
parents: 440
diff changeset
270 continue;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
271 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
272 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
273
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
274 /* Safely copy the next pathname component. */
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
275 while (*path != '\0' && !IS_DIRECTORY_SEP (*path))
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
276 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
277 if (path > max_path)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
278 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
279 errno = ENAMETOOLONG;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
280 return NULL;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
281 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
282 *new_path++ = *path++;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
283 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
284
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
285 #if defined (S_IFLNK) || defined (WIN32_NATIVE)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
286 /* See if latest pathname component is a symlink. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
287 *new_path = '\0';
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
288 n = system_readlink (resolved_path, link_path, PATH_MAX - 1);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
289
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
290 if (n < 0)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
291 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
292 /* EINVAL means the file exists but isn't a symlink. */
462
0784d089fdc9 Import from CVS: tag r21-2-46
cvs
parents: 446
diff changeset
293 #ifdef CYGWIN
0784d089fdc9 Import from CVS: tag r21-2-46
cvs
parents: 446
diff changeset
294 if (errno != EINVAL && errno != ENOENT)
0784d089fdc9 Import from CVS: tag r21-2-46
cvs
parents: 446
diff changeset
295 #else
0784d089fdc9 Import from CVS: tag r21-2-46
cvs
parents: 446
diff changeset
296 if (errno != EINVAL)
0784d089fdc9 Import from CVS: tag r21-2-46
cvs
parents: 446
diff changeset
297 #endif
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
298 return NULL;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
299 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
300 else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
301 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
302 /* Protect against infinite loops. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
303 if (readlinks++ > MAX_READLINKS)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
304 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
305 errno = ELOOP;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
306 return NULL;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
307 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
308
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
309 /* Note: readlink doesn't add the null byte. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
310 link_path[n] = '\0';
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
311
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
312 if (ABS_LENGTH (link_path) > 0)
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
313 /* Start over for an absolute symlink. */
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
314 new_path = resolved_path + ABS_LENGTH (link_path) - 1;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
315 else
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
316 /* Otherwise back up over this component. */
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
317 for (--new_path; !IS_DIRECTORY_SEP (*new_path); --new_path)
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
318 assert (new_path > resolved_path);
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
319
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
320 /* Safe sex check. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
321 if (strlen(path) + n >= PATH_MAX)
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
322 {
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
323 errno = ENAMETOOLONG;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
324 return NULL;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
325 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
326
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
327 /* Insert symlink contents into path. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
328 strcat(link_path, path);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
329 strcpy(copy_path, link_path);
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
330 path = copy_path;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
331 }
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
332 #endif /* S_IFLNK || WIN32_NATIVE */
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
333 *new_path++ = DIRECTORY_SEP;
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
334 }
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
335
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
336 /* Delete trailing slash but don't whomp a lone slash. */
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
337 if (new_path != ABS_START (resolved_path) && IS_DIRECTORY_SEP (new_path[-1]))
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
338 new_path--;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
339
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
340 /* Make sure it's null terminated. */
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
341 *new_path = '\0';
446
1ccc32a20af4 Import from CVS: tag r21-2-38
cvs
parents: 442
diff changeset
342
428
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
343 return resolved_path;
3ecd8885ac67 Import from CVS: tag r21-2-22
cvs
parents:
diff changeset
344 }