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?