delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2000/08/08/08:56:06

Date: Tue, 8 Aug 2000 15:55:11 +0300 (IDT)
From: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
X-Sender: eliz AT is
To: djgpp-workers AT delorie DOT com
Subject: Changing letter-case with _rename
Message-ID: <Pine.SUN.3.91.1000808154921.7299E@is>
MIME-Version: 1.0
Reply-To: djgpp-workers AT delorie DOT com

The current version of _rename cannot be used to change the letter-case 
of a file name (under LFN).  For example, you cannot rename `foo' into 
`Foo': _rename will return zero, but will actually do nothing, because it 
thinks, not without a good reason, that these two files are actually the 
same file.

However, since sometimes people *do* want to rename files like that (and 
Windows' REN does allow it), I would like to commit the following change 
to _rename.c.  I will wait for some time for comments, before committing 
this.  Please try this version if you can, and tell me if you see any 
problems.  Thanks.

--- src/libc/ansi/stdio/_rename.c.~1~	Thu Jun  3 13:27:34 1999
+++ src/libc/ansi/stdio/_rename.c	Tue Aug  8 14:46:44 2000
@@ -1,3 +1,4 @@
+/* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
@@ -24,17 +25,40 @@ int _rename(const char *old, const char 
   char tempfile[FILENAME_MAX], tempfile1[FILENAME_MAX];
   const char *orig = old;
   int lfn_fd = -1;
+  int identical_but_for_case = 0;
 
-  /* If OLD and NEW are the same file, do nothing.  */
   if (__file_exists(new)
       && strcmp(_truename(old, tempfile), _truename(new, tempfile1)) == 0)
-    return 0;
+    {
+      /* NEW might seem to exist because the filesystem is case-
+	 insensitive, if OLD and NEW are identical but for the
+	 letter case.  Allow renaming `foo' into `Foo' under LFN.  */
+      if (use_lfn)
+	{
+	  const char *s1 = old + strlen(old), *s2 = new + strlen(new);
+
+	  /* Find the basename of both OLD and NEW.  */
+	  while (s1 > old && s2 > new
+		 && strchr(":/\\", s1[-1]) == NULL
+		 && strchr(":/\\", s2[-1]) == NULL)
+	  {
+	    s1--;
+	    s2--;
+	  }
+	  /* If OLD and NEW are really the same file, do nothing.  */
+	  if (strcmp(s1, s2) == 0)
+	    return 0;
+	  identical_but_for_case = 1;
+	}
+      else
+	return 0;  /* no LFN; foo and Foo ar *always* the same file */
+    }
 
   r.x.dx = __tb_offset;
   r.x.di = __tb_offset + olen;
   r.x.ds = r.x.es = __tb_segment;
 
-  if (use_lfn)
+  if (use_lfn && !identical_but_for_case)
   {
     /* Windows 95 bug: for some filenames, when you rename
        file -> file~ (as in Emacs, to leave a backup), the
@@ -108,6 +132,7 @@ int _rename(const char *old, const char 
     if(r.x.flags & 1)
     {
       if (i == 0
+	  && !identical_but_for_case /* don't nuke OLD! */
 	  && (r.x.ax == 5 || (r.x.ax == 2 && __file_exists(old))))
 	remove(new);		 /* and try again */
       else
@@ -115,7 +140,7 @@ int _rename(const char *old, const char 
 	errno = __doserr_to_errno(r.x.ax);
 
 	/* Restore to original name if we renamed it to temporary.  */
-	if (use_lfn)
+	if (use_lfn && !identical_but_for_case)
 	{
 	  if (lfn_fd != -1)
 	  {

- Raw text -


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