Date: Tue, 8 Aug 2000 15:55:11 +0300 (IDT) From: Eli Zaretskii X-Sender: eliz AT is To: djgpp-workers AT delorie DOT com Subject: Changing letter-case with _rename Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII 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) {