delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2003/08/03/11:05:52

Date: Sun, 03 Aug 2003 16:12:38 +0100
From: "Richard Dawe" <rich AT phekda DOT freeserve DOT co DOT uk>
Sender: rich AT phekda DOT freeserve DOT co DOT uk
To: djgpp-workers AT delorie DOT com
X-Mailer: Emacs 21.3.50 (via feedmail 8.3.emacs20_6 I) and Blat ver 1.8.6
Subject: Fix for rename bug: moving a directory into itself [PATCH]
Message-Id: <E19jKPX-0000Si-00@phekda.freeserve.co.uk>
Reply-To: djgpp-workers AT delorie DOT com

Hello.

Below is a patch to fix the problem with rename and moving a directory
into itself.

It looks like _truename will generate an SFN for a non-existing file.
The patch below adds a version of _truename that should always return
SFNs. Imaginatively it's called _truename_sfn. Better suggestions
are welcome. ;) Now rename will use this function to generate
the filenames for comparison with is_parent. This seems to fix
the problem on Windows '98 SE.

The patch will probably apply with some fuzz. I've hacked out
a couple of chunks from my last fstat patch.

I've put a version of mv from fileutils 4.1 release 6 for testing here:

    http://www.phekda.freeserve.co.uk/richdawe/djgpp/2.04/

The binary is stripped and gzip'd. (Sorry, I don't have enough space
for an unstripped version.) The binary was built against my development
tree, which is mostly clean. It has an fstat patch applied, but I don't
think that will make any difference to this problem.

Please test on other platforms and let me know how it goes.

OK to commit?

Thanks, bye, Rich =]

Index: include/sys/stat.h
===================================================================
RCS file: /cvs/djgpp/djgpp/include/sys/stat.h,v
retrieving revision 1.9
diff -p -u -3 -r1.9 stat.h
--- include/sys/stat.h	8 Mar 2003 00:40:39 -0000	1.9
+++ include/sys/stat.h	3 Aug 2003 14:45:53 -0000
@@ -96,6 +98,7 @@ int             _is_executable(const cha
 int             lstat(const char * _path, struct stat * _buf);
 int		mknod(const char *_path, mode_t _mode, dev_t _dev);
 char          * _truename(const char *, char *);
+char          * _truename_sfn(const char *, char *);
 
 /* Bit-mapped variable _djstat_flags describes what expensive
    f?stat() features our application needs.  If you don't need a
Index: src/libc/dos/dos/truename.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/dos/dos/truename.c,v
retrieving revision 1.4
diff -p -u -3 -r1.4 truename.c
--- src/libc/dos/dos/truename.c	14 Jun 1999 16:20:40 -0000	1.4
+++ src/libc/dos/dos/truename.c	3 Aug 2003 14:45:54 -0000
@@ -1,3 +1,4 @@
+/* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
 /*
@@ -46,8 +47,8 @@
    In case of any failure, returns a NULL pointer and sets errno.
 */
 
-char *
-_truename(const char *file, char *buf)
+static char *
+_truename_internal(const char *file, char *buf, const int try_lfn)
 {
   __dpmi_regs     regs;
   unsigned short  dos_mem_selector = _dos_ds;
@@ -106,7 +107,8 @@ _truename(const char *file, char *buf)
   /* Call DOS INT 21H undocumented function 60h. */
   if(use_lfn) {
     regs.x.ax = 0x7160;
-    regs.x.cx = 2;		/* Get Long Path Name (if there is one) */
+    /* Get Long Path Name (if there is one) and we want it. */
+    regs.x.cx = try_lfn ? 2 : 0;
   } else
     regs.x.ax = 0x6000;
 
@@ -150,6 +152,23 @@ _truename(const char *file, char *buf)
         }
       return buf;
     }
+}
+
+char *
+_truename(const char *file, char *buf)
+{
+  return _truename_internal(file, buf, 1);
+}
+
+/* Sometimes we want the truename for a file that doesn't exist yet.
+   In those cases Windows '98 seems to prefer returning an SFN truename.
+   So if you want to use truenames in a comparison, it's safer to use
+   the SFN truenames.
+ */
+char *
+_truename_sfn(const char *file, char *buf)
+{
+  return _truename_internal(file, buf, 0);
 }
 
 #ifdef  TEST
Index: src/libc/dos/dos/truename.txh
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/dos/dos/truename.txh,v
retrieving revision 1.4
diff -p -u -3 -r1.4 truename.txh
--- src/libc/dos/dos/truename.txh	1 Apr 2003 20:47:28 -0000	1.4
+++ src/libc/dos/dos/truename.txh	3 Aug 2003 14:46:02 -0000
@@ -29,6 +29,14 @@ or (2) contains only the drive letter (e
 whitespace.  It will also fail if it couldn't allocate memory required for
 its communication with DOS or for @var{true_path} (see below).
 
+@code{_truename} may not return what you expect for files that don't exist.
+For instance, if the current directory was entered using a short
+filename (@samp{c:\thisis~1} instead of @samp{c:\thisisalongname}, say),
+then the truename of an existing file will be a long filename,
+but the truename of an non-existing file will be a short filename.
+This can cause problems when comparing filenames.  Use
+@code{_truename_sfn} (@pxref{_truename_sfn}) instead in this case.
+
 Upon success, the function will place the result in @var{true_path},
 if that's non-NULL; the buffer should be large enough to contain the
 largest possible pathname (PATH_MAX characters).  If @var{true_path}
@@ -52,3 +60,35 @@ a NULL pointer is returned, and @code{er
           "True name of %s is %s\n", path, _truename(path, (char *)0));
 @end example
 
+@node _truename_sfn, stdio
+@findex _truename_sfn
+@subheading Syntax
+
+@example
+#include <sys/stat.h>
+
+char * _truename_sfn(const char *path, char *true_path);
+@end example
+
+@subheading Description
+
+@code{_truename_sfn} is like @code{_truename}, except that it always
+returns a short filename. See the documentation for @code{_truename}
+for more details (@pxref{_truename}).
+
+@subheading Return Value
+
+The function returns the pointer to the result.  In case of any failure,
+a NULL pointer is returned, and @code{errno} is set.
+
+@subheading Portability
+
+@portability !ansi, !posix
+
+@subheading Example
+
+@example
+  fprintf(stderr, 
+          "True short name of %s is %s\n", path,
+	  _truename_sfn(path, (char *)0));
+@end example
Index: src/libc/ansi/stdio/rename.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/libc/ansi/stdio/rename.c,v
retrieving revision 1.8
diff -p -u -3 -r1.8 rename.c
--- src/libc/ansi/stdio/rename.c	17 Oct 2002 23:00:24 -0000	1.8
+++ src/libc/ansi/stdio/rename.c	3 Aug 2003 14:46:04 -0000
@@ -1,3 +1,4 @@
+/* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
 /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
@@ -344,8 +345,8 @@ rename(const char *old, const char *new)
           /* Fail if both OLD and NEW are directories and
              OLD is parent of NEW.  */
           errno = 0;
-          if (is_parent(_truename(real_old, old_true), 
-                        _truename(real_new, new_true)))
+          if (is_parent(_truename_sfn(real_old, old_true), 
+                        _truename_sfn(real_new, new_true)))
             {
               errno = EINVAL;
               return -1;
@@ -377,8 +378,8 @@ rename(const char *old, const char *new)
       char new_true[FILENAME_MAX], old_true[FILENAME_MAX];
 
       errno = 0;
-      if (is_parent(_truename(real_old, old_true), 
-                    _truename(real_new, new_true)))
+      if (is_parent(_truename_sfn(real_old, old_true), 
+                    _truename_sfn(real_new, new_true)))
 	{
 	  errno = EINVAL;
 	  return -1;
Index: src/docs/kb/wc204.txi
===================================================================
RCS file: /cvs/djgpp/djgpp/src/docs/kb/wc204.txi,v
retrieving revision 1.158
diff -p -u -3 -r1.158 wc204.txi
--- src/docs/kb/wc204.txi	10 May 2003 17:12:53 -0000	1.158
+++ src/docs/kb/wc204.txi	3 Aug 2003 14:46:16 -0000
@@ -990,3 +996,13 @@ The functions @code{strtod}, @code{strto
 @code{_strtold} now understand ``Inf'', ``Infinity'', ``NaN'',
 ``NaN()'', ``NaN(@var{hex-number})'' and any variations of case in the
 input string.
+
+@findex _truename_sfn
+The @code{_truename_sfn} function was added.  Please use
+@code{_truename_sfn} when comparing truenames, to avoid problems
+when comparing the truenames of existing and non-existing files.
+
+@findex rename AT r{, and moving directories into themselves}
+Fix a bug in moving directories into themselves.   Previously
+@code{rename} failed to detect that a subdirectory was being moved
+into itself, when the current directory was a short filename.

- Raw text -


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