diff options
| author | Geoff Voelker | 1996-03-29 04:24:58 +0000 |
|---|---|---|
| committer | Geoff Voelker | 1996-03-29 04:24:58 +0000 |
| commit | 15c5ec83fd20bf6faf0cfa1ac67b58c3da972129 (patch) | |
| tree | ccfb2f99f8c4792741705c2301771649602a3062 /src | |
| parent | dbb3623fac00f764d7a18f1e23ecb6b8a8ffb40c (diff) | |
| download | emacs-15c5ec83fd20bf6faf0cfa1ac67b58c3da972129.tar.gz emacs-15c5ec83fd20bf6faf0cfa1ac67b58c3da972129.zip | |
(rename): New function.
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32.c | 102 |
1 files changed, 102 insertions, 0 deletions
| @@ -218,6 +218,108 @@ nt_sleep (int seconds) | |||
| 218 | Sleep (seconds * 1000); | 218 | Sleep (seconds * 1000); |
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | /* Emulate rename. */ | ||
| 222 | |||
| 223 | #ifndef ENOENT | ||
| 224 | #define ENOENT 2 | ||
| 225 | #endif | ||
| 226 | #ifndef EXDEV | ||
| 227 | #define EXDEV 18 | ||
| 228 | #endif | ||
| 229 | #ifndef EINVAL | ||
| 230 | #define EINVAL 22 | ||
| 231 | #endif | ||
| 232 | |||
| 233 | int | ||
| 234 | rename (const char *oldname, const char *newname) | ||
| 235 | { | ||
| 236 | #ifdef WINDOWS95 | ||
| 237 | int i, len, len0, len1; | ||
| 238 | char *dirs[2], *names[2], *ptr; | ||
| 239 | |||
| 240 | /* A bug in MoveFile under Windows 95 incorrectly renames files in | ||
| 241 | some cases. If the old name is of the form FILENAME or | ||
| 242 | FILENAME.SUF, and the new name is of the form FILENAME~ or | ||
| 243 | FILENAME.SUF~, and both the source and target are in the same | ||
| 244 | directory, then MoveFile renames the long form of the filename to | ||
| 245 | FILENAME~ (FILENAME.SUF~) but leaves the DOS short form as | ||
| 246 | FILENAME (FILENAME.SUF). The result is that the two different | ||
| 247 | filenames refer to the same file. In this case, rename the | ||
| 248 | source to a temporary name that can then successfully be renamed | ||
| 249 | to the target. */ | ||
| 250 | |||
| 251 | dirs[0] = names[0] = oldname; | ||
| 252 | dirs[1] = names[1] = newname; | ||
| 253 | for (i = 0; i < 2; i++) | ||
| 254 | { | ||
| 255 | /* Canonicalize and remove prefix. */ | ||
| 256 | len = strlen (names[i]); | ||
| 257 | for (ptr = names[i] + len - 1; ptr > names[i]; ptr--) | ||
| 258 | { | ||
| 259 | if (IS_ANY_SEP (ptr[0]) && ptr[1] != '\0') | ||
| 260 | { | ||
| 261 | names[i] = ptr + 1; | ||
| 262 | break; | ||
| 263 | } | ||
| 264 | } | ||
| 265 | } | ||
| 266 | |||
| 267 | len0 = strlen (names[0]); | ||
| 268 | len1 = strlen (names[1]); | ||
| 269 | |||
| 270 | /* The predicate is whether the file is being renamed to a filename | ||
| 271 | with ~ appended. This is conservative, but should be correct. */ | ||
| 272 | if ((len0 == len1 - 1) | ||
| 273 | && (names[1][len0] == '~') | ||
| 274 | && (!strnicmp (names[0], names[1], len0))) | ||
| 275 | { | ||
| 276 | /* Rename the source to a temporary name that can succesfully be | ||
| 277 | renamed to the target. The temporary name is in the directory | ||
| 278 | of the target. */ | ||
| 279 | char *tmp, *fulltmp; | ||
| 280 | |||
| 281 | tmp = "eXXXXXX"; | ||
| 282 | fulltmp = alloca (strlen (dirs[1]) + strlen (tmp) + 1); | ||
| 283 | fulltmp[0] = '\0'; | ||
| 284 | if (dirs[1] != names[1]) | ||
| 285 | { | ||
| 286 | len = names[1] - dirs[1]; | ||
| 287 | strncpy (fulltmp, dirs[1], len); | ||
| 288 | fulltmp[len] = '\0'; | ||
| 289 | } | ||
| 290 | strcat (fulltmp, tmp); | ||
| 291 | mktemp (fulltmp); | ||
| 292 | |||
| 293 | if (rename (oldname, fulltmp) < 0) | ||
| 294 | return -1; | ||
| 295 | |||
| 296 | oldname = fulltmp; | ||
| 297 | } | ||
| 298 | #endif | ||
| 299 | |||
| 300 | if (!MoveFile (oldname, newname)) | ||
| 301 | { | ||
| 302 | switch (GetLastError ()) | ||
| 303 | { | ||
| 304 | case ERROR_FILE_NOT_FOUND: | ||
| 305 | errno = ENOENT; | ||
| 306 | break; | ||
| 307 | case ERROR_ACCESS_DENIED: | ||
| 308 | /* This gets returned when going across devices. */ | ||
| 309 | errno = EXDEV; | ||
| 310 | break; | ||
| 311 | case ERROR_FILE_EXISTS: | ||
| 312 | case ERROR_ALREADY_EXISTS: | ||
| 313 | default: | ||
| 314 | errno = EINVAL; | ||
| 315 | break; | ||
| 316 | } | ||
| 317 | return -1; | ||
| 318 | } | ||
| 319 | errno = 0; | ||
| 320 | return 0; | ||
| 321 | } | ||
| 322 | |||
| 221 | /* Emulate the Unix directory procedures opendir, closedir, | 323 | /* Emulate the Unix directory procedures opendir, closedir, |
| 222 | and readdir. We can't use the procedures supplied in sysdep.c, | 324 | and readdir. We can't use the procedures supplied in sysdep.c, |
| 223 | so we provide them here. */ | 325 | so we provide them here. */ |