3

I have to fix a bug deeply buried in legacy code. This code makes a call to FtpFindFirstFileW to collect info about files on an FTP server. It then iterates over the files using InternetFindNextFile, puts the info into a vector and returns this vector.

The problem, however, is that the "path" passed to FtpFindFirstFileW could also be the path to a single file. FtpFindFirstFileW is fine with that an just returns info about this single file. But afterwards I see no possibility to reliably get the full path to the file (i.e. the path passed to FtpFindFirstFileW in the first place). The WIN32_FIND_DATA structure only contains the filename without its path.

My method could be called with a path like

  1. empty path (e.g. list files in current directory)
  2. path/to/some/subdir
  3. path/to/file.txt
  4. file.txt (e.g. just a filename)

If ever possible I would like to just change this single method to reduce the risk of breaking the legacy code.

WIN32_FIND_DATA FileData;
FtpFindFirstFile(hFTP, Path.c_str(), &FileData, 0, 0);

do
{
    auto PathToFile = Path + FileData.cFileName; // wrong result if Path is full path to file (e.g. Path = path/to/file.txt and FileData.cFileName = file.txt)
    auto PathToFile = Path; // wrong result if Path is path to directory (e.g. Path = path/ and FileData.cFileName = file.txt)
    auto PathToFile = FileData.cFileName; // wrong result if Path path to directory (e.g. Path = path/ and FileData.cFileName = file.txt)
} while(InternetFindNextFile(Hdl,&FileData));

I dont see methods to check if a path is a directory/file or to get the full path to a file in the Windows-FTP-API.


EDIT

Regarding the comments suggesting to use FileData.dwFileAttributes to distinguish between files and directories:

If I call FtpFindFirstFile with the path /foo/bar I might get a single result with FileData.cFilename = bar. If FileData.dwFileAttributes has the FILE_ATTRIBUTE_DIRECTORY bit not set I don't see a way to know if this is because /file/bar is a file or because /file/bar is a directory and there is a file /foo/bar/bar.

sigy
  • 2,408
  • 1
  • 24
  • 55
  • I don't see a way making that distinction by using the API. Why do you need the function to also accept a file path in the first place? IMO querying directory content and asking for information about a single file is semantically different, so it shouldn't be handled by a *single* function. – zett42 Sep 22 '17 at 10:57
  • @zett42 I agree but this is how the legacy code is atm. I would like to make as little changes as possible to reduce the risk of breaking it. Additionally I dont know how to make the distinction a priori either since I would face the same problem. There simply is no sate where I know if the path is a file or a directory. It is user input. – sigy Sep 22 '17 at 11:23
  • `if(FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)...` should tell you if path is directory. – Barmak Shemirani Sep 22 '17 at 22:17
  • @BarmakShemirani If for a path like `/foo/bar` I get a result with `cFilename = bar` and `FILE_ATTRIBUTE_DIRECTORY` is not set for this result. How should I know if this is because `/file/bar` is a file or because there is actually a file `/foo/bar/bar`? – sigy Dec 18 '17 at 15:06

0 Answers0