Mercurial > hg > octave-lojdl > gnulib-hg
annotate lib/rename.c @ 12094:67458384fb3f
rename: fix Solaris 10 bug
rename("file","name/") mistakenly succeeded. But since Solaris 10
already obeys POSIX behavior on rename("link/","name"), we avoid
blindly forcing GNU behavior of rejecting symlinks with trailing slash.
* m4/rename.m4 (gl_FUNC_RENAME): Detect Solaris bug.
* lib/rename.c (rpl_rename): Don't cripple POSIX behavior if this
was the only bug.
Signed-off-by: Eric Blake <ebb9@byu.net>
author | Eric Blake <ebb9@byu.net> |
---|---|
date | Wed, 30 Sep 2009 21:57:58 -0600 |
parents | b07a0a61b0c1 |
children | 724dd32f13f7 |
rev | line source |
---|---|
12093 | 1 /* Work around rename bugs in some systems. |
7302
8a1a9361108c
* _fpending.c: Include <config.h> unconditionally, since we no
Paul Eggert <eggert@cs.ucla.edu>
parents:
6259
diff
changeset
|
2 |
11972 | 3 Copyright (C) 2001, 2002, 2003, 2005, 2006, 2009 Free Software |
4 Foundation, Inc. | |
3099 | 5 |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
7302
diff
changeset
|
6 This program is free software: you can redistribute it and/or modify |
3099 | 7 it under the terms of the GNU General Public License as published by |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
7302
diff
changeset
|
8 the Free Software Foundation; either version 3 of the License, or |
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
7302
diff
changeset
|
9 (at your option) any later version. |
3099 | 10 |
11 This program is distributed in the hope that it will be useful, | |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 GNU General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
7302
diff
changeset
|
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
3099 | 18 |
12093 | 19 /* Written by Volker Borchert, Eric Blake. */ |
3099 | 20 |
7302
8a1a9361108c
* _fpending.c: Include <config.h> unconditionally, since we no
Paul Eggert <eggert@cs.ucla.edu>
parents:
6259
diff
changeset
|
21 #include <config.h> |
11972 | 22 |
23 #include <stdio.h> | |
24 | |
4229
c7ddde35beec
Make this module usable in shared libraries.
Bruno Haible <bruno@clisp.org>
parents:
3782
diff
changeset
|
25 #undef rename |
c7ddde35beec
Make this module usable in shared libraries.
Bruno Haible <bruno@clisp.org>
parents:
3782
diff
changeset
|
26 |
11972 | 27 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ |
28 /* The mingw rename has problems with trailing slashes; it also | |
29 requires use of native Windows calls to allow atomic renames over | |
30 existing files. */ | |
11478
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
31 |
11972 | 32 # include <errno.h> |
33 | |
34 # define WIN32_LEAN_AND_MEAN | |
35 # include <windows.h> | |
11478
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
36 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
37 /* Rename the file SRC to DST. This replacement is necessary on |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
38 Windows, on which the system rename function will not replace |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
39 an existing DST. */ |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
40 int |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
41 rpl_rename (char const *src, char const *dst) |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
42 { |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
43 int error; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
44 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
45 /* MoveFileEx works if SRC is a directory without any flags, |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
46 but fails with MOVEFILE_REPLACE_EXISTING, so try without |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
47 flags first. */ |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
48 if (MoveFileEx (src, dst, 0)) |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
49 return 0; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
50 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
51 /* Retry with MOVEFILE_REPLACE_EXISTING if the move failed |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
52 * due to the destination already existing. */ |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
53 error = GetLastError (); |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
54 if (error == ERROR_FILE_EXISTS || error == ERROR_ALREADY_EXISTS) |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
55 { |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
56 if (MoveFileEx (src, dst, MOVEFILE_REPLACE_EXISTING)) |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
57 return 0; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
58 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
59 error = GetLastError (); |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
60 } |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
61 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
62 switch (error) |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
63 { |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
64 case ERROR_FILE_NOT_FOUND: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
65 case ERROR_PATH_NOT_FOUND: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
66 case ERROR_BAD_PATHNAME: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
67 case ERROR_DIRECTORY: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
68 errno = ENOENT; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
69 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
70 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
71 case ERROR_ACCESS_DENIED: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
72 case ERROR_SHARING_VIOLATION: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
73 errno = EACCES; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
74 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
75 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
76 case ERROR_OUTOFMEMORY: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
77 errno = ENOMEM; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
78 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
79 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
80 case ERROR_CURRENT_DIRECTORY: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
81 errno = EBUSY; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
82 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
83 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
84 case ERROR_NOT_SAME_DEVICE: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
85 errno = EXDEV; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
86 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
87 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
88 case ERROR_WRITE_PROTECT: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
89 errno = EROFS; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
90 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
91 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
92 case ERROR_WRITE_FAULT: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
93 case ERROR_READ_FAULT: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
94 case ERROR_GEN_FAILURE: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
95 errno = EIO; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
96 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
97 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
98 case ERROR_HANDLE_DISK_FULL: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
99 case ERROR_DISK_FULL: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
100 case ERROR_DISK_TOO_FRAGMENTED: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
101 errno = ENOSPC; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
102 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
103 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
104 case ERROR_FILE_EXISTS: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
105 case ERROR_ALREADY_EXISTS: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
106 errno = EEXIST; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
107 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
108 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
109 case ERROR_BUFFER_OVERFLOW: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
110 case ERROR_FILENAME_EXCED_RANGE: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
111 errno = ENAMETOOLONG; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
112 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
113 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
114 case ERROR_INVALID_NAME: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
115 case ERROR_DELETE_PENDING: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
116 errno = EPERM; /* ? */ |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
117 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
118 |
11972 | 119 # ifndef ERROR_FILE_TOO_LARGE |
11478
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
120 /* This value is documented but not defined in all versions of windows.h. */ |
11972 | 121 # define ERROR_FILE_TOO_LARGE 223 |
122 # endif | |
11478
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
123 case ERROR_FILE_TOO_LARGE: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
124 errno = EFBIG; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
125 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
126 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
127 default: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
128 errno = EINVAL; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
129 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
130 } |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
131 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
132 return -1; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
133 } |
11972 | 134 |
135 #else /* ! W32 platform */ | |
3102
a17f2d7d7ee1
Include stdlib.h, string.h or strings.h, and xalloc.h.
Jim Meyering <jim@meyering.net>
parents:
3099
diff
changeset
|
136 |
11972 | 137 # if RENAME_DEST_EXISTS_BUG |
138 # error Please report your platform and this message to bug-gnulib@gnu.org. | |
12094 | 139 # elif RENAME_TRAILING_SLASH_SOURCE_BUG || RENAME_TRAILING_SLASH_DEST_BUG |
12093 | 140 |
141 # include <errno.h> | |
11972 | 142 # include <stdio.h> |
143 # include <stdlib.h> | |
144 # include <string.h> | |
12093 | 145 # include <sys/stat.h> |
11972 | 146 |
147 # include "dirname.h" | |
3099 | 148 |
12093 | 149 /* Rename the file SRC to DST, fixing any trailing slash bugs. */ |
3099 | 150 |
151 int | |
5907 | 152 rpl_rename (char const *src, char const *dst) |
3099 | 153 { |
12093 | 154 size_t src_len = strlen (src); |
155 size_t dst_len = strlen (dst); | |
156 char *src_temp = (char *) src; | |
157 char *dst_temp = (char *) dst; | |
158 bool src_slash; | |
159 bool dst_slash; | |
160 int ret_val = -1; | |
161 int rename_errno = ENOTDIR; | |
162 struct stat src_st; | |
163 struct stat dst_st; | |
164 | |
165 if (!src_len || !dst_len) | |
166 return rename (src, dst); /* Let strace see the ENOENT failure. */ | |
3099 | 167 |
12093 | 168 src_slash = src[src_len - 1] == '/'; |
169 dst_slash = dst[dst_len - 1] == '/'; | |
170 if (!src_slash && !dst_slash) | |
171 return rename (src, dst); | |
172 | |
173 /* Presence of a trailing slash requires directory semantics. If | |
174 the source does not exist, or if the destination cannot be turned | |
175 into a directory, give up now. Otherwise, strip trailing slashes | |
176 before calling rename. */ | |
177 if (lstat (src, &src_st)) | |
178 return -1; | |
179 if (lstat (dst, &dst_st)) | |
180 { | |
181 if (errno != ENOENT || !S_ISDIR (src_st.st_mode)) | |
182 return -1; | |
183 } | |
184 else if (!S_ISDIR (dst_st.st_mode)) | |
185 { | |
186 errno = ENOTDIR; | |
187 return -1; | |
188 } | |
189 else if (!S_ISDIR (src_st.st_mode)) | |
3099 | 190 { |
12093 | 191 errno = EISDIR; |
192 return -1; | |
3099 | 193 } |
194 | |
12094 | 195 # if RENAME_TRAILING_SLASH_SOURCE_BUG |
196 /* If the only bug was that a trailing slash was allowed on a | |
197 non-existing file destination, as in Solaris 10, then we've | |
198 already covered that situation. But if there is any problem with | |
199 a trailing slash on an existing source or destination, as in | |
200 Solaris 9, then we must strip the offending slash and check that | |
201 we have not encountered a symlink instead of a directory. | |
202 | |
203 Stripping a trailing slash interferes with POSIX semantics, where | |
204 rename behavior on a symlink with a trailing slash operates on | |
205 the corresponding target directory. We prefer the GNU semantics | |
206 of rejecting any use of a symlink with trailing slash, but do not | |
207 enforce them, since Solaris 10 is able to obey POSIX semantics | |
208 and there might be clients expecting it, as counter-intuitive as | |
209 those semantics are. | |
210 | |
211 Technically, we could also follow the POSIX behavior by chasing a | |
212 readlink trail, but that is harder to implement. */ | |
12093 | 213 if (src_slash) |
214 { | |
215 src_temp = strdup (src); | |
216 if (!src_temp) | |
217 { | |
218 /* Rather than rely on strdup-posix, we set errno ourselves. */ | |
219 rename_errno = ENOMEM; | |
220 goto out; | |
221 } | |
222 strip_trailing_slashes (src_temp); | |
223 if (lstat (src_temp, &src_st)) | |
224 { | |
225 rename_errno = errno; | |
226 goto out; | |
227 } | |
228 if (S_ISLNK (src_st.st_mode)) | |
229 goto out; | |
230 } | |
231 if (dst_slash) | |
232 { | |
233 dst_temp = strdup (dst); | |
234 if (!dst_temp) | |
235 { | |
236 rename_errno = ENOMEM; | |
237 goto out; | |
238 } | |
239 strip_trailing_slashes (dst_temp); | |
240 if (lstat (dst_temp, &dst_st)) | |
241 { | |
242 if (errno != ENOENT) | |
243 { | |
244 rename_errno = errno; | |
245 goto out; | |
246 } | |
247 } | |
248 else if (S_ISLNK (dst_st.st_mode)) | |
249 goto out; | |
250 } | |
12094 | 251 # endif /* RENAME_TRAILING_SLASH_SOURCE_BUG */ |
252 | |
12093 | 253 ret_val = rename (src_temp, dst_temp); |
254 rename_errno = errno; | |
255 out: | |
5907 | 256 if (src_temp != src) |
3099 | 257 free (src_temp); |
12093 | 258 if (dst_temp != dst) |
259 free (dst_temp); | |
260 errno = rename_errno; | |
3102
a17f2d7d7ee1
Include stdlib.h, string.h or strings.h, and xalloc.h.
Jim Meyering <jim@meyering.net>
parents:
3099
diff
changeset
|
261 return ret_val; |
3099 | 262 } |
12094 | 263 # endif /* RENAME_TRAILING_SLASH_*_BUG */ |
11972 | 264 #endif /* ! W32 platform */ |