/*static char *SCCSID = "@(#)fs_fsinf.c	6.2 91/01/14";*/
#define SCCSID "@(#)fs_fsinf.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_FSINF.C
 *
 *    DESCRIPTION
 *    
 *      Returns information for a filesystem device.
 *
 *
 *    FUNCTIONS DEFINED
 *
 *      FS_FSINFO ()    -   Returns information for a file system device.
 *
 * 
 *  REVISION HISTORY (in reverse chronological order)
 *  -----------------------------------------------------------------------
 *  7/20/90     Brian Andrew    Used FSINFO2 instead of FSINFO to test
 *                              size of buffer.  MSBUG OSO1328        
 * 
 *  2/22/90     Brian Andrew    Returned error indicating volume is
 *                              write protected when setting file system
 *                              information.
 * 
 *  9/10/89     Brian Andrew    Incorporated into FSD
 * 
 *  8/11/89     Paul Bingman    First CD_ROM 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 "path.h"
#include "vol.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"
#include "memory.h"

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

/***    FS_FSINFO ()    -   Return information for a filesystem device
 *      
 *  DESCRIPTION
 *
 *      We first recover the volume parameters.  Then, using the 'flag' and
 *      'level' parameters, we return the desired values from the
 *      volume structures.
 *
 *      
 *  ENTRY
 *
 *      flag    = Indicates retrieval of information vs. setting.  We
 *                  only support retrieval.
 *      hVPB    = Handle to volume.
 *      pData   = Address of application output.
 *      cbData  = Length in bytes of the application area.
 *      level   = Level of information to return.
 *
 *
 *  LOCAL
 *
 *      usRet       = Return value.
 *      pvi         = Pointer to volume independent area.
 *      pvddVolData = Pointer to volume dependent area.
 *      cp          = Local pointer into character string.
 *      i           = Index into array.
 *
 *
 *  EXIT
 *
 *      ERROR_INVALID_HANDLE if hVPB is invalid.
 *      ERROR_BUFFER_OVERFLOW if user's area is too small.
 *      Error value from PROBEBUF if failure.
 *      ERROR_INVALID_PARAMETER if invalid flag.
 *      ERROR_NOT_SUPPORTED if trying to set data.
 *      ERROR_INVALID_LEVEL if unsupported level value.
 */


int far pascal
FS_FSINFO (flag, hVPB, pData, cbData, level)
USHORT          flag;
USHORT          hVPB;
PCHAR           pData;
USHORT          cbData;
USHORT          level;
{
		USHORT          usRet;
		PVPFSI          pvi;
		PVOL_DEP_DATA   pvddVolData;
		PCHAR           cp;
		UCHAR           i;

#ifdef DEBUG
	dprintf ("FS_FSINFO(flag=%d, hVPB=%d, level=%d)\n", flag, hVPB, level);
#endif

	/*
	 *  Check for memory initialization
	 */

#ifdef STATS_H
		CurSt.st_fsinfo++;
#endif

	/* Check if first time initialization */
	if (usRet = CHECK_INIT)
	{
		return usRet;

	} /* end if init memory failed */

	/* Check that the buffer is the stated size */
	if (cbData)
	{
		usRet = FSH_PROBEBUF (PB_OPWRITE, pData, cbData);
	}

	/* Continue if no errors */
	if (!usRet)
	{
		/*
		 *  Check the value of flag, we only support getting information.
		 *  We return CDROM_WRITE_PROTECT if setting information.
		 */
			
		if (flag & INFO_SET)
		{
			return CDROM_WRITE_PROTECT;

		} /* end if trying to set information */

		/*
		 * Use the VPB handle to get pointers to this volume's vpfsi & vpfsd.
		 * It's an error if the handle is invalid or won't produce valid ptrs.
		 */

		FSH_GETVOLPARM(hVPB, &pvi, (struct vpfsd far * far *) &pvddVolData);
		if (pvi == NULL || pvddVolData == NULL)
			return (ERROR_INVALID_HANDLE);

		switch (level)

		{
			case 1:

				/*
				* Level 1 information:
				*
				*   Sectors per allocation unit
				*   Total allocation units
				*   Free allocation units
				*   Bytes per sector
				*/

				/*
				* validate that the caller passed enough room
				* for the info they asked for
				*/

				if (cbData < sizeof (FSALLOCATE))
					return (ERROR_BUFFER_OVERFLOW);

				/* copy over the sectors per allocation unit */

				((FSALLOCATE FAR *) pData)->cSectorUnit = 1L;

				/* copy over the total allocated sectors */

				((FSALLOCATE FAR *) pData )->cUnit =
						pvddVolData->pvdVolDesc->clbVolSpace;

				/* copy over the free sectors (never any) */

				((FSALLOCATE FAR *) pData)->cUnitAvail = 0L;

				/* copy over the bytes per sector */

				((FSALLOCATE FAR *) pData)->cbSector =
				pvddVolData->pvdVolDesc->cbLogBlk;

				break;

			case 2:

				/*
				* Level 2 information:
				*
				*   Volume ID
				*   (length of Volume Label)
				*   Volume Label
				*/

				/*
				* validate that the caller passed enough room
				* for the info they asked for
				*/

				if (cbData < sizeof(FSINFO2))
				return (ERROR_BUFFER_OVERFLOW);

				/* copy over Volume Serial Number */

				((FSINFO2 FAR *) pData)->ulVSN = pvi->vpi_vid;

				/* copy over Volume Label */

				memcpy((UCHAR FAR *)
							&((FSINFO2 FAR *) pData)->vol.szVolLabel[0],
							pvi->vpi_text,
							VPSFI_ID_LEN + 1);

				/*
				* Determine and set the length of label.
				* First, trailing blanks must be removed.
				*/

				cp = &((FSINFO2 FAR *) pData)->vol.szVolLabel[VPSFI_ID_LEN - 1];
				for (i = VPSFI_ID_LEN; *cp == ' ' && i; cp--, i--)
				;
				cp[1] = '\0';
				((FSINFO2 FAR *) pData)->vol.cch = i; /* set length */

				/* done with level 2, flag = INFO_RETREIVE */

				break;

			/*
			* Catch any other levels that might sneak through
			*/

			default:
				usRet = ERROR_INVALID_LEVEL;
				break;

		} /* end switch (level) */

	}
#ifdef DEBUG
	dprintf ("    FS_FSINFO: Return value  --  %d\n", usRet);
#endif

	return (usRet);
}

/* end FS_FSINFO */
