/*static char *SCCSID = "@(#)fs_mkdir.c 6.3 92/02/19";*/
#define _BTXT _BTXT
#define INCL_DOSERRORS
#include <os2def.h>
#include <bse.h>
#include <fsh.h>
#include <basemid.h>                                             // @63751
#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 "lw.h"
#include "frame.h"
#include "fsdata.h"
#include "fnode.h"
#include "ea.h"
#include "heap.h"
#include "shutdown.h"
#include "log.h"                                                 // @76193
#include "pr_fsd.h"
#include "pr_CACHE.h"
#include "pr_del.h"
#include "pr_dir.h"
#include "pr_ea.h"
#include "pr_FCN.h"
#include "pr_HEAP.h"
#include "pr_MISC.h"
#include "pr_WRSUB.h"
#include "pr_DEBUG.h"

/*
 * HISTORY:
 *  @63751  23-Nov-1993 by D.Azzarito - Use better msg for dirty volumes
 *  @76193  23-Nov-1993 by D.Azzarito - Change holds for LOG support
 */

int far pascal
FS_MKDIR (struct cdfsi far *pcdfsi,
          struct cdfsd far *pcdfsd,
          char far *        pName,
          unsigned short    iCurDirEnd,
          char far *        pEABuf,
          unsigned short    flags)
{
    PCRACKEDPATH pcp;
    USHORT erc;
    SHUTDOWN_LOCAL_VARS;
    USHORT usRet;       /*  return code from FSH_PROBEBUF--for errors  */
    USHORT oError = 0;
    FRAME  frm;

    INCR_WRITE_THREADS;         /* Tell shutdown we're writing. */

    frm.usHardErr = NO_ERROR;
    frm.fRecheckAddr = TRUE;

    if ((frm.pvol = FindPVol (pcdfsi -> cdi_hVPB)) == NULL) {
//@63751        erc = ERROR_INVALID_HANDLE;
        erc = MSG_HPFS_VOLUME_DIRTY;  // @63751
        goto MDExit1;
    }

    if ((erc = CrackPath(pcdfsi->cdi_hVPB,pName,&pcp,&frm)) == NO_ERROR) {
        erc = MkDir (pcp, flags, &frm);

#ifdef EAFIX

        if ( (erc == NO_ERROR) && !IS_USER_NULL(pEABuf) )
        {

            PFEALIST pfeal;
            PGEALIST pgeal;
            PDIRBLK pdb;                /*  dirblock of entry in parent */
            PDIRENT pde;                /*  dirent of entry in parent   */
            PBUFNODE pbuf;              /*  buffer for pdb and pde      */
            LHANDLE lhFEA, lhGEA;       /*  Lock handles for the
                                                FEA and GEA lists  */

            /*
             *  Call Lookfile to find the pde and pdb for the
             *  directory we just created.  LookFile will leave
             *  the parent Subdir held (if it succeeds)--hold the
             *  buffer, as well, so SetPathEA can use the pdb and
             *  pde with impunity.
             *  BUGBUG -- this is kind of wasteful.
             */
            if ((erc = LookFile (pcp, &pdb, &pde, &pbuf,&frm)) != NO_ERROR) {
                FS_SETHARDERR(erc);
            } else {

                IncrHoldsBUF( pbuf );  // @76193

                LOCKSWAP(&swapBSWAP0);
                if ( (erc = LockEAs((PEAOP)pEABuf,
                                         LEAS_SET,
                                         &lhFEA, &lhGEA,
                                         &pfeal, &pgeal, TRUE, &frm)) == NO_ERROR ) {

                        /*
                         *  The FEA list is locked in place, so we
                         *  can read it at will.  Now we call SetPathEA.
                         *  Then, since we'll be done with the EA lists,
                         *  unlock them.
                         */

                        /* assume no write through */
                        frm.u.fWrtThru = FALSE;
                        CHECKSWAP(&swapBSWAP0);
                        erc = SetPathEA(pfeal,pdb,pde,pbuf,&oError,&frm);
                        UnlockEAs(lhFEA, lhGEA, &frm);
                }
                UNLOCKSWAP(&swapBSWAP0);

                DecrHoldsBUF( pbuf );  // @76193
                UnHoldDir_(frm.psbd); /* Release the hold of LookFile */
            }

            if (erc != NO_ERROR) {

                /*  The Extended Attributes could not be set, for one
                 *  reason or another.  This means we have to remove
                 *  the directory we just created, since the FS_MKDIR
                 *  operation has to be atomic.  We also have to set
                 *  the oError field of the user's PEAOP.
                 *
                 */
                RmDir( pcp,&frm );

                FS_MAYBLOCK( usRet = FSH_PROBEBUF (PB_OPWRITE,
                                                pEABuf,
                                                sizeof(EAOP) ) )
                if (usRet == NO_ERROR) ((PEAOP)pEABuf)->oError = oError;

            }

        }
#endif
    }

/* MDExit2: */
    if (pcp!= NULL)
        RetHeap (pcp);

MDExit1:
#ifdef DEBUG
    VBS ();
#endif

    DECR_WRITE_THREADS;                 /* Tell shutdown we're done. */

    return erc;

    /*  Remove warning */
    pcdfsd, iCurDirEnd, pEABuf;

}
