digitalmars.D.bugs - [Issue 885] New: Recursion into folders with FindFirstFileA/FindNextFileA behaves incorrectly
- d-bugmail puremagic.com (84/84) Jan 24 2007 http://d.puremagic.com/issues/show_bug.cgi?id=885
- kris (3/99) Jan 25 2007 You're certain FindFirst() et al can be recursed like this? IIRC, they
- d-bugmail puremagic.com (4/4) Jan 27 2007 http://d.puremagic.com/issues/show_bug.cgi?id=885
- d-bugmail puremagic.com (6/87) Jan 28 2007 http://d.puremagic.com/issues/show_bug.cgi?id=885
- d-bugmail puremagic.com (12/12) Feb 26 2007 http://d.puremagic.com/issues/show_bug.cgi?id=885
http://d.puremagic.com/issues/show_bug.cgi?id=885
Summary: Recursion into folders with FindFirstFileA/FindNextFileA
behaves incorrectly
Product: D
Version: 1.001
Platform: PC
OS/Version: Windows
Status: NEW
Severity: major
Priority: P2
Component: www.digitalmars.com
AssignedTo: bugzilla digitalmars.com
ReportedBy: fdp mcs.be
The accompanying program was used to find files in a (quite huge) directory
structure using a regex expression. When I noticed that some files that were
there were not found, I added a line to print the directories that get
'visited'. That's where I noticed that some directories were not recursed
into. Furthermore this behaviour is not constant; the directories that are
skipt are not always the same ones. Thinking of a memory problem, I also
experimented by adding fullCollect and genCollect calls at various places and
this had indeed an influence on which directories were skipped.
Here is the code:
import std.c.windows.windows;
import std.path;
import std.stdio;
import std.regexp;
import std.utf;
void visit (char[] p_strFolder, RegExp p_patt)
{
writefln (">>> ", p_strFolder); // added for debugging purposes
WIN32_FIND_DATA fd;
char[] strSpec = join (p_strFolder, "*");
HANDLE h = FindFirstFileA (cast(char*)strSpec, &fd);
bool bOK = h != INVALID_HANDLE_VALUE;
while (bOK)
{
wchar[] wbuf;
size_t clength = std.string.strlen(fd.cFileName.ptr);
// Convert cFileName[] to unicode
size_t wlength =
MultiByteToWideChar(0,0,fd.cFileName.ptr,clength,null,0);
if (wlength > wbuf.length)
{
wbuf.length = wlength;
}
size_t n =
MultiByteToWideChar(0,0,fd.cFileName.ptr,clength,cast(wchar*)wbuf,wlength);
assert(n == wlength);
// toUTF8() returns a new buffer
char[] strName = std.utf.toUTF8(wbuf[0 .. wlength]);
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
{
if (0 != std.string.cmp (strName, ".") &&
0 != std.string.cmp (strName, "..") &&
0 != std.string.cmp (strName, ".svn"))
{
visit (join (p_strFolder, strName), p_patt);
}
}
else
{
char[] strFullName = join (p_strFolder, strName);
if (-1 != p_patt.find(std.string.tolower (strFullName)))
{
// removed code for debugging purposes
}
}
bOK = cast(bool)FindNextFileA (h, &fd);
}
FindClose (h);
}
void main (char [][] p_args)
{
if (p_args.length == 1)
{
visit (curdir, RegExp ("."));
}
else
{
visit (p_args[1], RegExp (std.string.tolower (p_args[1])));
}
}
PS: I just tested on 1.002 also and the behaviour is the same.
--
Jan 24 2007
d-bugmail puremagic.com wrote:
http://d.puremagic.com/issues/show_bug.cgi?id=885
Summary: Recursion into folders with FindFirstFileA/FindNextFileA
behaves incorrectly
Product: D
Version: 1.001
Platform: PC
OS/Version: Windows
Status: NEW
Severity: major
Priority: P2
Component: www.digitalmars.com
AssignedTo: bugzilla digitalmars.com
ReportedBy: fdp mcs.be
The accompanying program was used to find files in a (quite huge) directory
structure using a regex expression. When I noticed that some files that were
there were not found, I added a line to print the directories that get
'visited'. That's where I noticed that some directories were not recursed
into. Furthermore this behaviour is not constant; the directories that are
skipt are not always the same ones. Thinking of a memory problem, I also
experimented by adding fullCollect and genCollect calls at various places and
this had indeed an influence on which directories were skipped.
Here is the code:
import std.c.windows.windows;
import std.path;
import std.stdio;
import std.regexp;
import std.utf;
void visit (char[] p_strFolder, RegExp p_patt)
{
writefln (">>> ", p_strFolder); // added for debugging purposes
WIN32_FIND_DATA fd;
char[] strSpec = join (p_strFolder, "*");
HANDLE h = FindFirstFileA (cast(char*)strSpec, &fd);
bool bOK = h != INVALID_HANDLE_VALUE;
while (bOK)
{
wchar[] wbuf;
size_t clength = std.string.strlen(fd.cFileName.ptr);
// Convert cFileName[] to unicode
size_t wlength =
MultiByteToWideChar(0,0,fd.cFileName.ptr,clength,null,0);
if (wlength > wbuf.length)
{
wbuf.length = wlength;
}
size_t n =
MultiByteToWideChar(0,0,fd.cFileName.ptr,clength,cast(wchar*)wbuf,wlength);
assert(n == wlength);
// toUTF8() returns a new buffer
char[] strName = std.utf.toUTF8(wbuf[0 .. wlength]);
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
{
if (0 != std.string.cmp (strName, ".") &&
0 != std.string.cmp (strName, "..") &&
0 != std.string.cmp (strName, ".svn"))
{
visit (join (p_strFolder, strName), p_patt);
}
}
else
{
char[] strFullName = join (p_strFolder, strName);
if (-1 != p_patt.find(std.string.tolower (strFullName)))
{
// removed code for debugging purposes
}
}
bOK = cast(bool)FindNextFileA (h, &fd);
}
FindClose (h);
}
void main (char [][] p_args)
{
if (p_args.length == 1)
{
visit (curdir, RegExp ("."));
}
else
{
visit (p_args[1], RegExp (std.string.tolower (p_args[1])));
}
}
PS: I just tested on 1.002 also and the behaviour is the same.
You're certain FindFirst() et al can be recursed like this? IIRC, they
maintain some global state?
Jan 25 2007
http://d.puremagic.com/issues/show_bug.cgi?id=885 Could you try this again with DMD 1.004? --
Jan 27 2007
http://d.puremagic.com/issues/show_bug.cgi?id=885The accompanying program was used to find files in a (quite huge) directory structure using a regex expression. When I noticed that some files that were there were not found, I added a line to print the directories that get 'visited'. That's where I noticed that some directories were not recursed into. Furthermore this behaviour is not constant; the directories that are skipt are not always the same ones. Thinking of a memory problem, I also experimented by adding fullCollect and genCollect calls at various places and this had indeed an influence on which directories were skipped. Here is the code: import std.c.windows.windows; import std.path; import std.stdio; import std.regexp; import std.utf; void visit (char[] p_strFolder, RegExp p_patt) { writefln (">>> ", p_strFolder); // added for debugging purposes WIN32_FIND_DATA fd; char[] strSpec = join (p_strFolder, "*"); HANDLE h = FindFirstFileA (cast(char*)strSpec, &fd); bool bOK = h != INVALID_HANDLE_VALUE; while (bOK) { wchar[] wbuf; size_t clength = std.string.strlen(fd.cFileName.ptr); // Convert cFileName[] to unicode size_t wlength = MultiByteToWideChar(0,0,fd.cFileName.ptr,clength,null,0); if (wlength > wbuf.length) { wbuf.length = wlength; } size_t n = MultiByteToWideChar(0,0,fd.cFileName.ptr,clength,cast(wchar*)wbuf,wlength); assert(n == wlength); // toUTF8() returns a new buffer char[] strName = std.utf.toUTF8(wbuf[0 .. wlength]); if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { if (0 != std.string.cmp (strName, ".") && 0 != std.string.cmp (strName, "..") && 0 != std.string.cmp (strName, ".svn")) { visit (join (p_strFolder, strName), p_patt); } } else { char[] strFullName = join (p_strFolder, strName); if (-1 != p_patt.find(std.string.tolower (strFullName))) { // removed code for debugging purposes } } bOK = cast(bool)FindNextFileA (h, &fd); } FindClose (h); } void main (char [][] p_args) { if (p_args.length == 1) { visit (curdir, RegExp (".")); } else { visit (p_args[1], RegExp (std.string.tolower (p_args[1]))); } } PS: I just tested on 1.002 also and the behaviour is the same.Could you try this again with DMD 1.004?I regret to say that the problem persists in 1.004. --
Jan 28 2007
http://d.puremagic.com/issues/show_bug.cgi?id=885
fdp mcs.be changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|NEW |RESOLVED
Resolution| |INVALID
My mistake, sorry; had to use toStringz instead of just cast(char*) in the
line:
HANDLE h = FindFirstFileA (cast(char*)strSpec, &fd);
sorry for the trouble
--
Feb 26 2007









kris <foo bar.com> 