/*static char *SCCSID = "@(#)fs_close.c	6.2 91/01/14";*/
#define SCCSID "@(#)fs_close.c	6.2 91/01/14"
/*
 *	IBM/Microsoft Confidential
 *
 *	Copyright (c) IBM Corporation 1987, 1989
 *	Copyright (c) Microsoft Corporation 1987, 1989
 *
 *	All Rights Reserved
 *
 */

/*
 *  FS_CLOSE.C
 *
 *    DESCRIPTION
 *    
 *      Close a file.
 *
 *
 *    FUNCTIONS DEFINED
 *
 *      FS_CLOSE () -   Close a file.
 *
 * 
 *  REVISION HISTORY (in reverse chronological order)
 *  -----------------------------------------------------------------------
 *  8/6/90      Brian Andrw     Back out the 4/19 changes.  Close for system
 *                              only.
 *
 *  4/20/90     Brian Andrew    Make file operation multithreaded.
 * 
 *  4/19/90     Brian Andrew    Free the FILE_DEP_DATA structure for any
 *                              close operation.
 * 
 *  9/10/89     Brian Andrew    First working version
 * 
 *  8/4/89      Brian Andrew    Initial Blank Template
 *
 *
 *  TO DO
 *  -------------------------------------------------------------------------
 *
 */


#define INCL_DOSERRORS
#define INCL_NOPMAPI
#include <os2.h>
#include <fsd.h>
#include <fsh.h>

#include "cdfs.h"
#include "sem.h"
#include "vol.h"
#include "path.h"
#include "file.h"
#include "buffer.h"
#include "mem.h"
#include "heap.h"
#include "message.h"

#ifdef STATS_H
#include "stats.h"
#endif

#include "fsdata.h"
#include "pr_memin.h"

#ifdef DEBUG
#include "pr_DEBUG.h"
#endif

/***    FS_CLOSE () -   Close a file.
 *      
 *  DESCRIPTION
 *
 *
 *      The close process is the same as for FINDCLOSE.  We check if the close
 *      has already started, if so we exit directly.  Otherwise we set the
 *      close flag, wait for any active processes to finish with the
 *      file and then free the structures in the FILE_DEP_DATA area.
 *
 *      
 *  ENTRY
 *
 *      type    = Type of close operation, we only take action for
 *                CL_FORSYS.
 *      ioFlag  = Indicates information about operation (not used).
 *      psffsi  = Pointer to file independent area.  Contains the file's
 *                time stamps, size and position information.
 *      psffsd  = Pointer to file dependent area.  Contains the
 *                directory entry for the first and most recently accessed
 *                extents.  It also contains the semaphores and flags
 *                which control the access to this data.
 *
 *
 *  EXIT
 *
 *      NO_ERROR
 *      ERROR_INVALID_PARAMETER if type is invalid
 */

int far pascal
FS_CLOSE (USHORT            type,
		  USHORT            IOflag,
		  PSFFSI            psffsi,
		  PSFFSD            psffsd)
{
		USHORT  usRet;

#ifdef DEBUG
	dprintf ("FS_CLOSE: Type=%d\n", type);
#endif

#ifdef STATS_H
		CurSt.st_close++;
#endif

	if (usRet = CHECK_INIT)
		return usRet;

	/*
	 *  For CLOSE operations we free all the resources associated
	 *  with this FILE_DEP_DATA structure.  This is for system close only.
	 */
	switch (type)
	{

		case FS_CL_FORSYS :

			/* Wait on the semaphore */
			SEM_REQ (((PFILE_DEP_DATA) psffsd)->sFileSem);

			/* Check if the close has not already started */
			if (!((PFILE_DEP_DATA) psffsd)->fCloseFlag)
			{
				/* Show that a close is starting */
				((PFILE_DEP_DATA) psffsd)->fCloseFlag = TRUE;

				/* Loop until no readers left */
				while (((PFILE_DEP_DATA) psffsd)->usCountRead)
				{
					/* Sleep and try again */
					SEM_CLEAR (((PFILE_DEP_DATA) psffsd)->sFileSem);

					SEM_REQ (((PFILE_DEP_DATA) psffsd)->sFileSem);
				}

				/* Free the structures */
				FREE_DIR_ENTRY (((PFILE_DEP_DATA) psffsd)->pdeFirstDirRec);
				FREE_DIR_ENTRY (((PFILE_DEP_DATA) psffsd)->pdeLastDirRec);

			} /* end if close hasn't started */

			/* Give up the semaphore */
			SEM_CLEAR (((PFILE_DEP_DATA) psffsd)->sFileSem);

		case FS_CL_FORPROC   :
		case FS_CL_ORDINARY  :

			usRet = NO_ERROR;
			break;

		default:

			usRet = ERROR_INVALID_PARAMETER;

	} /* end switch on type */

	return usRet;

	/* no warnings */
	type; IOflag; psffsi; psffsd;

}   /* end FS_CLOSE */
