/* Recursive file directory of most recent files David Horton, Centre for Information Technology Research, University of Queensland horton@citr.uq.oz.au */ #include #include #ifdef msdos #include #else #define _INCLUDE_POSIX_SOURCE #endif #include #define _INCLUDE_HPUX_SOURCE /* HP/UX */ #define _INCLUDE_XOPEN_SOURCE /* HP/UX */ #define _INCLUDE_AES_SOURCE /* HP/UX */ #include #include #include #include #include #include #include #include #define MF 2000 #define FNLEN 256 #define DISTANT 0x7fffffff char reverse = '\0'; char st_time = 'm'; /* default to modification time */ int uid = -1; /* restrict to this uid */ int gid = -1; /* restrict to this gid */ char nodate = '\0'; /* indicator that no date field should be printed */ char device_mode = '\0'; /* s means will be only one device, S means device set */ dev_t device = 0; /* the device number */ char follow = '\0'; /* follow symbolic link mode */ char do_trace = '\0'; /* debug tracing */ struct context { /* context we need to keep for a bigfile */ long lst_mtime; char name[FNLEN]; }; struct context c[MF]; void big (long lst_mtime, char *fname) { /* see if this is a big file */ int i; for (i = MF-1; i >= 0; i--) { /* starting from smallest we have */ if (((!reverse) && (c[i].lst_mtime >= lst_mtime)) || ( reverse && (c[i].lst_mtime <= lst_mtime))) /* see if bigger */ break; else { if ( i != (MF-1)) { /* if it is, shuffle into place */ c[i+1].lst_mtime = c[i].lst_mtime; memcpy(c[i+1].name, c[i].name, sizeof(c[i].name)); } } } if ( i != (MF-1)) { /* final test for top of tree */ c[i+1].lst_mtime = lst_mtime; memcpy(c[i+1].name, fname, sizeof(c[i].name)); } } void tree(char *root) { /* Process a unix directory */ DIR *dirp; struct dirent *dp; struct stat s; char buf[FNLEN]; int rlen; dirp = opendir(root); /* Open top of the directory tree */ rlen = strlen(root); if (dirp == NULL) return; /* cannot open */ while ((dp = readdir(dirp)) != NULL) { /* process entries in directory */ if (strcmp(dp->d_name, ".") == 0) continue; /* don't go infinite */ if (strcmp(dp->d_name, "..") == 0) continue; /* don't go infinite */ if ((rlen + strlen(dp->d_name)) >= sizeof(buf)) { fprintf(stderr,"%s:%d: buffer length exceeded\n%s/%s\n", __FILE__, __LINE__, root, dp->d_name); continue; } sprintf(buf,"%s/%s", root, dp->d_name); if (do_trace) { printf("[%s]\n", buf); } if (follow) { if (stat(buf, &s)) { continue; /* no data available */ } } else { /* not following the link */ if (lstat(buf, &s)) { continue; /* no data available */ } } switch (device_mode) { case 's': device = s.st_dev; device_mode = 'S'; break; case 'S': if (s.st_dev != device) { continue; } break; default: break; } if ( !follow && S_ISLNK(s.st_mode)) { ; /* don't go down at sym linked directories */ } else { if (S_IFDIR & s.st_mode) { tree(buf); /* go down subdirectory */ } } if ((S_IFREG & s.st_mode) == 0) { continue; /* only look at regular files */ } /* Check for matching against particular UID/GID */ if ((uid >= 0) && (uid != s.st_uid)) continue; if ((gid >= 0) && (gid != s.st_gid)) continue; /* Grap the requested file date, modification/status/access */ switch (st_time) { case 'c': big(s.st_ctime, buf); /* See if big file or not */ break; case 'a': big(s.st_atime, buf); /* See if big file or not */ break; case 'm': default: big(s.st_mtime, buf); /* See if big file or not */ break; } } (void) closedir(dirp); } static char Copyright[] = "@(#) Copyright 1994, David Horton"; static char rcs[] = "@(#)$RCSfile$ $Revision$"; void main(int argc, char *argv[]) { int arg; int i; int many = MF; char when[100]; int dirs = 0; struct passwd *pwent = NULL; struct group *grent = NULL; memset(c, 0, sizeof(c)); for(arg = 1; arg < argc; arg++) { if ((strcmp(argv[arg], "/?") == 0) || (strcmp(argv[arg], "-h") == 0)) { printf("Usage: %s [-r] [-nn] [-{m|a|c}] [-u username] [-g groupname] [-f] [-t] [directory...]\nWhere nn is number of files reported\n", argv[0]); continue; } if (argv[arg][0] == '-') { switch(argv[arg][1]) { case 'r': case 'R': reverse = 'r'; for(i = 0; i < MF; i++) c[i].lst_mtime = DISTANT; continue; case 'm': case 'M': /* last modification time */ st_time = 'm'; continue; case 'a': case 'A': /* last access time */ st_time = 'a'; continue; case 'c': case 'C': /* last status change */ st_time = 'c'; continue; case 'd': case 'D': nodate = 'd'; continue; case 'u': case 'U': if ((pwent = getpwnam(argv[++arg])) != NULL) { uid = pwent->pw_uid; } else { perror(argv[arg]); exit (errno); } break; case 'g': case 'G': if ((grent = getgrnam(argv[++arg])) != NULL) { gid = grent->gr_gid; } else { perror(argv[arg]); exit (errno); } break; case 's': case 'S': device_mode = 's'; break; case 'v': fprintf(stderr, "%s : %s\n",argv[0], Copyright); fprintf(stderr, "%s\n", rcs); exit(0); break; case 'f': case 'F': /* follow sym links */ follow = 'F'; continue; case 't': case 'T': /* debug trace*/ do_trace = 'Y'; setbuf(stdout, NULL); continue; default: many = - atoi(argv[arg]); if ((many == 0) || (many > MF)) many = MF; continue; } } tree(argv[arg]); dirs ++; } if(dirs == 0) tree("."); /* report the findings */ for(i = 0; i < many; i++) { if((c[i].lst_mtime == 0) || (c[i].lst_mtime == DISTANT)) break; if(nodate) { printf("%s\n", c[i].name); } else { (void) strftime(when, sizeof(when), "%d-%b-%y %H:%M:%S", localtime(&c[i].lst_mtime)); printf("%20s %s\n", when, c[i].name); } } exit(0); }