comparison src/msdos.c @ 16524:84440bd95727

[__DJGPP_MINOR__ == 0] (_rename): New function, a substitute for library low-level file-renaming function which works around Windows 95 bug.
author Richard M. Stallman <rms@gnu.org>
date Wed, 06 Nov 1996 19:51:38 +0000
parents c987c025d448
children 4b0b6719bbd2
comparison
equal deleted inserted replaced
16523:53306ee8953d 16524:84440bd95727
2325 } 2325 }
2326 return total_written; 2326 return total_written;
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,
2333 0, 0, 0, 2449 0, 0, 0,
2334 "Return non-nil if long file names are supported on MSDOS.") 2450 "Return non-nil if long file names are supported on MSDOS.")