Mercurial > emacs
changeset 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 | 53306ee8953d |
children | 521d5794ac2b |
files | src/msdos.c |
diffstat | 1 files changed, 116 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/msdos.c Wed Nov 06 19:03:53 1996 +0000 +++ b/src/msdos.c Wed Nov 06 19:51:38 1996 +0000 @@ -2327,6 +2327,122 @@ } } +/* A low-level file-renaming function which works around Windows 95 bug. + This is pulled directly out of DJGPP v2.01 library sources, and only + used when you compile with DJGPP v2.0. */ + +#include <io.h> + +int _rename(const char *old, const char *new) +{ + __dpmi_regs r; + int olen = strlen(old) + 1; + int i; + int use_lfn = _USE_LFN; + char tempfile[FILENAME_MAX]; + const char *orig = old; + int lfn_fd = -1; + + r.x.dx = __tb_offset; + r.x.di = __tb_offset + olen; + r.x.ds = r.x.es = __tb_segment; + + if (use_lfn) + { + /* Windows 95 bug: for some filenames, when you rename + file -> file~ (as in Emacs, to leave a backup), the + short 8+3 alias doesn't change, which effectively + makes OLD and NEW the same file. We must rename + through a temporary file to work around this. */ + + char *pbase = 0, *p; + static char try_char[] = "abcdefghijklmnopqrstuvwxyz012345789"; + int idx = sizeof(try_char) - 1; + + /* Generate a temporary name. Can't use `tmpnam', since $TMPDIR + might point to another drive, which will fail the DOS call. */ + strcpy(tempfile, old); + for (p = tempfile; *p; p++) /* ensure temporary is on the same drive */ + if (*p == '/' || *p == '\\' || *p == ':') + pbase = p; + if (pbase) + pbase++; + else + pbase = tempfile; + strcpy(pbase, "X$$djren$$.$$temp$$"); + + do + { + if (idx <= 0) + return -1; + *pbase = try_char[--idx]; + } while (_chmod(tempfile, 0) != -1); + + r.x.ax = 0x7156; + _put_path2(tempfile, olen); + _put_path(old); + __dpmi_int(0x21, &r); + if (r.x.flags & 1) + { + errno = __doserr_to_errno(r.x.ax); + return -1; + } + + /* Now create a file with the original name. This will + ensure that NEW will always have a 8+3 alias + different from that of OLD. (Seems to be required + when NameNumericTail in the Registry is set to 0.) */ + lfn_fd = _creat(old, 0); + + olen = strlen(tempfile) + 1; + old = tempfile; + r.x.di = __tb_offset + olen; + } + + for (i=0; i<2; i++) + { + if(use_lfn) + r.x.ax = 0x7156; + else + r.h.ah = 0x56; + _put_path2(new, olen); + _put_path(old); + __dpmi_int(0x21, &r); + if(r.x.flags & 1) + { + if (r.x.ax == 5 && i == 0) /* access denied */ + remove(new); /* and try again */ + else + { + errno = __doserr_to_errno(r.x.ax); + + /* Restore to original name if we renamed it to temporary. */ + if (use_lfn) + { + if (lfn_fd != -1) + { + _close (lfn_fd); + remove (orig); + } + _put_path2(orig, olen); + _put_path(tempfile); + r.x.ax = 0x7156; + __dpmi_int(0x21, &r); + } + return -1; + } + } + else + break; + } + + /* Success. Delete the file possibly created to work + around the Windows 95 bug. */ + if (lfn_fd != -1) + return (_close (lfn_fd) == 0) ? remove (orig) : -1; + return 0; +} + #endif /* __DJGPP__ == 2 && __DJGPP_MINOR__ == 0 */ DEFUN ("msdos-long-file-names", Fmsdos_long_file_names, Smsdos_long_file_names,