scandir() function
Chris Torek
chris at umcp-cs.UUCP
Wed May 14 04:57:09 AEST 1986
In article <218 at transys.UUCP>, root at transys.UUCP (The Super User)
supplies a public-domain scandir(). The routine looks workable,
but is sensitive to `active' directories: if the number of directory
entries increases between the two scans, it will probably crash.
The following routines are *not* equivalent, but (assuming readdir()
is properly written) do not suffer from this problem. In addition,
I think this version is generally more convenient. It drops the
inode number and the other redundant information in a 4.2 style
directory, and it generates various error messages (both fatal and
non-fatal), but it does what I wanted at the time....
/*
* Save a string in managed memory.
*/
char *
savestr(s)
char *s;
{
char *t, *malloc(), *strcpy();
if ((t = malloc((unsigned) (strlen(s) + 1))) == 0)
error(1, errno, "out of memory");
return (strcpy(t, s));
}
/*
* For qsort: perform a machine-collating-sequence sort.
*/
machinesort(s1, s2)
char **s1, **s2;
{
int i;
return ((i = **s1 - **s2) ? i : strcmp(*s1, *s2));
}
/*
* Scan a directory. Return a sorted list of the names contained therein.
* The list is dynamically allocated, and can be freed with freeit().
*/
char **
scanit(dname)
char *dname;
{
register DIR *d;
register struct direct *dp;
register char **names, **np;
register int nleft;
int nnames;
char *malloc(), *realloc();
if ((d = opendir(dname)) == 0) {
error(0, errno, "can't read %s", dname);
return (0);
}
nnames = 10;
names = (char **) malloc((unsigned) (10 * sizeof *names));
if (names == 0)
error(1, errno, "out of memory");
nleft = nnames - 1; /* start off-by-one for terminator */
np = names;
while ((dp = readdir(d)) != 0) {
if (dp->d_namlen == 1 && dp->d_name[0] == '.')
continue;
if (dp->d_namlen == 2 && dp->d_name[0] == '.' &&
dp->d_name[1] == '.')
continue;
if (--nleft < 0) {
nleft = nnames - 1; /* we're about to use one */
nnames <<= 1;
names = (char **) realloc((char *) names,
(unsigned) (nnames * sizeof *names));
if (names == 0)
error(1, errno, "out of memory");
np = names + nleft;
}
*np++ = savestr(dp->d_name);
}
qsort((char *) names, np - names, sizeof *names, machinesort);
*np = 0;
closedir(d);
return (names);
}
/*
* Free a directory as returned by scanit().
*/
freeit(p)
char **p;
{
register char **q = p;
while (*q)
free(*q++);
free((char *) p);
}
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1415)
UUCP: seismo!umcp-cs!chris
CSNet: chris at umcp-cs ARPA: chris at mimsy.umd.edu
More information about the Comp.sources.bugs
mailing list