/*
 * Simulate DOS findfirst()/findnext().  We do this rather than rewriting
 * the original code both (a) for simplicity and (b) because we also need to
 * handle globbing.
 */
  
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
  
#define DIRUTIL_INTERNAL    /* so we get the hidden members */
#include "global.h"
#include "dirutil.h"
  
int
findnext(fbp)
struct ffblk *fbp;
{
    char statname[1024];
    struct stat statbuf;
    struct dirent *fp;
    char *snp;
  
    strcpy(statname, fbp->ddir);
    strcat(statname, "/");
    for (snp = statname; *snp; snp++)
        ;
    for (;;)
    {
        if (!(fp = readdir(fbp->dp)))
        {
            closedir(fbp->dp);
            free(fbp->ddir);
            free(fbp->dpat);
            return -1;      /* no more matches */
        }
        if (!fp->d_ino)
            continue;       /* deleted file */
        if (fp->d_name[0] == '.' && !(fbp->ff_attrib & FA_HIDDEN))
            continue;       /* skip dot-files unless FA_HIDDEN */
        if (!wildmat(fp->d_name, fbp->dpat, (char **) 0))
            continue;       /* name doesn't match glob */
        strcpy(snp, fp->d_name);
        if (stat(statname, &statbuf) == -1)
            continue;       /* file disappeared??? */
        switch (statbuf.st_mode & S_IFMT)
        {
            case S_IFREG:       /* ordinary file */
            case S_IFIFO:       /* allow a FIFO to masquerade as a file */
            case 0:         /* *ix anachronism */
                fbp->ff_attrib = FA_NORMAL;
                break;
            case S_IFDIR:       /* directory */
                if (!(fbp->ff_sattrib & FA_DIREC))
                    continue;
                fbp->ff_attrib = FA_DIREC;
                break;
            default:        /* device/name(Xenix)/etc. */
                if (!(fbp->ff_sattrib & FA_SYSTEM))
                    continue;
                fbp->ff_attrib = FA_SYSTEM;
                break;
        }
        strcpy(fbp->ff_name, fp->d_name);
        fbp->ff_fsize = (fbp->ff_attrib == FA_SYSTEM? 0: statbuf.st_size);
        fbp->ff_ftime = *localtime(&statbuf.st_mtime);
        return 0;
    }
}
  
int
findfirst(name, fbp, attr)
char *name;
struct ffblk *fbp;
int attr;
{
    register char *np;
    char nbuf[1024];
  
    strcpy(nbuf, name);
    for (np = nbuf; *np; np++)
        ;
    if (np == nbuf || np[-1] == '/')
    {
        strcat(nbuf, "*");
        np++;
    }
    while (np != nbuf && *--np != '/')
        ;
    if (*np == '/')
        *np++ = '\0';
    fbp->ddir = strdup((np == nbuf? ".": nbuf));
    fbp->dpat = strdup(np);
    fbp->ff_attrib = attr;
    if (!(fbp->dp = opendir(fbp->ddir)))
        return -1;
    return findnext(fbp);
}
