Listing 1: older.c
#ifndef lint
static char sccsid[]="%Z%%M% %I% %E% %U% %Q%";
#endif
/* OLDER.C
*
* The Unix find command has no option that tells if a file is older
* than a certain time less than one day. It has a -newer option for
* comparing one file's date against all the others, but not an -older
* option.
*
* Here's the original problem: A bunch of files have come in
* through uucp, collected in a subdir in the uucppublic dir. Files
* of this sort can be coming in at any time. At a certain time of
* the day, a cron job wakes up and wants to move the files already
* arrived to another dir for further processing. It mustn't move
* all the files in the subdir since a new one could be coming in at
* the very time the mv is requested by cron. We don't want the
* partial file in transit moved. So, we need all files older than,
* say, 15 minutes prior to the current system time to be moved.
* That should be sufficient to capture the filenames prior to the
* one still in transit.
*
* For future application, this program will take a command line
* parameter specifying the actual number of minutes to use prior to
* the current system time, and a list of directories. If no time is
* given, 15 minutes will be presumed. If no directories are given,
* the '.' dir will be presumed. The program will write all matching
* filenames to stdout.
*
* Copyright 1992, by Lawrence S Reznick -- Feb 5, 1992
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include <dirent.h>
#include <sys/stat.h>
/*
* Prototypes
*/
extern int stat(char *, struct stat *); /* SCO didn't prototype it */
static int show_files(char *dirname, time_t start_time);
static time_t reduce_time(int minutes);
/*
* Constants
*/
#define FALSE 0
#define TRUE 1
/*
* Macros
*/
#define FEBDAYS(year) (((((year) % 400) == 0) || \
((((year) % 100) != 0) && (((year) & 3) == 0))) ? 29 : 28)
/*
* Globals
*/
char *progname;
/*
* Statics
*/
/*
* General Functions
*/
main(int argc, char *argv[])
{
int i,
err;
time_t start_time;
progname = argv[0]; /* For errors */
if (argc > 1 && argv[1][0] == '-') {
fputs("Usage:\t", stderr);
fputs(progname, stderr);
fputs(" [minutes [dir ...]]\n\n", stderr);
fputs("Shows all filenames in the dir list older than the "
"number of minutes\nprior to the current time. If "
"no minutes given, use 15. If no dir\nlist given "
"use current dir. Filenames are output to stdout.\n",
stderr);
exit(1);
}
if (argc < 2) {
start_time = reduce_time(15); /* Reduce by std prior min */
}
else {
start_time = reduce_time(atoi(argv[1]));
}
if (argc < 3) {
show_files(".", start_time);
}
else {
err = FALSE;
for (i = 2; !err && i < argc; i++) {
err = show_files(argv[i], start_time);
}
}
return(0);
}
/*
* Special Functions
*/
static time_t reduce_time(int min)
{
static int day[] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
int minutes, hours, days;
time_t now; /* Current time */
struct tm *t; /* Use localtime()'s workspace */
now = time(NULL);
t = localtime(&now); /* Convert for time arithmetic */
minutes = min % 60;
hours = (min /= 60) % 24;
days = min /= 24;
if ((t->tm_min -= minutes) < 0) { /* Reduce minutes */
t->tm_min += 60; /* 60 minutes/hour */
t->tm_hour--;
}
if ((t->tm_hour -= hours) < 0) { /* Reduce hours */
t->tm_hour += 24; /* 24 hours/day */
t->tm_mday--;
}
/* Days adjustment requires correspondence with the
* calendar. Reduce the days by the day in the current
* month and then go back to the previous month (previous
* year if needed) until the number of days have been
* reduced to less than the time of one month. That
* number of days gets taken away from the last day number
* of the adjusted month and becomes the actual calendar
* date.
*/
day[1] = FEBDAYS(t->tm_year); /* Adjust February */
while (days > t->tm_mday) { /* Still within this month? */
days -= t->tm_mday; /* Reduce by this day number */
if (--t->tm_mon < 0) { /* Correct for previous year */
t->tm_mon = 11;
t->tm_year--;
day[1] = FEBDAYS(t->tm_year);
}
t->tm_mday = day[t->tm_mon]; /* Use previous month */
}
t->tm_mday -= days; /* Take days off the date */
return(mktime(t)); /* Return the earlier time */
}
static int show_files(char *dirname, time_t start_time)
{
char pathname[256]; /* Full pathname of file */
int dirlen;
DIR *d; /* Dir being examined */
struct dirent *dp; /* Directory structure */
struct stat statbuf;
if ((d = opendir(dirname)) == NULL) {
fputs(progname, stderr);
fputs(": Error opening dir ", stderr);
perror(dirname);
return(TRUE);
}
dirlen = strlen(dirname);
strcpy(pathname, dirname);
pathname[dirlen++] = '/';
pathname[dirlen] = '\0';
while ((dp = readdir(d)) != NULL) {
if (dp->d_name[0] != '.') { /* Skip ., .., & hidden files */
strcpy(pathname + dirlen, dp->d_name);
if (!stat(pathname, &statbuf) &&
difftime(start_time, statbuf.st_mtime) >= 0.0) {
puts(pathname);
}
}
}
closedir(d);
return(FALSE);
}
|