123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257 |
- /*
- * find.c - locate and optionally perform operations on files.
- * The author says this is only partly done, but I don't know what is missing.
- * But one thing that is certainly a bug is the existence of
- * MAXNAMELEN and MAXPATHLEN.
- */
- #include <stdio.h>
- #include <sys/types.h> /* typedefs */
- #include <sys/stat.h> /* structure returned by stat */
- #ifdef HP-UX
- #include <ndir.h> /* BSD directory entry structure */
- #else
- #include <dir.h> /* directory entry structure */
- #endif
- #define MAXPATHLEN 256
- #define MAXNAMELEN 256
- #define TRUE 1
- #define FALSE 0
- #define VALID 1
- #define INVALID 0
- #define MIN_NODES 20
- extern DIR *opendir();
- extern struct direct *readdir();
- extern long telldir();
- extern void seekdir();
- extern void closedir();
- extern char *malloc();
- void ScanDir();
- struct fnode *GetNode();
- typedef unsigned char bool;
- struct fnode {
- struct fnode *next;
- char name[MAXNAMELEN];
- };
- struct fnode *avail_head = NULL;
- int numpaths; /* Number of paths to search */
- int Argc; /* Global argc for functions */
- char **Argv; /* Global argv for functions */
- int max_nodes_avail = 0;
- int nodes_used = 0;
- int nodes_freed = 0;
- main (argc, argv)
- int argc;
- char *argv[];
- {
- int i; /* general purpose index */
- int pathindex; /* argv[pathindex] = current path */
- char buf[MAXPATHLEN]; /* buffer to contain current path */
- /* Validate Usage */
- if (argc < 2) {
- fprintf(stderr,"Usage: find path-list predicate-list\n");
- exit(1);
- }
- /* Make argv and argc global for other functions */
- Argc = argc;
- Argv = argv;
- /* Parse Arguments and Validate */
- if (! ParseArguments()) {
- fprintf(stderr,"find: parsing error\n");
- exit(1);
- }
- /* Refresh the pool used to contain unevaluated directory entrys */
- RefreshPool();
- /* Descend argv[1] through argv[numpaths] */
- for (pathindex = 1; pathindex <= numpaths; pathindex++) {
- for (i = 0; i < sizeof (buf); i++)
- buf[i] = '\0';
- strcpy(buf,argv[pathindex]);
- ScanDir(buf);
- }
-
- /* Print statistics */
- printf("\n\n\n");
- printf("Max nodes avail: %d\n",max_nodes_avail);
- printf("Nodes used: %d\n",nodes_used);
- printf("Nodes freed: %d\n",nodes_freed);
- }
- /*
- * Parse Arguments - calculate number of paths in path-list and compile
- * arguments into a linked list of functions to be
- * applied to each visited node.
- *
- * side effects: global variable "numpaths" = numpaths to search.
- *
- * returns: VALID = argument list is valid
- * INVALID = invalid argument list
- */
- int
- ParseArguments()
- {
- /* Calculate the number of paths in the path list */
- numpaths = Argc - 1;
- return VALID;
- }
- /*
- * RefreshPool - keep a minimum number of nodes to remember directory in.
- */
- int
- RefreshPool()
- {
- struct fnode *anode;
- int i;
- for (i = 0; i < MIN_NODES; i++) {
- anode = (struct fnode *) malloc(sizeof(struct fnode));
- anode->next = avail_head;
- avail_head = anode;
- }
- max_nodes_avail += MIN_NODES;
- }
- /*
- * GetNode - acquire a node to save directory's file names in during descent.
- */
- struct fnode
- *GetNode()
- {
- struct fnode *ap;
- if (avail_head == NULL)
- RefreshPool();
- ap = avail_head;
- avail_head = avail_head->next;
- ap->next = NULL;
- nodes_used++;
- return ap;
- }
- /*
- * FreeNode - return file node to pool.
- */
- void
- FreeNode(nodeptr)
- struct fnode *nodeptr;
- {
- nodeptr->next = avail_head;
- avail_head = nodeptr;
- nodes_freed++;
- }
- /*
- * ScanDir - scan the named directory and if file matches search criteria
- * apply any specified operations to it.
- */
- void
- ScanDir(name)
- char *name;
- {
- struct direct dirbuf, *dp = &dirbuf;
- DIR *d;
- struct fnode anode, *ap, *list_head, *trailp;
- struct stat filestat;
- /* If we cannot open this directory, ignore it */
- if ((d = opendir(name)) == NULL) {
- printf("Cannot open directory: %s\n",name);
- return;
- }
- /* Change directories to requested directory */
- chdir(name);
- /* Obtain the head of the linked list of directory entries */
- list_head = GetNode();
- ap = list_head;
- /* Build a list of all of the relevant entries within this directory */
- for (dp = readdir(d); dp != NULL; dp = readdir(d)) {
- /* skip the current directory and its parent */
- if ( (strcmp(dp->d_name,".") == 0) || (strcmp(dp->d_name,"..") == 0) )
- continue;
- strcpy(ap->name,dp->d_name);
- trailp = ap;
- ap = GetNode();
- trailp->next = ap;
- }
- /* We've saved a copy of all the entries in this directory */
- closedir(d);
- /* Perform processing for all files within this directory */
- for (ap=list_head;ap->next!=NULL;trailp=ap->next,FreeNode(ap),ap=trailp) {
- /* Get file status */
- if (stat(ap->name, &filestat) == -1) {
- fprintf(stderr, "newfind: can't find %s\n", ap->name);
- return;
- }
- /* Print the size of this file */
- printf("Visiting: %8ld %s/%s\n", filestat.st_size, name,ap->name);
- /* If file is a directory, descend */
- if (filestat.st_mode & S_IFDIR) {
- DIR *subd; /* sub-directory */
- char cwd[MAXPATHLEN+1]; /* current working directory */
- chdir(ap->name);
- if ((subd = opendir(".")) == NULL) {
- printf("cannot open directory: %s\n",ap->name);
- exit(-1);
- }
- getwd(cwd);
- closedir(subd);
- ScanDir(cwd);
- chdir("..");
- }
- }
- /* Free the unused trailing node on the list */
- FreeNode(ap);
- }
|