/******************************************************************************
*
* NSSDC/CDF CDF `put' operations, part 2.
*
* 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 16-Sep-92, J Love CDF V2.3 (shareable/NeXT/zVar).
* V1.2 24-Jan-94, J Love CDF V2.4.
* V1.3 5-Dec-94, J Love CDF V2.5.
* V1.3a 6-Jan-95, J Love Encode/decode changes. More cache-residency.
* V1.3b 24-Feb-95, J Love Solaris 2.3 IDL i/f.
* V1.3c 4-Aug-95, J Love CDFexport-related changes.
* V1.4 3-Oct-96, J Love CDF V2.6.
* V1.4a 21-Feb-97, J Love Removed RICE.
* V2.0 08-Apr-04, M Liu Removed calls to LocateCurrentVar function as
* its offset becomes available when it is
* selected/created.
* V2.1 29-Jun-04, M Liu Added LFS (Large File Support > 2G).
* V2.2 16-Nov-05, M Liu Changed code for data spec modification. -99
* is passed as a special indicator for the
* number of elements as it can't be change.
*
******************************************************************************/
#include "cdflib.h"
#include "cdflib64.h"
/******************************************************************************
* CDFput2_64.
******************************************************************************/
STATICforIDL CDFstatus CDFput2_64 (Va, Cur)
struct VAstruct *Va;
struct CurStruct *Cur;
{
CDFstatus tStatus, pStatus = CDF_OK;
switch (Va->item) {
/****************************************************************************
* CDF_ENCODING_,
* Can't change if any variables have been written to (including pad
* values). Can't change if any attribute entries have been written.
****************************************************************************/
case CDF_ENCODING_: {
struct CDFstruct *CDF;
Int32 actualEncoding;
Int32 encoding = (Int32) va_arg (Va->ap, long);
Logical no;
SelectCDF (Cur->cdf, CDF)
if (!ValidEncoding(encoding,&actualEncoding)) return BAD_ENCODING;
if (!sX(VerifyNoRecordsWritten64(CDF,&no),&pStatus)) return pStatus;
if (!no) return CANNOT_CHANGE;
if (!sX(VerifyNoPadsSpecified64(CDF,&no),&pStatus)) return pStatus;
if (!no) return CANNOT_CHANGE;
if (!sX(VerifyNoEntriesWritten64(CDF,&no),&pStatus)) return pStatus;
if (!no) return CANNOT_CHANGE;
if (!WriteAccess64(CDF,FALSE,&pStatus)) return pStatus;
CDF->encoding = actualEncoding;
/**************************************************************************
* Update the `encoding' field in the CDR.
**************************************************************************/
if (!sX(WriteCDR64(CDF->fp,V3_CDR_OFFSET64,
CDR_ENCODING,&(CDF->encoding),
CDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
/**************************************************************************
* Update the initialized variables for the new encoding.
**************************************************************************/
if (!sX(UpdateConversions64(CDF),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
break;
}
/****************************************************************************
* CDF_MAJORITY_,
* Can't change if any variable values have been written.
****************************************************************************/
case CDF_MAJORITY_: {
struct CDFstruct *CDF;
long majority = va_arg (Va->ap,long);
Logical no, zVar; Int32 CDRflags;
SelectCDF (Cur->cdf, CDF)
if (majority != ROW_MAJOR && majority != COLUMN_MAJOR) return BAD_MAJORITY;
if (!sX(VerifyNoRecordsWritten64(CDF,&no),&pStatus)) return pStatus;
if (!no) return CANNOT_CHANGE;
if (!WriteAccess64(CDF,FALSE,&pStatus)) return pStatus;
CDF->rowMajor = ROWmajor(majority);
/**************************************************************************
* Update the `flags' field in the CDR.
**************************************************************************/
if (!sX(ReadCDR64(CDF->fp,CDF->CDRoffset64,
CDR_FLAGS,&CDRflags,
CDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
if (CDF->rowMajor)
SetBit32 (&CDRflags, CDR_MAJORITY_BIT);
else
ClearBit32 (&CDRflags, CDR_MAJORITY_BIT);
if (!sX(WriteCDR64(CDF->fp,V3_CDR_OFFSET64,
CDR_FLAGS,&CDRflags,
CDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
/**************************************************************************
* Update the initialized variables for the new majority.
**************************************************************************/
for (zVar = 0; zVar <= 1; zVar++) {
int varN; Int32 nVars = BOO(zVar,CDF->NzVars,CDF->NrVars);
for (varN = 0; varN < nVars; varN++) {
struct VarStruct *Var = BOO(zVar,CDF->zVars[varN],CDF->rVars[varN]);
if (Var != NULL) CalcNumDimValues (CDF, Var);
}
}
break;
}
/****************************************************************************
* CDF_FORMAT_,
* Can't change if any variables have been created or if a compressed
* single-file CDF.
****************************************************************************/
case CDF_FORMAT_: {
long format = va_arg (Va->ap,long);
struct CDFstruct *CDF; Int32 CDRflags;
SelectCDF (Cur->cdf, CDF)
if (format != SINGLE_FILE && format != MULTI_FILE) return BAD_FORMAT;
if (CDF->NrVars > 0) return CANNOT_CHANGE;
if (CDF->NzVars > 0) return CANNOT_CHANGE;
if (CDF->uDotFp != NULL) return CANNOT_CHANGE;
if (!WriteAccess64(CDF,FALSE,&pStatus)) return pStatus;
if (format == MULTI_FILE && CDF->checksum != NO_CHECKSUM)
return CANNOT_CHANGE;
CDF->singleFile = (format == SINGLE_FILE);
/**************************************************************************
* Update the `flags' field in the CDR.
**************************************************************************/
if (!sX(ReadCDR64(CDF->fp,CDF->CDRoffset64,
CDR_FLAGS,&CDRflags,
CDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
if (CDF->singleFile)
SetBit32 (&CDRflags, CDR_FORMAT_BIT);
else
ClearBit32 (&CDRflags, CDR_FORMAT_BIT);
if (!sX(WriteCDR64(CDF->fp,V3_CDR_OFFSET64,
CDR_FLAGS,&CDRflags,
CDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
/**************************************************************************
* Reset cache size for "working" dotCDF file to the default for the CDF's
* format.
**************************************************************************/
CDF->workingCacheSize = BOO(CDF->singleFile,NUMcacheSINGLE,NUMcacheMULTI);
if (!CACHEv64(CDF->fp,CDF->workingCacheSize)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return BAD_CACHE_SIZE;
}
break;
}
/****************************************************************************
* CDF_COMPRESSION_
****************************************************************************/
case CDF_COMPRESSION_: {
long cType = va_arg (Va->ap, long); /* Compression type. */
long *cParms = va_arg (Va->ap, long *); /* Compression parameters. */
struct CDFstruct *CDF; int parmN; vSTATS vStats;
SelectCDF (Cur->cdf, CDF)
/**************************************************************************
* Validate compression type/parameters.
**************************************************************************/
if (!sX(ValidateCompression64(cType,cParms),&pStatus)) return pStatus;
/**************************************************************************
* Verify that compression is not being attempted on a multi-file CDF. (It
* is allowed to specify no compression.)
**************************************************************************/
if (!CDF->singleFile) {
if (cType != NO_COMPRESSION) return CANNOT_COMPRESS;
break;
}
/**************************************************************************
* Depending on the type of compression...
**************************************************************************/
switch (cType) {
/************************************************************************
* Turning off compression.
************************************************************************/
case NO_COMPRESSION:
/**********************************************************************
* If the CDF is currently compressed...
**********************************************************************/
if (CDF->uDotFp != NULL) {
char pathName[DU_MAX_PATH_LEN+1];
/********************************************************************
* First get write access.
********************************************************************/
if (!WriteAccess64(CDF,FALSE,&pStatus)) return pStatus;
/********************************************************************
* Delete the compressed dotCDF file.
********************************************************************/
if (!DELETEv64(CDF->dotFp,&vStats)) {
CDF->dotFp = NULL;
AbortAccess64 (CDF, UPDATE, noDELETE);
return CDF_CLOSE_ERROR;
}
CDF->dotFp = NULL;
AddTOvStats (&CDF->dotCDFvStats, &vStats);
#if defined(DEBUG)
DisplayVs (getenv("VSTREAM_STATS"), "DotCDF..", &vStats);
#endif
/********************************************************************
* Recreate the dotCDF file (now uncompressed) and set its cache size
* to that of the "working" dotCDF file (which it now has become).
********************************************************************/
BuildFilePath (CDFt, CDF->CDFname, CDF->no_append,
CDF->upper_case_ext, CDF->version_numbers,
INT32_ZERO, pathName);
CDF->dotFp = V_open64 (pathName, WRITE_PLUS_a_mode);
if (CDF->dotFp == NULL) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return CDF_CREATE_ERROR;
}
if (!CACHEv64(CDF->dotFp,CDF->workingCacheSize)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return BAD_CACHE_SIZE;
}
/********************************************************************
* Copy the uncompressed dotCDF file to the recreated dotCDF file.
********************************************************************/
if (!sX(CopyCDF64(CDF->uDotFp,CDF->dotFp),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
/********************************************************************
* Flush the recreated dotCDF file.
********************************************************************/
if (!FLUSHv64(CDF->dotFp)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return CDF_WRITE_ERROR;
}
/********************************************************************
* Delete the uncompressed dotCDF file.
********************************************************************/
if (!DELETEv64(CDF->uDotFp,&vStats)) {
CDF->uDotFp = NULL;
AbortAccess64 (CDF, UPDATE, noDELETE);
return SCRATCH_DELETE_ERROR;
}
CDF->uDotFp = NULL;
AddTOvStats (&CDF->uDotCDFvStats, &vStats);
#if defined(DEBUG)
DisplayVs (getenv("VSTREAM_STATS"), "uDotCDF.", &vStats);
#endif
/********************************************************************
* Reset the "working" dotCDF file.
********************************************************************/
CDF->fp = CDF->dotFp;
}
break;
/************************************************************************
* Turning on/changing compression.
************************************************************************/
case RLE_COMPRESSION:
case HUFF_COMPRESSION:
case AHUFF_COMPRESSION:
case GZIP_COMPRESSION: {
/*
case ZLIB_COMPRESSION: {
*/
char pathName[DU_MAX_PATH_LEN+1]; struct CPRstruct64 CPR; Int32 pCount;
/**********************************************************************
* Get read/write access.
**********************************************************************/
if (!WriteAccess64(CDF,FALSE,&pStatus)) return pStatus;
/**********************************************************************
* If the CDF is not currently compressed, create an uncompressed dotCDF
* file and copy the current contents into it.
**********************************************************************/
if (CDF->uDotFp == NULL) {
CDF->uDotFp = V_scratch (ScratchDirectory(CDF), "cdf");
if (CDF->uDotFp == NULL) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return CDF_CREATE_ERROR;
}
if (!CACHEv64(CDF->uDotFp,CDF->workingCacheSize)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return BAD_CACHE_SIZE;
}
if (!sX(CopyCDF64(CDF->dotFp,CDF->uDotFp),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
if (!FLUSHv64(CDF->uDotFp)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return CDF_WRITE_ERROR;
}
CDF->fp = CDF->uDotFp;
}
/**********************************************************************
* Delete/recreate the dotCDF file and write a CCR and CPR.
**********************************************************************/
if (!DELETEv64(CDF->dotFp,&vStats)) {
CDF->dotFp = NULL;
AbortAccess64 (CDF, UPDATE, noDELETE);
return CDF_DELETE_ERROR;
}
CDF->dotFp = NULL;
AddTOvStats (&CDF->dotCDFvStats, &vStats);
#if defined(DEBUG)
DisplayVs (getenv("VSTREAM_STATS"), "DotCDF..", &vStats);
#endif
BuildFilePath (CDFt, CDF->CDFname, CDF->no_append,
CDF->upper_case_ext, CDF->version_numbers,
INT32_ZERO, pathName);
CDF->dotFp = V_open64 (pathName, WRITE_PLUS_a_mode);
if (CDF->dotFp == NULL) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return CDF_CREATE_ERROR;
}
pCount = CompressionParmsCount ((Int32) cType);
CPR.RecordSize = CPR_BASE_SIZE64 + (pCount * sizeof(Int32));
CPR.RecordType = CPR_;
CPR.rfuA = 0;
CPR.cType = (Int32) cType;
CPR.pCount = pCount;
for (parmN = 0; parmN < pCount; parmN++) {
CPR.cParms[parmN] = (Int32) cParms[parmN];
}
if (!sX(WriteCompressedCDF64(CDF,&CPR,EMPTY),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
if (!FLUSHv64(CDF->dotFp)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return CDF_WRITE_ERROR;
}
break;
}
}
break;
}
/****************************************************************************
* r/zVAR_COMPRESSION_
****************************************************************************/
case rVAR_COMPRESSION_:
case zVAR_COMPRESSION_: {
Logical zOp = (Va->item == zVAR_COMPRESSION_), zVar;
Int32 maxAllocated, pCount; int p; OFF_T VDRoffset;
struct CDFstruct *CDF; struct VarStruct *Var;
struct VDRstruct64 VDR; struct CPRstruct64 CPR;
long cType = va_arg (Va->ap, long); /* Compression type. */
long *cParms = va_arg (Va->ap, long *); /* Compression parameters. */
/**************************************************************************
* Verify the current CDF and variable and that this operation is legal for
* the current zMode.
**************************************************************************/
SelectCDF (Cur->cdf, CDF)
if (BADzOP(CDF,!zOp)) return ILLEGAL_IN_zMODE;
if (!CURRENTvarSELECTED(CDF,zOp)) return NO_VAR_SELECTED;
/**************************************************************************
* Validate compression type/parameters.
**************************************************************************/
if (!sX(ValidateCompression64(cType,cParms),&pStatus)) return pStatus;
/**************************************************************************
* Get write access.
**************************************************************************/
if (!WriteAccess64(CDF,FALSE,&pStatus)) return pStatus;
/**************************************************************************
* Verify that compression isn't being attempted on a multi-file CDF. (It
* is allowed to specify no compression.) After this point a single-file
* CDF can be assumed.
**************************************************************************/
if (!CDF->singleFile) {
if (cType != NO_COMPRESSION) return CANNOT_COMPRESS;
break;
}
/**************************************************************************
* Locate the current variable.
**************************************************************************/
zVar = CurrentVarMode(CDF,zOp);
if (zModeON(CDF) || zVar) VDRoffset = CDF->CURzVarOffset64;
else VDRoffset = CDF->CURrVarOffset64;
if (zModeON(CDF))
if (CDF->CURzVarNum < CDF->NrVars)
Var = CDF->rVars[(int)CDF->CURzVarNum];
else
Var = CDF->zVars[(int)(CDF->CURzVarNum - CDF->NrVars)];
else
Var = BOO(zOp,CDF->zVars[(int)CDF->CURzVarNum],
CDF->rVars[(int)CDF->CURrVarNum]);
/**************************************************************************
* Read VDR.
**************************************************************************/
if (!sX(ReadVDR64(CDF,CDF->fp,VDRoffset,zVar,
VDR_RECORD,&VDR,NULL,
VDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
/**************************************************************************
* Verify that no records have been written or allocated. If so, the
* compression cannot be changed.
**************************************************************************/
if (!sX(LastRecord64(CDF,VDRoffset,zVar,&maxAllocated),&pStatus)){
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
if (maxAllocated > NO_RECORD) return CANNOT_COMPRESS;
if (VDR.MaxRec > NO_RECORD) return CANNOT_COMPRESS;
/**************************************************************************
* If array sparseness is selected, then the variable cannot be compressed.
**************************************************************************/
if (SPARSEarraysBITset(VDR.Flags)) {
if (cType != NO_COMPRESSION) return CANNOT_COMPRESS;
}
/**************************************************************************
* Disable current compression (if any).
**************************************************************************/
if (VARcompressionBITset(VDR.Flags)) {
ClearBit32 (&VDR.Flags, VDR_COMPRESSION_BIT);
if (!sX(ReadCPR64(CDF->fp,VDR.CPRorSPRoffset,
CPR_RECORD,&CPR,
CPR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
if (!sX(WasteIR64(CDF,VDR.CPRorSPRoffset,CPR.RecordSize),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
VDR.CPRorSPRoffset = (OFF_T) NO_OFFSET64;
}
/**************************************************************************
* Set up new compression.
**************************************************************************/
switch (cType) {
case NO_COMPRESSION:
break;
case RLE_COMPRESSION:
case HUFF_COMPRESSION:
case AHUFF_COMPRESSION:
case GZIP_COMPRESSION:
/*
case ZLIB_COMPRESSION:
*/
pCount = CompressionParmsCount ((Int32) cType);
SetBit32 (&VDR.Flags, VDR_COMPRESSION_BIT);
CPR.RecordSize = CPR_BASE_SIZE64 + (pCount * sizeof(Int32));
CPR.RecordType = CPR_;
CPR.cType = (Int32) cType;
CPR.rfuA = 0;
CPR.pCount = pCount;
for (p = 0; p < pCount; p++) CPR.cParms[p] = (Int32) cParms[p];
if (!sX(AllocateIR64(CDF,CPR.RecordSize,&VDR.CPRorSPRoffset),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
if (!sX(WriteCPR64(CDF->fp,VDR.CPRorSPRoffset,
CPR_RECORD,&CPR,
CPR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
break;
}
/**************************************************************************
* Update VDR.
**************************************************************************/
if (!sX(WriteVDR64(CDF,CDF->fp,VDRoffset,zVar,
VDR_RECORD,&VDR,NULL,
VDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
/**************************************************************************
* If this variable has been initialized, recalculate the affected
* parameters.
**************************************************************************/
if (Var != NULL) {
if (!sX(VariableType64(CDF,VDRoffset,zVar,&(Var->vType)),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
if (cType != NO_COMPRESSION) {
Var->cType = (Int32) cType;
for (p = 0; p < pCount; p++) Var->cParms[p] = (Int32) cParms[p];
Var->reservePct = 0;
}
if (!sX(CalcBF64(CDF,Var),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
}
break;
}
/****************************************************************************
* CDF_CHECKSUM_,
****************************************************************************/
case CDF_CHECKSUM_: {
long checksumValue = va_arg (Va->ap, long);
long version, release;
struct CDFstruct *CDF; Int32 CDRflags;
SelectCDF (Cur->cdf, CDF)
if (!CDF->singleFile) return CANNOT_CHANGE;
if (checksumValue != NONE_CHECKSUM &&
checksumValue != MD5_CHECKSUM &&
checksumValue != OTHER_CHECKSUM) return BAD_CHECKSUM;
/**************************************************************************
* Update the `flags' field in the CDR.
**************************************************************************/
if (!sX(ReadCDR64(CDF->fp,CDF->CDRoffset64,
CDR_VERSION,&version,
CDR_RELEASE,&release,
CDR_FLAGS,&CDRflags,
CDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
/**************************************************************************
* Only apply to Version 2.6 and later CDFs.
**************************************************************************/
if ((version*10+release) < 26) return pStatus;
/**************************************************************************
* Get write access.
**************************************************************************/
if (!WriteAccess64(CDF,FALSE,&pStatus)) return pStatus;
if (checksumValue == NONE_CHECKSUM) {
ClearBit32 (&CDRflags, CDR_CHECKSUM_BIT);
ClearBit32 (&CDRflags, CDR_CHECKSUM_MD5_BIT);
ClearBit32 (&CDRflags, CDR_CHECKSUM_OTHER_BIT);
} else {
SetBit32 (&CDRflags, CDR_CHECKSUM_BIT);
if (checksumValue == MD5_CHECKSUM) {
SetBit32 (&CDRflags, CDR_CHECKSUM_MD5_BIT);
ClearBit32 (&CDRflags, CDR_CHECKSUM_OTHER_BIT);
} else {
ClearBit32 (&CDRflags, CDR_CHECKSUM_MD5_BIT);
SetBit32 (&CDRflags, CDR_CHECKSUM_OTHER_BIT);
}
}
if (!sX(WriteCDR64(CDF->fp,CDF->CDRoffset64,
CDR_FLAGS,&CDRflags,
CDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
CDF->checksum = checksumValue;
break;
}
/****************************************************************************
* r/zVAR_SPARSERECORDS_
****************************************************************************/
case rVAR_SPARSERECORDS_:
case zVAR_SPARSERECORDS_: {
Logical zOp = (Va->item == zVAR_SPARSERECORDS_), zVar;
Int32 maxAllocated, maxRec; OFF_T VDRoffset;
struct CDFstruct *CDF; struct VarStruct *Var;
Int32 sRecordsType = (Int32) va_arg (Va->ap, long);
/**************************************************************************
* Verify the current CDF and variable and that this operation is legal for
* the current zMode.
**************************************************************************/
SelectCDF (Cur->cdf, CDF)
if (BADzOP(CDF,!zOp)) return ILLEGAL_IN_zMODE;
if (!CURRENTvarSELECTED(CDF,zOp)) return NO_VAR_SELECTED;
/**************************************************************************
* Get write access.
**************************************************************************/
if (!WriteAccess64(CDF,FALSE,&pStatus)) return pStatus;
/**************************************************************************
* Verify that sparseness isn't being attempted on a multi-file CDF. (It
* is allowed to specify sRecords.NO.) After this point a single-file CDF
* can be assumed.
**************************************************************************/
if (!CDF->singleFile) {
if (sRecordsType != NO_SPARSERECORDS) return CANNOT_SPARSERECORDS;
break;
}
/**************************************************************************
* Locate the current variable.
**************************************************************************/
zVar = CurrentVarMode(CDF,zOp);
if (zModeON(CDF) || zVar) VDRoffset = CDF->CURzVarOffset64;
else VDRoffset = CDF->CURrVarOffset64;
if (zModeON(CDF))
if (CDF->CURzVarNum < CDF->NrVars)
Var = CDF->rVars[(int)CDF->CURzVarNum];
else
Var = CDF->zVars[(int)(CDF->CURzVarNum - CDF->NrVars)];
else
Var = BOO(zOp,CDF->zVars[(int)CDF->CURzVarNum],
CDF->rVars[(int)CDF->CURrVarNum]);
/**************************************************************************
* Verify that no records have been written or allocated. If so, the
* sparseness cannot be changed.
**************************************************************************/
if (!sX(ReadVDR64(CDF,CDF->fp,VDRoffset,zVar,
VDR_MAXREC,&maxRec,
VDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
if (maxRec > NO_RECORD) return CANNOT_SPARSERECORDS;
if (!sX(LastRecord64(CDF,VDRoffset,zVar,&maxAllocated),&pStatus)){
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
if (maxAllocated > NO_RECORD) return CANNOT_SPARSERECORDS;
/**************************************************************************
* Based on type of sparseness...
**************************************************************************/
switch (sRecordsType) {
case NO_SPARSERECORDS:
case PAD_SPARSERECORDS:
case PREV_SPARSERECORDS:
if (!sX(WriteVDR64(CDF,CDF->fp,VDRoffset,zVar,
VDR_sRECORDS,&sRecordsType,
VDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
break;
default:
return UNKNOWN_SPARSENESS;
}
/**************************************************************************
* If this variable has been initialized, recalculate the affected
* parameters.
**************************************************************************/
if (Var != NULL) {
if (!sX(VariableType64(CDF,VDRoffset,zVar,&(Var->vType)),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
Var->prevIfMissing = (sRecordsType == PREV_SPARSERECORDS);
}
break;
}
/****************************************************************************
* r/zVAR_SPARSEARRAYS_
****************************************************************************/
case rVAR_SPARSEARRAYS_:
case zVAR_SPARSEARRAYS_: {
Logical zOp = (Va->item == zVAR_SPARSEARRAYS_);
struct CDFstruct *CDF;
long sArraysType = va_arg (Va->ap, long); /* Sparseness type. */
(void) va_arg (Va->ap, long *); /* Doing it this way quiets
the Borland C compiler. */
/**************************************************************************
* Verify the current CDF and variable and that this operation is legal for
* the current zMode.
**************************************************************************/
SelectCDF (Cur->cdf, CDF)
if (BADzOP(CDF,!zOp)) return ILLEGAL_IN_zMODE;
if (!CURRENTvarSELECTED(CDF,zOp)) return NO_VAR_SELECTED;
/**************************************************************************
* Verify that sparse arrays aren't being attempted on a multi-file CDF.
* (It is allowed to specify no sparse arrays.)
**************************************************************************/
if (!CDF->singleFile) {
if (sArraysType != NO_SPARSEARRAYS) return CANNOT_SPARSEARRAYS;
break;
}
/**************************************************************************
* Sparse arrays are not yet supported.
**************************************************************************/
switch (sArraysType) {
case NO_SPARSEARRAYS:
/* Nothing needs to be done until sparse arrays are supported. */
break;
default:
return UNKNOWN_SPARSENESS;
}
break;
}
/****************************************************************************
* ATTR_NAME_,
****************************************************************************/
case ATTR_NAME_: {
struct CDFstruct *CDF;
char tmpname[CDF_ATTR_NAME_LEN256+1];
char *attrname = va_arg (Va->ap, char *);
OFF_T offsetFound;
SelectCDF (Cur->cdf, CDF)
if (!CURRENTattrSELECTED64(CDF)) return NO_ATTR_SELECTED;
if (strlen(attrname) > (size_t) CDF_ATTR_NAME_LEN256) {
if (!sX(ATTR_NAME_TRUNC,&pStatus)) return pStatus;
}
strcpyX (tmpname, attrname, CDF_ATTR_NAME_LEN256);
if (!ValidAttrName(tmpname)) return BAD_ATTR_NAME;
/**************************************************************************
* Check that the new attribute name is not already in use. Don't flag as
* an error if the new name is the same as the old name (ignoring trailing
* blanks). Trailing blanks may be being eliminated.
**************************************************************************/
tStatus = FindAttrByName64 (CDF, tmpname, &offsetFound);
switch (tStatus) {
case CDF_OK:
if (offsetFound != CDF->CURattrOffset64) return ATTR_EXISTS;
break;
case NO_SUCH_ATTR:
break;
default:
AbortAccess64 (CDF, UPDATE, noDELETE);
return tStatus;
}
if (!WriteAccess64(CDF,FALSE,&pStatus)) return pStatus;
NulPad (tmpname, CDF_ATTR_NAME_LEN256);
if (!sX(WriteADR64(CDF->fp,CDF->CURattrOffset64,
ADR_NAME,tmpname,
ADR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
break;
}
/****************************************************************************
* ATTR_SCOPE_
****************************************************************************/
case ATTR_SCOPE_: {
struct CDFstruct *CDF;
Int32 scope = (Int32) va_arg (Va->ap, long);
SelectCDF (Cur->cdf, CDF)
if (!CURRENTattrSELECTED64(CDF)) return NO_ATTR_SELECTED;
if (!ValidAttrScope(scope)) return BAD_SCOPE;
if (!WriteAccess64(CDF,FALSE,&pStatus)) return pStatus;
if (!sX(WriteADR64(CDF->fp,CDF->CURattrOffset64,
ADR_SCOPE,&scope,
ADR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
/**************************************************************************
* Reset current entry offsets.
**************************************************************************/
if (!sX(SetCURgrEntry64(CDF,FALSE,CDF->CURgrEntryNum),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
if (!sX(SetCURzEntry64(CDF,FALSE,CDF->CURzEntryNum),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
break;
}
/****************************************************************************
* gENTRY_DATASPEC_/rENTRY_DATASPEC_/zENTRY_DATASPEC_, change the data
* specification of an existing entry. Currently, only the data type can
* be changed (and must be equivalent). The number of elements must remain
* the same.
****************************************************************************/
case rENTRY_DATASPEC_:
case gENTRY_DATASPEC_:
case zENTRY_DATASPEC_: {
int entryType = E3p(Va->item,gENTRY_DATASPEC_,
rENTRY_DATASPEC_,
zENTRY_DATASPEC_);
struct CDFstruct *CDF;
Int32 newDataType = (Int32) va_arg (Va->ap, long);
Int32 newNumElems = (Int32) va_arg (Va->ap, long);
Int32 oldDataType, oldNumElems; OFF_T eOffset;
SelectCDF (Cur->cdf, CDF)
if (!CURRENTattrSELECTED64(CDF)) return NO_ATTR_SELECTED;
if (E3(entryType,
CDF->CURgrEntryNum,
CDF->CURgrEntryNum,
CDF->CURzEntryNum) == RESERVED_ENTRYNUM) return NO_ENTRY_SELECTED;
if (!ValidDataType(newDataType)) return BAD_DATA_TYPE;
if (newNumElems != -99 && newNumElems < 1) return BAD_NUM_ELEMS;
if (!sX(CheckEntryOp64(CDF,entryType),&pStatus)) return pStatus;
eOffset = E3(entryType,CDF->CURgrEntryOffset64,
CDF->CURgrEntryOffset64,
CDF->CURzEntryOffset64);
if (eOffset == (OFF_T) RESERVED_ENTRYOFFSET64) return NO_SUCH_ENTRY;
if (!WriteAccess64(CDF,FALSE,&pStatus)) return pStatus;
if (!sX(ReadAEDR64(CDF->fp,eOffset,
AEDR_DATATYPE,&oldDataType,
AEDR_NUMELEMS,&oldNumElems,
AEDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
if ((!EquivDataTypes(newDataType,oldDataType)) ||
(newNumElems != -99 && newNumElems != oldNumElems))
return CANNOT_CHANGE;
if (!sX(WriteAEDR64(CDF,CDF->fp,eOffset,
AEDR_DATATYPE,&newDataType,
AEDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
break;
}
/****************************************************************************
* gENTRY_DATA_/rENTRY_DATA_/zENTRY_DATA_,
****************************************************************************/
case rENTRY_DATA_:
case gENTRY_DATA_:
case zENTRY_DATA_: {
int entryType = E3p(Va->item,gENTRY_DATA_,rENTRY_DATA_,zENTRY_DATA_);
struct CDFstruct *CDF;
struct ADRstruct64 ADR;
long entryN; /* True entry number. */
Logical zEntry; /* If true, a AzEDR. If FALSE, a AgrEDR. */
int nBytesNew; /* Size of new entry value. */
OFF_T eOffset; /* Offset of AEDR. */
long dataType = va_arg (Va->ap, long);
long numElems = va_arg (Va->ap, long);
void *value = va_arg (Va->ap, void *);
SelectCDF (Cur->cdf, CDF)
if (!CURRENTattrSELECTED64(CDF)) return NO_ATTR_SELECTED;
if (E3(entryType,
CDF->CURgrEntryNum,
CDF->CURgrEntryNum,
CDF->CURzEntryNum) == RESERVED_ENTRYNUM) return NO_ENTRY_SELECTED;
if (!ValidDataType((Int32)dataType)) return BAD_DATA_TYPE;
if (numElems < 1) return BAD_NUM_ELEMS;
if (!sX(ReadADR64(CDF->fp,CDF->CURattrOffset64,
ADR_RECORD,&ADR,
ADR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
if (!sX(CheckEntryOp64(CDF,entryType),&pStatus)) return pStatus;
if (!WriteAccess64(CDF,FALSE,&pStatus)) return pStatus;
nBytesNew = (int) (CDFelemSize(dataType) * numElems);
eOffset = E3(entryType,CDF->CURgrEntryOffset64,
CDF->CURgrEntryOffset64,
CDF->CURzEntryOffset64);
if (eOffset != (OFF_T) RESERVED_ENTRYOFFSET64) {
/************************************************************************
* The entry already exists.
************************************************************************/
struct AEDRstruct64 AEDR; int nBytesCur;
if (!sX(ReadAEDR64(CDF->fp,eOffset,
AEDR_RECORD,&AEDR,NULL,
AEDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
nBytesCur = (int) (CDFelemSize(AEDR.DataType) * AEDR.NumElems);
zEntry = (AEDR.RecordType == AzEDR_);
if (nBytesNew != nBytesCur) {
/********************************************************************
* The size of the new entry value is different than the size of the
* old entry value. The AEDR is changing size.
********************************************************************/
OFF_T prevOffset, newOffset;
if (!sX(FindPrevEntry64(CDF,CDF->CURattrOffset64,eOffset,
zEntry,&prevOffset),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
if (!sX(ResizeIR64(CDF,eOffset,
AEDR_BASE_SIZE64+nBytesNew,
&newOffset,TRUE,NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
AEDR.RecordSize = AEDR_BASE_SIZE64 + nBytesNew;
AEDR.DataType = dataType;
AEDR.NumElems = numElems;
if (!sX(WriteAEDR64(CDF,CDF->fp,newOffset,
AEDR_RECORD,&AEDR,value,
AEDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
switch (entryType) {
case gENTRYt:
case rENTRYt:
CDF->CURgrEntryOffset64 = newOffset;
break;
case zENTRYt:
CDF->CURzEntryOffset64 = newOffset;
break;
}
if (prevOffset == 0) {
if (!sX(WriteADR64(CDF->fp,CDF->CURattrOffset64,
BOO(zEntry,ADR_AzEDRHEAD,ADR_AgrEDRHEAD),&newOffset,
ADR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
}
else {
if (!sX(WriteAEDR64(CDF,CDF->fp,prevOffset,
AEDR_AEDRNEXT,&newOffset,
AEDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
}
}
else {
/********************************************************************
* The AEDR is not changing size.
********************************************************************/
AEDR.DataType = dataType;
AEDR.NumElems = numElems;
if (!sX(WriteAEDR64(CDF,CDF->fp,eOffset,
AEDR_RECORD,&AEDR,value,
AEDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
}
}
else {
/************************************************************************
* The entry does not exist.
************************************************************************/
struct AEDRstruct64 AEDR;
OFF_T lastOffset;
zEntry = E3(entryType,FALSE,FALSE,
BOO(zModeON(CDF),
BOO(CDF->CURzEntryNum < CDF->NrVars,FALSE,TRUE),TRUE));
entryN = E3(entryType,CDF->CURgrEntryNum,CDF->CURgrEntryNum,
BOO(zModeON(CDF),
BOO(CDF->CURzEntryNum < CDF->NrVars,
CDF->CURzEntryNum,CDF->CURzEntryNum - CDF->NrVars),
CDF->CURzEntryNum));
AEDR.RecordSize = AEDR_BASE_SIZE64 + nBytesNew;
AEDR.RecordType = BOO(zEntry,AzEDR_,AgrEDR_);
AEDR.AEDRnext = (OFF_T) 0;
AEDR.AttrNum = ADR.Num;
AEDR.DataType = dataType;
AEDR.Num = entryN;
AEDR.NumElems = numElems;
AEDR.rfuA = 0;
AEDR.rfuB = 0;
AEDR.rfuC = 0;
AEDR.rfuD = -1;
AEDR.rfuE = -1;
if (!sX(AllocateIR64(CDF,AEDR.RecordSize,&eOffset),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
if (!sX(WriteAEDR64(CDF,CDF->fp,eOffset,
AEDR_RECORD,&AEDR,value,
AEDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
switch (entryType) {
case gENTRYt:
case rENTRYt:
CDF->CURgrEntryOffset64 = eOffset;
break;
case zENTRYt:
CDF->CURzEntryOffset64 = eOffset;
break;
}
if (!sX(FindLastEntry64(CDF,CDF->CURattrOffset64,
zEntry,&lastOffset),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
if (lastOffset == (OFF_T) 0) {
/********************************************************************
* This is the first entry (of this type). The ADR will point to
* this entry.
********************************************************************/
if (zEntry) {
ADR.NzEntries = 1;
ADR.MAXzEntry = entryN;
ADR.AzEDRhead = eOffset;
}
else {
ADR.NgrEntries = 1;
ADR.MAXgrEntry = entryN;
ADR.AgrEDRhead = eOffset;
}
if (!sX(WriteADR64(CDF->fp,CDF->CURattrOffset64,
ADR_RECORD,&ADR,
ADR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
}
else {
/********************************************************************
* Entries already exist (of this type). The currently last entry
* will point to this entry.
********************************************************************/
if (zEntry) {
ADR.NzEntries++;
ADR.MAXzEntry = MAXIMUM(ADR.MAXzEntry,entryN);
}
else {
ADR.NgrEntries++;
ADR.MAXgrEntry = MAXIMUM(ADR.MAXgrEntry,entryN);
}
if (!sX(WriteADR64(CDF->fp,CDF->CURattrOffset64,
ADR_RECORD,&ADR,
ADR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
if (!sX(WriteAEDR64(CDF,CDF->fp,lastOffset,
AEDR_AEDRNEXT,&eOffset,
AEDR_NULL),&pStatus)) {
AbortAccess64 (CDF, UPDATE, noDELETE);
return pStatus;
}
}
}
break;
}
}
return pStatus;
}
syntax highlighted by Code2HTML, v. 0.9.1