X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f X-Recipient: djgpp-workers AT delorie DOT com X-Authenticated: #27081556 X-Provags-ID: V01U2FsdGVkX1/O3LFaxj/OqN/3hXljckvqNVhjFzGBFRVR7tzsHa gczVwOblWI3gGF Message-ID: <001101c957cd$86db7010$2602a8c0@computername> From: "Juan Manuel Guerrero" To: Subject: One bug fix for opendir/readdir commited Date: Sat, 6 Dec 2008 19:07:38 +0100 MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2800.1106 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106 X-Y-GMX-Trusted: 0 X-FuHaFi: 0.43 Reply-To: djgpp-workers AT delorie DOT com OFYI: I have checked in the patch below to fix an issue in the DIR structure that I have already reported some months ago in With this patch the DIR structure no longer will have a trailing "/*.*" string appended to the canonicalized directory name. All libc functions that require such a trailing string will take care to append it to the dir name when they need it. This avoids difficulties with code that appends a path string to the end of the dir string without first checking that no "/*.*" string is already append to it. Regards, Juan M. Guerrero 2008-05-21 Juan Manuel Guerrero * djgpp/src/libc/posix/dirent/opendir.c (opendir): No longer add a trailing "/*.*" string to the canonicalized directory string stored in the DIR directory structure. (__set_need_fake_dot_dotdot): Add "/*.*" to the directory string before passing it to findfirst. * djgpp/src/libc/posix/dirent/readdir.c (readdir): Add "/*.*" to the directory string before passing it to findfirst. * src/docs/kb/wc204.txi: Document changes. Index: djgpp/src/docs/kb/wc204.txi =================================================================== RCS file: /cvs/djgpp/djgpp/src/docs/kb/wc204.txi,v retrieving revision 1.188 diff -U5 -r1.188 wc204.txi --- djgpp/src/docs/kb/wc204.txi 6 Dec 2008 13:53:42 -0000 1.188 +++ djgpp/src/docs/kb/wc204.txi 6 Dec 2008 14:03:04 -0000 @@ -1163,5 +1163,14 @@ @findex _fixpath AT r{, and Windows 2000/XP root directories and drive specifier character case} @findex __canonicalize_path AT r{, and Windows 2000/XP root directories and drive specifier character case} Lower case drive specifier characters will now be recognized as valid drive specifier too. Relative paths that start from the root directory will be correctly canonicalized because the backslash following the drive specifier is now removed. + +@findex opendir AT r{, fixed malformed path string for symlinks} +@findex readdir AT r{, fixed malformed path string for symlinks} +@findex __set_need_fake_dot_dotdot AT r{, fixed malformed path string for symlinks} +The trailing search pattern @code{/*.*} has been removed from the path string +stored in the member @code{name} of the @code{DIR} structure created by @code{opendir} +and used by @code{readdir}, @code{rewinddir} and @code{__set_need_fake_dot_dotdot}. +Now it only contains the canonicalized path to the directory without a terminating slash. +Those functions that require the trailing search pattern @code{/*.*} will append it. Index: djgpp/src/libc/posix/dirent/opendir.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/posix/dirent/opendir.c,v retrieving revision 1.6 diff -U5 -r1.6 opendir.c --- djgpp/src/libc/posix/dirent/opendir.c 17 Oct 2002 23:00:25 -0000 1.6 +++ djgpp/src/libc/posix/dirent/opendir.c 6 Dec 2008 14:03:06 -0000 @@ -1,5 +1,6 @@ +/* Copyright (C) 2008 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2000 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 */ /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ @@ -18,10 +19,26 @@ #include #include #include #include "dirstruc.h" +#define IS_ROOT_DIR(path) (((path)[1] == ':') && ((path)[2] == '/') && ((path)[3] == '\0')) + +#define APPEND_STAR_DOT_STAR(dst, src) \ + do { \ + int _i; \ + \ + for (_i = 0; (src)[_i]; _i++) \ + (dst)[_i] = (src)[_i]; \ + (dst)[_i++] = '/'; \ + (dst)[_i++] = '*'; \ + (dst)[_i++] = '.'; \ + (dst)[_i++] = '*'; \ + (dst)[_i++] = '\0'; \ + } while(1) + + void _lfn_find_close(int handle) { __dpmi_regs r; @@ -38,14 +55,17 @@ __set_need_fake_dot_dotdot(DIR *dir) { int oerrno = errno; dir->need_fake_dot_dotdot = 0; - if (strlen(dir->name) == 6) /* "d:/" + "*.*" */ + if (IS_ROOT_DIR(dir->name)) { /* see if findfirst finds "." anyway */ - if (findfirst(dir->name, &dir->ff, FA_ARCH|FA_RDONLY|FA_DIREC) + char dir_name[FILENAME_MAX + 1]; + + APPEND_STAR_DOT_STAR(dir_name, dir->name); + if (findfirst(dir_name, &dir->ff, FA_ARCH|FA_RDONLY|FA_DIREC) || strcmp(dir->ff.ff_name, ".")) { dir->need_fake_dot_dotdot = 2; /* Restore errno in certain cases. findfirst() will fail for empty @@ -97,11 +117,14 @@ free(dir->name); free(dir); return 0; } - /* Strip trailing slashes, so we can append "/ *.*" */ + /* Strip trailing slashes. + The "/ *.*" is no longer part of the directory + name but is appended in every libc function + that requires it. */ length = strlen(dir->name); while (1) { if (length == 0) break; length--; @@ -112,14 +135,10 @@ { length++; break; } } - dir->name[length++] = '/'; - dir->name[length++] = '*'; - dir->name[length++] = '.'; - dir->name[length++] = '*'; dir->name[length++] = 0; /* If we're doing opendir of the root directory, we need to fake out the . and .. entries, as some unix programs (like mkisofs) expect them and fail if they don't exist */ Index: djgpp/src/libc/posix/dirent/readdir.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/posix/dirent/readdir.c,v retrieving revision 1.6 diff -U5 -r1.6 readdir.c --- djgpp/src/libc/posix/dirent/readdir.c 17 Jun 2008 11:54:55 -0000 1.6 +++ djgpp/src/libc/posix/dirent/readdir.c 6 Dec 2008 14:03:06 -0000 @@ -1,5 +1,6 @@ +/* Copyright (C) 2008 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2001 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 */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include @@ -12,10 +13,23 @@ #include #include #include #include "dirstruc.h" +#define APPEND_STAR_DOT_STAR(dst, src) \ + do { \ + int _i; \ + \ + for (_i = 0; (src)[_i]; _i++) \ + (dst)[_i] = (src)[_i]; \ + (dst)[_i++] = '/'; \ + (dst)[_i++] = '*'; \ + (dst)[_i++] = '.'; \ + (dst)[_i++] = '*'; \ + (dst)[_i++] = '\0'; \ + } while(1) + struct dirent * readdir(DIR *dir) { int done; int oerrno = errno; @@ -39,24 +53,26 @@ if (dir->num_read) done = findnext(&dir->ff); else { + char dir_name[FILENAME_MAX + 1]; int ff_flags = FA_ARCH|FA_RDONLY|FA_DIREC|FA_SYSTEM; if (!(dir->flags & __OPENDIR_NO_HIDDEN)) ff_flags |= FA_HIDDEN; if (dir->flags & __OPENDIR_FIND_LABEL) ff_flags |= FA_LABEL; - done = findfirst(dir->name, &dir->ff, ff_flags); + APPEND_STAR_DOT_STAR(dir_name, dir->name); + done = findfirst(dir_name, &dir->ff, ff_flags); } if (done) { if (errno == ENMFILE) errno = oerrno; return 0; } - dir->num_read ++; + dir->num_read++; if (!(dir->flags & __OPENDIR_PRESERVE_CASE)) { char *cp; if (_is_DOS83(dir->ff.ff_name))