diff options
| author | Richard M. Stallman | 1996-11-06 19:51:38 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1996-11-06 19:51:38 +0000 |
| commit | 22819cd94f1338130cd1c97f64a6b3451f5b82cd (patch) | |
| tree | c2ba5129ec9cdadb90a3d38be897f4e554842129 /src | |
| parent | 2fa5888149f36487203f542b57fb69058b610c4b (diff) | |
| download | emacs-22819cd94f1338130cd1c97f64a6b3451f5b82cd.tar.gz emacs-22819cd94f1338130cd1c97f64a6b3451f5b82cd.zip | |
[__DJGPP_MINOR__ == 0] (_rename): New function, a
substitute for library low-level file-renaming function which
works around Windows 95 bug.
Diffstat (limited to 'src')
| -rw-r--r-- | src/msdos.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/src/msdos.c b/src/msdos.c index 2f19901a20f..89925cc7e36 100644 --- a/src/msdos.c +++ b/src/msdos.c | |||
| @@ -2327,6 +2327,122 @@ __write (int handle, const void *buffer, size_t count) | |||
| 2327 | } | 2327 | } |
| 2328 | } | 2328 | } |
| 2329 | 2329 | ||
| 2330 | /* A low-level file-renaming function which works around Windows 95 bug. | ||
| 2331 | This is pulled directly out of DJGPP v2.01 library sources, and only | ||
| 2332 | used when you compile with DJGPP v2.0. */ | ||
| 2333 | |||
| 2334 | #include <io.h> | ||
| 2335 | |||
| 2336 | int _rename(const char *old, const char *new) | ||
| 2337 | { | ||
| 2338 | __dpmi_regs r; | ||
| 2339 | int olen = strlen(old) + 1; | ||
| 2340 | int i; | ||
| 2341 | int use_lfn = _USE_LFN; | ||
| 2342 | char tempfile[FILENAME_MAX]; | ||
| 2343 | const char *orig = old; | ||
| 2344 | int lfn_fd = -1; | ||
| 2345 | |||
| 2346 | r.x.dx = __tb_offset; | ||
| 2347 | r.x.di = __tb_offset + olen; | ||
| 2348 | r.x.ds = r.x.es = __tb_segment; | ||
| 2349 | |||
| 2350 | if (use_lfn) | ||
| 2351 | { | ||
| 2352 | /* Windows 95 bug: for some filenames, when you rename | ||
| 2353 | file -> file~ (as in Emacs, to leave a backup), the | ||
| 2354 | short 8+3 alias doesn't change, which effectively | ||
| 2355 | makes OLD and NEW the same file. We must rename | ||
| 2356 | through a temporary file to work around this. */ | ||
| 2357 | |||
| 2358 | char *pbase = 0, *p; | ||
| 2359 | static char try_char[] = "abcdefghijklmnopqrstuvwxyz012345789"; | ||
| 2360 | int idx = sizeof(try_char) - 1; | ||
| 2361 | |||
| 2362 | /* Generate a temporary name. Can't use `tmpnam', since $TMPDIR | ||
| 2363 | might point to another drive, which will fail the DOS call. */ | ||
| 2364 | strcpy(tempfile, old); | ||
| 2365 | for (p = tempfile; *p; p++) /* ensure temporary is on the same drive */ | ||
| 2366 | if (*p == '/' || *p == '\\' || *p == ':') | ||
| 2367 | pbase = p; | ||
| 2368 | if (pbase) | ||
| 2369 | pbase++; | ||
| 2370 | else | ||
| 2371 | pbase = tempfile; | ||
| 2372 | strcpy(pbase, "X$$djren$$.$$temp$$"); | ||
| 2373 | |||
| 2374 | do | ||
| 2375 | { | ||
| 2376 | if (idx <= 0) | ||
| 2377 | return -1; | ||
| 2378 | *pbase = try_char[--idx]; | ||
| 2379 | } while (_chmod(tempfile, 0) != -1); | ||
| 2380 | |||
| 2381 | r.x.ax = 0x7156; | ||
| 2382 | _put_path2(tempfile, olen); | ||
| 2383 | _put_path(old); | ||
| 2384 | __dpmi_int(0x21, &r); | ||
| 2385 | if (r.x.flags & 1) | ||
| 2386 | { | ||
| 2387 | errno = __doserr_to_errno(r.x.ax); | ||
| 2388 | return -1; | ||
| 2389 | } | ||
| 2390 | |||
| 2391 | /* Now create a file with the original name. This will | ||
| 2392 | ensure that NEW will always have a 8+3 alias | ||
| 2393 | different from that of OLD. (Seems to be required | ||
| 2394 | when NameNumericTail in the Registry is set to 0.) */ | ||
| 2395 | lfn_fd = _creat(old, 0); | ||
| 2396 | |||
| 2397 | olen = strlen(tempfile) + 1; | ||
| 2398 | old = tempfile; | ||
| 2399 | r.x.di = __tb_offset + olen; | ||
| 2400 | } | ||
| 2401 | |||
| 2402 | for (i=0; i<2; i++) | ||
| 2403 | { | ||
| 2404 | if(use_lfn) | ||
| 2405 | r.x.ax = 0x7156; | ||
| 2406 | else | ||
| 2407 | r.h.ah = 0x56; | ||
| 2408 | _put_path2(new, olen); | ||
| 2409 | _put_path(old); | ||
| 2410 | __dpmi_int(0x21, &r); | ||
| 2411 | if(r.x.flags & 1) | ||
| 2412 | { | ||
| 2413 | if (r.x.ax == 5 && i == 0) /* access denied */ | ||
| 2414 | remove(new); /* and try again */ | ||
| 2415 | else | ||
| 2416 | { | ||
| 2417 | errno = __doserr_to_errno(r.x.ax); | ||
| 2418 | |||
| 2419 | /* Restore to original name if we renamed it to temporary. */ | ||
| 2420 | if (use_lfn) | ||
| 2421 | { | ||
| 2422 | if (lfn_fd != -1) | ||
| 2423 | { | ||
| 2424 | _close (lfn_fd); | ||
| 2425 | remove (orig); | ||
| 2426 | } | ||
| 2427 | _put_path2(orig, olen); | ||
| 2428 | _put_path(tempfile); | ||
| 2429 | r.x.ax = 0x7156; | ||
| 2430 | __dpmi_int(0x21, &r); | ||
| 2431 | } | ||
| 2432 | return -1; | ||
| 2433 | } | ||
| 2434 | } | ||
| 2435 | else | ||
| 2436 | break; | ||
| 2437 | } | ||
| 2438 | |||
| 2439 | /* Success. Delete the file possibly created to work | ||
| 2440 | around the Windows 95 bug. */ | ||
| 2441 | if (lfn_fd != -1) | ||
| 2442 | return (_close (lfn_fd) == 0) ? remove (orig) : -1; | ||
| 2443 | return 0; | ||
| 2444 | } | ||
| 2445 | |||
| 2330 | #endif /* __DJGPP__ == 2 && __DJGPP_MINOR__ == 0 */ | 2446 | #endif /* __DJGPP__ == 2 && __DJGPP_MINOR__ == 0 */ |
| 2331 | 2447 | ||
| 2332 | DEFUN ("msdos-long-file-names", Fmsdos_long_file_names, Smsdos_long_file_names, | 2448 | DEFUN ("msdos-long-file-names", Fmsdos_long_file_names, Smsdos_long_file_names, |