LinuxQuestions.org
Register a domain and help support LQ
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 05-29-2002, 03:24 PM   #1
lucianomx
LQ Newbie
 
Registered: May 2002
Location: Brazil
Distribution: Conectiva
Posts: 7

Rep: Reputation: 0
Question linux system call to detect changes in a directory


Can someone help me to know how to do a program that detect changes in a directory ?

I need to do a program that stay in "idle mode" until a occurency of any changes in directory monitored by the program.

Thanks.
 
Old 05-29-2002, 03:32 PM   #2
vfs
Member
 
Registered: Apr 2002
Location: Brazil
Distribution: Slackware
Posts: 184

Rep: Reputation: 30
Vixe!!! Acho que era baum ocê usá um daemon, não?

I think you need a daemon to log the disk activity and check if something was changed.

Check 'stat()' and friends (man stat). Something like a daemon saves log with disk contents list now. Then it runs within the next 5 seconds, f.e., save new log, then compare the old with the new... I don't know, just "vaporware" tinkering...

HTH,

vfs
 
Old 05-29-2002, 04:08 PM   #3
lucianomx
LQ Newbie
 
Registered: May 2002
Location: Brazil
Distribution: Conectiva
Posts: 7

Original Poster
Rep: Reputation: 0
(Eu nao gostaria de fazer assim)

I would not like to develop the program, using internal timing embbed into it.

I'm looking for ways to use API (system call) like as FindFirstChangeNotification() / FindNextChangeNotification() / Wait() from Windows SDK, where the Operating System notify the program on any changes (like as file creation, file change, etc...) and the applicatin stay in idle, not using resources of system while waiting for "events".

I have another sample on TCP/IP:

In sockets we use select() to put the program in idle until the occurency of events as timeout (previous configured) or data traffic, etc ...

Do you know way to monitor directory changes in the similar way ?


thanks,
 
Old 06-04-2002, 07:49 PM   #4
crabboy
Moderator
 
Registered: Feb 2001
Location: Atlanta, GA
Distribution: Slackware
Posts: 1,823

Rep: Reputation: 120Reputation: 120
I'm not aware of a way to do it how you want. I don't know of a call like Windows has. The only way I can think to do it is with a daemon like vfs suggested. Here is a very hacked together example. The program started out in C, but changed to C++ so I could use the stl map class. The daemon code is commented out so you can see the output. Some logging would have to be added for daemon mode.
Code:
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <unistd.h>

#include <map>
#include <string>

class cStat
{
   private:
      struct stat _mStat;
   public:
      cStat( void ) {};
      cStat( struct stat& sstat ) { memcpy( (struct stat *)&_mStat, (struct stat*)&sstat, sizeof( sstat ));}; 
      cStat( const cStat & cstat ) { memcpy( (struct stat *)&_mStat, &cstat._mStat, sizeof( cstat._mStat )); };
      struct stat *data() { return &_mStat; }; 
      bool operator==( const cStat& cstat1 ) { return( !memcmp( (struct stat *)&_mStat, (struct stat *)&cstat1._mStat, sizeof( struct stat ) )); };
      bool operator!=( const cStat& cstat1 ) { return( memcmp( (struct stat *)&_mStat, (struct stat *)&cstat1._mStat, sizeof( struct stat ) )); };
};

int makedaemon(void)
{ 
   int iForkRet = 0;

   iForkRet = fork();
   if ( iForkRet != 0 )
      exit(0);
      
   setsid();
   chdir("/");
   umask(0);
}

int readDir( const char *szDirectory,
             std::map<std::string, cStat>& mapFileList )
{
   struct stat stDirInfo;
   struct dirent * stFiles;
   DIR * stDirIn;
   char szFullName[MAXPATHLEN];
   struct stat stFileInfo;
   short int mode;
   bool bFirstTime = mapFileList.empty();

   if (lstat( szDirectory, &stDirInfo) < 0)
   {
      perror (szDirectory);
      return 0;
   }
   if (!S_ISDIR(stDirInfo.st_mode))
      return 0;
   if ((stDirIn = opendir( szDirectory)) == NULL)
   {
      perror( szDirectory );
      return 0;
   }
   while (( stFiles = readdir(stDirIn)) != NULL)
   {
      sprintf(szFullName, "%s/%s", szDirectory, stFiles -> d_name );

      if (lstat(szFullName, &stFileInfo) < 0)
         perror ( szFullName );

      cStat cstat( stFileInfo );
      mapFileList[ std::string( stFiles -> d_name ) ] = cstat; 

   }  // end while
   closedir(stDirIn);
   return 0;

} // end checkDir

bool compare( std::map<std::string, cStat > mapTempFileList, 
              std::map<std::string, cStat > mapFileList )
{

   bool bChange = false;

   for (std::map<std::string, cStat>::iterator mapItr1 = 
        mapFileList.begin(); mapItr1 != mapFileList.end(); 
        mapItr1++ ) 
   {
//      cout << "Name: [" << (*mapItr1).first.c_str() << "] = [" 
//           << (*mapItr1).second.data()->st_size << "]" << endl;

      std::map<std::string, cStat>::iterator mapItr2 = 
         mapTempFileList.find( (*mapItr1).first ); 

      if ( mapItr2 != mapTempFileList.end() )
      {
         // Found
         if ( (*mapItr2).second != (*mapItr1).second )
         {
            cout << "File [" << (*mapItr2).first << "] changed" <<  endl;
            bChange = true;
         }
         mapTempFileList.erase( mapItr2 );
      }
      else
      {
         // Not Found
         cout << "File [" << (*mapItr1).first << "] Added" <<  endl;
         bChange = true;
      
      }
      
   }
   if ( !mapTempFileList.empty() )
   {
      for (std::map<std::string, cStat>::iterator mapItr1 = 
           mapTempFileList.begin(); mapItr1 != mapTempFileList.end(); 
           mapItr1++ ) 
      {
         cout << "File [" << (*mapItr1).first.c_str() << "]  deleted" << endl;
      }
         bChange = true;
   }

   return( bChange );
}

void doChanged(void)
{

}

main(int argc, char * argv[] )
{

//   makedaemon();

   std::map<std::string, cStat > mapFileList;
   int iChanged = 0;

   readDir( argv[1], mapFileList );

   while( 1 )
   {
      std::map<std::string, cStat > mapTempFileList;
      readDir( argv[1], mapTempFileList );

      if ( compare( mapFileList, mapTempFileList ) )
      {
         doChanged();
         mapFileList.clear();
         readDir( argv[1], mapFileList );
      }

      sleep(5);
   }

}  /* end main */
 
Old 06-05-2002, 06:54 AM   #5
vfs
Member
 
Registered: Apr 2002
Location: Brazil
Distribution: Slackware
Posts: 184

Rep: Reputation: 30
Luciano, do you study at USP?

vfs
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Adding system call in linux guam Programming 2 12-04-2004 01:38 PM
how to use ls in a system call in C in linux newguy21 Programming 15 08-01-2004 01:38 PM
open system call in linux udayan Linux - Newbie 1 05-06-2002 10:21 AM
adding system call in linux udayan Programming 1 05-02-2002 03:26 AM
C system call in linux nerak Programming 6 04-10-2002 03:04 PM


All times are GMT -5. The time now is 11:39 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration