Mail Archives: djgpp-workers/2000/08/08/08:56:06
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 -