home *** CD-ROM | disk | FTP | other *** search
- From: bogatko@lzga.ATT.COM (George Bogatko)
- Newsgroups: alt.sources
- Subject: tree dumper
- Message-ID: <2018@lzga.ATT.COM>
- Date: 23 Aug 90 01:21:46 GMT
-
-
- HI:
-
- Yeah, I know, another directory tree dumper. But THIS one is
- smaller, *FAR* less complicated then some that I've seen, and
- did precisely what I wanted, namely generate a directory tree
- that I could then comment into a "where everything is" document.
-
- GB
-
- ****** CUT HERE ****** CUT HERE ****** CUT HERE ****** CUT HERE ****** CUT HERE
-
- /******************************************************************************
- * *
- * tree.c *
- * *
- ******************************************************************************/
-
- /*-------------------------- INITIAL CODING DATE -----------------------------
- Wed Aug 22 20:03:03 EDT 1990 by George M. Bogatko
-
- -------------------------------- HEADER FILES -----------------------------*/
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <dirent.h>
- #include <string.h>
- #include <malloc.h>
- #include <errno.h>
-
- /*------------------ TYPEDEF'S, DEFINES, STRUCTURE DEF'S ------------------*/
- #define INCR BUFSIZ
- #define USAGE fprintf(stderr, usage, argv[0])
-
- /*---------------- IMPORTED GLOBAL VARIABLE/FUNCTION DEF'S ----------------*/
- extern char *calloc();
- extern char *optarg;
- extern int getopt();
- extern int optind;
- extern char *sys_errlist[];
-
- /*---------------- EXPORTED GLOBAL VARIABLE/FUNCTION DEF'S ----------------*/
-
- /*---------------- INTERNAL GLOBAL VARIABLE/FUNCTION DEF'S ----------------*/
- #ident "@(#)tree.c 1.1 8/22/90 - George M. Bogatko -"
- char *arg1;
- char *seperator="\t";
- char *usage = "usage: %s [-t(abstr)] directory\n";
- char dirname[BUFSIZ];
- char tbuf[BUFSIZ];
- extern char **grabmem();
- extern int compar();
- extern void addmore();
- extern void addname();
- extern void delname();
- extern void tab();
- int tlevel = -1;
-
- /*-----------------------------------------------------------------------------
-
- SYNOPSIS:
- tree [-t(abstr)] directory
-
- DESCRIPTION:
- TREE prints a directory tree similar to the one that MS-DOS
- supplies, with the following additions for UNIX.
-
- When the file name is printed, it is appended with:
-
- ALL SYSTEMS:
- / - if the file is a directory
- * - if the file is a regular file, and is executable
- # - if the file is a FIFO
- BSD SYSTEMS:
- @ - if the file is a symbolic link
- = - if the file is a socket.
-
- If a subdirectory cannot be entered, the directory name will
- be followed with "(cannot open)". If the directory can
- be entered, but cannot be read, the name will be followed with
- a "(cannot read)". Following that is the UNIX error.
-
- OPTIONS:
- The one option, '-t' allows you to supply a different indent
- string. The default is a TAB character ("\t").
-
- One suggestion is "| ", which will show a visual link with
- the parent directory
-
- CAVEATS:
- Compile with -DBSD for BSD systems to get the defines for
- symbolic links and sockets. Otherwise just compile straight.
-
- COMMENTS:
- Suggestions for improvements are welcome as long as they are not
- of the 'kitchen sink' or 'second system' variety.
-
-
- =============================================================================*/
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int c;
-
- while( (c = getopt(argc, argv, "t:")) != EOF )
- {
- switch(c)
- {
- case 't':
- seperator = strdup(optarg);
- break;
- case '?':
- USAGE;
- exit(-1);
- }
- }
-
- if(optind == argc)
- {
- USAGE;
- exit(-1);
- }
-
- arg1=argv[optind];
- if( access(arg1,05) == -1 )
- {
- fprintf(stderr, "%s: %s\n", arg1, sys_errlist[errno]);
- exit(-1);
- }
- chdir(arg1);
- dumpdir();
- return 0;
- }
-
- int dumpdir()
- {
- DIR *dirp;
- char **dnames;
- char **fnames;
- char *str;
- int dnameoff=0;
- int dnamesz=INCR;
- int fnameoff=0;
- int fnamesz=INCR;
- int i;
- int tl;
- int x = 0;
- struct dirent *dp;
- struct stat sbuf;
-
- dnames = grabmem(dnamesz);
- fnames = grabmem(fnamesz);
- /*
- * increment the tab level (see tab() )
- */
- tlevel++;
- /*
- * try to open the directory
- */
- if( (dirp = opendir(".")) == (DIR *)NULL )
- return -1;
- /*
- * KLUDGE number 1. See the line with the printf statement
- * "printf("%s%s/",arg1,dirname);". This is how we print
- * the (cannot open) statements, and then get a carrage return
- */
- putchar('\n');
- /*
- * read the directory to the end
- */
- while( (dp = readdir (dirp)) != NULL )
- {
- /*
- * gather some file statistics
- */
- if( stat(dp->d_name, &sbuf) == -1 )
- {
- perror("stat");
- return -1;
- }
- /*
- * If the file is a directory, remember the name, in the directory
- * names bucket.
- */
- if((sbuf.st_mode & S_IFMT) == S_IFDIR)
- {
- dnames[dnameoff++] = strdup(dp->d_name);
- if( dnameoff > dnamesz )
- addmore(&dnames, &dnamesz);
- dnames[dnameoff+1] = (char *)NULL;
- }
- else
- {
- /*
- * else it is some other file. Put the name in another bucket. Add
- * the mneumonic character (#=@*).
- */
- str = "";
- if((sbuf.st_mode & S_IFMT) == S_IFIFO)
- str = "#";
- else if((sbuf.st_mode & S_IFMT) == S_IFREG)
- {
- if(sbuf.st_mode & S_IXUSR)
- str="*";
- }
- #if pyr || BSD
- else if((sbuf.st_mode & S_IFMT) == S_IFLNK)
- str = "@";
- else if((sbuf.st_mode & S_IFMT) == S_IFSOCK)
- str = "=";
- #endif
- sprintf(tbuf, "%s%s",dp->d_name,str);
- fnames[fnameoff++]=strdup(tbuf);
- if( fnameoff >= fnamesz )
- addmore(&fnames, &fnamesz);
- fnames[fnameoff+1] = (char *)NULL;
- }
- }
- /*
- * sort the buckets
- */
- qsort(fnames, fnameoff, sizeof(char *), compar);
- qsort(dnames, dnameoff, sizeof(char *), compar);
- /*
- * dump the sorted list of non directory files
- */
- for(i=0; fnames[i] != (char *)NULL; i++)
- {
- tab();
- printf("%s\n",fnames[i]);
-
- }
- /*
- * go through the sorted list of directory files.
- */
- for(i=0; dnames[i] != (char *)NULL; i++)
- {
- if( strcmp(dnames[i], ".") &&
- strcmp(dnames[i], "..") )
- {
- /*
- * build up the pathname
- */
- addname(dnames[i]);
- tab();
- /*
- * print it out
- */
- printf("%s%s/",arg1,dirname);
- /*
- * chdir to the directory, and recurse.
- */
- if( chdir(dnames[i]) == -1 )
- {
- printf(" (cannot open: %s)\n", sys_errlist[errno]);
- delname();
- }
- else if( dumpdir() == -1 )
- {
- printf(" (cannot read: %s)\n", sys_errlist[errno]);
- tlevel--;
- chdir("..");
- delname();
- }
- }
- }
- /*
- * cleanup the mallocs, close the files, decrement the tab level,
- * and go back up a level
- */
- for(i=0; dnames[i] != (char *)NULL; i++)
- {
- free(dnames[i]);
- }
- free(dnames);
-
- for(i=0; fnames[i] != (char *)NULL; i++)
- {
- free(fnames[i]);
- }
- free(fnames);
- tlevel--;
- closedir(dirp);
- delname();
- chdir("..");
- return 0;
- }
-
- /*
- * indent according to current tab level
- */
- void tab()
- {
- int tl = tlevel;
-
- while(tl--)
- printf("%s",seperator);
- return;
- }
-
- /*
- * add a name to the current path name
- */
- void addname(s)
- char *s;
- {
- strcat(dirname,"/");
- strcat(dirname,s);
- return;
- }
-
- /*
- * delete a name from the current path name
- */
- void delname()
- {
- char *ps;
-
- if( ps = strrchr(dirname, '/') )
- *ps = '\0';
- return;
- }
-
- /*
- * allocate memory
- */
- char **grabmem(size)
- unsigned size;
- {
- char **s;
-
- if( (s = (char **)calloc((size+2), sizeof(char **))) == (char **)NULL )
- {
- perror("calloc");
- exit(-1);
- }
- return s;
- }
-
- /*
- * grow memory
- */
- void addmore(s, size)
- char ***s;
- unsigned *size;
- {
- *size += INCR;
- if( (*s = (char **)realloc(*s, ((*size+2) * sizeof(char **)) )) == (char **)NULL )
- {
- perror("realloc");
- exit(-1);
- }
- return;
- }
-
- /*
- * function for qsort
- */
- int compar(s1,s2)
- char **s1, **s2;
- {
- return( strcmp(*s1, *s2) );
- }
-