#include #include #include #include #include #include /* 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; }