/*
                            F I L E F O U N . C

    With the MS-DOS implementation the received attribute is compared
    to the request:

    O_FILE:     accepts only A_NORMAL, A_ARCH/A_READ with A_NORMAL accepted
    O_DIR:      accepts only A_SUBDIR
    O_SUBDIR:   accepts only A_SUBDIR, but not the . and ..
    O_ALL:      accepts all

    Not yet supported: O_VOLID:    accepts A_VOLID

    When a '.' starts the searchpattern, the . and .. are the only entries
    that can be returned with MS-DOS. This is tested separately. Otherwise,
    the *, *. and *.* patterns will return the . and ..-subdir entries.

    When a . or .. is thus accepted, it is nonetheless rejected by the function
    if the O_SUBDIR (and not O_ALL or O_DIR) was requested.
*/

#include "icrssdef.h"

char *filefound()
{
    register unsigned
        request,
        received;

    received = ifs.find.attrib;             /* use fast registers */
    request = ifs.attrib;

    /* First part: see if request */
    /* matches attribute of entry */

    if                                      /* (list all accepted variants) */
    (
        !                                   /* if not: */
        (
            (
             (request & O_FILE)             /* FILE requested, and */
             &&                             /* an attribute received  */
             !                              /* indicating that it's no file */
             (
                 received &
                 (A_SUBDIR | A_HIDDEN | A_SYSTEM | A_VOLID)
             )
            )
            ||
            (
             (request & (O_SUBDIR | O_DIR)) /* OR: any subdir requested */
             &&                             /* and A_SUBDIR received */
             (received & A_SUBDIR)
            )
            ||
            (
             (request & O_ALL)              /* OR: ALL requested */
             &&                             /* and not volume label received */
             !(received & A_VOLID)
            )
        )
    )
        return (NULL);                      /* then reject the entry */


    /* Second part: O_SUBDIR (overruled by O_ALL / O_DIR)   */
    /*              entries '.' and '..' are rejected       */

    if
    (
        !(request & (O_DIR | O_ALL))        /* not O_DIR / O_ALL requested, */
        &&                                  /* AND */
        (request & O_SUBDIR)                /* clean subdir requested */
        &&                                  /* AND */
        (
            !strcmp(ifs.find.name, ".")     /* . or .. found */
            ||
            !strcmp(ifs.find.name, "..")
        )
    )
        return (NULL);                      /* then reject the entry */


#ifdef MSDOS                                /* Check . and .. dir entries */
                                            /* for DOS */
    /* Third part: dot-patterns   */
    /* are inspected              */

    if
    (
        ifs.pattern                         /* dot-pattern requested */
        &&                                  /* accept only . and ..  */
        (
            !(request & (O_DIR | O_ALL))    /* not DIR/ALL requested */
            ||                              /* OR */
            ifs.find.name[0] != '.'         /* 1st char of name found != '.' */
            ||                              /* OR */
            !                               /* not one of listed below: */
            (
                ifs.find.name[1]            /* chars [1] match */
                          == ifs.pattern[1]
                ||                          /* OR */
                memchr("*?",                /* wildcard in the pattern */
                       ifs.pattern[1], 2)
            )
        )
    )
        return (NULL);                      /* reject the entry */

#endif

    return (ifs.find.name);                 /* return found name */
}
