delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1996/10/16/08:18:29

Date: Wed, 16 Oct 1996 14:12:00 +0200 (IST)
From: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
To: djgpp-workers AT delorie DOT com
Cc: Ian Miller <itmiller AT dra DOT hmg DOT gb>
Subject: `_rename' fixed for Windows95
Message-Id: <Pine.SUN.3.91.961016132139.22412G-100000@is>
Mime-Version: 1.0

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 <itmiller AT dra DOT hmg DOT gb> 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 <stdio.h>
  #include <errno.h>
  #include <fcntl.h>
+ #include <io.h>
  #include <go32.h>
  #include <dpmi.h>
  #include <libc/dosio.h>
***************
*** 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;
  }
  

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019