Solved

FtpFindFirstFile problem

Posted on 2000-04-15
8
511 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
 

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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

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…
For a while now I'v been searching for a circular progress control, much like the one you get when first starting your Silverlight application. I found a couple that were written in WPF and there were a few written in Silverlight, but all appeared o…
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…
Many functions in Excel can make decisions. The most simple of these is the IF function: it returns a value depending on whether a condition you describe is true or false. Once you get the hang of using the IF function, you will find it easier to us…

895 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now