/*static char *SCCSID = "@(#)fs_fattr.c 6.2 92/01/31";*/
#define _BTXT _BTXT
#define INCL_DOSERRORS
#include <os2.h>
#include <fsh.h>
#include "heap.h"
#include "api.h"
#include "const.h"
#include "misc.h"
#include "chain.h"
#include "buf.h"
#include "dir.h"
#include "storage.h"
#include "volume.h"
#include "tables.h"
#include "pb_ifs.h"
#include "pbmacros.h"
#include "superb.h"
#include "lw.h"
#include "frame.h"
#include "fsdata.h"
#include "notify.h"
#include "shutdown.h"
#include "log.h"                                                 // @76193
#include "pr_fsd.h"
#include "pr_CACHE.h"
#include "pr_DIR.h"
#include "pr_HEAP.h"
#include "pr_MISC.h"
#include "pr_WRSUB.h"
#include "pr_DEBUG.h"

/*
 *      HISTORY
 *  @76193  23-Nov-1993 by D.Azzarito - Change holds for LOG support
 *          26-May-1989 by JR (John Rogers, JohnRo@Microsoft)
 *              - DCR 259.2: added counting of write threads for shutdown.
 *              - DCR 259.2: changed names of macros in "frame.h".
 */


int far pascal
FS_FILEATTRIBUTE (flag, pcdfsi, pcdfsd, pName, iCurDirEnd, pAttr)
USHORT                  flag;
struct cdfsi far *      pcdfsi;
struct cdfsd far *      pcdfsd;
char far *              pName;
USHORT                  iCurDirEnd;
PUSHORT                 pAttr;
{
    SHUTDOWN_LOCAL_VARS;
    PCRACKEDPATH pcp;
    USHORT erc;
    PDIRBLK pdb;
    PBUFNODE pbuf;
    PSUBDIR psbd;
    PDIRENT pde;
    FRAME   frm;

    frm.usHardErr = NO_ERROR;
    frm.fRecheckAddr = TRUE;
    frm.fFlag = 0;               // Clear Frame flag  @132506

    /*  Handle root specially;  since . and .. are no longer in
     *  directory hierarchy, we must simulate them on the fly.
     */

    if (fstrlen (pName) == 3) {
#ifdef DEBUG
        if (pName[1] != ':' || pName[2] != '\\')
            INTERR ("Weird pathname");
#endif
        erc = NO_ERROR;
        if (flag == 0)
            *pAttr = ATTR_DIRECTORY;
        else
            erc = ERROR_ACCESS_DENIED;
        return erc;
    }

    INCR_WRITE_THREADS;         /* Allow tracking of writes for shutdown. */

    if ((erc = CrackPath(pcdfsi->cdi_hVPB, pName, &pcp, &frm)) != NO_ERROR) {
        goto FAttrExit;
    }

    if (FindDir (pcp, &pdb, &pbuf, &psbd, &frm)) {

        /*  Directory was found, now go find file
         */

        erc = LDE (pdb, OAC_OF, FALSE, pbuf, FILE_NAME (pcp), &pbuf,
                   &pdb, &pde, FALSE, &frm);  //#90495

        if (erc == LDE_FOUND) {

            erc = NO_ERROR;

            if (flag == FA_RETRIEVE) {

                /*  Retrieve the attribute */
                *pAttr = pde->fAttr & ~ATTR_NEWNAME;

            } else if (flag == FA_SET) {

                /* check for ACL on file dcr1505 */               /*dcr1505*/
                if ((pde->fFlags & DF_ACL ) != 0)                 /*dcr1505*/
                  {                                               /*dcr1505*/
                  erc = ERROR_ACCESS_DENIED;                      /*dcr1505*/
                  }                                               /*dcr1505*/
                else {                                            /*dcr1505*/
                /*  Set the attribute */
                pde->fAttr = (BYTE) *pAttr | (pde->fAttr & ~ATTR_CHANGEABLE);
                SetDirt (&pde->fAttr, pbuf, FALSE, &frm);
                NotifyCheck(N_SETATTR, psbd, pde, &frm);
                }                                                 /*dcr1505*/
            } else {
                erc = ERROR_INVALID_FLAG_NUMBER;
            }
        }
        else
            erc = ERROR_FILE_NOT_FOUND;

        DecrHoldsBUF (pbuf);  // @76193
        UnHoldDir_(frm.psbd);
    }
    else
        erc = ERROR_PATH_NOT_FOUND;

FAttrExit:

#ifdef DEBUG
    VBS ();
#endif

    if (pcp != NULL)
        RetHeap (pcp);

    DECR_WRITE_THREADS;                 /* Revise write counting (shutdown). */
    return erc;

    pcdfsi, pcdfsd, iCurDirEnd;
}
