A customer was having trouble with some code that copies a bunch of files and then processes the copy. Here's the code they shared (suitably redacted):
// copy the files char command[512] = {NULL}; sprintf_s(command, 512, "copy /Y %s %s >nul 2>&1", sourcePath, destPath); printf("The command is %s\n", command); Log("The command is %s", command); system(command); // process the files char searchPattern[256] = {NULL}; sprintf_s(searchPattern, 256, "%s\\*", destPath); printf("The directory is %s.\n", searchPattern); Log("The directory is %s", searchPattern); hFile = FindFirstFileA(searchPattern, &FindFileData); // error when searching files if (hFile == INVALID_HANDLE_VALUE) { DWORD lastError = GetLastError(); if (lastError == ERROR_FILE_NOT_FOUND) { printf("No files under directory %s.\n", searchPattern); Log("No files under directory %s", searchPattern); return S_OK; } else { printf("FindFirstFile failed in directory %s with error: %d.\n", searchPattern, lastError); Log("FindFirstFile failed under directory %s with error: %d", searchPattern, lastError); return E_FAIL; } } do { printf("The file is %s.\n", FindFileData.cFileName); Log("The file is %s", FindFileData.cFileName); ...
The customer reported that
"It appears that
FindFirstFileA
does not
wait for
system()
to finish copying the files.
Here's a sample log file:
The command is copy /Y \\server\path\to\data\* D:\data >nul 2>&1 The directory is D:\data\* The file is .
"Observe that FindFirstFileA
did not find the files we copied.
How can we wait for the system()
function to finish copying the files
before the program proceeds to the
FindFirstFileA
?"
In the ensuing discussion,
people suggested using
CopyFile
or
SHFileOperation
instead of shelling
out to cmd.exe
.
Issues with spaces and other characters in the directory
names.
But can you find the reason why
FindFirstFileA
couldn't
find the files?
Look carefully at the last line of the log: "The file is ." Part of this is confusing because the program both prints its output to the screen as well as to the log file, but prints them differently. The output to the screen includes a period at the end; the output to the log file does not.
And that's the key.
Since the output to the log file does not include a period
at the end,
it means that the period in the output is the actual
contents of
FindFileData.
.
The customer misread their log file.
The issue isn't that the
FindFirstFileA
ran
before the files were copied.
The issue is that the first thing found by
FindFirstFileA
was
the file whose name consists of a single period.
Recall that every directory has two artificial
entries,
one for the directory itself (.
),
and one for the directory's parent
(..
).
What you found was the first artificial entry,
the one that represents the directory itself.
Instead of giving up right away,
keep looking,
and the files you copied will show up later.
(Assuming they were all successfully copied. The program doesn't actually check.)