ftp.nice.ch/pub/next/connectivity/infosystems/WAIStation.1.9.6.N.b.tar.gz#/WAIS/lib/ftw.c

This is ftw.c in view mode; [Download] [Up]

/*
**  FTW
**  Walk a directory hierarchy from a given point, calling a user-supplied
**  function at each thing we find.  If we go below a specified depth,
**  recycle file descriptors.
*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "pdftw.h"

#ifdef	RCSID
static char RCS[] = "$Header: /proj/wais/wais-8-b2/lib/RCS/ftw.c,v 1.1 91/07/17 16:37:58 jonathan Exp $";
#endif	/* RCSID */

#define EQ(a, b)	(strcmp((a), (b)) == 0)

extern char		*malloc();
extern char		*strcpy();

int
ftw(directory, funcptr, depth)
    char		 *directory;
    int			(*funcptr)();
    int			  depth;
{
    register DIR	 *dirp;
    struct dirent		 *entp;
    struct stat		  stats;
    register char	 *p;
    register int	  i;
    long		  seekpoint;
    char		 *fullpath;

    /* If can't stat, tell the user so. */
    if (stat(directory, &stats) < 0)
	return (*funcptr)(directory, &stats, FTW_NS);

    /* If it's not a directory, call the user's function. */
    if ((stats.st_mode & S_IFMT) != S_IFDIR)
	/* Saying "FTW_F" here is lying; what if this is a symlink? */
	return (*funcptr)(directory, &stats, FTW_F);

    /* Open directory; if we can't, tell the user so. */
    dirp = opendir(directory);
    if (dirp == NULL)
	return (*funcptr)(directory, &stats, FTW_DNR);

    /* See if user wants to go further. */
    i = (*funcptr)(directory, &stats, FTW_D);
    if (i) {
	closedir(dirp);
	return i;
    }

    /* Get ready to hold the full paths. */
    i = strlen(directory);
    fullpath = malloc(i + 1 + MAXNAMLEN + 1);
    if (fullpath == NULL) {
	closedir(dirp);
	return -1;
    }
    (void)strcpy(fullpath, directory);
    p = &fullpath[i];
    if (i && p[-1] != '/')
	*p++ = '/';

    /* Read all entries in the directory.. */
    while (entp = readdir(dirp))
	if (!EQ(entp->d_name, ".") && !EQ(entp->d_name, "..")) {
	    if (depth <= 1) {
		/* Going too deep; checkpoint and close this directory. */
		seekpoint = telldir(dirp);
		closedir(dirp);
		dirp = NULL;
	    }

	    /* Process the file. */
	    (void)strcpy(p, entp->d_name);
	    i = ftw(fullpath, funcptr, depth - 1);
	    if (i) {
		/* User's finished; clean up. */
		free(fullpath);
		if (dirp)
		    closedir(dirp);
		return i;
	    }

	    /* Reopen the directory if necessary. */
	    if (dirp == NULL) {
		dirp = opendir(directory);
		if (dirp == NULL) {
		    free(fullpath);
		    return -1;
		}
		seekdir(dirp, seekpoint);
	    }
	}

    /* Clean up. */
    free(fullpath);
    closedir(dirp);
    return 0;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.