Mercurial > hg > octave-jordi > gnulib-hg
annotate lib/rename.c @ 14379:2330aac2ae54
maint: adjust cpp indentation to reflect nesting depth
I.e., in a block of code that begins with an unnested "#if",
put one space between the "#" in column 1 and following token.
For example,
-#include <sys/vfs.h>
+# include <sys/vfs.h>
Do this only in .c files that are part of a module I maintain.
* lib/linkat.c: Filter through cppi.
* lib/nanosleep.c: Likewise.
* lib/openat.c: Likewise.
* lib/openat-die.c: Likewise.
* lib/dup3.c: Likewise.
* lib/fchownat.c: Likewise.
* lib/flock.c: Likewise.
* lib/fsync.c: Likewise.
* lib/fts.c: Likewise.
* lib/getpass.c: Likewise.
* lib/gettimeofday.c: Likewise.
* lib/userspec.c: Likewise.
* Makefile (sc_cpp_indent_check): New rule, to check this.
author | Jim Meyering <meyering@redhat.com> |
---|---|
date | Sun, 20 Feb 2011 23:02:43 +0100 |
parents | 97fc9a21a8fb |
children | 8250f2777afc |
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 |
14079
97fc9a21a8fb
maint: update almost all copyright ranges to include 2011
Jim Meyering <meyering@redhat.com>
parents:
12559
diff
changeset
|
3 Copyright (C) 2001-2003, 2005-2006, 2009-2011 Free Software Foundation, Inc. |
3099 | 4 |
9309
bbbbbf4cd1c5
Change copyright notice from GPLv2+ to GPLv3+.
Bruno Haible <bruno@clisp.org>
parents:
7302
diff
changeset
|
5 This program is free software: you can redistribute it and/or modify |
3099 | 6 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
|
7 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
|
8 (at your option) any later version. |
3099 | 9 |
10 This program 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 | |
13 GNU General Public License for more details. | |
14 | |
15 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
|
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
3099 | 17 |
12093 | 18 /* Written by Volker Borchert, Eric Blake. */ |
3099 | 19 |
7302
8a1a9361108c
* _fpending.c: Include <config.h> unconditionally, since we no
Paul Eggert <eggert@cs.ucla.edu>
parents:
6259
diff
changeset
|
20 #include <config.h> |
11972 | 21 |
22 #include <stdio.h> | |
23 | |
4229
c7ddde35beec
Make this module usable in shared libraries.
Bruno Haible <bruno@clisp.org>
parents:
3782
diff
changeset
|
24 #undef rename |
c7ddde35beec
Make this module usable in shared libraries.
Bruno Haible <bruno@clisp.org>
parents:
3782
diff
changeset
|
25 |
11972 | 26 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ |
27 /* The mingw rename has problems with trailing slashes; it also | |
28 requires use of native Windows calls to allow atomic renames over | |
29 existing files. */ | |
11478
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
30 |
11972 | 31 # include <errno.h> |
12098 | 32 # include <stdbool.h> |
33 # include <stdlib.h> | |
34 # include <sys/stat.h> | |
35 # include <unistd.h> | |
11972 | 36 |
37 # define WIN32_LEAN_AND_MEAN | |
38 # include <windows.h> | |
11478
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
39 |
12098 | 40 # include "dirname.h" |
41 | |
11478
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
42 /* 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
|
43 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
|
44 an existing DST. */ |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
45 int |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
46 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
|
47 { |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
48 int error; |
12098 | 49 size_t src_len = strlen (src); |
50 size_t dst_len = strlen (dst); | |
51 char *src_base = last_component (src); | |
52 char *dst_base = last_component (dst); | |
53 bool src_slash; | |
54 bool dst_slash; | |
55 bool dst_exists; | |
56 struct stat src_st; | |
57 struct stat dst_st; | |
11478
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
58 |
12098 | 59 /* Filter out dot as last component. */ |
60 if (!src_len || !dst_len) | |
61 { | |
62 errno = ENOENT; | |
63 return -1; | |
64 } | |
65 if (*src_base == '.') | |
66 { | |
67 size_t len = base_len (src_base); | |
68 if (len == 1 || (len == 2 && src_base[1] == '.')) | |
69 { | |
70 errno = EINVAL; | |
71 return -1; | |
72 } | |
73 } | |
74 if (*dst_base == '.') | |
75 { | |
76 size_t len = base_len (dst_base); | |
77 if (len == 1 || (len == 2 && dst_base[1] == '.')) | |
78 { | |
79 errno = EINVAL; | |
80 return -1; | |
81 } | |
82 } | |
83 | |
84 /* Presence of a trailing slash requires directory semantics. If | |
85 the source does not exist, or if the destination cannot be turned | |
86 into a directory, give up now. Otherwise, strip trailing slashes | |
87 before calling rename. There are no symlinks on mingw, so stat | |
88 works instead of lstat. */ | |
89 src_slash = ISSLASH (src[src_len - 1]); | |
90 dst_slash = ISSLASH (dst[dst_len - 1]); | |
91 if (stat (src, &src_st)) | |
92 return -1; | |
93 if (stat (dst, &dst_st)) | |
94 { | |
95 if (errno != ENOENT || (!S_ISDIR (src_st.st_mode) && dst_slash)) | |
96 return -1; | |
97 dst_exists = false; | |
98 } | |
99 else | |
100 { | |
101 if (S_ISDIR (dst_st.st_mode) != S_ISDIR (src_st.st_mode)) | |
12102
3ba227551e1d
maint: cleanup whitespace in recent commits
Eric Blake <ebb9@byu.net>
parents:
12098
diff
changeset
|
102 { |
3ba227551e1d
maint: cleanup whitespace in recent commits
Eric Blake <ebb9@byu.net>
parents:
12098
diff
changeset
|
103 errno = S_ISDIR (dst_st.st_mode) ? EISDIR : ENOTDIR; |
3ba227551e1d
maint: cleanup whitespace in recent commits
Eric Blake <ebb9@byu.net>
parents:
12098
diff
changeset
|
104 return -1; |
3ba227551e1d
maint: cleanup whitespace in recent commits
Eric Blake <ebb9@byu.net>
parents:
12098
diff
changeset
|
105 } |
12098 | 106 dst_exists = true; |
107 } | |
108 | |
109 /* There are no symlinks, so if a file existed with a trailing | |
110 slash, it must be a directory, and we don't have to worry about | |
111 stripping strip trailing slash. However, mingw refuses to | |
112 replace an existing empty directory, so we have to help it out. | |
113 And canonicalize_file_name is not yet ported to mingw; however, | |
114 for directories, getcwd works as a viable alternative. Ensure | |
12103
832357ca223a
rename, fchdir: don't ignore chdir failure
Eric Blake <ebb9@byu.net>
parents:
12102
diff
changeset
|
115 that we can get back to where we started before using it; later |
832357ca223a
rename, fchdir: don't ignore chdir failure
Eric Blake <ebb9@byu.net>
parents:
12102
diff
changeset
|
116 attempts to return are fatal. Note that we can end up losing a |
832357ca223a
rename, fchdir: don't ignore chdir failure
Eric Blake <ebb9@byu.net>
parents:
12102
diff
changeset
|
117 directory if rename then fails, but it was empty, so not much |
832357ca223a
rename, fchdir: don't ignore chdir failure
Eric Blake <ebb9@byu.net>
parents:
12102
diff
changeset
|
118 damage was done. */ |
12098 | 119 if (dst_exists && S_ISDIR (dst_st.st_mode)) |
120 { | |
121 char *cwd = getcwd (NULL, 0); | |
122 char *src_temp; | |
123 char *dst_temp; | |
12103
832357ca223a
rename, fchdir: don't ignore chdir failure
Eric Blake <ebb9@byu.net>
parents:
12102
diff
changeset
|
124 if (!cwd || chdir (cwd)) |
12098 | 125 return -1; |
126 if (IS_ABSOLUTE_FILE_NAME (src)) | |
127 { | |
128 dst_temp = chdir (dst) ? NULL : getcwd (NULL, 0); | |
129 src_temp = chdir (src) ? NULL : getcwd (NULL, 0); | |
130 } | |
131 else | |
132 { | |
133 src_temp = chdir (src) ? NULL : getcwd (NULL, 0); | |
12103
832357ca223a
rename, fchdir: don't ignore chdir failure
Eric Blake <ebb9@byu.net>
parents:
12102
diff
changeset
|
134 if (!IS_ABSOLUTE_FILE_NAME (dst) && chdir (cwd)) |
832357ca223a
rename, fchdir: don't ignore chdir failure
Eric Blake <ebb9@byu.net>
parents:
12102
diff
changeset
|
135 abort (); |
12098 | 136 dst_temp = chdir (dst) ? NULL : getcwd (NULL, 0); |
137 } | |
12103
832357ca223a
rename, fchdir: don't ignore chdir failure
Eric Blake <ebb9@byu.net>
parents:
12102
diff
changeset
|
138 if (chdir (cwd)) |
832357ca223a
rename, fchdir: don't ignore chdir failure
Eric Blake <ebb9@byu.net>
parents:
12102
diff
changeset
|
139 abort (); |
12098 | 140 free (cwd); |
141 if (!src_temp || !dst_temp) | |
142 { | |
143 free (src_temp); | |
144 free (dst_temp); | |
145 errno = ENOMEM; | |
146 return -1; | |
147 } | |
148 src_len = strlen (src_temp); | |
149 if (strncmp (src_temp, dst_temp, src_len) == 0 | |
150 && (ISSLASH (dst_temp[src_len]) || dst_temp[src_len] == '\0')) | |
151 { | |
152 error = dst_temp[src_len]; | |
153 free (src_temp); | |
154 free (dst_temp); | |
155 if (error) | |
156 { | |
157 errno = EINVAL; | |
158 return -1; | |
159 } | |
160 return 0; | |
161 } | |
162 if (rmdir (dst)) | |
163 { | |
164 error = errno; | |
165 free (src_temp); | |
166 free (dst_temp); | |
167 errno = error; | |
168 return -1; | |
169 } | |
170 free (src_temp); | |
171 free (dst_temp); | |
172 } | |
173 | |
174 /* MoveFileEx works if SRC is a directory without any flags, but | |
175 fails with MOVEFILE_REPLACE_EXISTING, so try without flags first. | |
176 Thankfully, MoveFileEx handles hard links correctly, even though | |
177 rename() does not. */ | |
11478
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
178 if (MoveFileEx (src, dst, 0)) |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
179 return 0; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
180 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
181 /* Retry with MOVEFILE_REPLACE_EXISTING if the move failed |
12098 | 182 due to the destination already existing. */ |
11478
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
183 error = GetLastError (); |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
184 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
|
185 { |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
186 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
|
187 return 0; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
188 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
189 error = GetLastError (); |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
190 } |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
191 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
192 switch (error) |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
193 { |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
194 case ERROR_FILE_NOT_FOUND: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
195 case ERROR_PATH_NOT_FOUND: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
196 case ERROR_BAD_PATHNAME: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
197 case ERROR_DIRECTORY: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
198 errno = ENOENT; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
199 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
200 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
201 case ERROR_ACCESS_DENIED: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
202 case ERROR_SHARING_VIOLATION: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
203 errno = EACCES; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
204 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
205 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
206 case ERROR_OUTOFMEMORY: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
207 errno = ENOMEM; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
208 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
209 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
210 case ERROR_CURRENT_DIRECTORY: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
211 errno = EBUSY; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
212 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
213 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
214 case ERROR_NOT_SAME_DEVICE: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
215 errno = EXDEV; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
216 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
217 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
218 case ERROR_WRITE_PROTECT: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
219 errno = EROFS; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
220 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
221 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
222 case ERROR_WRITE_FAULT: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
223 case ERROR_READ_FAULT: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
224 case ERROR_GEN_FAILURE: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
225 errno = EIO; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
226 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
227 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
228 case ERROR_HANDLE_DISK_FULL: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
229 case ERROR_DISK_FULL: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
230 case ERROR_DISK_TOO_FRAGMENTED: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
231 errno = ENOSPC; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
232 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
233 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
234 case ERROR_FILE_EXISTS: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
235 case ERROR_ALREADY_EXISTS: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
236 errno = EEXIST; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
237 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
238 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
239 case ERROR_BUFFER_OVERFLOW: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
240 case ERROR_FILENAME_EXCED_RANGE: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
241 errno = ENAMETOOLONG; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
242 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
243 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
244 case ERROR_INVALID_NAME: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
245 case ERROR_DELETE_PENDING: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
246 errno = EPERM; /* ? */ |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
247 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
248 |
11972 | 249 # ifndef ERROR_FILE_TOO_LARGE |
12098 | 250 /* This value is documented but not defined in all versions of windows.h. */ |
11972 | 251 # define ERROR_FILE_TOO_LARGE 223 |
252 # endif | |
11478
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
253 case ERROR_FILE_TOO_LARGE: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
254 errno = EFBIG; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
255 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
256 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
257 default: |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
258 errno = EINVAL; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
259 break; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
260 } |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
261 |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
262 return -1; |
df9a59a3f8bc
Make rename replace existing destinations on Windows.
Ben Pfaff <blp@cs.stanford.edu>
parents:
9309
diff
changeset
|
263 } |
11972 | 264 |
265 #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
|
266 |
12095 | 267 # include <errno.h> |
268 # include <stdio.h> | |
269 # include <stdlib.h> | |
270 # include <string.h> | |
271 # include <sys/stat.h> | |
12097
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
272 # include <unistd.h> |
12093 | 273 |
12095 | 274 # include "dirname.h" |
275 # include "same-inode.h" | |
3099 | 276 |
12093 | 277 /* Rename the file SRC to DST, fixing any trailing slash bugs. */ |
3099 | 278 |
279 int | |
5907 | 280 rpl_rename (char const *src, char const *dst) |
3099 | 281 { |
12093 | 282 size_t src_len = strlen (src); |
283 size_t dst_len = strlen (dst); | |
284 char *src_temp = (char *) src; | |
285 char *dst_temp = (char *) dst; | |
286 bool src_slash; | |
287 bool dst_slash; | |
12097
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
288 bool dst_exists; |
12093 | 289 int ret_val = -1; |
290 int rename_errno = ENOTDIR; | |
291 struct stat src_st; | |
292 struct stat dst_st; | |
293 | |
294 if (!src_len || !dst_len) | |
295 return rename (src, dst); /* Let strace see the ENOENT failure. */ | |
3099 | 296 |
12095 | 297 # if RENAME_DEST_EXISTS_BUG |
298 { | |
299 char *src_base = last_component (src); | |
300 char *dst_base = last_component (dst); | |
301 if (*src_base == '.') | |
302 { | |
303 size_t len = base_len (src_base); | |
304 if (len == 1 || (len == 2 && src_base[1] == '.')) | |
305 { | |
306 errno = EINVAL; | |
307 return -1; | |
308 } | |
309 } | |
310 if (*dst_base == '.') | |
311 { | |
312 size_t len = base_len (dst_base); | |
313 if (len == 1 || (len == 2 && dst_base[1] == '.')) | |
314 { | |
315 errno = EINVAL; | |
316 return -1; | |
317 } | |
318 } | |
319 } | |
320 # endif /* RENAME_DEST_EXISTS_BUG */ | |
321 | |
12093 | 322 src_slash = src[src_len - 1] == '/'; |
323 dst_slash = dst[dst_len - 1] == '/'; | |
12095 | 324 |
12097
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
325 # if !RENAME_HARD_LINK_BUG && !RENAME_DEST_EXISTS_BUG |
12095 | 326 /* If there are no trailing slashes, then trust the native |
327 implementation unless we also suspect issues with hard link | |
12097
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
328 detection or file/directory conflicts. */ |
12093 | 329 if (!src_slash && !dst_slash) |
330 return rename (src, dst); | |
12097
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
331 # endif /* !RENAME_HARD_LINK_BUG && !RENAME_DEST_EXISTS_BUG */ |
12093 | 332 |
333 /* Presence of a trailing slash requires directory semantics. If | |
334 the source does not exist, or if the destination cannot be turned | |
335 into a directory, give up now. Otherwise, strip trailing slashes | |
336 before calling rename. */ | |
337 if (lstat (src, &src_st)) | |
338 return -1; | |
339 if (lstat (dst, &dst_st)) | |
340 { | |
12095 | 341 if (errno != ENOENT || (!S_ISDIR (src_st.st_mode) && dst_slash)) |
12093 | 342 return -1; |
12097
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
343 dst_exists = false; |
12093 | 344 } |
12095 | 345 else |
12093 | 346 { |
12095 | 347 if (S_ISDIR (dst_st.st_mode) != S_ISDIR (src_st.st_mode)) |
12102
3ba227551e1d
maint: cleanup whitespace in recent commits
Eric Blake <ebb9@byu.net>
parents:
12098
diff
changeset
|
348 { |
3ba227551e1d
maint: cleanup whitespace in recent commits
Eric Blake <ebb9@byu.net>
parents:
12098
diff
changeset
|
349 errno = S_ISDIR (dst_st.st_mode) ? EISDIR : ENOTDIR; |
3ba227551e1d
maint: cleanup whitespace in recent commits
Eric Blake <ebb9@byu.net>
parents:
12098
diff
changeset
|
350 return -1; |
3ba227551e1d
maint: cleanup whitespace in recent commits
Eric Blake <ebb9@byu.net>
parents:
12098
diff
changeset
|
351 } |
12097
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
352 # if RENAME_HARD_LINK_BUG |
12095 | 353 if (SAME_INODE (src_st, dst_st)) |
12102
3ba227551e1d
maint: cleanup whitespace in recent commits
Eric Blake <ebb9@byu.net>
parents:
12098
diff
changeset
|
354 return 0; |
12097
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
355 # endif /* RENAME_HARD_LINK_BUG */ |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
356 dst_exists = true; |
3099 | 357 } |
358 | |
12097
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
359 # if (RENAME_TRAILING_SLASH_SOURCE_BUG || RENAME_DEST_EXISTS_BUG \ |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
360 || RENAME_HARD_LINK_BUG) |
12094 | 361 /* If the only bug was that a trailing slash was allowed on a |
362 non-existing file destination, as in Solaris 10, then we've | |
363 already covered that situation. But if there is any problem with | |
364 a trailing slash on an existing source or destination, as in | |
12095 | 365 Solaris 9, or if a directory can overwrite a symlink, as on |
12096
1f43035b0900
rename-dest-slash: merge into rename module
Eric Blake <ebb9@byu.net>
parents:
12095
diff
changeset
|
366 Cygwin 1.5, or if directories cannot be created with trailing |
1f43035b0900
rename-dest-slash: merge into rename module
Eric Blake <ebb9@byu.net>
parents:
12095
diff
changeset
|
367 slash, as on NetBSD 1.6, then we must strip the offending slash |
1f43035b0900
rename-dest-slash: merge into rename module
Eric Blake <ebb9@byu.net>
parents:
12095
diff
changeset
|
368 and check that we have not encountered a symlink instead of a |
1f43035b0900
rename-dest-slash: merge into rename module
Eric Blake <ebb9@byu.net>
parents:
12095
diff
changeset
|
369 directory. |
12094 | 370 |
371 Stripping a trailing slash interferes with POSIX semantics, where | |
372 rename behavior on a symlink with a trailing slash operates on | |
373 the corresponding target directory. We prefer the GNU semantics | |
374 of rejecting any use of a symlink with trailing slash, but do not | |
375 enforce them, since Solaris 10 is able to obey POSIX semantics | |
376 and there might be clients expecting it, as counter-intuitive as | |
377 those semantics are. | |
378 | |
379 Technically, we could also follow the POSIX behavior by chasing a | |
380 readlink trail, but that is harder to implement. */ | |
12093 | 381 if (src_slash) |
382 { | |
383 src_temp = strdup (src); | |
384 if (!src_temp) | |
385 { | |
386 /* Rather than rely on strdup-posix, we set errno ourselves. */ | |
387 rename_errno = ENOMEM; | |
388 goto out; | |
389 } | |
390 strip_trailing_slashes (src_temp); | |
391 if (lstat (src_temp, &src_st)) | |
392 { | |
393 rename_errno = errno; | |
394 goto out; | |
395 } | |
396 if (S_ISLNK (src_st.st_mode)) | |
397 goto out; | |
398 } | |
399 if (dst_slash) | |
400 { | |
401 dst_temp = strdup (dst); | |
402 if (!dst_temp) | |
403 { | |
404 rename_errno = ENOMEM; | |
405 goto out; | |
406 } | |
407 strip_trailing_slashes (dst_temp); | |
408 if (lstat (dst_temp, &dst_st)) | |
409 { | |
410 if (errno != ENOENT) | |
411 { | |
412 rename_errno = errno; | |
413 goto out; | |
414 } | |
415 } | |
416 else if (S_ISLNK (dst_st.st_mode)) | |
417 goto out; | |
418 } | |
12097
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
419 # endif /* RENAME_TRAILING_SLASH_SOURCE_BUG || RENAME_DEST_EXISTS_BUG |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
420 || RENAME_HARD_LINK_BUG */ |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
421 |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
422 # if RENAME_DEST_EXISTS_BUG |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
423 /* Cygwin 1.5 sometimes behaves oddly when moving a non-empty |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
424 directory on top of an empty one (the old directory name can |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
425 reappear if the new directory tree is removed). Work around this |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
426 by removing the target first, but don't remove the target if it |
12103
832357ca223a
rename, fchdir: don't ignore chdir failure
Eric Blake <ebb9@byu.net>
parents:
12102
diff
changeset
|
427 is a subdirectory of the source. Note that we can end up losing |
832357ca223a
rename, fchdir: don't ignore chdir failure
Eric Blake <ebb9@byu.net>
parents:
12102
diff
changeset
|
428 a directory if rename then fails, but it was empty, so not much |
832357ca223a
rename, fchdir: don't ignore chdir failure
Eric Blake <ebb9@byu.net>
parents:
12102
diff
changeset
|
429 damage was done. */ |
12097
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
430 if (dst_exists && S_ISDIR (dst_st.st_mode)) |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
431 { |
12103
832357ca223a
rename, fchdir: don't ignore chdir failure
Eric Blake <ebb9@byu.net>
parents:
12102
diff
changeset
|
432 if (src_st.st_dev != dst_st.st_dev) |
832357ca223a
rename, fchdir: don't ignore chdir failure
Eric Blake <ebb9@byu.net>
parents:
12102
diff
changeset
|
433 { |
832357ca223a
rename, fchdir: don't ignore chdir failure
Eric Blake <ebb9@byu.net>
parents:
12102
diff
changeset
|
434 rename_errno = EXDEV; |
832357ca223a
rename, fchdir: don't ignore chdir failure
Eric Blake <ebb9@byu.net>
parents:
12102
diff
changeset
|
435 goto out; |
832357ca223a
rename, fchdir: don't ignore chdir failure
Eric Blake <ebb9@byu.net>
parents:
12102
diff
changeset
|
436 } |
12097
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
437 if (src_temp != src) |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
438 free (src_temp); |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
439 src_temp = canonicalize_file_name (src); |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
440 if (dst_temp != dst) |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
441 free (dst_temp); |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
442 dst_temp = canonicalize_file_name (dst); |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
443 if (!src_temp || !dst_temp) |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
444 { |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
445 rename_errno = ENOMEM; |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
446 goto out; |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
447 } |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
448 src_len = strlen (src_temp); |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
449 if (strncmp (src_temp, dst_temp, src_len) == 0 |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
450 && dst_temp[src_len] == '/') |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
451 { |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
452 rename_errno = EINVAL; |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
453 goto out; |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
454 } |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
455 if (rmdir (dst)) |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
456 { |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
457 rename_errno = errno; |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
458 goto out; |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
459 } |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
460 } |
bb32464985d7
rename: fix another cygwin 1.5 bug
Eric Blake <ebb9@byu.net>
parents:
12096
diff
changeset
|
461 # endif /* RENAME_DEST_EXISTS_BUG */ |
12094 | 462 |
12093 | 463 ret_val = rename (src_temp, dst_temp); |
464 rename_errno = errno; | |
465 out: | |
5907 | 466 if (src_temp != src) |
3099 | 467 free (src_temp); |
12093 | 468 if (dst_temp != dst) |
469 free (dst_temp); | |
470 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
|
471 return ret_val; |
3099 | 472 } |
11972 | 473 #endif /* ! W32 platform */ |