static void recursedir(const char *path) { int fd; char buf[1024]; char newpath[1024]; int len; /* * Open it. */ fd = open(path, O_RDONLY); if (fd<0) { err(1, "%s", path); } /* * List the directory. */ while ((len = getdirentry(fd, buf, sizeof(buf)-1)) > 0) { buf[len] = 0; /* Assemble the full name of the new item */ snprintf(newpath, sizeof(newpath), "%s/%s", path, buf); if (!aopt && buf[0]=='.') { /* skip this one */ continue; } if (!strcmp(buf, ".") || !strcmp(buf, "..")) { /* always skip these */ continue; } if (!isdir(newpath)) { continue; } listdir(newpath, 1 /*showheader*/); if (Ropt) { recursedir(newpath); } } if (len<0) { err(1, "%s", path); } close(fd); }
static void listitem(const char *path, int showheader) { if (!dopt && isdir(path)) { listdir(path, showheader || Ropt); if (Ropt) { recursedir(path); } } else { print(path); } }
int main(int argc, char **argv) { int opt, age, quiet; char topdir[PATH_MAX]; char aunit = 'Y'; struct stat sb; char *datestr; char command[PATH_MAX]; char **workfile; // set up defaults quiet = 0; age = 3; strcpy(topdir, getenv("HOME")); head = newlistitem(); opfn = (char *)NULL; oldcount = 0; workfile = workfiles("/tmp/", argv[0], 4); fpo=dofopen(workfile[0], "w"); while((opt = getopt(argc, argv, ":ha:o:q")) != -1) { switch(opt){ /* I have no idea what the value of topdir will be during * options processing so all I can do is set a task variable * to select action after topdir is known or whether it's * actually needed. */ case 'h': dohelp(0); break; case 'a': // change default age age = strtol(optarg, NULL, 10); if (strchr(optarg, 'M')) aunit = 'M'; if (strchr(optarg, 'm')) aunit = 'M'; if (strchr(optarg, 'D')) aunit = 'D'; if (strchr(optarg, 'd')) aunit = 'D'; break; case 'q': quiet = 1; break; case 'o': // list files older than input file time datestr = strdup(optarg); fileage = parsetimestring(datestr); break; case ':': fprintf(stderr, "Option %c requires an argument\n",optopt); dohelp(1); break; case '?': fprintf(stderr, "Illegal option: %c\n",optopt); dohelp(1); break; } //switch() }//while() // now process the non-option arguments // 1.See if argv[1] exists. if ((argv[optind])) { strcpy(topdir, argv[optind]); // default is /home/$USER } // Check that the top dir is legitimate. if (stat(topdir, &sb) == -1) { perror(topdir); exit(EXIT_FAILURE); } // It exists then, but is it a dir? if (!(S_ISDIR(sb.st_mode))) { fprintf(stderr, "%s is not a directory!\n", topdir); exit(EXIT_FAILURE); } // Convert relative path to absolute if needed. if (topdir[0] != '/') dorealpath(argv[optind], topdir); fileage = cutofftimebyage(age, aunit); recursedir(topdir); fclose(fpo); if (oldcount > 0) { sprintf(command, "sort -u %s > %s", workfile[0], workfile[1]); dosystem(command); } else { if (!quiet) { fprintf(stderr, "No old files found\n"); } unlink(workfile[0]); exit(EXIT_SUCCESS); } // get rid of the leading inode and sort on pathname stripinode(workfile[1], workfile[2]); sprintf(command, "sort %s > %s", workfile[2], workfile[3]); dosystem(command); dumpfile(workfile[3], stdout); return 0; }//main()
void recursedir(char *path) { /* * Output a list of old files if such exist */ struct dirent *de; DIR *dp; dp = opendir(path); if (!(dp)) { perror(path); exit(EXIT_FAILURE); } while ((de = readdir(dp))) { time_t thisfiletime; struct stat sb; char newpath[PATH_MAX]; if (strcmp(de->d_name, ".") == 0) continue; if (strcmp(de->d_name, "..") == 0) continue; strcpy(newpath, path); if (newpath[strlen(newpath)-1] != '/') strcat(newpath, "/"); switch (de->d_type) { case DT_DIR: // process this dir strcat(newpath, de->d_name); recursedir(newpath); break; case DT_REG: strcat(newpath, de->d_name); if (stat(newpath, &sb) == -1) { perror(newpath); // just note the error, don't abort. break; } // do the file m time check thisfiletime = sb.st_mtime; if (thisfiletime < fileage) { // report the thing fprintf(fpo, "%.16lx %s%s %s" ,sb.st_ino, newpath, pathend, asctime(localtime(&thisfiletime))); oldcount++; } break; case DT_LNK: /* symlink processing. I once did have separate processing for errors ELOOP and ENOENT but circular links are simply reported as ENOENT along with missing links. So I'll just let perror take care of it all. */ /* stat() gives me times applicable to the target not the link, but unlink() will remove the link, not the target. That much is fine because, if old, I want to remove the link as well as the target. */ if (stat(newpath, &sb) == -1) { perror(newpath); // just note the error, don't abort. break; } // do the file m time check thisfiletime = sb.st_mtime; if (thisfiletime < fileage) { /* NB if link or links are within the given search dir, * the target will be reported more than once. Sort -u * will take care of such happenings.*/ char target[PATH_MAX]; // report the symlink fprintf(fpo, "%.16lx %s%s %s" ,sb.st_ino, newpath, pathend, asctime(localtime(&thisfiletime)) ); oldcount++; // Dealt with the link, now report the target of the link dorealpath(newpath, target); fprintf(fpo, "%.16lx %s%s %s" ,sb.st_ino, target, pathend, asctime(localtime(&thisfiletime)) ); oldcount++; } break; default: continue; // ignore all other d_types break; } } closedir(dp); } // recursedir()