Date: Wed, 16 Oct 1996 14:12:00 +0200 (IST) From: Eli Zaretskii To: djgpp-workers AT delorie DOT com Cc: Ian Miller Subject: `_rename' fixed for Windows95 Message-Id: Mime-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII The patch below makes `_rename' work around the Windows 95 bug whereby sometimes the short 8+3 alias stays the same, and therefore the file is effectively NOT renamed. Many thanks to Ian Miller for helping me test the fixed version. *** src/libc/ansi/stdio/_rename.c~0 Mon Aug 28 00:15:38 1995 --- src/libc/ansi/stdio/_rename.c Wed Oct 16 13:44:32 1996 *************** *** 3,8 **** --- 3,9 ---- #include #include #include + #include #include #include #include *************** *** 13,23 **** --- 14,79 ---- 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); + + /* 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) *************** *** 34,45 **** --- 90,120 ---- 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; }