Mail Archives: djgpp-workers/2003/08/03/11:05:52
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 -