[net.sources] scandir

root@transys.UUCP (05/10/86)

[ eat this, line eater ]

A few weeks ago I posted a request to the net for a public domain version
of scandir().

Well....., I got no takers so I hacked my own. Since it is used in the pathalias
software I have decided to release it to the net.

Also included is a small test program which will demonstrate the routine.


Have fun and enjoy, all flames to /dev/null, all praise to me at
root@transys.UUCP.


#!/bin/sh
#
# ####################################################################
# --------CUT---------CUT---------CUT---------CUT--------CUT---------#
#                                                                    #
#  This is a shell archive. These archives are packed by the program #
#  packmail(1). If you have the program unshar(1), I suggest you use #
#  it.  If you don't, remove  anything  before the cut line and then #
#  feed to sh(1).  To extract files using the second method:         #
#                                                                    #
#             1) Make a directory for the files.                     #
#             2) Write a file, such as "file.shar", containing       #
#                this archive file into the directory.               #
#             3) Type "sh file.shar".  Do not use csh.               #
#                                                                    #
# ####################################################################
#
echo 'Start of Scandir routines, part 01 of 01:'
echo 'x - makefile'
sed 's/^X//' > makefile << '/'
X#	Author J.L. Portman (root@transys.UUCP)
X#
X#
XSRCS= test.c scandir.c
X
X
Xscandir: test.c scandir.c
X	$(CC) $(CFLAGS) test.c scandir.c -o scandir
X	rm -f test.o scandir.o
/
echo 'x - test.c'
sed 's/^X//' > test.c << '/'
X/*
X**	Author J.L Portman III (root@transys.UUCP)
X**	This is just included as a test driver for the scandir()
X**	Function. Kind of a crude ls
X**	Pretty brain damaged, in that it does not free() any of the
X**	allocated structures.
X*/
X
X#include <stdio.h>
X#include <ctype.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/ndir.h>
X
Xmain(argc,argv,envp)
Xint argc;
Xchar **argv;
Xchar **envp;
X{
X	struct direct **filst;
X	int	nfils, x, y;
X	extern int scandir();
X	int	compare(), select();
X	char *strcpy(), *strncat();
X
X	if (argc<2) {
X		printf("Usage: scandir 'dirname'\n");
X		exit(1);
X	}
X
X	for(x=1;x<argc;x++) {
X	     if ((nfils = scandir(argv[x], &filst, select, compare)) == -1) {
X		     printf("scandir: scandir() failed on directory %s\n", 
X			  argv[x]);
X		     exit(1);
X	     }
X		for (y = 0; y < nfils; y++) 
X			printf("nfile[%d] = %s\n",y, filst[y]->d_name);
X	}
X
X	exit(0);
X
X}
X
X
X/*
X**	Dummy selection routine, always returns true
X*/
X
Xselect(d)
X	struct direct *d;
X{
X	return(1);
X
X}
X
X/*
X**	For the qsort() in scandir. 
X*/
X
Xcompare(a, b)
X	struct direct **a, **b;
X{
X	return(strcmp((*a)->d_name,(*b)->d_name)); 
X}
/
echo 'x - scandir.c'
sed 's/^X//' > scandir.c << '/'
X/*----------------------------------------------------------------------*/
X/*                           scandir()					*/
X/*    returns a pointer to an array of pointers to structures of type   */
X/*    "direct", based on a user supplied selection routine.		*/
X/*    The structures are sorted according to the user supplied compare()*/
X/*    routine.								*/
X/*----------------------------------------------------------------------*/
X/*  	uses calls to malloc() to allocate space for the structures     */
X/*	History:							*/
X/*	March 25, 1985	- written and tested ( out of desperation )     */
X/*	Author:	J.L. Portman III 					*/
X/*              of ... ihnp4!uw-beaver!tikal!teldata!transys!root	*/
X/*	Environment: IBM-AT(tm) under XENIX(tm) system V from SCO	*/
X/*									*/
X/*		Copyright: Author claims exclusive ownership of the	*/
X/* 		following. You are free to use the material in any 	*/
X/*		form as long as this notice remains in place.		*/
X/*		Hint: It may or may not have bugs!!			*/
X/*----------------------------------------------------------------------*/
X/* usage:								*/
X/* scandir(dir,area,select,compare) where				*/
X/* char *dir;		  directory to scan				*/
X/* struct direct ***area; ptr to ptr to array of ptr's to struct direct */
X/* int (select*)();	  ptr to function returning an int		*/
X/* int (compare*)();	  ptr to function returning an int		*/
X/*----------------------------------------------------------------------*/
X
X#include <stdio.h>
X#include <ctype.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/ndir.h>			/* might be dir.h on Usg	  */
X#include <malloc.h>
X#ifndef FAIL
X#define FAIL (-1)
X#endif
X#define DNULL ((DIR *)(0))
X#define DPNULL ((struct direct *)(0))
X#define DPPNULL ((struct direct **)(0))
X
Xint scandir(dir,filst,select,compare)
Xchar *dir;				/* directory to scan 		   */
Xstruct direct **filst[];  		/* where to put the sorted answers */
Xint (*select)();			/* pointer to selection routine    */
Xint (*compare)();			/* pointer to comparison for sort  */
X{
X	register DIR  *fp;
X	register struct direct *dirp;
X	register struct direct  **temp;		/* temporary storage ptr   */
X	register unsigned int count = 0;	/* uunsigned math is faster*/
X	void qsort();			/* sorts the directories pointers  */
X	char *calloc(),*malloc();	/* works just fine here		   */
X	char *strcpy();
X
X	if (((fp = opendir(dir))==DNULL))
X		return(FAIL);		/* could not open the dir	   */
X
X	/* count the number of entries in the directory */
X	
X	for(count=0,dirp=readdir(fp);dirp != DPNULL;dirp=readdir(fp)) {
X		if ((*select)(dirp))
X			count++;
X	}
X	if (count==0)			/* skip this if no match */
X		return(0);
X
X	/* allocate a contiguous space of memory for pointers to the   */
X	/* entries , allow for new files that might be created         */
X
X        temp=((struct direct**) malloc((count+10) * sizeof(struct direct *))); 
X	if (temp==DPPNULL)
X		return(FAIL);
X	
X	/* rewind the directory */
X	rewinddir(fp);
X
X	/* put the pointers to all active elements in the newly allocated */
X 	/* array */
X
X	for(count=0,dirp=readdir(fp);dirp != DPNULL;dirp=readdir(fp))
X		if ((*select)(dirp)){
X		temp[count]=((struct direct *)malloc(sizeof(struct direct)));
X			if (temp[count] == DPNULL) {
X				return(FAIL);
X  			}
X		 temp[count]->d_ino=dirp->d_ino;		/* put it in */
X		 temp[count]->d_reclen=dirp->d_reclen;	        /* put it in */
X		 temp[count]->d_namlen=dirp->d_namlen;	        /* put it in */
X	   (void)strcpy(temp[count]->d_name,dirp->d_name);      /* put it in */
X		 count++;				        /* tell me   */
X		}
X
X	/* now sort the entries */
X
X  	(void)qsort((char*)temp,count,sizeof(struct direct*),compare);
X
X	*filst=temp;		/* don't ask me, it works!! */
X	return((int)count);
X}
/
echo 'Part 01 of Scandir routines complete.'
exit
-- 
          ****************************************************
          *        These are my own opinions, not those of   *
          *            my employer (self), or any one        *
          *           connected with the company (mine)      *
          ****************************************************

Joe Portman (SA)                                USPS: TransSystems Incorporated
AT&T: 1-206-453-5560                                  1280 116th Avenue NE
                                                      Bellevue WA 98009
              /-- uw-beaver!\         /-- camco!  \
... ihnp4! --<               >-tikal!<             >-- transys!root
              \-- microsoft!/         \-- teldata!/