?
Solved

FtpFindFirstFile problem

Posted on 2000-04-15
8
Medium Priority
?
754 Views
Last Modified: 2013-12-03
Im writing my own little automatic FTP program that will backup web sites.  Im using the WinInet API.  I created a function which utilizes FtpFindFirstFile() & InternetFindNextFile().  This function gets called recursively whenever it find a subdirectory.  The biggest problem im having is when I try to traverse a directory tree using FtpFindFirstFile() & InternetFindNextFile().  When the code detects a subdirectory and I call my function recurses, I have to call FtpFindFirstFile() again inside of that recursive call.  In order for that to work, I needed to have closed the hFind in the calling function.  When the recursive function returns, I find myself having to call FtpFindFirstFile() again in the calling function in which it simply finds the same folder again.  An endless loop.  

I can't seem to figure a way around it.  Does anyone have any good code snippets or ideas for traversing a tree using WinInet FTP functions?

Thanks for the help,
-Dan  
0
Comment
Question by:dmaroff
8 Comments
 
LVL 23

Expert Comment

by:chensu
ID: 2720008
Look into the following sample. It uses MFC, but you can definitely get the idea.

FTPTREE: Displays the Structure and Content of an FTP Site
http://msdn.microsoft.com/isapi/msdnlib.idc?theURL=/library/devprods/vs6/visualc/vcsample/_sample_mfc_ftptree.htm
0
 

Author Comment

by:dmaroff
ID: 2720561
I've seen this code already. The program is designed to be a bit different than mine.  The way that code works is it displays all of the files and folders in breadth order.  In other words it displays all of the files and folders in a root folder, then when you click a folder, it just does another search on that folder by issuing a FindFirstFile for that folder and so on.  

According to this code I'd have to keep a list of all the subfolders Ive seen in a given folder before I dive into one of those subfolders.  This way when I pop back up to that folder, I have a list of folders to go to without reissuing the search on that folder again.  


In other words if the tree looks like this:

\MainFolder
  - File1a
  - Folder1a
      - File1b
      - File2b
      - File3b
  - File2a
  - Folder2a
  - Folder3a

Id first use FindFirstFile() in Mainfolder which will traverse all of the files and folders of MainFolder.  As I do that, Id push all of the folders found (Folder1a, Folder2a, and Folder3a) onto a list.  

Once thats done I'd then dive into the first folder in my list (Folder1a), traverse that folder and when finished, pop back up to MainFolder.  At this point instead of doing a FindFirstFile() again, Id just go to the next folder in the list (Folder2a) and dive into that folder, and so on.  

This avoids having to use FindFirstFile() more than once on a folder, because each folder will have a list of its subfolders.   Thats the only way I can think of doing it.


Im trying to avoid that technique if possible.  If there is no way around it I guess I'll have to do that.  If you know another way that would be great.


Thanks,
-Dan
0
 
LVL 2

Expert Comment

by:xLs
ID: 2723687
maybe this will give you an idea

this is just some semipseudo code for doing your list recursivly.

int ListFiles(char* root,filelist* list)
{

   SFILE filestruct;
   DFile data;
   int count = 0;
   FindFirstFile(root,filestruct);
   while(FindNextFile(filestruct,data))
   {
      if(data.type == DIRECTORY)
       count =+ListFiles(data.name,list);
     else
        {
       list.insert(data);
        count++;
        }
   }

 return count;
}


no idea if you want it that way, but could be useful :)

cheers
0
Transaction-level recovery for Oracle database

Veeam Explore for Oracle delivers low RTOs and RPOs with agentless transaction log backup and transaction-level recovery of Oracle databases. You can restore the database to a precise point in time, even to a specific transaction.

 

Author Comment

by:dmaroff
ID: 2726982
Thanks, as a matter of fact I did finish it.  I used an STL list which came in real handy.  I pretty much did it the same way you did.
0
 

Accepted Solution

by:
pThread earned 400 total points
ID: 2727159
Try this code, I had the same problem and I fixed it with this.  I added in an STL list for you.

Good luck.


void BeginBackup(HANDLE& hConnect, char* remDir)
{
      DWORD size = MAX_PATH;
      
      WIN32_FIND_DATA remData;

      /* Files modification times */
      FILETIME locModified, a, b;
      
      /* Tests if file exists */
      HANDLE hFile;

      /* enumerates all files in a directory */
      HINTERNET hFind;

      /* Keeps track of paths used in directory searches */
      char fullPath[MAX_PATH];
      char parentDir[MAX_PATH];

      /* An STL list used to store enumerated directories */
      list <string> l;
      list <string>::iterator i;
      const char* path;
      
      /* Get the local working directory */
      GetCurrentDirectory(255, parentDir);
      
      /* Find the first file in a directory */
      hFind = FtpFindFirstFile(hConnect, NULL, &remData, NULL, NULL);


      /* If we locate a directory, add it to our list of
            directories that we will latere search */
      if(remData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) {
            
            /* Add directory to the list here */
            l.push_back(remData.cFileName);
      }

      /* Get the file if it doesn't exist or if file modified time is greater
         than the local file */
      else {
            sprintf(fullPath, "%s\\%s", parentDir, remData.cFileName);
            hFile = CreateFile(fullPath, GENERIC_READ , NULL, NULL, OPEN_EXISTING, NULL, NULL);
            
            if(GetFileTime(hFile, &a, &b, &locModified)) {      
                  if (CompareFileTime(&locModified, &remData.ftLastWriteTime) == -1) {
                        FtpGetFile(hConnect, remData.cFileName, remData.cFileName,
                        FALSE, NULL, FTP_TRANSFER_TYPE_BINARY , NULL);
                  }
            }
            else {
                        FtpGetFile(hConnect, remData.cFileName, remData.cFileName,
                                            FALSE, NULL, FTP_TRANSFER_TYPE_BINARY , NULL);
            }
            CloseHandle(hFile);
      }
            

      /* Search through the rest of the directory */
      while(InternetFindNextFile(hFind, &remData)) {
                        
            /* If we locate a directory, set it as current
            and search that directory using a recursive call */
            if(remData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) {
                  
                  /* Add directory to the list */
                  l.push_back(remData.cFileName);
            }
            /* If its a file, get it. */
            else {
                  sprintf(fullPath, "%s\\%s", parentDir, remData.cFileName);
                  hFile = CreateFile(fullPath, GENERIC_READ , NULL,
                                                       NULL, OPEN_EXISTING, NULL, NULL);
            
                  if(GetFileTime(hFile, &a, &b, &locModified)) {      
                        if (CompareFileTime(&locModified, &remData.ftLastWriteTime) == -1) {
                              FtpGetFile(hConnect, remData.cFileName, remData.cFileName,
                                                  FALSE, NULL, FTP_TRANSFER_TYPE_BINARY , NULL);
                        }
                  }
                  else {
                        FtpGetFile(hConnect, remData.cFileName, remData.cFileName,
                                                  FALSE, NULL, FTP_TRANSFER_TYPE_BINARY , NULL);
                  }
                  CloseHandle(hFile);
            }      

      }
      InternetCloseHandle(hFind);

      /* Traverse list of directories and dive into them */
      for(i = l.begin(); i != l.end(); ++i) {
            path = (*i).c_str();
            sprintf(fullPath, "%s\\%s", parentDir, path);
            
            if (!SetCurrentDirectory(fullPath)) {
                        CreateDirectory(fullPath, NULL);
                        SetCurrentDirectory(fullPath);
            }
            
            FtpSetCurrentDirectory(hConnect, path);
            BeginBackup(hConnect, (char*)path);
            FtpSetCurrentDirectory(hConnect, "..");
      }
0
 

Author Comment

by:dmaroff
ID: 2727165
Thanks, even though I finished it you did give me a few new ideas.

-Dan
0
 
LVL 2

Expert Comment

by:xLs
ID: 2729038
just as a tip, try use vector<string> instead of list (list tends to have some allocation problems among other). you will not need to change your code that way anyway.
0
 

Author Comment

by:dmaroff
ID: 2731111
Ok, I'll do that.

Thanks,
-Dan
0

Featured Post

Windows Server 2016: All you need to know

Learn about Hyper-V features that increase functionality and usability of Microsoft Windows Server 2016. Also, throughout this eBook, you’ll find some basic PowerShell examples that will help you leverage the scripts in your environments!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This tutorial is about how to put some of your C++ program's functionality into a standard DLL, and how to make working with the EXE and the DLL simple and seamless.   We'll be using Microsoft Visual Studio 2008 and we will cut out the noise; that i…
What my article will show is if you ever had to do processing to a listbox without being able to just select all the items in it. My software Visual Studio 2008 crystal report v11 My issue was I wanted to add crystal report to a form and show…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question