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!/