dirwatch101 monitors a directory and all the files in it for any changes, any files that have new data added to them, that data logged to a file.
a117fcea816a0a6d30c4820fd7bcee4024b81edc957a567e2cc6737fce4a1986
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>
/* dirwatch.c v1.01 by ajax@mobis.com March 1998
this program monitors a directory and all the files in it for
any changes, any files that have new data added to them, that data
logged to a file.
I can think of only two uses for this program offhand, that of
monitoring /var/spool/mail to log all new mail traffic on the system
and of course the other use being to g0bbl3 k0d3z, its primary
function.
TODO:
1.Add a function to check for new files, add them to the original
struct file_size_mtime table, and increment the number_of_files.
2.Use intelligent file buffering instead of crappy system() calls.
3.Command line options to bind to socket, log to file or dump
data to stdout.
*/
/* GLOBALS */
int seconds; /* seconds between stat's, set by argv[3] */
char *outfile;
/* first structured array with which we will
* save file stat information
*/
struct file_size_mtime
{ char *filename;
size_t file_size;
time_t file_mtime;
};
struct file_size_mtime table[1024]; /* 1024 max files per directory */
int chk_stat(struct file_size_mtime *tabletwo)
{
FILE *infile_fp, *outfile_fp;
int result;
char buf[200];
struct stat stat;
char buffer[65535]; /* if it changes more than 64k between passes, we
overrun this buffer. to fix: while(bytesread=fread(4096..))fwrite */
off_t file_pos;
lstat(tabletwo->filename, &stat);
/* check to see if the newly stat'd mtime is greater than the
previous mtime in the old structure, if it is, check to make
sure the filesize also is greater than that of the old stat'd
structure. */
if(stat.st_mtime > tabletwo->file_mtime)
{
/* if file size is smaller make
* the assumption that it is all new data
*/
if(stat.st_size < tabletwo->file_size)
tabletwo->file_size = 0;
if ((infile_fp = fopen(tabletwo->filename,"rb"))==NULL)
{
printf("fopen: error opening infile_fp for reading\n");
return 0;
}
/* swapped terms of -, SEEK_END is bytes+eof */
file_pos = tabletwo->file_size-stat.st_size;
if ((result=fseek(infile_fp,file_pos,SEEK_END))!=0)
{
printf("fseek: error during seek of %s.\n",tabletwo->filename);
return 0;
}
/* there was a sizeof here. inexplicable. -fb */
/* swapped size and count, stdio sucks -fb*/
result = fread(buffer,1,stat.st_size-tabletwo->file_size,infile_fp);
if (ferror(infile_fp)) {
perror("fread");
}
fclose(infile_fp);
if ((outfile_fp = fopen(outfile,"ab"))==NULL) {
printf("fopen: error opening %s for writing.\n",outfile);
return 0;
}
result = fwrite(buffer,1,result,outfile_fp);
fclose(outfile_fp);
}
tabletwo->file_size=stat.st_size;
tabletwo->file_mtime=stat.st_mtime;
}
void usage(char *program_name){
printf("usage: %s pathname outfile seconds\n", program_name); return;}
main(argc, argv)
int argc;
char *argv[];
{ DIR *directory;
/* int end_of_entries = 0; CAN BE DELETED */
char *directory_to_open;
int count; /* interval of stat array structure */
int number_of_files; /* complete number of files to work with */
struct dirent *directory_entry;
if (argc < 4)
{
usage(argv[0]);
exit(1);
}
directory_to_open=argv[1];
outfile=argv[2];
seconds=atoi(argv[3]);
/* open directory_to_open pointed to by argv[1] and go into a while
loop using readdir to read each directory_entry_pointer until
it reaches the end of the directory (NULL). */
chdir(directory_to_open); /* Change to that directory */
directory = opendir(directory_to_open);
if(!directory) /* Error opening directory? */
{
perror(directory_to_open); /* Print the error and exit */
exit(1);
}
count = 0; /* initialize struct array number to 0 */
while((directory_entry = readdir(directory)) != NULL)
{
struct stat stat;
lstat(directory_entry->d_name, &stat);
if(!S_ISREG(stat.st_mode)) /* not a normal file */
continue;
table[count].filename = strdup(directory_entry->d_name);
table[count].file_size = stat.st_size;
table[count].file_mtime = stat.st_mtime;
++count;
}
closedir(directory);
number_of_files = count; /* save the number of files in dir */
/* ok, the table has been constructed. Now, its time to process
whats given and keep stat'ing it, comparing what is put into
the new struct temp_filetable to what was in the original table. */
while(1)
{
count = 0; /* reset counter again */
sleep(seconds);
while (count < number_of_files)
{
chk_stat(&table[count]);
++count;
}
}
return 0;
}