/******************************************************************************
*
* NSSDC/CDF CDF `open' operations.
*
* Version 1.4a, 21-Feb-97, Hughes STX.
*
* Modification history:
*
* V1.0 20-May-92, J Love Original version (was part of `cdflib.c').
* V1.1 29-Sep-92, J Love CDF V2.3 (shareable/NeXT/zVar).
* V1.2 25-Jan-94, J Love CDF V2.4.
* V1.3 15-Dec-94, J Love CDF V2.5.
* V1.3a 9-Jan-95, J Love Encode/decode changes, etc.
* V1.3b 24-Feb-95, J Love Solaris 2.3 IDL i/f.
* V1.3c 8-May-95, J Love Only check version/release for FUTURE_CDF.
* V1.3d 7-Sep-95, J Love CDFexport-related changes. Fixed clean up
* when a CDF is aborted.
* V1.4 21-Aug-96, J Love CDF V2.6.
* V1.4a 21-Feb-97, J Love Removed RICE.
* V1.5 21-Jun-04, M Liu Modified the error message for NOT_A_CDF.
* V2.0 29-Jun-04, M Liu Added support for LFS (Large File System >2G).
* V1.7 13-Oct-06, M Liu Changed to allow upper and lower case CDF
* name to be used on win32.
* V3.2 17-Jun-07, D Berger Added setting of Cur->cdf and id prior to calls
* to ReadGDR in support of READONLY perfomance
* improvement changes.
*
******************************************************************************/
#include "cdflib.h"
#include "cdflib64.h"
#include "cdfrev.h"
/******************************************************************************
* CDFope.
******************************************************************************/
STATICforIDL CDFstatus CDFope (Va, Cur)
struct VAstruct *Va;
struct CurStruct *Cur;
{
CDFstatus pStatus = CDF_OK;
switch (Va->item) {
/****************************************************************************
* CDF_, open an existing CDF.
****************************************************************************/
case CDF_: {
char CDFnameT[CDF_PATHNAME_LEN+1], CDFnameX[DU_MAX_PATH_LEN+1];
char CDFnameTx[CDF_PATHNAME_LEN+1];
char *CDFnameP; struct CDFstruct *CDF;
vFILE *dotFp, *uDotFp;
size_t nBytes; int varN; CDFid *id;
Logical upper_case_ext, version_numbers, no_append;
Int32 magicNumber1, magicNumber2, CDRflags, version, release, increment;
Logical largeFile;
/**************************************************************************
* Get arguments for this operation/item.
**************************************************************************/
CDFnameP = va_arg (Va->ap, char *);
id = va_arg (Va->ap, CDFid *);
*id = (CDFid) NULL;
/**************************************************************************
* Validate arguments.
**************************************************************************/
if (strlen(CDFnameP) > (size_t) CDF_PATHNAME_LEN) {
if (!sX(CDF_NAME_TRUNC,&pStatus)) return pStatus;
}
strcpyX (CDFnameT, CDFnameP, CDF_PATHNAME_LEN);
#if STRIP_TRAILING_BLANKS_FROM_CDFPATH
StripTrailingBlanks (CDFnameT);
#endif
#if defined(vms) || defined(dos)
MakeUpperString (CDFnameT);
#endif
RemoveCDFFileExtension(CDFnameT, CDFnameTx);
if (!ValidCDFname(CDFnameTx)) return BAD_CDF_NAME;
if (!sX(FindCDF(CDFnameTx,&no_append,
&upper_case_ext,
&version_numbers),&pStatus)) return pStatus;
/**************************************************************************
* Open CDF file.
**************************************************************************/
BuildFilePath (CDFt, CDFnameTx, no_append, upper_case_ext, version_numbers,
INT32_ZERO, CDFnameX);
if (!sX(CheckLFS(CDFnameX, &largeFile, NULL),&pStatus)) return pStatus;
if (!largeFile)
dotFp = V_open (CDFnameX, READ_ONLY_a_mode);
else
dotFp = V_open64 (CDFnameX, READ_ONLY_a_mode);
if (dotFp == NULL) return CDF_OPEN_ERROR;
/*
if (dotFp->length > 0)
largeFile = FALSE;
else
largeFile = TRUE;
*/
/**************************************************************************
* Read the magic numbers.
**************************************************************************/
if (!largeFile) { /* 32-bit offset file.... */
if (!Read32(dotFp,&magicNumber1)) {
V_close (dotFp, NULL, NULL);
return CDF_READ_ERROR;
}
if (!Read32(dotFp,&magicNumber2)) {
V_close (dotFp, NULL, NULL);
return CDF_READ_ERROR;
}
} else { /* 64-bit offset file.... */
if (!Read32_64(dotFp,&magicNumber1)) {
V_close64 (dotFp, NULL, NULL);
return CDF_READ_ERROR;
}
if (!Read32_64(dotFp,&magicNumber2)) {
V_close64 (dotFp, NULL, NULL);
return CDF_READ_ERROR;
}
}
/**************************************************************************
* Determine what version CDF this is, if it is compressed (and if this is
* actually a CDF).
**************************************************************************/
switch (magicNumber1) {
case V1magicNUMBER_flip:
if (!largeFile)
V_close (dotFp, NULL, NULL);
else
V_close64 (dotFp, NULL, NULL);
return ILLEGAL_ON_V1_CDF;
case V2magicNUMBER_1pre:
uDotFp = NULL;
break;
case V2magicNUMBER_1:
case V3magicNUMBER_1:
switch (magicNumber2) {
case V2magicNUMBER_2u: /* Same as V3magicNUMBER_2u */
/* case V3magicNUMBER_2u: */
if (magicNumber1 == V2magicNUMBER_1) { /* 32-offset */
if (!CACHEv(dotFp,NUMcacheUNKNOWN)) {
V_close (dotFp, NULL, NULL);
return BAD_CACHE_SIZE;
}
} else { /* 64-bit */
if (!CACHEv64(dotFp,NUMcacheUNKNOWN)) {
V_close64 (dotFp, NULL, NULL);
return BAD_CACHE_SIZE;
}
}
uDotFp = NULL;
break;
case V2magicNUMBER_2c:
/* case V3magicNUMBER_2c: */
uDotFp = V_scratch (ScratchDirectory(NULL), "cdf");
if (uDotFp == NULL) {
V_close (dotFp, NULL, NULL);
return CDF_CREATE_ERROR;
}
if (magicNumber1 == V2magicNUMBER_1) {
if (!CACHEv(uDotFp,NUMcacheUNKNOWN)) {
V_close (dotFp, NULL, NULL);
V_delete (uDotFp, NULL);
return BAD_CACHE_SIZE;
}
if (!sX(DecompressCDF(dotFp,uDotFp),&pStatus)) {
V_close (dotFp, NULL, NULL);
V_delete (uDotFp, NULL);
return pStatus;
}
} else {
if (!CACHEv64(uDotFp,NUMcacheUNKNOWN)) {
V_close64 (dotFp, NULL, NULL);
V_delete64 (uDotFp, NULL);
return BAD_CACHE_SIZE;
}
if (!sX(DecompressCDF64(dotFp,uDotFp),&pStatus)) {
V_close64 (dotFp, NULL, NULL);
V_delete64 (uDotFp, NULL);
return pStatus;
}
}
break;
default:
if (!largeFile)
V_close (dotFp, NULL, NULL);
else
V_close64 (dotFp, NULL, NULL);
return NOT_A_CDF;
}
break;
default:
if (!largeFile)
V_close (dotFp, NULL, NULL);
else
V_close64 (dotFp, NULL, NULL);
return NOT_A_CDF_OR_NOT_SUPPORTED;
}
/**************************************************************************
* Allocate and begin initializing CDF structure.
**************************************************************************/
CDF = (struct CDFstruct *) cdf_AllocateMemory (sizeof(struct CDFstruct), NULL);
if (CDF == NULL) {
if (!largeFile) {
V_close (dotFp, NULL, NULL);
if (uDotFp != NULL) V_delete (uDotFp, NULL);
} else {
V_close64 (dotFp, NULL, NULL);
if (uDotFp != NULL) V_delete64 (uDotFp, NULL);
}
return BAD_MALLOC;
}
CDF->CDFname = (char *) cdf_AllocateMemory (strlen(CDFnameTx) + 1, NULL);
if (CDF->CDFname == NULL) {
if (!largeFile) {
V_close (dotFp, NULL, NULL);
if (uDotFp != NULL) V_delete (uDotFp, NULL);
} else {
V_close64 (dotFp, NULL, NULL);
if (uDotFp != NULL) V_delete64 (uDotFp, NULL);
}
cdf_FreeMemory (CDF, NULL);
return BAD_MALLOC;
}
else
strcpyX (CDF->CDFname, CDFnameTx, 0);
CDF->magic = VALIDid_MAGIC_NUMBER;
CDF->largeFile = largeFile;
CDF->dotFp = dotFp;
CDF->uDotFp = uDotFp;
CDF->fp = BOO(uDotFp == NULL,dotFp,uDotFp);
CDF->no_append = no_append;
CDF->upper_case_ext = upper_case_ext;
CDF->version_numbers = version_numbers;
CDF->decoding = HOST_DECODING;
CDF->readOnly = FALSE;
CDF->zMode = zMODEoff;
CDF->negToPosFp0 = FALSE;
CDF->status = READ_ONLY;
CDF->pseudo_clock = 0;
CDF->stage.fp = NULL;
CDF->stage.mark = ZERO_OFFSET;
CDF->stage.mark64 = (OFF_T) ZERO_OFFSET64;
CDF->stage.cacheSize = NUMcacheSTAGE;
CDF->compressCacheSize = NUMcacheCOMPRESS;
CDF->compressFp = NULL;
CDF->scratchDir = NULL;
CDF->NrVars = 0; /* Updated below if the read is OK. */
CDF->NzVars = 0; /* Updated below if the read is OK. */
CDF->rVars = NULL;
CDF->zVars = NULL;
CDF->CURzVarNum = RESERVED_VARNUM;
CDF->CURrVarNum = RESERVED_VARNUM;
CDF->CURzVarOffset = 0;
CDF->CURzVarOffset64 = (OFF_T) 0;
CDF->CURrVarOffset = 0;
CDF->CURrVarOffset64 = (OFF_T) 0;
/**************************************************************************
* Read necessary fields from the CDR and GDR.
**************************************************************************/
if (!largeFile) {
CDF->CDRoffset = V2_CDR_OFFSET;
if (!sX(ReadCDR(CDF->fp,CDF->CDRoffset,
CDR_GDROFFSET,&(CDF->GDRoffset),
CDR_ENCODING,&(CDF->encoding),
CDR_FLAGS,&CDRflags,
CDR_VERSION,&version,
CDR_RELEASE,&release,
CDR_INCREMENT,&increment,
CDR_NULL),&pStatus)) {
AbortAccess (CDF, noUPDATE, noDELETE);
cdf_FreeMemory (CDF, NULL);
return pStatus;
}
/************************************************************************
* Set state info for use in ReadGDR - required by changes to support
* READONLY performance enhancement.
***********************************************************************/
Cur->cdf = CDF;
*id = CDF;
if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
GDR_NrVARS,&(CDF->NrVars),
GDR_NzVARS,&(CDF->NzVars),
GDR_rMAXREC,&(CDF->rMaxRec),
GDR_rNUMDIMS,&(CDF->rNumDims),
GDR_rDIMSIZES,CDF->rDimSizes,
GDR_NULL),&pStatus)) {
AbortAccess (CDF, noUPDATE, noDELETE);
cdf_FreeMemory (CDF, NULL);
Cur->cdf = NULL;
*id = (CDFid) NULL;
return pStatus;
}
} else {
/************************************************************************
* Set state info for use in ReadGDR - required by changes to support
* READONLY performance enhancement.
***********************************************************************/
Cur->cdf = CDF;
*id = CDF;
CDF->CDRoffset64 = (OFF_T) V3_CDR_OFFSET64;
if (!sX(ReadCDR64(CDF->fp,CDF->CDRoffset64,
CDR_GDROFFSET,&(CDF->GDRoffset64),
CDR_ENCODING,&(CDF->encoding),
CDR_FLAGS,&CDRflags,
CDR_VERSION,&version,
CDR_RELEASE,&release,
CDR_INCREMENT,&increment,
CDR_NULL),&pStatus)) {
AbortAccess (CDF, noUPDATE, noDELETE);
cdf_FreeMemory (CDF, NULL);
Cur->cdf = NULL;
*id = (CDFid) NULL;
return pStatus;
}
/************************************************************************
* Set state info for use in ReadGDR - required by changes to support
* READONLY performance enhancement.
***********************************************************************/
Cur->cdf = CDF;
*id = CDF;
if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64,
GDR_NrVARS,&(CDF->NrVars),
GDR_NzVARS,&(CDF->NzVars),
GDR_rMAXREC,&(CDF->rMaxRec),
GDR_rNUMDIMS,&(CDF->rNumDims),
GDR_rDIMSIZES,CDF->rDimSizes,
GDR_NULL),&pStatus)) {
AbortAccess (CDF, noUPDATE, noDELETE);
cdf_FreeMemory (CDF, NULL);
Cur->cdf = NULL;
*id = (CDFid) NULL;
return pStatus;
}
}
/**************************************************************************
* Continue initializing CDF structure.
**************************************************************************/
CDF->singleFile = SINGLEfileBITset (CDRflags);
CDF->rowMajor = ROWmajorBITset (CDRflags);
CDF->checksum = (PriorTo("3.2.0",version,release,increment) ?
NO_CHECKSUM : ChecksumMethod (CDRflags));
CDF->fakeEPOCH = PriorTo("2.1.1",version,release,increment);
CDF->wastedSpace = PriorTo("2.5",version,release,increment);
CDF->badEOF = PriorTo("2.1",version,release,increment);
CDF->badTerminatingOffsets = PriorTo("2.1",version,release,increment);
CDF->assumedScopes = PriorTo("2.5",version,release,increment);
CDF->workingCacheSize = BOO(CDF->singleFile,NUMcacheSINGLE,NUMcacheMULTI);
/**************************************************************************
* Set the cache size for the "working" dotCDF file based on the format
* of the CDF.
**************************************************************************/
if (!largeFile) {
if (!CACHEv(CDF->fp,CDF->workingCacheSize)) {
AbortAccess (CDF, noUPDATE, noDELETE);
cdf_FreeMemory (CDF, NULL);
return BAD_CACHE_SIZE;
}
} else {
if (!CACHEv64(CDF->fp,CDF->workingCacheSize)) {
AbortAccess (CDF, noUPDATE, noDELETE);
cdf_FreeMemory (CDF, NULL);
return BAD_CACHE_SIZE;
}
}
/**************************************************************************
* Allocate and initialize variable data structures kept in memory.
**************************************************************************/
if (CDF->NrVars > 0) {
nBytes = (size_t) (CDF->NrVars * sizeof(struct VarStruct *));
CDF->rVars = (struct VarStruct **) cdf_AllocateMemory (nBytes, NULL);
if (CDF->rVars == NULL) {
AbortAccess (CDF, noUPDATE, noDELETE);
cdf_FreeMemory (CDF, NULL);
return BAD_MALLOC;
}
for (varN = 0; varN < CDF->NrVars; varN++) CDF->rVars[varN] = NULL;
CDF->MAXrVars = (int) CDF->NrVars;
}
else {
CDF->rVars = NULL;
CDF->MAXrVars = 0;
}
if (CDF->NzVars > 0) {
nBytes = (size_t) (CDF->NzVars * sizeof(struct VarStruct *));
CDF->zVars = (struct VarStruct **) cdf_AllocateMemory (nBytes, NULL);
if (CDF->zVars == NULL) {
AbortAccess (CDF, noUPDATE, noDELETE);
cdf_FreeMemory (CDF, NULL);
return BAD_MALLOC;
}
for (varN = 0; varN < CDF->NzVars; varN++) CDF->zVars[varN] = NULL;
CDF->MAXzVars = (int) CDF->NzVars;
}
else {
CDF->zVars = NULL;
CDF->MAXzVars = 0;
}
/**************************************************************************
* If this is a multi-file CDF and a CDF pathname that doesn't require file
* extensions to be appended was specified (ie. a weird naming convention),
* close/free the CDF and return an error. This is because the extensions
* for the variable files would be known only to the user. We'd rather not
* guess.
**************************************************************************/
if (!CDF->singleFile && CDF->no_append) {
AbortAccess (CDF, noUPDATE, noDELETE);
cdf_FreeMemory (CDF, NULL);
return BAD_CDF_EXTENSION;
}
/**************************************************************************
* Initialize the current objects/states and the Vstream statistics.
**************************************************************************/
InitCURobjectsStates (CDF);
AddTOvStats (&CDF->dotCDFvStats, NULL);
AddTOvStats (&CDF->uDotCDFvStats, NULL);
/**************************************************************************
* Select the current CDF and pass back the CDF identifier.
**************************************************************************/
Cur->cdf = CDF;
*id = CDF;
if (CDF->singleFile && CDF->checksum != NO_CHECKSUM) {
if (!sX(CDFconfirmChecksum(*id),&pStatus)) return pStatus;
/*
} else {
int ev = CDFgetChecksumEnvVar();
if (CDF->checksum == NO_CHECKSUM && ev > 0) {
if (!sX(CDFsetChecksum(*id, (long) ev),&pStatus)) return pStatus;
}
*/
}
break;
}
/****************************************************************************
* Unknown item, must be the next function.
****************************************************************************/
default: {
Va->fnc = Va->item;
break;
}
}
return pStatus;
}
syntax highlighted by Code2HTML, v. 0.9.1