home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume1 / 8708 / 12 < prev    next >
Encoding:
Internet Message Format  |  1990-07-13  |  6.7 KB

  1. From: warren@pluto.UUCP (Warren Burstein)
  2. Newsgroups: comp.sources.misc
  3. Subject: utility to find changed files
  4. Message-ID: <4123@ncoast.UUCP>
  5. Date: 13 Aug 87 00:09:20 GMT
  6. Sender: allbery@ncoast.UUCP
  7. Organization: Industrial Automation Systems - New York, NY
  8. Lines: 265
  9. Approved: allbery@ncoast.UUCP
  10. X-Archive: comp.sources.misc/8708/12
  11.  
  12. changed searches for files underneath specified directories that have
  13. changed after a given date.  It does not check subdirectories on
  14. other filesystems.  I use it to find out what files have changed
  15. on my root and /usr filesystems without seeing everything under /.
  16.  
  17. Usage:  changed mmddyy directories
  18.  
  19. The code that parses mmddyy and produces the number of seconds
  20. since Jan 1, 1970 should be useful in other places, too.
  21.  
  22. Warren Burstein (pluto!warren) 8/11/87
  23.  
  24. No doubt I could have done it in find(1) but it took less time
  25. to write this than to figure it out.
  26. -----------cut somewhere else, why don't you?-----------------
  27.  
  28. # This is a shell archive.  Remove anything before this line, then
  29. # unpack it by saving it in a file and typing "sh file".  (Files
  30. # unpacked will be owned by you and have default permissions.)
  31. #
  32. # This archive contains:
  33. # Read.me Makefile changed.c
  34.  
  35. echo x - Read.me
  36. cat > "Read.me" << '//E*O*F Read.me//'
  37. This directory makes the "changed" program.
  38.  
  39. It searches for files underneath specified directories that have
  40. changed after a given date.  It does not check subdirectories on
  41. other filesystems.  I use it to find out what files have changed
  42. on my root and /usr filesystems without seeing everything under /.
  43.  
  44. Usage:  changed mmddyy directories
  45.  
  46. The code that parses mmddyy and produces the number of seconds
  47. since Jan 1, 1970 should be useful in other places, too.
  48.  
  49. Warren Burstein (pluto!warren) 8/11/87
  50. //E*O*F Read.me//
  51.  
  52. echo x - Makefile
  53. cat > "Makefile" << '//E*O*F Makefile//'
  54. changed: changed.c
  55.     cc changed.c -o changed
  56.  
  57. lint:
  58.     lint changed.c
  59.  
  60. shar:
  61.     shar Read.me Makefile changed.c > shar
  62.  
  63. clean:
  64.     -rm -f *.o core a.out changed
  65. //E*O*F Makefile//
  66.  
  67. echo x - changed.c
  68. cat > "changed.c" << '//E*O*F changed.c//'
  69. /*
  70.  * This program expects args mmddyy dir1 dir2 ....
  71.  *
  72.  * For each directory named, all files under that directory recusively
  73.  * that are newer than the specified date will be listed on stdout, but
  74.  * it does not check subdirectories that are not on the same device as
  75.  * their parent directory.
  76.  *
  77.  * It should be useful if you want to find out what files on your
  78.  * root and usr devices have been changed since your last upgrade without
  79.  * listing every user file, unless you keep users on /usr.
  80.  *
  81.  * Warren Burstein (pluto!warren) 7/22/87
  82.  */
  83.  
  84. #include <stdio.h>
  85. #include <time.h>
  86. #include <sys/types.h>
  87. #include <sys/dir.h>
  88. #include <sys/stat.h>
  89. #include <sys/param.h>
  90.  
  91. char *progname;
  92.  
  93. main(argc, argv)
  94. char **argv;
  95. {
  96.     int arg;
  97.     long date, parse_date();
  98.     char cwd[MAXPATHLEN];
  99.  
  100.     progname = argv[0];
  101.  
  102.     if (argc < 3) {
  103.         fprintf(stderr, "usage: %s mmddyy dir...\n", progname);
  104.         exit(1);
  105.     }
  106.  
  107.     date = parse_date(argv[1]);
  108.  
  109.     getwd(cwd);
  110.     for (arg = 2; arg < argc; arg++) {
  111.         /*
  112.          * look_at may change working directory, so come back
  113.          * to where we started if this directory arg doesn't start
  114.          * at /.  Don't bother if this is the first time thru here.
  115.          */
  116.         if (arg != 2 && *argv[arg] != '/' && chdir(cwd) < 0) {
  117.             fprintf(stderr, "%s: cannot return to %s: ", progname, cwd);
  118.             perror("");
  119.             exit(1);
  120.         }
  121.         look_at(argv[arg], date);
  122.     }
  123.  
  124.     exit(0);
  125. }
  126.  
  127. /*
  128.  * Turn a string that looks like mmddyy into a date in the format
  129.  * returned by time(2), seconds since 00:00:00 GMT Jan 1, 1970.
  130.  */
  131.  
  132. static int months[13] = {
  133.     0,                            /* let January be 1, not zero */
  134.     31, 28, 31, 30, 31, 30,
  135.     31, 31, 30, 31, 30, 31
  136. };
  137.  
  138. long parse_date(mmddyy)
  139. char *mmddyy;
  140. {
  141.     int month, day, year;
  142.     int m;
  143.     long date;
  144.     struct timeval tv;
  145.     struct timezone tz;
  146.  
  147.     (void) gettimeofday(&tv, &tz);
  148.  
  149.     if (sscanf(mmddyy, "%2d%2d%2d", &month, &day, &year) != 3) {
  150.         fprintf(stderr, "%s: date must be in mmddyy format\n", progname);
  151.         exit(1);
  152.     }
  153.  
  154.     if (year < 70) {
  155.         fprintf(stderr, "%s: the world was created in 1970!\n", progname);
  156.         exit(1);
  157.     }
  158.  
  159.     /*
  160.      * Adjust February
  161.      */
  162.     months[2] = is_leap(year + 1900) ? 29 : 28;
  163.  
  164.     if (month < 1 || month > 12) {
  165.         fprintf(stderr, "%s: month must be between 1 and 12\n", progname);
  166.         exit(1);
  167.     }
  168.  
  169.     if (day < 1 || day > months[month]) {
  170.         fprintf(stderr, "%s: day must be between 1 and %d\n",
  171.                progname, months[month]);
  172.         exit(1);
  173.     }
  174.  
  175.     /*
  176.      * Find days between Jan 1, 1970 and Jan 1 of year (ignore Julian
  177.      * corrections here), add days in months and day in month.
  178.      */
  179.     date = (year - 70) * 365 + year / 4 - 70 / 4;
  180.     for (m = 1; m < month; m++)
  181.       date += months[m];
  182.     date += day - 1;
  183.  
  184.     /*
  185.      * Turn into seconds, correct for longitude and daylight savings time.
  186.      */
  187.     date *= 24 * 60 *60;
  188.     date += tz.tz_minuteswest * 60;
  189.     if (localtime(&date)->tm_isdst)
  190.       date -= 60 * 60;
  191.  
  192.     return date;
  193. }
  194.  
  195. /*
  196.  * Return true if year is a leap year.
  197.  */
  198. int is_leap(year) {
  199.   return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
  200. }
  201.  
  202. /*
  203.  * List all entries in dir that are newer than date.  Recurse on
  204.  * subdirectories that are on the same device as dir.  Treat symbolic
  205.  * links like regular files - list them if the link is new, not the file
  206.  * referenced.
  207.  *
  208.  * Exit on any error since it's a pain to figure out what the current
  209.  * directory is afterwards.
  210.  */
  211.  
  212. look_at(dir, date)
  213. char *dir;
  214. long date;
  215. {
  216.     DIR *dirp;
  217.     struct direct *dp;
  218.     struct stat st;
  219.     dev_t dev;
  220.  
  221.     if (stat(dir, &st) < 0) {
  222.         fprintf(stderr, "%s: cannot stat directory %s\n", progname, dir);
  223.         exit(1);
  224.     }
  225.     dev = st.st_dev;
  226.  
  227.     if ( (dirp = opendir(dir)) == NULL) {
  228.         fprintf(stderr, "%s: cannot open directory %s\n", progname, dir);
  229.         exit(1);
  230.     }
  231.  
  232.     if (chdir(dir) < 0) {
  233.         fprintf(stderr, "%s: cannot chdir to %s\n", progname, dir);
  234.         exit(1);
  235.     }
  236.  
  237.     while ( (dp = readdir(dirp)) != NULL) {
  238.         /*
  239.          * Skip self and parent
  240.          */
  241.         if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
  242.           continue;
  243.  
  244.         /*
  245.          * Use lstat, so as not to follow symbolic links.
  246.          */
  247.         if (lstat(dp->d_name, &st) < 0) {
  248.             fprintf(stderr, "cannot stat file %s/%s\n", dir, dp->d_name);
  249.             continue;
  250.         }
  251.  
  252.         if ((st.st_mode & S_IFMT) == S_IFDIR) {
  253.             if (st.st_dev == dev) {
  254.                 char dirname[MAXPATHLEN];
  255.  
  256.                 /*
  257.                  * look_at chdir's to a subdirectory, go back up
  258.                  * when done.
  259.                  */
  260.                 (void) sprintf(dirname, "%s/%s", dir, dp->d_name);
  261.                 look_at(dirname, date);
  262.                 (void) chdir("..");
  263.             }
  264.         } else if (st.st_mtime > date)
  265.           printf("%s/%s\n", dir, dp->d_name);
  266.     }
  267.     (void) closedir(dirp);
  268. }
  269. //E*O*F changed.c//
  270.  
  271. exit 0
  272. -- 
  273. /|/~\~~\    The entire world             Warren Burstein
  274.  |__/__/_/  is a very strange carrot.
  275.  |          But the farmer               philabs!tg!pluto!warren
  276. /           is not afraid at all.        Why doesn't life come with subtitles?
  277.