[2 days left] What’s wrong with your cloud strategy? Learn why multicloud solutions matter with Nimble Storage.Register Now

x
?
Solved

FtpFindFirstFile problem

Posted on 2000-04-15
8
Medium Priority
?
683 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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
NFR key for Veeam Agent for Linux

Veeam is happy to provide a free NFR license for one year.  It allows for the non‑production use and valid for five workstations and two servers. Veeam Agent for Linux is a simple backup tool for your Linux installations, both on‑premises and in the public cloud.

 

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

On Demand Webinar: Networking for the Cloud Era

Ready to improve network connectivity? Watch this webinar to learn how SD-WANs and a one-click instant connect tool can boost provisions, deployment, and management of your cloud connection.

Question has a verified solution.

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

This article describes a technique for converting RTF (Rich Text Format) data to HTML and provides C++ source that does it all in just a few lines of code. Although RTF is coming to be considered a "legacy" format, it is still in common use... po…
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
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…
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…

649 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