warren@pluto.UUCP (Warren Burstein) (08/13/87)
changed searches for files underneath specified directories that have changed after a given date. It does not check subdirectories on other filesystems. I use it to find out what files have changed on my root and /usr filesystems without seeing everything under /. Usage: changed mmddyy directories The code that parses mmddyy and produces the number of seconds since Jan 1, 1970 should be useful in other places, too. Warren Burstein (pluto!warren) 8/11/87 No doubt I could have done it in find(1) but it took less time to write this than to figure it out. -----------cut somewhere else, why don't you?----------------- # This is a shell archive. Remove anything before this line, then # unpack it by saving it in a file and typing "sh file". (Files # unpacked will be owned by you and have default permissions.) # # This archive contains: # Read.me Makefile changed.c echo x - Read.me cat > "Read.me" << '//E*O*F Read.me//' This directory makes the "changed" program. It searches for files underneath specified directories that have changed after a given date. It does not check subdirectories on other filesystems. I use it to find out what files have changed on my root and /usr filesystems without seeing everything under /. Usage: changed mmddyy directories The code that parses mmddyy and produces the number of seconds since Jan 1, 1970 should be useful in other places, too. Warren Burstein (pluto!warren) 8/11/87 //E*O*F Read.me// echo x - Makefile cat > "Makefile" << '//E*O*F Makefile//' changed: changed.c cc changed.c -o changed lint: lint changed.c shar: shar Read.me Makefile changed.c > shar clean: -rm -f *.o core a.out changed //E*O*F Makefile// echo x - changed.c cat > "changed.c" << '//E*O*F changed.c//' /* * This program expects args mmddyy dir1 dir2 .... * * For each directory named, all files under that directory recusively * that are newer than the specified date will be listed on stdout, but * it does not check subdirectories that are not on the same device as * their parent directory. * * It should be useful if you want to find out what files on your * root and usr devices have been changed since your last upgrade without * listing every user file, unless you keep users on /usr. * * Warren Burstein (pluto!warren) 7/22/87 */ #include <stdio.h> #include <time.h> #include <sys/types.h> #include <sys/dir.h> #include <sys/stat.h> #include <sys/param.h> char *progname; main(argc, argv) char **argv; { int arg; long date, parse_date(); char cwd[MAXPATHLEN]; progname = argv[0]; if (argc < 3) { fprintf(stderr, "usage: %s mmddyy dir...\n", progname); exit(1); } date = parse_date(argv[1]); getwd(cwd); for (arg = 2; arg < argc; arg++) { /* * look_at may change working directory, so come back * to where we started if this directory arg doesn't start * at /. Don't bother if this is the first time thru here. */ if (arg != 2 && *argv[arg] != '/' && chdir(cwd) < 0) { fprintf(stderr, "%s: cannot return to %s: ", progname, cwd); perror(""); exit(1); } look_at(argv[arg], date); } exit(0); } /* * Turn a string that looks like mmddyy into a date in the format * returned by time(2), seconds since 00:00:00 GMT Jan 1, 1970. */ static int months[13] = { 0, /* let January be 1, not zero */ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; long parse_date(mmddyy) char *mmddyy; { int month, day, year; int m; long date; struct timeval tv; struct timezone tz; (void) gettimeofday(&tv, &tz); if (sscanf(mmddyy, "%2d%2d%2d", &month, &day, &year) != 3) { fprintf(stderr, "%s: date must be in mmddyy format\n", progname); exit(1); } if (year < 70) { fprintf(stderr, "%s: the world was created in 1970!\n", progname); exit(1); } /* * Adjust February */ months[2] = is_leap(year + 1900) ? 29 : 28; if (month < 1 || month > 12) { fprintf(stderr, "%s: month must be between 1 and 12\n", progname); exit(1); } if (day < 1 || day > months[month]) { fprintf(stderr, "%s: day must be between 1 and %d\n", progname, months[month]); exit(1); } /* * Find days between Jan 1, 1970 and Jan 1 of year (ignore Julian * corrections here), add days in months and day in month. */ date = (year - 70) * 365 + year / 4 - 70 / 4; for (m = 1; m < month; m++) date += months[m]; date += day - 1; /* * Turn into seconds, correct for longitude and daylight savings time. */ date *= 24 * 60 *60; date += tz.tz_minuteswest * 60; if (localtime(&date)->tm_isdst) date -= 60 * 60; return date; } /* * Return true if year is a leap year. */ int is_leap(year) { return year % 4 == 0 && year % 100 != 0 || year % 400 == 0; } /* * List all entries in dir that are newer than date. Recurse on * subdirectories that are on the same device as dir. Treat symbolic * links like regular files - list them if the link is new, not the file * referenced. * * Exit on any error since it's a pain to figure out what the current * directory is afterwards. */ look_at(dir, date) char *dir; long date; { DIR *dirp; struct direct *dp; struct stat st; dev_t dev; if (stat(dir, &st) < 0) { fprintf(stderr, "%s: cannot stat directory %s\n", progname, dir); exit(1); } dev = st.st_dev; if ( (dirp = opendir(dir)) == NULL) { fprintf(stderr, "%s: cannot open directory %s\n", progname, dir); exit(1); } if (chdir(dir) < 0) { fprintf(stderr, "%s: cannot chdir to %s\n", progname, dir); exit(1); } while ( (dp = readdir(dirp)) != NULL) { /* * Skip self and parent */ if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) continue; /* * Use lstat, so as not to follow symbolic links. */ if (lstat(dp->d_name, &st) < 0) { fprintf(stderr, "cannot stat file %s/%s\n", dir, dp->d_name); continue; } if ((st.st_mode & S_IFMT) == S_IFDIR) { if (st.st_dev == dev) { char dirname[MAXPATHLEN]; /* * look_at chdir's to a subdirectory, go back up * when done. */ (void) sprintf(dirname, "%s/%s", dir, dp->d_name); look_at(dirname, date); (void) chdir(".."); } } else if (st.st_mtime > date) printf("%s/%s\n", dir, dp->d_name); } (void) closedir(dirp); } //E*O*F changed.c// exit 0 -- /|/~\~~\ The entire world Warren Burstein |__/__/_/ is a very strange carrot. | But the farmer philabs!tg!pluto!warren / is not afraid at all. Why doesn't life come with subtitles?