/*

$Log:   S:\products\msprods\oiwh\libgfs\gfsopen.c_v  $
 * 
 *    Rev 1.16   11 Jun 1996 10:32:38   RWR08970
 * Replaced IMG_WIN95 conditionals for XIF processing with WITH_XIF conditionals
 * (I'm commented them out completely for the moment, until things get settled)
 * 
 *    Rev 1.15   26 Mar 1996 08:15:10   RWR08970
 * Remove IN_PROG_GENERAL conditionals surrounding XIF processing (IMG_WIN95 only)
 * 
 *    Rev 1.14   13 Mar 1996 09:08:28   RWR08970
 * Remove XIF check from last update (useless code - fct.format isn't set yet!)
 * 
 *    Rev 1.13   13 Mar 1996 08:51:02   RWR08970
 * Correct problem with obtaining filesize value for XIF and AWD files
 * 
 *    Rev 1.12   12 Mar 1996 17:59:24   RWR08970
 * Correct gfsopen() to exit if AWD file and WITH_AWD not defined
 * (was calling ErrorNoClose() but not returning!)
 * 
 *    Rev 1.11   12 Mar 1996 13:25:52   RWR08970
 * Two kludges: Support single-strip TIFF files with bad (too large) strip size,
 * and support TIFF files with bad (beyond EOF) IFD chains (ignore them)
 * 
 *    Rev 1.10   26 Feb 1996 14:45:12   KENDRAK
 * Added XIF support.
 * 
 *    Rev 1.9   05 Feb 1996 13:43:58   JFC
 * Remove AWD support for NT.
 * 
 *    Rev 1.8   14 Nov 1995 10:01:20   RWR
 * Change "delay_on_conflict" to "pause_on_conflict" to avoid conflict (ha ha)
 * with identically named function in FILING (i.e., problems w/MONSTER build)
 * 
 *    Rev 1.7   09 Oct 1995 19:58:22   KENDRAK
 * Added performance logging code with conditional compilation.
 * 
 *    Rev 1.6   06 Sep 1995 14:01:34   KENDRAK
 * Updated to handle changes in the interface to IsAWDFile.
 * 
 *    Rev 1.5   31 Jul 1995 15:33:48   KENDRAK
 * Fixed some areas where flag combinations were not checked correctly.
 * Added AWD read support.
 * 
 *    Rev 1.4   15 Jun 1995 16:17:36   HEIDI
 * 
 * fixed goofed up or'ing of flags
 * 
 *    Rev 1.3   15 Jun 1995 15:27:10   HEIDI
 * 
 * fixed goofed up comment
 * 
 *    Rev 1.2   15 Jun 1995 15:12:36   HEIDI
 * 
 * Changed the oflag from O_RDWR to (O_RDWR | OF_SHARE_DENY_WRITE)
 * 
 *    Rev 1.1   25 Apr 1995 13:17:36   RWR
 * Remove various "(unsigned short)" casts causing problems with 32-bit ints
 * 
 *    Rev 1.0   06 Apr 1995 14:02:20   HEIDI
 * Initial entry
 * 
 *    Rev 1.0   28 Mar 1995 15:41:02   JAR
 * Initial entry

*/

/*
 Copyright 1989, 1990, 1991 by Wang Laboratories Inc.

 Permission to use, copy, modify, and distribute this
 software and its documentation for any purpose and without
 fee is hereby granted, provided that the above copyright
 notice appear in all copies and that both that copyright
 notice and this permission notice appear in supporting
 documentation, and that the name of WANG not be used in
 advertising or publicity pertaining to distribution of the
 software without specific, written prior permission.
 WANG makes no representations about the suitability of
 this software for any purpose.  It is provided "as is"
 without express or implied warranty.
 *
 */
/*
 *  SccsId: @(#)Source gfsopen.c 1.32@(#)
 *
 *  gfsopen(3i)
 *
 *  GFS: File Open Call
 *
 *  SYNOPSIS:
 *      int gfsopen (path, oflag, format, pgcnt)
 *      int oflag, *format, *pgcnt;
 *      char *path;
 *
 *  UPDATE HISTORY:
 *    08/18/94 - KMC, multi-page TIFF write enhancements, addition of DCX file
 *               format.
 *    03/15/94 - RWR, anno_data_length is already init'd to 0, so no need here
 *    03/14/94 - RWR, initialize anno_data_length to 0 at open time, so we
 *               can use it to determine when we've received the first PUT
 *    02/03/94 - KMC, changed return value and 3rd parameter in pegasus_read
 *               and pegasus_write to u_ints.
 *    06/13/89 - bill, creation
 *
 */

/*LINTLIBRARY*/
#define  GFS_CORE

#ifndef O_RDONLY
	#include <fcntl.h>
#endif
#include "gfsintrn.h"
#include <stdio.h>
#include <errno.h>
#include "gfct.h"
#include "gfs.h"
#ifndef O_BINARY
	#define O_BINARY 00000
#endif
#ifdef OI_PERFORM_LOG
	#include "logtool.h"
#endif

#ifdef MSWINDOWS

	#define  ERROR_CONFLICT  5
	#define  RETRY_COUNT     23
	#define  RETRY_TIME      3000

	#undef O_BINARY
	#define O_BINARY 00000


	#ifdef DEBUGIT
	#include <monit.h>
	#endif

	/* define DEBUGITHIGH */

	#ifdef DEBUGITHIGH
	#include <monit.h>
	#endif

#endif

#define  AMODE_READ             04      /* Read */
#define  AMODE_WRITE            02      /* Write */
#define  AMODE_EXEC             01      /* Execute / Search */
#define  AMODE_VERIFY           00      /* Check Existence */

extern  int     FAR PASCAL putfct();    /* Call to insert FCT entry */
extern  int     FAR PASCAL rmfct();     /* Call to remove FCT entry (on error)*/
extern  int     FAR PASCAL getfmt();    /* Call to determine format of file */
extern  int     FAR PASCAL initroot();  /* Call to initialize WIFF Root Block */
extern  int     FAR PASCAL fillroot();  /* Call to fill WIFF Root in Memory */

extern  int     FAR PASCAL InitTocOrChain(struct _gfct FAR *);

extern void FAR PASCAL CloseAWDFile(p_GFCT lpFctPtr);
extern int FAR PASCAL IsAWDFile(char *szFilePath, int *lpBoolResult);
extern int FAR PASCAL OpenAWDFile(char *szFilePath, int iAccessFlags, p_GFCT lpFctPtr);
extern int FAR PASCAL ParseAWDFile(p_GFCT lpFctPtr);

        //#ifdef WITH_XIF
		extern int FAR PASCAL OpenXifFile(p_GFCT lpFctPtr);
		extern int FAR PASCAL GetXifNumPages(p_GFCT lpFctPtr);
        //#endif //WITH_XIF

/* internal function prototypes */
int	ErrorNoClose(p_GFCT p_fct);
int	ErrorAndClose(p_GFCT p_fct);

#ifdef MSWINDOWS

#ifdef PEGASUS
/* int get_error(void); */
int pause_on_conflict(LPINT);

/* 9503.24 jar - removed this int21 cal, using GetLastError instead!!! */

/* int get_error(void)
{
	_asm
        {
        push    ds
        push    es
        push    dx
        push    si
        mov     bx, 0
        mov     al, 0
        mov     ah, 59h
        pop     si
        pop     dx
        pop     es
        pop     ds
        int     21h
        }
}
*/

/******************************************************************
 * 
 * Function Name:  pause_on_conflict
 *
 ******************************************************************/
int pause_on_conflict(retrycount)
LPINT retrycount;
{
long retrytime;

/* 9503.24 jar - removed this int21 cal, using GetLastError instead!!!
	errno = get_error(); */

	errno = GetLastError();

#ifdef DEBUGIT
        monit1("errno = %d\n", (int) errno);
#endif
        if (errno == ERROR_CONFLICT)
        {
          if (++(*retrycount) <= RETRY_COUNT)
          {
#ifdef DEBUGITHIGH
                monit1("Errno retry #= %d MAX = %d\n", (int) *retrycount,
                                                (int) RETRY_COUNT);
#endif
                retrytime = GetTickCount();
                while((GetTickCount() - retrytime) < RETRY_TIME);
                return(1);
          }
        }
        return (0);
}

/******************************************************************
 * 
 * Function Name:  pegasus_open
 *
 ******************************************************************/
int     pegasus_open (path, oflag)
char    FAR *path;
int     oflag;
{
int  status;
int  retrycount=0;
BOOL loopit;

	do
    {
    	loopit = FALSE;
    	if ((status = _lopen(path, oflag)) == (int) -1)
		{
			/* 9503.23 JAR - changed call to isdirfp to isdirfp95 for the
				       new windows95 isdirp call
			 if (isdirfp(path))
			*/
	    	if (isdirfp95(path))
	     	{
	      		status = -1;
	      		break;
	     	}
            loopit = pause_on_conflict(&retrycount);
      	}
    }
    while (loopit);
        
	#ifdef DEBUGIT
	    monit1("**file %s pegasus_open status = %d\n", (LPSTR)path, (int) status);
	#endif
    return(status);
}

/******************************************************************
 * 
 * Function Name:  pegasus_creat
 *
 ******************************************************************/
int     pegasus_creat (path, oflag)
char    FAR *path;
int     oflag;
{
int  status;
int  retrycount=0;
BOOL loopit;

        do
        {
          loopit = FALSE;
          if ((status = _lcreat(path, oflag)) == (int) -1)
	  {
		/* 9503.23 JAR - changed call to isdirfp to isdirfp95 for the
			       new windows95 isdirp call
		if (isdirfp(path))
		*/
	       if (isdirfp95(path))
                 {
                  status = -1;
                  break;
                 }
                loopit = pause_on_conflict(&retrycount);
          }
        }
        while (loopit);
                
#ifdef DEBUGIT
        monit1("**file %s pegasus_creat status = %d\n", (LPSTR)path, (int) status);
#endif
        return(status);
}

/******************************************************************
 * 
 * Function Name:  pegasus_access
 *
 ******************************************************************/
int     pegasus_access (path, oflag)
char    FAR *path;
int     oflag;
{
int  status;
int  retrycount=0;
BOOL loopit;

        do
        {
	  loopit = FALSE;
	  /* 9503.23 JAR - changed call to gaccess to g95access for the
			 new windows95 gaccess call
	  if ((status = gaccess((char FAR *)path, oflag)) == (int) -1)
	  */
	  if ((status = (int)g95access((char FAR *)path, (short)oflag)) == (int) -1)
          {
                loopit = pause_on_conflict(&retrycount);
          }
        }
        while (loopit);

#ifdef DEBUGIT
        monit1("**file %s pegasus_access status = %d\n", (LPSTR)path, (int) status);
#endif
        return(status);
}


/******************************************************************
 * 
 * Function Name:  pegasus_close
 *
 ******************************************************************/
int  pegasus_close (fildes)
int fildes;
{
int  status;
int  retrycount=0;
BOOL loopit;

        do
        {
          loopit = FALSE;
          if ((status = _lclose(fildes)) == (int) -1)
          {
                loopit = pause_on_conflict(&retrycount);
          }
        }
        while (loopit);

#ifdef DEBUGIT
        monit1("**exit status pegasus_close status = %d\n", (int) status);
#endif
        return(status);
}

/******************************************************************
 * 
 * Function Name:  pegasus_seek
 *
 ******************************************************************/
long    pegasus_seek (filedes, loffset, iorigin)
int     filedes;
long    loffset;
int     iorigin;
{
long status;
int  retrycount=0;
BOOL loopit;

        do
        {
          loopit = FALSE;
          if ((status = _llseek(filedes, loffset, iorigin)) == (long) -1)
          {
                loopit = pause_on_conflict(&retrycount);
          }
        }
        while (loopit);

#ifdef DEBUGIT
        monit1("**exit status pegasus_seek status = %d\n", (int) status);
#endif

        return(status);
}

/******************************************************************
 * 
 * Function Name:  pegasus_read
 *
 ******************************************************************/
u_int   pegasus_read (filedes, lbuffer, wbytes)
int     filedes;
char FAR *lbuffer;
u_int   wbytes;
{
int  status;
int  retrycount=0;
BOOL loopit;


        do
        {
          loopit = FALSE;
          if ((status = _lread(filedes, (LPSTR)lbuffer, wbytes)) == (int) -1)
          {
                loopit = pause_on_conflict(&retrycount);
          }
        }
        while (loopit);
        
#ifdef DEBUGIT
        monit1("**read status = %d bytes max = %d\n", (int) status, wbytes);
#endif
        return(status);
}

/******************************************************************
 * 
 * Function Name:  pegasus_write
 *
 ******************************************************************/
u_int   pegasus_write (filedes, lbuffer, wbytes)
int     filedes;
char FAR *lbuffer;
u_int   wbytes;
{
int  status;
int  retrycount=0;
BOOL loopit;

        do
        {
          loopit = FALSE;
          if ((status = _bfwrite(filedes, lbuffer, wbytes)) == (int) -1)
          {
                loopit = pause_on_conflict(&retrycount);
          }
        }
        while (loopit);

        return(status);
}

#endif

#endif


/******************************************************************
 * 
 * Function Name:  gfsopen
 *
 ******************************************************************/
int     FAR PASCAL gfsopen (path, oflag, format, pgcnt)         /*errno_KEY*/
int     oflag, FAR *format, FAR *pgcnt;
char    FAR *path;
{
    int     ufd = 0;
    struct _gfct fct, *p_fct;
    int		bResult;

//#ifdef WITH_XIF
    UInt32  ret_code;
//#endif //WITH_XIF

	#ifdef OI_PERFORM_LOG
		RecordIt("GFS", 6, LOG_ENTER, "Entering gfsopen", NULL);
	#endif

	#ifdef PARM_CHECK
        if (path == (char FAR *) NULL) 
        {        /* Validate path */
            errno = (int) EINVAL;
			#ifdef OI_PERFORM_LOG
				RecordIt("GFS", 6, LOG_EXIT, "Exiting gfsopen", NULL);
			#endif
            return ( (int) -1);
        }
        if (oflag == (int) NULL) 
        {              /* Validate oflag */
            errno = (int) EINVAL;
			#ifdef OI_PERFORM_LOG
				RecordIt("GFS", 6, LOG_EXIT, "Exiting gfsopen", NULL);
			#endif
            return ( (int) -1);
        }
        if (format == (int FAR *) NULL) 
        {       /* Validate format */
            errno = (int) EINVAL;
			#ifdef OI_PERFORM_LOG
				RecordIt("GFS", 6, LOG_EXIT, "Exiting gfsopen", NULL);
			#endif
            return ( (int) -1);
        }
        if (pgcnt == (int FAR *) NULL) 
        {        /* Validate pgcnt */
            errno = (int) EINVAL;
			#ifdef OI_PERFORM_LOG
				RecordIt("GFS", 6, LOG_EXIT, "Exiting gfsopen", NULL);
			#endif
            return ( (int) -1);
        }
	#endif
    
    errno = 0;
    fct.fildes = (int) -1;
    p_fct = &fct;
    (void) memset((char FAR *) p_fct, (int) 0,
                    (int) (sizeof(struct _gfct)));

/* 1. Insure oflag contains a valid combination. */

/*    a.  O_RDONLY, O_WRONLY, O_RDWR are mutually exclusive.  But, at least
          one of them is required. */

	/* kjk 06/29/95:  Changed this code to do what the spec and comments
	                  say.  It used to only check for WRONLY and RDWR
					  together (but it checked it twice!). */

	if (((oflag & (int)(O_RDONLY|O_WRONLY|O_RDWR)) != (int)O_RDONLY) &&
		((oflag & (int)(O_RDONLY|O_WRONLY|O_RDWR)) != (int)O_WRONLY) &&
		((oflag & (int)(O_RDONLY|O_WRONLY|O_RDWR)) != (int)O_RDWR))
	{	   	
    	errno = (int) EINVALID_OFLAG;
		return(ErrorNoClose(p_fct));
    }

/*    b.  For now, exclude O_CREAT and O_EXCL , and O_TRUNC.            */
/*        Until further notice, these flags are excluded from GFS.      */

    if (oflag & (int) (O_TRUNC | O_CREAT | O_EXCL)) 
    {
        errno = (int) EINVALID_OFLAG;
		return(ErrorNoClose(p_fct));
    }

/* kjk 06/29/95:  Changed the following section to include O_WRONLY in
 *                addition to O_RDWR
 */
/*    c.  Finally, check to see if the O_APPEND flag is present.  If it is
 *        allow the user to open the file with the O_RDWR or O_WRONLY flags
 *        turned on. Otherwise disallow use of the O_RDWR and O_WRONLY 
 *        flags until the capability of modifying an existing image page 
 *        is provided.
 */

    if (((oflag & (int)O_RDWR) || (oflag & (int)O_WRONLY))
    		&& !(oflag & (int) O_APPEND)) 
    {
        errno = (int) EINVALID_OFLAG;
		return(ErrorNoClose(p_fct));
    }

/* 2. Open the file */

    fct.access_mode = oflag;
    if ((oflag & (int) O_WRONLY) || (oflag & (int) O_APPEND))
    {
         oflag = (int) O_RDWR;
       // DENIES OTHER PROGRAMS WRITE ACCESS TO THE FILE
        oflag |= (int) OF_SHARE_DENY_WRITE;
    }

/*    Not all variations of open() will like oflag containing our OVERRIDE
      value, so we better shut the darn thing off ....  */
    if (oflag & GFS_OVERRIDE)
            oflag &= ~(GFS_OVERRIDE);
/*                oflag &=  NOT_GFS_OVERRIDE; */

/*    NOTE 2: In order to properly support MS-DOS implementations of GFS, we
      need to 'or' in the O_BINARY flag.  In the MS-DOS environment, this
      opens the file in binary (untranslated) mode.  It is necessary to
      set this flag on since MS-DOS will default to O_TEXT which opens the
      file in text (translated) mode which causes control characters to be
      interpeted when the file is read.  Since we can have numerous ASCII
      control sequences in the files we must read, having these sequences
      interpeted WILL prove hazardous to our health.  In non-DOS environs,
      O_BINARY is defined as zero (0) and will have no effect. */

    oflag |= (int) O_BINARY;
    
	/* kjk 07/12/95  If this is an AWD file, we need to handle it 
	                 differently.
	 */
	if (IsAWDFile(path, &bResult) != 0)
	{ //error encountered
		return(ErrorNoClose(p_fct));
	}
	else if (bResult)
	{
		//yes, it's AWD
		#ifndef WITH_AWD
	        errno = EFORMAT_NOTSUPPORTED;
                return(ErrorNoClose(p_fct));
		#else
			fct.format = GFS_AWD;
			fct.fildes = OpenAWDFile(path, oflag, p_fct);
		#endif  //WITH_AWD
	}
	else
	{	//no, it's not AWD
		fct.fildes = open(path, oflag, (int) PMODE);
	}

    if (fct.fildes == (int) -1) 
    {
		return(ErrorNoClose(p_fct));
    }

/*    a.  Store the file size (we'll need this for some (TIFF) file types) */

#if defined(WITH_AWD)
    /* Note that fct.format hasn't been set yet except for AWD! */
    /* Fortunately, that's the only type we can't do lseek() on (below) */
    if (fct.format == GFS_AWD)
      fct.filesize = 1; /* Not needed, and I'm not sure how to get it */
    else
#endif
    { /* Keep this blocked for use w/conditional (preceding) "if" */
     fct.filesize = lseek(fct.fildes,0L,FROM_END);
     if ((int)fct.filesize < 0)
       return(ErrorAndClose(p_fct));
     lseek(fct.fildes,0L,FROM_BEGINNING);
    }

/*    b.  Set number of pages = 0, default type to GFS_MAIN */

    fct.num_pages = (u_short) 0;
    fct.type = (u_long) GFS_MAIN;

/*    c.  Determine the format and set format dependent fields */

    /* if the override bit is set, then user is forcing the format, do not
       look at file to determine the format.  Currently will only support
       GFS_FLAT in this manner, future will support all formats.  Note
       that we're checking against the value of oflag that we moved the
       the fct earlier.  This is because if override was set in oflag
       we turned it off to protect open(). */


    if ((fct.access_mode & GFS_OVERRIDE) == GFS_OVERRIDE) 
    {
    	fct.format = GFS_FLAT;
    } 

	/* 
	 * If we don't already know that we have an AWD file, 
	 *  go figure out what format we have.
	 */
    else if (fct.format != GFS_AWD) 
    {
		if (getfmt(p_fct)) 
		{
			return(ErrorAndClose(p_fct));
		} 
	} /* end: if not AWD */

	/* Since we are opening an existing file, we must preserve the current
	byteorder of the file for any writing we might do to it. If the user
	wishes to change the byteorder (TIFF only), then the gfsopts call
	must be done after gfsopen() or gfscreat().
	*/
	fct.out_byteorder = fct.u.tif.byte_order;

	switch (fct.format)
	{
//#ifdef WITH_XIF
		case GFS_XIF:
			if ((ret_code = OpenXifFile(p_fct)) != 0)
			{
				return(ErrorAndClose(p_fct));
			}
			else
			{
				/* get the number of pages */
				if ((ret_code = GetXifNumPages(p_fct)) != 0)
				{
					return(ErrorAndClose(p_fct));
				}
			}
			break;
//#endif //WITH_XIF

	  	case GFS_AWD:
			/* Parse the AWD file to find all the documents/pages.  
			   ParseAWDFile will allocate an array that holds pairs
			   of document names and number of pages.  A pointer to this
			   array gets put into the fct.  The total number of pages
			   gets calculated and put into fct.num_pages. If an error
			   is encountered, fct.last_errno is set.
			 */
			if (ParseAWDFile(p_fct))
            {
                CloseAWDFile(p_fct);
                fct.fildes = (int) -1;
                ufd = putfct(p_fct);
                if (ufd < 0)
                {
					#ifdef OI_PERFORM_LOG
						RecordIt("GFS", 6, LOG_EXIT, "Exiting gfsopen", NULL);
					#endif
                    return ((int) -1);
                } 
                else 
                {
					#ifdef OI_PERFORM_LOG
						RecordIt("GFS", 6, LOG_EXIT, "Exiting gfsopen", NULL);
					#endif
                    return ((int) (ufd * -1));
                }
            }
			break;

		case GFS_WIFF:
		    if (initroot(p_fct)) 
		   	{
				return(ErrorAndClose(p_fct));
			}
		    if (fillroot(p_fct)) 
		    {
				return(ErrorAndClose(p_fct));
			}
		    break;
#ifndef HVS1
        case GFS_GIF:
        case GFS_PCX:
        case GFS_BMP:
        case GFS_TGA:
        case GFS_JFIF:
            fct.num_pages = 1;
            break;
        case GFS_DCX:
            break;
        case GFS_FREESTYLE:
                break;
        case GFS_FLAT:
                break;
        case GFS_MILSTD:
                break;
        case GFS_TIFF:
            fct.u.tif.toc_offset = (long) 0;
            fct.u.tif.toc2_offset = (long) 0;
            fct.u.tif.cur_ifh_offset = (long) 0;
            
            if (fct.access_mode & (int) O_APPEND)
                fct.u.tif.action = A_APPEND;
            
            if (InitTocOrChain(p_fct))
            {
                fct.last_errno = (int) errno;
                close(fct.fildes);
                fct.fildes = (int) -1;
                /* If the error was WTOC_2MANY_PGS, continue processing 
                   and let the user know about it.
                */
                if (errno == (int) WTOC_2MANY_PGS)
                    break;
                ufd = putfct(p_fct);
                if (ufd < 0)
                {
					#ifdef OI_PERFORM_LOG
						RecordIt("GFS", 6, LOG_EXIT, "Exiting gfsopen", NULL);
					#endif
                    return ((int) -1);
                } 
                else 
                {
					#ifdef OI_PERFORM_LOG
						RecordIt("GFS", 6, LOG_EXIT, "Exiting gfsopen", NULL);
					#endif
                    return ((int) (ufd * -1));
                }
            }
            break;
#endif
        default:
                break;
	} /* end: switch on fct.format */

    *format = fct.format;
    *pgcnt = fct.num_pages;

/* 3. Insert the new entry into the FCT and return the file descriptor */

    if ((ufd = putfct(p_fct)) < 0) 
    {
		#ifdef OI_PERFORM_LOG
			RecordIt("GFS", 6, LOG_EXIT, "Exiting gfsopen", NULL);
		#endif
    	return ( (int) -1 );
    } 
    else 
    {
		#ifdef OI_PERFORM_LOG
			RecordIt("GFS", 6, LOG_EXIT, "Exiting gfsopen", NULL);
		#endif
    	return ( ufd );
    }
}


/***************************
 *  Function:   ErrorNoClose
 *      
 *  Description: processes error from gfsopen without closing the file 
 *  
 *	Returns:	returns the value that should be returned from gfsopen
 ***************************/
int	ErrorNoClose(p_GFCT p_fct)
{
    int     ufd;

	p_fct->last_errno = (int) errno;
    ufd = putfct(p_fct);
    if (ufd < 0) 
    {
		#ifdef OI_PERFORM_LOG
			RecordIt("GFS", 6, LOG_EXIT, "Exiting gfsopen", NULL);
		#endif
        return ( (int) -1);
    } 
    else 
    {
		#ifdef OI_PERFORM_LOG
			RecordIt("GFS", 6, LOG_EXIT, "Exiting gfsopen", NULL);
		#endif
        return ( (int) (ufd * -1));
    }
}

/***************************
 *  Function:   ErrorAndClose
 *      
 *  Description: processes error from gfsopen and closes the file 
 *  
 *	Returns:	returns the value that should be returned from gfsopen
 ***************************/
int	ErrorAndClose(p_GFCT p_fct)
{
    int     ufd;

	p_fct->last_errno = (int) errno;
	(void) close(p_fct->fildes);
	p_fct->fildes = (int) -1;
    ufd = putfct(p_fct);
    if (ufd < 0) 
    {
		#ifdef OI_PERFORM_LOG
			RecordIt("GFS", 6, LOG_EXIT, "Exiting gfsopen", NULL);
		#endif
        return ( (int) -1);
    } 
    else 
    {
		#ifdef OI_PERFORM_LOG
			RecordIt("GFS", 6, LOG_EXIT, "Exiting gfsopen", NULL);
		#endif
        return ( (int) (ufd * -1));
    }
}