Solved

FtpFindFirstFile problem

Posted on 2000-04-15
8
536 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
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 

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 100 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

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

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…
In this article, I will show how to use the Ribbon IDs Tool Window to assign the built-in Office icons to a ribbon button.  This tool will help us to find the OfficeImageId that corresponds to our desired built-in Office icon. The tool is part of…
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…
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…

856 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