/* * DIR by Richard Conn * * Revision History -- * DIR Version 1.1 -- Modified by Frank Wancho * Several changes made to provide operation with MORE * DIR Version 1.0 by Richard Conn * * DIR is an enhanced directory display utility for UNIX. * It produces a sorted listing of file names and sizes in two columns, * and the files are sorted down the columns. If a file is a directory, * its name is prefixed with a "D". File count and size totals are displayed * at the bottom of the listing. * */ /* C Libraries */ #include #include #include #include #define BUFSIZE 256 /* Structure of a Directory Element as Stored for DIR */ struct dirnode { char name[DIRSIZ]; /* Name of File */ int dir; /* Dir or Not? */ off_t size; /* Size in Bytes */ short mode; /* R/W/X */ struct dirnode *next; /* Ptr to Next File */ }; /* Global Environment */ struct environ { int showhid; /* Show Hidden Files? */ int showrwx; /* Show Attributes? */ int filecnt; /* Number of Files in List */ off_t totsize; /* Sum of All File Sizes */ struct dirnode *first; /* Ptr to First Elt in List */ struct dirnode *last; /* Ptr to Last Elt in List */ }; FILE *out; main(argc,argv) char *argv[]; { char buf[BUFSIZE]; struct environ env; int i, first; /* Init Environment */ env.first = NULL; /* No First Entry */ env.showhid = 0; /* No Hidden Files */ env.showrwx = 0; /* No R/W/X */ env.filecnt = 0; /* No Files */ env.totsize = 0; /* Accumulated File Size */ /* Build Linked List of DIR Elements */ if (argc == 1) build(".",&env,0); /* current dir */ else { first = 1; /* first file is 1 */ if (*argv[1] == '-') { first = 2; /* first file is 2 */ opts(argv[1],&env); if (argc == 2) build(".",&env,0); /* curr dir */ } for (i=first; ishowrwx = 1; /* show file attributes */ break; case 'H' : case 'h' : env->showhid = 1; /* show hidden files */ default : break; } } /* Display Entries in Linked List */ display(env) struct environ *env; { struct dirnode *lptr, *rptr, *elt(); char *fname; int i; if (env->filecnt > 0) { fprintf(out," -- Filename -- - Size -"); if (env->showrwx) fprintf(out," Atr"); } if (env->filecnt > 1) { fprintf(out," -- Filename -- - Size -"); if (env->showrwx) fprintf(out," Atr"); } fprintf(out,"\n"); lptr = elt(0,env); /* Pt to first element in left col */ rptr = elt(env->filecnt%2 ? env->filecnt/2+1 : env->filecnt/2, env); for (i=0; i < env->filecnt/2; i++) { prelt(lptr,env); /* Print Left Element */ prelt(rptr,env); /* Print Right Element */ fprintf(out,"\n"); /* New Line */ lptr = lptr->next; /* Pt to next */ rptr = rptr->next; } if (env->filecnt%2) { prelt(lptr,env); /* Print Odd Element */ fprintf(out,"\n"); } fprintf(out," -- %d Entries Displayed, %ld Bytes --\n", env->filecnt, env->totsize); } /* Print Element Pointed To */ prelt(ptr,env) struct dirnode *ptr; struct environ *env; { char *fname; int j; if (ptr->dir) fprintf(out,"D "); /* Print Dir Flag */ else fprintf(out," "); fname = ptr->name; for (j=0; j < DIRSIZ; j++) /* Print File Name */ if (*fname == '\0') fputc(' ',out); else fputc(*fname++,out); fprintf(out," %8ld", ptr->size); /* Print File Size */ if (env->showrwx) fprintf(out," %c%c%c", /* Print RWX Flags */ (ptr->mode & S_IREAD) ? 'r' : '-', (ptr->mode & S_IWRITE) ? 'w' : '-', (ptr->mode & S_IEXEC) ? 'x' : '-'); fprintf(out," "); } /* Shell Sort Directory Entries (See Pg 108 of K&R for Algorithm) */ sort(env) struct environ *env; { int gap, i, j; struct dirnode dir, *eltj, *eltjg, *elt(); for (gap = env->filecnt/2; gap > 0; gap /= 2) for (i = gap; i < env->filecnt; i++) for (j = i-gap; j >= 0; j -= gap) { eltj = elt(j,env); /* pt to elt j */ eltjg = elt(j+gap,env); /* pt to elt j+gap */ if (strcmp(eltj->name,eltjg->name) <= 0) break; /* temp = v[j] */ *dir.name = '\0'; /* clear str */ strcat(dir.name,eltj->name); dir.dir = eltj->dir; dir.size = eltj->size; dir.mode = eltj->mode; /* v[j] = v[j+gap] */ *eltj->name = '\0'; /* clear str */ strcat(eltj->name,eltjg->name); eltj->dir = eltjg->dir; eltj->size = eltjg->size; eltj->mode = eltjg->mode; /* v[j+gap] = temp */ *eltjg->name = '\0'; /* clear str */ strcat(eltjg->name,dir.name); eltjg->dir = dir.dir; eltjg->size = dir.size; eltjg->mode = dir.mode; } } /* Point to Nth (Starting at 0) Element in Linked List */ struct dirnode *elt(n,env) int n; struct environ *env; { struct dirnode *rover; int i; rover = env->first; /* pt to first element */ for (i=0; inext; /* adv thru list */ return (rover); } /* Build Linked List Structure Containing Directory Entries */ build(name,env,level) char *name; struct environ *env; int level; { struct stat stbuf; struct dirnode dir; struct dirnode *calloc(); char *nameptr; int i, ccnt; /* Check for File Existence */ if (stat(name,&stbuf) == -1) { fprintf(stderr,"Can't find %s\n", name); return; } /* Check to See if File is a Directory */ if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { /* we have a dir */ directory(name,env,level); if (!level) return; } /* Check Hidden Entries */ if (*name == '.' && !(env->showhid)) return; /* Store Entry in Memory */ if (env->first == NULL) { /* First Entry Processing */ env->first = calloc(1, sizeof(dir)); env->last = env->first; } else { /* Nth Entry Processing */ (*env->last).next = calloc(1, sizeof(dir)); env->last = (*env->last).next; } if (env->last == NULL) { fprintf(stderr, "Dynamic Memory Overflow\n"); exit(0); } /* Store Entry Values */ env->filecnt++; /* Increment File Count */ (*env->last).next = NULL; nameptr = name; /* Pt to first char of file name */ ccnt = strlen(name); /* Number of chars in file name */ for (i=0; i < ccnt; i++) /* Find Last Part of Name */ if (*name++ == '/') nameptr = name; strcat((*env->last).name,nameptr); /* Save File Name */ (*env->last).size = stbuf.st_size; /* Save File Size */ (*env->last).mode = stbuf.st_mode; /* Save Mode Bits */ env->totsize += stbuf.st_size; /* Increment Total Sizes */ if ((stbuf.st_mode & S_IFMT) == S_IFDIR) /* Set Dir Flag */ (*env->last).dir = 1; else (*env->last).dir = 0; } /* Process All Entries in a Directory */ directory(name,env,level) char *name; struct environ *env; int level; { struct direct dirbuf; char *nbp, *nep; char dirname[BUFSIZE]; char filename[DIRSIZ]; int i,fd; if (level) return; /* don't recurse */ /* Build Name of Directory into DIRNAME */ nep = dirname; nbp = name; while (*nbp != '\0') *nep++ = *nbp++; *nep = '\0'; /* terminate string */ if (nep+DIRSIZ+2 >= dirname+BUFSIZE) /* name too long */ return; /* Log Into Directory */ if (chdir(dirname)) { fprintf(stderr, "Directory %s Not Found\n", dirname); return; } /* Open Directory File */ if ((fd = open(".",0)) == -1) return; /* Read Through the Elements in the Directory */ while (read(fd, (char *)&dirbuf, sizeof(dirbuf)) > 0) { if (dirbuf.d_ino == 0) /* slot not in use */ continue; for (i=0, nep=filename; i