LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   linux system call to detect changes in a directory (https://www.linuxquestions.org/questions/programming-9/linux-system-call-to-detect-changes-in-a-directory-22105/)

lucianomx 05-29-2002 03:24 PM

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.

vfs 05-29-2002 03:32 PM

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

lucianomx 05-29-2002 04:08 PM

(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,

crabboy 06-04-2002 07:49 PM

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 */


vfs 06-05-2002 06:54 AM

Luciano, do you study at USP?

vfs


All times are GMT -5. The time now is 04:56 AM.