/nemo_cvs/src/tools/misc/changed10.c

https://github.com/Milkyway-at-home/nemo · C · 209 lines · 125 code · 28 blank · 56 comment · 38 complexity · f18c61b840f2056879779879b0ae8af0 MD5 · raw file

  1. /*
  2. * This program expects args mmddyy dir1 dir2 ....
  3. *
  4. * For each directory named, all files under that directory recursively
  5. * that are newer than the specified date will be listed on stdout, but
  6. * it does not check subdirectories that are not on the same device as
  7. * their parent directory.
  8. *
  9. * It should be useful if you want to find out what files on your
  10. * root and usr devices have been changed since your last upgrade without
  11. * listing every user file, unless you keep users on /usr.
  12. *
  13. * Warren Burstein (pluto!warren) 7/22/87
  14. * Peter Teuben 8/13/87 small mods for SUN
  15. */
  16. #include <stdio.h>
  17. #include <errno.h>
  18. #ifdef SUN
  19. # include <sys/time.h>
  20. #else
  21. # include <time.h>
  22. #endif
  23. #include <sys/types.h>
  24. #include <sys/dir.h>
  25. #include <sys/stat.h>
  26. #include <sys/param.h>
  27. char *progname;
  28. main(argc, argv)
  29. char **argv;
  30. {
  31. int arg;
  32. long date, parse_date();
  33. char cwd[MAXPATHLEN];
  34. progname = argv[0];
  35. if (argc < 3) {
  36. fprintf(stderr, "Lists changed files since specified date in directories and below\n");
  37. fprintf(stderr, "usage: %s mmddyy dir...\n", progname);
  38. exit(1);
  39. }
  40. date = parse_date(argv[1]);
  41. getwd(cwd);
  42. for (arg = 2; arg < argc; arg++) {
  43. /*
  44. * look_at may change working directory, so come back
  45. * to where we started if this directory arg doesn't start
  46. * at /. Don't bother if this is the first time thru here.
  47. */
  48. if (arg != 2 && *argv[arg] != '/' && chdir(cwd) < 0) {
  49. fprintf(stderr, "%s: cannot return to %s: ", progname, cwd);
  50. perror("");
  51. exit(1);
  52. }
  53. look_at(argv[arg], date);
  54. }
  55. exit(0);
  56. }
  57. /*
  58. * Turn a string that looks like mmddyy into a date in the format
  59. * returned by time(2), seconds since 00:00:00 GMT Jan 1, 1970.
  60. */
  61. static int months[13] = {
  62. 0, /* let January be 1, not zero */
  63. 31, 28, 31, 30, 31, 30,
  64. 31, 31, 30, 31, 30, 31
  65. };
  66. long parse_date(mmddyy)
  67. char *mmddyy;
  68. {
  69. int month, day, year;
  70. int m;
  71. long date;
  72. struct timeval tv;
  73. struct timezone tz;
  74. (void) gettimeofday(&tv, &tz);
  75. if (sscanf(mmddyy, "%2d%2d%2d", &month, &day, &year) != 3) {
  76. fprintf(stderr, "%s: date must be in mmddyy format\n", progname);
  77. exit(1);
  78. }
  79. if (year < 70) {
  80. fprintf(stderr, "%s: the world was created in 1970!\n", progname);
  81. exit(1);
  82. }
  83. /*
  84. * Adjust February
  85. */
  86. months[2] = is_leap(year + 1900) ? 29 : 28;
  87. if (month < 1 || month > 12) {
  88. fprintf(stderr, "%s: month must be between 1 and 12\n", progname);
  89. exit(1);
  90. }
  91. if (day < 1 || day > months[month]) {
  92. fprintf(stderr, "%s: day must be between 1 and %d\n",
  93. progname, months[month]);
  94. exit(1);
  95. }
  96. /*
  97. * Find days between Jan 1, 1970 and Jan 1 of year (ignore Julian
  98. * corrections here), add days in months and day in month.
  99. */
  100. date = (year - 70) * 365 + year / 4 - 70 / 4;
  101. for (m = 1; m < month; m++)
  102. date += months[m];
  103. date += day - 1;
  104. /*
  105. * Turn into seconds, correct for longitude and daylight savings time.
  106. */
  107. date *= 24 * 60 *60;
  108. date += tz.tz_minuteswest * 60;
  109. if (localtime(&date)->tm_isdst)
  110. date -= 60 * 60;
  111. return date;
  112. }
  113. /*
  114. * Return true if year is a leap year.
  115. */
  116. int is_leap(year) {
  117. return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
  118. }
  119. /*
  120. * List all entries in dir that are newer than date. Recurse on
  121. * subdirectories that are on the same device as dir. Treat symbolic
  122. * links like regular files - list them if the link is new, not the file
  123. * referenced.
  124. *
  125. * Exit on any error since it's a pain to figure out what the current
  126. * directory is afterwards.
  127. */
  128. look_at(dir, date)
  129. char *dir;
  130. long date;
  131. {
  132. extern int errno;
  133. DIR *dirp;
  134. struct direct *dp;
  135. struct stat st;
  136. dev_t dev;
  137. if (stat(dir, &st) < 0) {
  138. fprintf(stderr, "%s: cannot stat directory %s\n", progname, dir);
  139. fprintf(stderr, "Errno=%d\n",errno);
  140. exit(1);
  141. }
  142. dev = st.st_dev;
  143. if ( (dirp = opendir(dir)) == NULL) {
  144. fprintf(stderr, "%s: cannot open directory %s\n", progname, dir);
  145. exit(1);
  146. }
  147. if (chdir(dir) < 0) {
  148. fprintf(stderr, "%s: cannot chdir to %s\n", progname, dir);
  149. exit(1);
  150. }
  151. while ( (dp = readdir(dirp)) != NULL) {
  152. /*
  153. * Skip self and parent
  154. */
  155. if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
  156. continue;
  157. /*
  158. * Use lstat, so as not to follow symbolic links.
  159. */
  160. if (lstat(dp->d_name, &st) < 0) {
  161. fprintf(stderr, "cannot stat file %s/%s\n", dir, dp->d_name);
  162. continue;
  163. }
  164. if ((st.st_mode & S_IFMT) == S_IFDIR) {
  165. if (st.st_dev == dev) {
  166. char dirname[MAXPATHLEN];
  167. /*
  168. * look_at chdir's to a subdirectory, go back up
  169. * when done.
  170. */
  171. (void) sprintf(dirname, "%s/%s", dir, dp->d_name);
  172. look_at(dirname, date);
  173. (void) chdir("..");
  174. }
  175. } else if (st.st_mtime > date)
  176. printf("%s/%s\n", dir, dp->d_name);
  177. }
  178. (void) closedir(dirp);
  179. }