2020-09-30 17:12:29 +02:00

882 lines
23 KiB
C

/*
$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));
}
}