1 /******************************************************************************
2 *
3 *  NSSDC/CDF                     CDF library miscellaneous functions, part 3.
4 *
5 *  Version 1.0e, 29-Oct-97, Hughes STX.
6 *
7 *  Modification history:
8 *
9 *   V1.0   5-Sep-96, J Love     Original version.
10 *   V1.0a 21-Feb-97, J Love	Removed RICE.
11 *   V1.0b  4-Mar-97, J Love	Windows NT for MS Visual C/C++ on an IBM PC.
12 *   V1.0c 11-Sep-97, J Love	Magic number are now uInt32.
13 *   V1.0d 20-Oct-97, J Love	Properly cast the uInt32 magic numbers.  More
14 *				Windows NT.
15 *   V2.0  29-Jun-04, M Liu      Added LFS (Large File Support > 2G).
16 *   V3.2  25-Apr-07, D Berger   Changed COPYblockSIZE from 512.
17 *   V3.3  10-Jan-09, M Liu      Added CDFsetValidate and CDFgetValidate.
18 *
19 ******************************************************************************/
20 
21 #include "cdflib.h"
22 #include "cdflib64.h"
23 
24 /******************************************************************************
25 * Macros/function prototypes.
26 ******************************************************************************/
27 
28 #define COPYblockSIZE nCACHE_BUFFER_BYTEs
29 
30 static CDFstatus SearchForRecord_r_64 PROTOARGs((
31   vFILE *fp, OFF_T vxrOffset, Int32 recNum, Int32 *firstRec, Int32 *lastRec,
32   OFF_T *offset, Logical *found
33 ));
34 static CDFstatus IndexingStatistics_r_64 PROTOARGs((
35   vFILE *fp, OFF_T vxrOffset, Int32 maxRec, int level, Int32 *nLevels,
36   Int32 *nVXRs, Int32 *nEntries, Int32 *nAlloc, Int32 *nRecords
37 ));
38 static CDFstatus PrevRecord_r_64 PROTOARGs((
39   vFILE *fp, OFF_T vxrOffset, Int32 baseRec, Int32 *prevRec, Logical *found
40 ));
41 static CDFstatus NextRecord_r_64 PROTOARGs((
42   vFILE *fp, OFF_T vxrOffset, Int32 baseRec, Int32 *nextRec, Logical *found
43 ));
44 static CDFstatus CalcCompressionPct_r_64 PROTOARGs((
45   vFILE *fp, OFF_T vxrOffset, Int32 nPhyRecBytes, OFF_T *uTotal, OFF_T *cTotal
46 ));
47 static CDFstatus ModIndexOffset_r_64 PROTOARGs((
48   vFILE *fp, OFF_T vxrOffset, Int32 firstRec, Int32 lastRec, OFF_T newOffset
49 ));
50 static CDFstatus ReadSparseFull PROTOARGs((
51   struct CDFstruct *CDF, struct VarStruct *Var, Int32 firstRec, Int32 lastRec,
52   void *buffer
53 ));
54 static CDFstatus ReadSparsePartial PROTOARGs((
55   struct CDFstruct *CDF, struct VarStruct *Var, Int32 recNum, OFF_T offset,
56   Int32 nValues, void *buffer
57 ));
58 static CDFstatus ReadCompressedFull PROTOARGs((
59   struct CDFstruct *CDF, struct VarStruct *Var, Int32 firstRec, Int32 lastRec,
60   void *buffer
61 ));
62 static CDFstatus ReadCompressedPartial PROTOARGs((
63   struct CDFstruct *CDF, struct VarStruct *Var, Int32 recNum, OFF_T offset,
64   Int32 nValues, void *buffer
65 ));
66 static CDFstatus BringToStage PROTOARGs((
67   struct CDFstruct *CDF, struct VarStruct *Var, Int32 recNum, Logical *found
68 ));
69 static CDFstatus WriteCompressedRecords PROTOARGs((
70   struct CDFstruct *CDF, struct VarStruct *Var, Int32 firstRec, Int32 lastRec,
71   void *buffer, Int32 nValues, OFF_T offset, Logical fullRecord
72 ));
73 
74 /******************************************************************************
75 * DecompressCDF64.
76 ******************************************************************************/
77 
DecompressCDF64(dotFp,uDotFp)78 STATICforIDL CDFstatus DecompressCDF64 (dotFp, uDotFp)
79 vFILE *dotFp;           /* In: File pointer to dotCDF file. */
80 vFILE *uDotFp;          /* In: Uncompressed CDF file pointer. */
81 {
82   CDFstatus pStatus = CDF_OK; struct CCRstruct64 CCR; struct CPRstruct64 CPR;
83   uInt32 magicNumber1 = V3magicNUMBER_1, magicNumber2u = V2magicNUMBER_2u;
84   OFF_T cSize, cOffset;
85   /****************************************************************************
86   * Read/validate CCR.
87   ****************************************************************************/
88   if (!sX(ReadCCR64(dotFp,V3_CCR_OFFSET64,
89 		    CCR_RECORD,&CCR,
90 		    CCR_NULL),&pStatus)) return pStatus;
91   if (CCR.uSize == 0) return EMPTY_COMPRESSED_CDF;
92   /****************************************************************************
93   * Read CPR.
94   ****************************************************************************/
95   if (!sX(ReadCPR64(dotFp,CCR.CPRoffset,
96 		    CPR_RECORD,&CPR,
97 		    CPR_NULL),&pStatus)) return pStatus;
98   /****************************************************************************
99   * Write magic numbers.
100   ****************************************************************************/
101   if (!SEEKv64(uDotFp,(OFF_T) V3_MAGIC_OFFSET_1,vSEEK_SET)) return CDF_WRITE_ERROR;
102   if (!Write32_64(uDotFp,(Int32 *)&magicNumber1)) return CDF_WRITE_ERROR;
103   if (!Write32_64(uDotFp,(Int32 *)&magicNumber2u)) return CDF_WRITE_ERROR;
104   /****************************************************************************
105   * Copy/decompress.
106   ****************************************************************************/
107   cOffset = (OFF_T) (V3_CCR_OFFSET64 + CCR_BASE_SIZE64);
108   cSize = CCR.RecordSize - CCR_BASE_SIZE64;
109   if (!sX(Decompress64(dotFp,cOffset,
110 		       cSize,CDF_READ_ERROR,
111 		       CPR.cType,CPR.cParms,
112 		       uDotFp,FIRST_IR_OFFSET,
113 		       CDF_WRITE_ERROR),&pStatus)) return pStatus;
114   return pStatus;
115 }
116 
117 /******************************************************************************
118 * WriteCompressedCDF64.
119 ******************************************************************************/
120 
WriteCompressedCDF64(CDF,CPR,empty)121 STATICforIDL CDFstatus WriteCompressedCDF64 (CDF, CPR, empty)
122 struct CDFstruct *CDF;
123 struct CPRstruct64 *CPR;
124 Logical empty;          /* In: If TRUE, write an empty CCR. */
125 {
126   uInt32 magicNumber1 = V3magicNUMBER_1;
127   uInt32 magicNumber2c = V2magicNUMBER_2c;
128   struct CCRstruct64 CCR; CDFstatus pStatus = CDF_OK;
129   /****************************************************************************
130   * Write magic numbers.
131   ****************************************************************************/
132   if (!SEEKv64(CDF->dotFp,(OFF_T) V3_MAGIC_OFFSET_1,vSEEK_SET)) return CDF_WRITE_ERROR;
133   if (!Write32_64(CDF->dotFp,(Int32 *)&magicNumber1)) return CDF_WRITE_ERROR;
134   if (!Write32_64(CDF->dotFp,(Int32 *)&magicNumber2c)) return CDF_WRITE_ERROR;
135   /****************************************************************************
136   * Write CCR.
137   ****************************************************************************/
138   if (empty) {
139     CCR.RecordSize = CCR_BASE_SIZE64;
140     CCR.RecordType = CCR_;
141     CCR.CPRoffset = (OFF_T) V3_CCR_OFFSET64 + CCR.RecordSize;
142     CCR.uSize = 0;
143     CCR.rfuA = 0;
144     if (!sX(WriteCCR64(CDF->dotFp,V3_CCR_OFFSET64,
145 		       CCR_RECORD,&CCR,
146 		       CCR_NULL),&pStatus)) return CDF_WRITE_ERROR;
147   }
148   else {
149     OFF_T uSize, eof, cSize, cOffset, GDRoffset;
150     if (!sX(ReadCDR64(CDF->uDotFp,V3_CDR_OFFSET64,
151 		      CDR_GDROFFSET,&GDRoffset,
152 		      CDR_NULL),&pStatus)) return pStatus;
153     if (!sX(ReadGDR64(CDF->uDotFp,GDRoffset,
154 		      GDR_EOF,&eof,
155 		      GDR_NULL),&pStatus)) return pStatus;
156     uSize = eof - FIRST_IR_OFFSET;
157     cOffset = (OFF_T) (V3_CCR_OFFSET64 + CCR_BASE_SIZE64);
158     if (!sX(Compress64(CDF->uDotFp,FIRST_IR_OFFSET,
159 		       uSize,CDF_READ_ERROR,CPR->cType,
160 		       CPR->cParms,CDF->dotFp,cOffset,
161 		       &cSize,CDF_WRITE_ERROR),&pStatus)) return pStatus;
162     CCR.RecordSize = (OFF_T) (CCR_BASE_SIZE64 + cSize);
163     CCR.RecordType = CCR_;
164     CCR.CPRoffset = (OFF_T) (V3_CCR_OFFSET64 + CCR.RecordSize);
165     CCR.uSize = uSize;
166     CCR.rfuA = 0;
167     if (!sX(WriteCCR64(CDF->dotFp,V3_CCR_OFFSET64,
168 		       CCR_RECORD,&CCR,
169 		       CCR_NULL),&pStatus)) return CDF_WRITE_ERROR;
170   }
171   /****************************************************************************
172   * Write CPR.
173   ****************************************************************************/
174   if (!sX(WriteCPR64(CDF->dotFp,CCR.CPRoffset,
175 		     CPR_RECORD,CPR,
176 		     CPR_NULL),&pStatus)) return CDF_WRITE_ERROR;
177   return pStatus;
178 }
179 
180 /******************************************************************************
181 * CopyCDF64.
182 ******************************************************************************/
183 
CopyCDF64(srcFp,destFp)184 STATICforIDL CDFstatus CopyCDF64 (srcFp, destFp)
185 vFILE *srcFp;
186 vFILE *destFp;
187 {
188   OFF_T nBytes, offset; Byte buffer[nCACHE_BUFFER_BYTEs];
189   CDFstatus pStatus = CDF_OK;
190   if (!SEEKv64(srcFp,(OFF_T)0,vSEEK_END)) return CDF_READ_ERROR;
191   nBytes = V_tell64 (srcFp);
192   if (nBytes == EOF) return CDF_READ_ERROR;
193   if (!SEEKv64(srcFp,(OFF_T)0,vSEEK_SET)) return CDF_READ_ERROR;
194   if (!SEEKv64(destFp,(OFF_T)0,vSEEK_SET)) return CDF_WRITE_ERROR;
195   for (offset = 0; offset < nBytes; offset += nCACHE_BUFFER_BYTEs) {
196      OFF_T nBytesRemaining = nBytes - offset;
197      size_t count = (size_t) MINIMUM (nBytesRemaining, nCACHE_BUFFER_BYTEs);
198      if (!READv64(buffer,count,1,srcFp)) return CDF_READ_ERROR;
199      if (!WRITEv64(buffer,count,1,destFp)) return CDF_WRITE_ERROR;
200   }
201   return pStatus;
202 }
203 
204 /******************************************************************************
205 * WriteVarValues64.
206 *    NOTE: If more than one record is being written, full records are assumed
207 * and the `offset' must be zero.
208 ******************************************************************************/
209 
WriteVarValues64(CDF,Var,startRec,offset,nValues,buffer)210 STATICforIDL CDFstatus WriteVarValues64 (CDF, Var, startRec, offset, nValues,
211 				         buffer)
212 struct CDFstruct *CDF;
213 struct VarStruct *Var;
214 Int32 startRec;          /* Physical record number at which to write. */
215 Int32 offset;            /* Byte offset within (first) record at which to
216 			    begin writing. */
217 Int32 nValues;           /* Number of values to write. */
218 void *buffer;
219 {
220   OFF_T tOffset; Logical fullRecord; Byte *tBuffer = buffer;
221   Int32 numElems, firstRec, lastRec, lastRecInVVR, nBytes, padTo, recNum;
222   Int32 writeTo, recCount; CDFstatus pStatus = CDF_OK;
223   /****************************************************************************
224   * Determine first/last record(s) being written and if full physical
225   * record(s).
226   ****************************************************************************/
227   firstRec = startRec;
228   if (nValues < Var->NphyRecValues) {
229     fullRecord = FALSE;
230     lastRec = startRec;
231   }
232   else {
233     fullRecord = TRUE;
234     lastRec = startRec + ((nValues - 1) / Var->NphyRecValues);
235   }
236   /****************************************************************************
237   * Based on variable type...
238   ****************************************************************************/
239   switch (Var->vType) {
240     /**************************************************************************
241     * Standard variable in single-file CDF...
242     **************************************************************************/
243     case STANDARD_: {
244       /************************************************************************
245       * Allocate/pad records.
246       ************************************************************************/
247       if (lastRec > Var->maxAllocated) {
248 	struct AllocStruct alloc;
249 	Int32 nNeeded = lastRec - Var->maxAllocated;
250 	Int32 nRecords = MAXIMUM(nNeeded,Var->blockingFactor);
251 	LoadAllocVVR64 (alloc, Var->maxAllocated + 1,
252 		        Var->maxAllocated + nRecords, FALSE)
253 	if (!sX(AllocateRecords64(CDF,Var,alloc),&pStatus)) return pStatus;
254 	Var->maxAllocated = alloc.last;
255       }
256       padTo = BOO(fullRecord,firstRec - 1,firstRec);
257       if (padTo > Var->maxWritten) {
258 	Int32 padFrom = Var->maxWritten + 1;
259 	if (!sX(PadUnRecords64(CDF,Var,padFrom,padTo),&pStatus)) return pStatus;
260 	Var->maxWritten = padTo;
261       }
262       /************************************************************************
263       * Write value(s).
264       ************************************************************************/
265       if (fullRecord) {
266 	recNum = firstRec;
267 	while (recNum <= lastRec) {
268 	  if (!sX(SearchForRecord64(CDF,Var->VDRoffset64,
269 				    Var->zVar,recNum,
270 				    NULL,&lastRecInVVR,
271 				    NULL,NULL),&pStatus)) return pStatus;
272 	  writeTo = MINIMUM(lastRec,lastRecInVVR);
273 	  recCount = writeTo - recNum + 1;
274 	  if (!sX(RecordByteOffset64(CDF,Var,
275 				     recNum,
276 				     &tOffset),&pStatus)) return pStatus;
277 	  numElems = recCount * Var->NphyRecElems;
278 	  if (!sX(WriteVarElems64(Var,CDF->fp,tOffset,
279 				  numElems,tBuffer),&pStatus)) return pStatus;
280 	  recNum += recCount;
281 	  tBuffer += (size_t) (recCount * Var->NphyRecBytes);
282 	}
283       }
284       else {
285 	if (!sX(RecordByteOffset64(CDF,Var,
286 				   firstRec,
287 				   &tOffset),&pStatus)) return pStatus;
288 	tOffset += (OFF_T) offset;
289 	numElems = nValues * Var->NvalueElems;
290 	if (!sX(WriteVarElems64(Var,CDF->fp,tOffset,
291 			        numElems,buffer),&pStatus)) return pStatus;
292       }
293       /************************************************************************
294       * Update the maximum record written.
295       ************************************************************************/
296       Var->maxWritten = MAXIMUM(Var->maxWritten,lastRec);
297       break;
298     }
299     /**************************************************************************
300     * Sparse records...
301     **************************************************************************/
302     case SPARSE_RECORDS_: {
303       Int32 maxRecInStage, recordOffsetInStage, nextRec;
304       int how; void *padBuffer; Logical found;
305       /************************************************************************
306       * Pad records.
307       ************************************************************************/
308       padTo = BOO(fullRecord,firstRec - 1,firstRec);
309       if (padTo > Var->maxWritten) {
310 	Int32 padFrom = Var->maxWritten + 1;
311 	if (!sX(PadUnRecords64(CDF,Var,padFrom,padTo),&pStatus)) return pStatus;
312 	Var->maxWritten = padTo;
313       }
314       /************************************************************************
315       * Write value(s).
316       ************************************************************************/
317       recNum = firstRec;
318       while (recNum <= lastRec) {
319 	/**********************************************************************
320 	* Check if this record already exists (is allocated).
321 	**********************************************************************/
322 	if (!sX(SearchForRecord64(CDF,Var->VDRoffset64,
323 				  Var->zVar,recNum,
324 				  NULL,&lastRecInVVR,
325 				  NULL,&found),&pStatus)) return pStatus;
326 	if (found) {
327 	  writeTo = MINIMUM(lastRec,lastRecInVVR);
328 	  recCount = writeTo - recNum + 1;
329 	  if (!sX(RecordByteOffset64(CDF,Var,
330 				     recNum,&tOffset),&pStatus)) return pStatus;
331 	  if (fullRecord)
332 	    numElems = recCount * Var->NphyRecElems;
333 	  else {
334 	    tOffset += offset;
335 	    numElems = nValues * Var->NvalueElems;
336 	  }
337 	  if (!sX(WriteVarElems64(Var,CDF->fp,tOffset,
338 				  numElems,tBuffer),&pStatus)) return pStatus;
339 	  Var->maxWritten = MAXIMUM(Var->maxWritten,writeTo);
340 	  recNum += recCount;
341 	  tBuffer += (size_t) (numElems * Var->NelemBytes);
342 	  continue;
343 	}
344 	/**********************************************************************
345 	* This record doesn't exist - initialize the staging area.
346 	**********************************************************************/
347 	if (Var->stage.areaOffset64 == (OFF_T) NO_OFFSET64) {
348 	  nBytes = Var->blockingFactor * Var->NphyRecBytes;
349 	  if (!sX(InitVarStage64(CDF,Var,nBytes),&pStatus)) return pStatus;
350 	}
351 	/**********************************************************************
352 	* Check if this record is in the staging area.
353 	**********************************************************************/
354 	if (INCLUSIVE(Var->stage.firstRec,recNum,Var->stage.lastRec)) {
355 	  maxRecInStage = Var->stage.firstRec + Var->blockingFactor - 1;
356 	  writeTo = MINIMUM(lastRec,maxRecInStage);
357 	  if (!sX(NextRecord64(CDF,Var->VDRoffset64,Var->zVar,
358 			       recNum,&nextRec,&found),&pStatus)) return pStatus;
359 	  if (found) {
360 	    Int32 prevRecN = nextRec - 1;
361 	    writeTo = MINIMUM(writeTo,prevRecN);
362 	  }
363 	  recCount = writeTo - recNum + 1;
364 	  recordOffsetInStage = recNum - Var->stage.firstRec;
365 	  tOffset = Var->stage.areaOffset64;
366 	  tOffset += (recordOffsetInStage * Var->NphyRecBytes);
367 	  if (fullRecord)
368 	    numElems = recCount * Var->NphyRecElems;
369 	  else {
370 	    tOffset += offset;
371 	    numElems = nValues * Var->NvalueElems;
372 	  }
373 	  if (!sX(WriteVarElems64(Var,CDF->stage.fp,tOffset,
374 				  numElems,tBuffer),&pStatus)) return pStatus;
375 	  Var->stage.lastRec = MAXIMUM(Var->stage.lastRec,writeTo);
376 	  Var->stage.modified = TRUE;
377 	  recNum += recCount;
378 	  tBuffer += (size_t) (numElems * Var->NelemBytes);
379 	  continue;
380 	}
381 	/**********************************************************************
382 	* This record is not in the staging area.  Check if it can be added.
383 	**********************************************************************/
384 	if (Var->stage.firstRec != NO_RECORD) {
385 	  if (recNum == Var->stage.lastRec + 1) {
386 	    maxRecInStage = Var->stage.firstRec + Var->blockingFactor - 1;
387 	    if (recNum <= maxRecInStage) {
388 	      writeTo = MINIMUM(lastRec,maxRecInStage);
389 	      if (!sX(NextRecord64(CDF,Var->VDRoffset64,
390 				   Var->zVar,recNum,
391 				   &nextRec,&found),&pStatus)) return pStatus;
392 	      if (found) {
393 		Int32 prevRecN = nextRec - 1;
394 		writeTo = MINIMUM(writeTo,prevRecN);
395 	      }
396 	      recCount = writeTo - recNum + 1;
397 	      recordOffsetInStage = recNum - Var->stage.firstRec;
398 	      tOffset = Var->stage.areaOffset64;
399 	      tOffset += (recordOffsetInStage * Var->NphyRecBytes);
400 	      if (fullRecord)
401 		numElems = recCount * Var->NphyRecElems;
402 	      else {
403 		if (!sX(BuildPadBuffer64(CDF,Var,recCount,
404 				         &how,&padBuffer,
405 				         TRUE),&pStatus)) return pStatus;
406 		if (!sX(WritePadValues64(Var,CDF->stage.fp,tOffset,
407 				         recCount,how,padBuffer),&pStatus)) {
408 		  cdf_FreeMemory (padBuffer, NULL);
409 		  return pStatus;
410 		}
411 		cdf_FreeMemory (padBuffer, NULL);
412 		tOffset += offset;
413 		numElems = nValues * Var->NvalueElems;
414 	      }
415 	      if (!sX(WriteVarElems64(Var,CDF->stage.fp,
416 				      tOffset,numElems,
417 				      tBuffer),&pStatus)) return pStatus;
418 	      Var->stage.lastRec = MAXIMUM(Var->stage.lastRec,writeTo);
419 	      Var->stage.modified = TRUE;
420 	      recNum += recCount;
421 	      tBuffer += (size_t) (numElems * Var->NelemBytes);
422 	      continue;
423 	    }
424 	  }
425 	}
426 	/**********************************************************************
427 	* This record cannot be added to the staging area.  First flush the
428 	* staging area (if necessary)...
429 	**********************************************************************/
430 	if (!sX(FlushStage64(CDF,Var),&pStatus)) return pStatus;
431 	/**********************************************************************
432 	* ...and then start a new staging area with this record.
433 	**********************************************************************/
434 	maxRecInStage = recNum + Var->blockingFactor - 1;
435 	writeTo = MINIMUM(lastRec,maxRecInStage);
436 	if (!sX(NextRecord64(CDF,Var->VDRoffset64,Var->zVar,
437 			     recNum,&nextRec,&found),&pStatus)) return pStatus;
438 	if (found) {
439 	  Int32 prevRecN = nextRec - 1;
440 	  writeTo = MINIMUM(writeTo,prevRecN);
441 	}
442 	recCount = writeTo - recNum + 1;
443 	tOffset = Var->stage.areaOffset64;
444 	if (fullRecord)
445 	  numElems = recCount * Var->NphyRecElems;
446 	else {
447 	  if (!sX(BuildPadBuffer64(CDF,Var,recCount,
448 				   &how,&padBuffer,
449 				   TRUE),&pStatus)) return pStatus;
450 	  if (!sX(WritePadValues64(Var,CDF->stage.fp,tOffset,
451 				   recCount,how,padBuffer),&pStatus)) {
452 	  cdf_FreeMemory (padBuffer, NULL);
453 	  return pStatus;
454 	  }
455 	  cdf_FreeMemory (padBuffer, NULL);
456 	  tOffset += offset;
457 	  numElems = nValues * Var->NvalueElems;
458 	}
459 	if (!sX(WriteVarElems64(Var,CDF->stage.fp,tOffset,
460 			        numElems,tBuffer),&pStatus)) return pStatus;
461 	Var->stage.firstRec = recNum;
462 	Var->stage.lastRec = writeTo;
463 	Var->stage.modified = TRUE;
464 	recNum += recCount;
465 	tBuffer += (size_t) (numElems * Var->NelemBytes);
466       }
467       break;
468     }
469     /**************************************************************************
470     * Compressed records...
471     * Sparse/compressed records...
472     **************************************************************************/
473     case COMPRESSED_:
474     case SPARSE_COMPRESSED_RECORDS_: {
475       Logical sparseRecords = (Var->vType == SPARSE_COMPRESSED_RECORDS_);
476       /************************************************************************
477       * Initialize staging area.
478       ************************************************************************/
479       if (Var->stage.areaOffset64 == (OFF_T) NO_OFFSET64) {
480 	if (Var->blockingFactor == 0) {
481 	  if (Var->recVary) {
482 	    Int32 bf = ((MIN_BLOCKING_BYTES_compressed-1)/Var->NphyRecBytes)+1;
483 	    Var->blockingFactor = MAXIMUM(bf,MIN_BLOCKING_RECS_compressed);
484 	  }
485 	  else
486 	    Var->blockingFactor = 1;
487 	  if (!sX(WriteVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar,
488 			     VDR_BLOCKING,&(Var->blockingFactor),
489 			     VDR_NULL),&pStatus)) return pStatus;
490 	}
491 	nBytes = Var->blockingFactor * Var->NphyRecBytes;
492 	if (!sX(InitVarStage64(CDF,Var,nBytes),&pStatus)) return pStatus;
493       }
494       /************************************************************************
495       * Pad records (if necessary).
496       ************************************************************************/
497       if (!sparseRecords) {
498 	padTo = firstRec - 1;
499 	if (Var->maxRec < padTo) {
500 	  Int32 nRecords = padTo + 1, recN, valueN; void *padBuffer; int how;
501 	  if (!sX(BuildPadBuffer64(CDF,Var,
502 				   nRecords,&how,
503 				   &padBuffer,FALSE),&pStatus)) return pStatus;
504 	  switch (how) {
505 	    case ALLrecordsATonce:
506 	      if (!sX(WriteCompressedRecords(CDF,Var,Var->maxRec+1,
507 					     padTo,padBuffer,
508 					     nRecords*Var->NphyRecValues,
509 					     (OFF_T) ZERO_OFFSET64,
510 					     TRUE),&pStatus)) return pStatus;
511 	      break;
512 	    case ONErecordATaTIME:
513 	      for (recN = Var->maxRec + 1; recN <= padTo; recN++) {
514 		 if (!sX(WriteCompressedRecords(CDF,Var,recN,recN,
515 					        padBuffer,Var->NphyRecValues,
516 						(OFF_T) ZERO_OFFSET64,TRUE),&pStatus)) {
517 		   cdf_FreeMemory (padBuffer, NULL);
518 		   return pStatus;
519 		 }
520 	      }
521 	      break;
522 	    case ONEvalueATaTIME:
523 	      for (recN = 0; recN < nRecords; recN++) {
524 		 for (valueN = 0; valueN < Var->NphyRecValues; valueN++) {
525 		    tOffset = valueN * Var->NvalueBytes;
526 		    if (!sX(WriteCompressedRecords(CDF,Var,recN,recN,
527 						   padBuffer,INT32_ONE,
528 						   tOffset,FALSE),&pStatus)) {
529 		      cdf_FreeMemory (padBuffer, NULL);
530 		      return pStatus;
531 		    }
532 		 }
533 	      }
534 	      break;
535 	  }
536 	  cdf_FreeMemory (padBuffer, NULL);
537 	}
538       }
539       /************************************************************************
540       * Write the record(s).
541       ************************************************************************/
542       if (!sX(WriteCompressedRecords(CDF,Var,firstRec,lastRec,
543 				     buffer,nValues,offset,
544 				     fullRecord),&pStatus)) return pStatus;
545       break;
546     }
547     /**************************************************************************
548     * Can't do sparse arrays yet...
549     **************************************************************************/
550     case SPARSE_ARRAYS_:
551     case SPARSE_RECORDS_AND_ARRAYS_:
552       return UNKNOWN_SPARSENESS;
553     /**************************************************************************
554     * Variable in multi-file CDF...
555     **************************************************************************/
556     case IN_MULTI_: {
557       padTo = BOO(fullRecord,firstRec - 1,firstRec);
558       /************************************************************************
559       * Extend variable (if necessary).
560       ************************************************************************/
561       if (padTo > Var->maxRec) {
562 	Int32 padFrom = Var->maxRec + 1;
563 	if (!sX(PadUnRecords64(CDF,Var,padFrom,padTo),&pStatus)) return pStatus;
564       }
565       /************************************************************************
566       * Write value(s).
567       ************************************************************************/
568       if (!sX(RecordByteOffset64(CDF,Var,
569 			         firstRec,
570 			         &tOffset),&pStatus)) return pStatus;
571       tOffset += (OFF_T) offset;
572       numElems = nValues * Var->NvalueElems;
573       if (!sX(WriteVarElems64(Var,Var->fp,tOffset,
574 			      numElems,buffer),&pStatus)) return pStatus;
575       break;
576     }
577     /**************************************************************************
578     * Unknown variable type - this should never happen.
579     **************************************************************************/
580     default:
581       return CDF_INTERNAL_ERROR;
582   }
583   /****************************************************************************
584   * Update maximum record numbers.
585   ****************************************************************************/
586   if (!sX(UpdateMaxRec64(CDF,Var,lastRec),&pStatus)) return pStatus;
587   return pStatus;
588 }
589 
590 /******************************************************************************
591 * WriteVarElems64.
592 *   NOTE: On IBM PCs, it is assumed that the number of bytes being written
593 * will not exceed 65535.
594 ******************************************************************************/
595 
WriteVarElems64(Var,fp,offset,numElems,buffer)596 STATICforIDL CDFstatus WriteVarElems64 (Var, fp, offset, numElems, buffer)
597 struct VarStruct *Var;
598 vFILE *fp;
599 OFF_T offset;
600 Int32 numElems;
601 void *buffer;
602 {
603   CDFstatus pStatus = CDF_OK; Int32 elemCount;
604   /****************************************************************************
605   * Seek to the desired offset.
606   ****************************************************************************/
607   if (!SEEKv64(fp,offset,vSEEK_SET)) return VAR_WRITE_ERROR;
608   /****************************************************************************
609   * If no encoding is necessary, simply write the buffer and return.
610   ****************************************************************************/
611   if (Var->EncodeFunction == NULL) {
612     Int32 nBytes = numElems * Var->NelemBytes;
613     if (!WRITEv64(buffer,1,(size_t)nBytes,fp)) return VAR_WRITE_ERROR;
614     return pStatus;
615   }
616   /****************************************************************************
617   * Use as large a temporary buffer as possible for the encoding conversion.
618   * Start at the full number of elements and then halve that number until an
619   * allocation succeeds.
620   ****************************************************************************/
621   elemCount = numElems;
622   for (;;) {
623      OFF_T xBytes = (OFF_T) elemCount * Var->NelemBytes;
624 #if defined(win32)
625      if (xBytes < (OFF_T) ((1i64 << 31) - 1)) {
626 #else
627      if (xBytes < (OFF_T) ((1LL << 31) - 1)) {
628 #endif
629        size_t nBytes = (size_t) (elemCount * Var->NelemBytes);
630        void *tBuffer;
631        if ((int) nBytes <= 0) return VAR_READ_ERROR;
632        tBuffer = cdf_AllocateMemory (nBytes, NULL);
633        if (tBuffer != NULL) {
634          Int32 elemN = 0; Byte *bOffset = buffer;
635          while (elemN < numElems) {
636 	   Int32 thisElemCount = MinInt32 (elemCount, numElems - elemN);
637 	   size_t thisByteCount = (size_t) (thisElemCount * Var->NelemBytes);
638 	   memmove (tBuffer, bOffset, thisByteCount);
639 	   if (!sX(Var->EncodeFunction(tBuffer,thisElemCount),&pStatus)) {
640 	     cdf_FreeMemory (tBuffer, NULL);
641 	     return pStatus;
642 	   }
643 	   if (!WRITEv64(tBuffer,1,thisByteCount,fp)) {
644 	     cdf_FreeMemory (tBuffer, NULL);
645 	     return VAR_WRITE_ERROR;
646 	   }
647 	   elemN += thisElemCount;
648 	   bOffset += thisByteCount;
649          }
650          cdf_FreeMemory (tBuffer, NULL);
651          return pStatus;
652        }
653      }
654      if (elemCount == 1) break;
655      elemCount = (elemCount + 1) / 2;
656   }
657   return BAD_MALLOC;
658 }
659 
660 /******************************************************************************
661 * PrevRecord64.
662 *   Determine the last record allocated AT or BEFORE `baseRec'.  This routine
663 * should only be used for single-file CDFs.
664 ******************************************************************************/
665 
PrevRecord64(CDF,VDRoffset,zVar,baseRec,prevRec,found)666 STATICforIDL CDFstatus PrevRecord64 (CDF, VDRoffset, zVar, baseRec, prevRec,
667 				     found)
668 struct CDFstruct *CDF;
669 OFF_T VDRoffset;
670 Logical zVar;
671 Int32 baseRec;
672 Int32 *prevRec;
673 Logical *found;         /* If NULL, return NO_SUCH_RECORD if the previous
674 			   record doesn't exist.  Otherwise, set according to
675 			   whether or not the previous record exists and
676 			   return the pending status. */
677 {
678   CDFstatus pStatus = CDF_OK; OFF_T VXRoffset;
679   /****************************************************************************
680   * If multi-file...
681   ****************************************************************************/
682   if (!CDF->singleFile) return CDF_INTERNAL_ERROR;
683   /****************************************************************************
684   * Single-file...read the offset of the first VXR.
685   ****************************************************************************/
686   if (!sX(ReadVDR64(CDF,CDF->fp,VDRoffset,zVar,
687 		    VDR_VXRHEAD,&VXRoffset,
688 		    VDR_NULL),&pStatus)) return pStatus;
689   /****************************************************************************
690   * ...and start there (unless there are no VXRs).
691   ****************************************************************************/
692   if (VXRoffset != (OFF_T) ZERO_OFFSET64) {
693     if (!sX(PrevRecord_r_64(CDF->fp,VXRoffset,
694 			    baseRec,prevRec,found),&pStatus)) return pStatus;
695   }
696   else {
697     ASSIGNnotNULL (found, FALSE)
698     if (found == NULL) pStatus = NO_SUCH_RECORD;
699   }
700   return pStatus;
701 }
702 
PrevRecord_r_64(fp,vxrOffset,baseRec,prevRec,found)703 static CDFstatus PrevRecord_r_64 (fp, vxrOffset, baseRec, prevRec, found)
704 vFILE *fp;
705 OFF_T vxrOffset;
706 Int32 baseRec;
707 Int32 *prevRec;
708 Logical *found;
709 {
710   CDFstatus pStatus = CDF_OK; int entryN = 0;
711   struct VXRstruct64 VXR, nextVXR; Int32 irType;
712   /****************************************************************************
713   * Read the first VXR.
714   ****************************************************************************/
715   if (!sX(ReadVXR64(fp,vxrOffset,
716 		    VXR_RECORD,&VXR,
717 		    VXR_NULL),&pStatus)) return pStatus;
718   /****************************************************************************
719   * Check if there isn't a previous allocated record.  This could only be the
720   * case at the top level of VXRs (ie. not when this routine is recursively
721   * called).
722   ****************************************************************************/
723   if (baseRec < VXR.First[0]) {
724     ASSIGNnotNULL (found, FALSE)
725     return BOO(found == NULL,NO_SUCH_RECORD,pStatus);
726   }
727   /****************************************************************************
728   * Until it's time to return...
729   ****************************************************************************/
730   for (;;) {
731      /*************************************************************************
732      * If the record is in the current entry...
733      *************************************************************************/
734      if (INCLUSIVE(VXR.First[entryN],baseRec,VXR.Last[entryN])) {
735        if (!sX(ReadIrType64(fp,VXR.Offset[entryN],&irType),&pStatus)) {
736 	 return pStatus;
737        }
738        switch (irType) {
739 	 case VXR_:
740 	   return PrevRecord_r_64(fp,VXR.Offset[entryN],baseRec,prevRec,found);
741 	 case VVR_:
742 	 case CVVR_:
743 	   *prevRec = baseRec;
744 	   ASSIGNnotNULL (found, TRUE)
745 	   return pStatus;
746 	 default:
747 	   return CORRUPTED_V3_CDF;
748        }
749      }
750      /*************************************************************************
751      * If this is the last entry in the current VXR...
752      *************************************************************************/
753      if (entryN == VXR.NusedEntries - 1) {
754        if (VXR.VXRnext == (OFF_T) ZERO_OFFSET64) {
755 	 *prevRec = VXR.Last[entryN];
756 	 ASSIGNnotNULL (found, TRUE)
757 	 return pStatus;
758        }
759        if (!sX(ReadVXR64(fp,VXR.VXRnext,
760 		         VXR_RECORD,&nextVXR,
761 		         VXR_NULL),&pStatus)) return pStatus;
762        if (baseRec < nextVXR.First[0]) {
763 	 *prevRec = VXR.Last[entryN];
764 	 ASSIGNnotNULL (found, TRUE)
765 	 return pStatus;
766        }
767        VXR = nextVXR;
768        entryN = 0;
769      }
770      else {
771        if (baseRec < VXR.First[entryN+1]) {
772 	 *prevRec = VXR.Last[entryN];
773 	 ASSIGNnotNULL (found, TRUE)
774 	 return pStatus;
775        }
776        entryN++;
777      }
778   }
779 }
780 
781 /******************************************************************************
782 * NextRecord64.
783 *   Determine the next allocated record AT or AFTER `baseRec'.  I.e., if
784 * `baseRec' is allocated, it is returned as `nextRec'.
785 ******************************************************************************/
786 
NextRecord64(CDF,VDRoffset,zVar,baseRec,nextRec,found)787 STATICforIDL CDFstatus NextRecord64 (CDF, VDRoffset, zVar, baseRec, nextRec,
788 				     found)
789 struct CDFstruct *CDF;
790 OFF_T VDRoffset;
791 Logical zVar;
792 Int32 baseRec;
793 Int32 *nextRec;
794 Logical *found;         /* If NULL, return NO_SUCH_RECORD if the next record
795 			   doesn't exist.  Otherwise, set according to whether
796 			   or not the next record exists and return the pending
797 			   status. */
798 {
799   CDFstatus pStatus = CDF_OK; Int32 maxRec;
800   OFF_T VXRoffset;
801   /****************************************************************************
802   * If multi-file...
803   ****************************************************************************/
804   if (!CDF->singleFile) {
805     if (!sX(ReadVDR64(CDF,CDF->fp,VDRoffset,zVar,
806 		      VDR_MAXREC,&maxRec,
807 		      VDR_NULL),&pStatus)) return pStatus;
808     if (baseRec <= maxRec) {
809       *nextRec = baseRec;
810       ASSIGNnotNULL (found, TRUE)
811     }
812     else {
813       ASSIGNnotNULL (found, FALSE)
814       if (found == NULL) pStatus = NO_SUCH_RECORD;
815     }
816     return pStatus;
817   }
818   /****************************************************************************
819   * ...single-file, read the offset of the first VXR.
820   ****************************************************************************/
821   if (!sX(ReadVDR64(CDF,CDF->fp,VDRoffset,zVar,
822 		    VDR_VXRHEAD,&VXRoffset,
823 		    VDR_NULL),&pStatus)) return pStatus;
824   /****************************************************************************
825   * ...and start there.
826   ****************************************************************************/
827   if (!sX(NextRecord_r_64(CDF->fp,VXRoffset,
828 		          baseRec,nextRec,found),&pStatus)) return pStatus;
829   return pStatus;
830 }
831 
NextRecord_r_64(fp,vxrOffset,baseRec,nextRec,found)832 static CDFstatus NextRecord_r_64 (fp, vxrOffset, baseRec, nextRec, found)
833 vFILE *fp;
834 OFF_T vxrOffset;
835 Int32 baseRec;
836 Int32 *nextRec;
837 Logical *found;
838 {
839   CDFstatus pStatus = CDF_OK;
840   int entryN; struct VXRstruct64 VXR; Int32 irType;
841   /****************************************************************************
842   * While more VXRs...
843   ****************************************************************************/
844   while (vxrOffset != (OFF_T) ZERO_OFFSET64) {
845     /**************************************************************************
846     * Read the VXR.
847     **************************************************************************/
848     if (!sX(ReadVXR64(fp,vxrOffset,
849 		      VXR_RECORD,&VXR,
850 		      VXR_NULL),&pStatus)) return pStatus;
851     /**************************************************************************
852     * Search entries...
853     **************************************************************************/
854     if (baseRec <= VXR.Last[(int)(VXR.NusedEntries-1)]) {
855       for (entryN = 0; entryN < VXR.NusedEntries; entryN++) {
856 	 if (baseRec <= VXR.Last[entryN]) {
857 	   if (!sX(ReadIrType64(fp,
858 			        VXR.Offset[entryN],
859 			        &irType),&pStatus)) return pStatus;
860 	   switch (irType) {
861 	     case VXR_:
862 	       return NextRecord_r_64(fp,VXR.Offset[entryN],
863 				      baseRec,nextRec,found);
864 	     case VVR_:
865 	     case CVVR_:
866 	       *nextRec = BOO(VXR.First[entryN] <= baseRec,
867 			      baseRec,VXR.First[entryN]);
868 	       ASSIGNnotNULL (found, TRUE)
869 	       return pStatus;
870 	     default:
871 	       return CORRUPTED_V3_CDF;
872 	   }
873 	 }
874       }
875     }
876     vxrOffset = VXR.VXRnext;
877   }
878   /****************************************************************************
879   * No (more) VXRs.  The record number was never found.
880   ****************************************************************************/
881   ASSIGNnotNULL (found, FALSE)
882   return BOO(found == NULL,NO_SUCH_RECORD,pStatus);
883 }
884 
885 /******************************************************************************
886 * SearchForRecord64.
887 ******************************************************************************/
888 
SearchForRecord64(CDF,VDRoffset,zVar,recNum,firstRec,lastRec,offset,found)889 STATICforIDL CDFstatus SearchForRecord64 (CDF, VDRoffset, zVar, recNum,
890 					  firstRec, lastRec, offset, found)
891 struct CDFstruct *CDF;
892 OFF_T VDRoffset;
893 Logical zVar;
894 Int32 recNum;
895 Int32 *firstRec;
896 Int32 *lastRec;
897 OFF_T *offset;
898 Logical *found;         /* If NULL, return NO_SUCH_RECORD if the record is
899 			   not found.  Otherwise, set according to whether
900 			   or not the record is found and return the pending
901 			   status. */
902 {
903   CDFstatus pStatus = CDF_OK; Int32 maxRec;
904   OFF_T vxrOffset;
905   /****************************************************************************
906   * If multi-file...
907   ****************************************************************************/
908   if (!CDF->singleFile) {
909     if (!sX(ReadVDR64(CDF,CDF->fp,VDRoffset,zVar,
910 		      VDR_MAXREC,&maxRec,
911 		      VDR_NULL),&pStatus)) return pStatus;
912     if (recNum <= maxRec) {
913       ASSIGNnotNULL (firstRec, 0)
914       ASSIGNnotNULL (lastRec, maxRec)
915       ASSIGNnotNULL (offset, (OFF_T) ZERO_OFFSET64)
916       ASSIGNnotNULL (found, TRUE)
917     }
918     else {
919       ASSIGNnotNULL (found, FALSE)
920       if (found == NULL) pStatus = NO_SUCH_RECORD;
921     }
922     return pStatus;
923   }
924   /****************************************************************************
925   * ...single-file, read the offset of the first VXR.
926   ****************************************************************************/
927   if (!sX(ReadVDR64(CDF,CDF->fp,VDRoffset,zVar,
928 		    VDR_VXRHEAD,&vxrOffset,
929 		    VDR_NULL),&pStatus)) return pStatus;
930   /****************************************************************************
931   * ...and start searching there.
932   ****************************************************************************/
933   if (!sX(SearchForRecord_r_64(CDF->fp,vxrOffset,recNum,
934 			       firstRec,lastRec,
935 			       offset,found),&pStatus)) return pStatus;
936   return pStatus;
937 }
938 
SearchForRecord_r_64(fp,vxrOffset,recNum,firstRec,lastRec,offset,found)939 static CDFstatus SearchForRecord_r_64 (fp, vxrOffset, recNum, firstRec, lastRec,
940 				       offset, found)
941 vFILE *fp;
942 OFF_T vxrOffset;
943 Int32 recNum;
944 Int32 *firstRec;
945 Int32 *lastRec;
946 OFF_T *offset;
947 Logical *found;
948 {
949   CDFstatus pStatus = CDF_OK;
950   int entryN; struct VXRstruct64 VXR; Int32 irType;
951   /****************************************************************************
952   * While more VXRs...
953   ****************************************************************************/
954   while (vxrOffset != (OFF_T) ZERO_OFFSET64) {
955     /**************************************************************************
956     * Read the VXR.
957     **************************************************************************/
958     if (!sX(ReadVXR64(fp,vxrOffset,
959 		      VXR_RECORD,&VXR,
960 		      VXR_NULL),&pStatus)) return pStatus;
961     /**************************************************************************
962     * Search entries...
963     **************************************************************************/
964     if (recNum <= VXR.Last[(int)(VXR.NusedEntries-1)]) {
965       for (entryN = 0; entryN < VXR.NusedEntries; entryN++) {
966 	 if (recNum <= VXR.Last[entryN]) {
967 	   if (VXR.First[entryN] <= recNum) {
968 	     if (!sX(ReadIrType64(fp,
969 				  VXR.Offset[entryN],
970 				  &irType),&pStatus)) return pStatus;
971 	     switch (irType) {
972 	       case VXR_:
973 		 return SearchForRecord_r_64(fp,VXR.Offset[entryN],recNum,
974 					     firstRec,lastRec,offset,found);
975 	       case VVR_:
976 	       case CVVR_:
977 		 ASSIGNnotNULL (firstRec, VXR.First[entryN])
978 		 ASSIGNnotNULL (lastRec, VXR.Last[entryN])
979 		 ASSIGNnotNULL (offset, VXR.Offset[entryN])
980 		 ASSIGNnotNULL (found, TRUE)
981 		 return pStatus;
982 	       default:
983 		 return CORRUPTED_V3_CDF;
984 	     }
985 	   }
986 	   else {
987 	     ASSIGNnotNULL (found, FALSE)
988 	     return BOO(found == NULL,NO_SUCH_RECORD,pStatus);
989 	   }
990 	 }
991       }
992     }
993     vxrOffset = VXR.VXRnext;
994   }
995   /****************************************************************************
996   * No (more) VXRs.  The record number was never found.
997   ****************************************************************************/
998   ASSIGNnotNULL (found, FALSE)
999   return BOO(found == NULL,NO_SUCH_RECORD,pStatus);
1000 }
1001 
1002 /******************************************************************************
1003 * IndexingStatistics64.
1004 ******************************************************************************/
1005 
IndexingStatistics64(CDF,VDRoffset,zVar,nVXRsP,nEntriesP,nAllocP,nRecordsP,nLevelsP)1006 STATICforIDL CDFstatus IndexingStatistics64 (CDF, VDRoffset, zVar, nVXRsP,
1007 					     nEntriesP, nAllocP, nRecordsP,
1008 					     nLevelsP)
1009 struct CDFstruct *CDF;
1010 OFF_T VDRoffset;
1011 Logical zVar;
1012 Int32 *nVXRsP;
1013 Int32 *nEntriesP;
1014 Int32 *nAllocP;
1015 Int32 *nRecordsP;
1016 Int32 *nLevelsP;
1017 {
1018   CDFstatus pStatus = CDF_OK; Int32 maxRec; int level = 1;
1019   Int32 nVXRs = 0, nEntries = 0, nAlloc = 0, nRecords = 0, nLevels = 0;
1020   OFF_T vxrOffset;
1021   /****************************************************************************
1022   * Read the maximum record and the offset of the first VXR...
1023   ****************************************************************************/
1024   if (!sX(ReadVDR64(CDF,CDF->fp,VDRoffset,zVar,
1025 		    VDR_VXRHEAD,&vxrOffset,
1026 		    VDR_MAXREC,&maxRec,
1027 		    VDR_NULL),&pStatus)) return pStatus;
1028   /****************************************************************************
1029   * ...and start there.
1030   ****************************************************************************/
1031   if (vxrOffset != (OFF_T) ZERO_OFFSET64) {
1032     if (!sX(IndexingStatistics_r_64(CDF->fp,vxrOffset,
1033 				    maxRec,level,&nLevels,
1034 				    &nVXRs,&nEntries,
1035 				    &nAlloc,&nRecords),&pStatus)) return pStatus;
1036   }
1037   /****************************************************************************
1038   * Pass back requested statistics.
1039   ****************************************************************************/
1040   ASSIGNnotNULL (nVXRsP, nVXRs)
1041   ASSIGNnotNULL (nEntriesP, nEntries)
1042   ASSIGNnotNULL (nAllocP, nAlloc)
1043   ASSIGNnotNULL (nRecordsP, nRecords)
1044   ASSIGNnotNULL (nLevelsP, nLevels)
1045   return pStatus;
1046 }
1047 
IndexingStatistics_r_64(fp,vxrOffset,maxRec,level,nLevels,nVXRs,nEntries,nAlloc,nRecords)1048 static CDFstatus IndexingStatistics_r_64 (fp, vxrOffset, maxRec, level, nLevels,
1049 				          nVXRs, nEntries, nAlloc, nRecords)
1050 vFILE *fp;
1051 OFF_T vxrOffset;
1052 Int32 maxRec;
1053 int level;
1054 Int32 *nLevels;
1055 Int32 *nVXRs;
1056 Int32 *nEntries;
1057 Int32 *nAlloc;
1058 Int32 *nRecords;
1059 {
1060   CDFstatus pStatus = CDF_OK;
1061   int e; Int32 irType; struct VXRstruct64 VXR;
1062   /****************************************************************************
1063   * Check if a new level has been reached.
1064   ****************************************************************************/
1065   *nLevels = MAXIMUM(*nLevels,level);
1066   /****************************************************************************
1067   * While more VXRs...
1068   ****************************************************************************/
1069   while (vxrOffset != (OFF_T) ZERO_OFFSET64) {
1070     /**************************************************************************
1071     * Read/tally the VXR.
1072     **************************************************************************/
1073     if (!sX(ReadVXR64(fp,vxrOffset,
1074 		      VXR_RECORD,&VXR,
1075 		      VXR_NULL),&pStatus)) return pStatus;
1076     (*nVXRs)++;
1077     /**************************************************************************
1078     * Scan/count entries...
1079     **************************************************************************/
1080     for (e = 0; e < VXR.NusedEntries; e++) {
1081        (*nEntries)++;
1082        if (!sX(ReadIrType64(fp,
1083 			    VXR.Offset[e],
1084 			    &irType),&pStatus)) return pStatus;
1085        switch (irType) {
1086 	 case VXR_:
1087 	   if (!sX(IndexingStatistics_r_64(fp,VXR.Offset[e],
1088 					   maxRec,level+1,
1089 					   nLevels,nVXRs,
1090 					   nEntries,nAlloc,
1091 					   nRecords),&pStatus)) return pStatus;
1092 	   break;
1093 	 case VVR_:
1094 	 case CVVR_:
1095 	   *nAlloc += (VXR.Last[e] - VXR.First[e] + 1);
1096 	   if (VXR.First[e] <= maxRec) {
1097 	     *nRecords += MINIMUM(maxRec,VXR.Last[e]) - VXR.First[e] + 1;
1098 	   }
1099 	   break;
1100 	 default:
1101 	   return CORRUPTED_V3_CDF;
1102        }
1103     }
1104     vxrOffset = VXR.VXRnext;
1105   }
1106   return pStatus;
1107 }
1108 
1109 /******************************************************************************
1110 * BuildPadBuffer64.
1111 ******************************************************************************/
1112 
BuildPadBuffer64(CDF,Var,nRecords,how,buffer,encode)1113 STATICforIDL CDFstatus BuildPadBuffer64 (CDF, Var, nRecords, how, buffer, encode)
1114 struct CDFstruct *CDF;
1115 struct VarStruct *Var;
1116 Int32 nRecords;
1117 int *how;
1118 void **buffer;
1119 Logical encode;         /* If TRUE, return values in CDF's encoding.  If FALSE,
1120 			   return values in host computer's encoding. */
1121 {
1122   Byte *ptr; Int32 nBytes, nValues, valueN; void *padValue;
1123   Int32 VDRflags, dataType, numElems; CDFstatus pStatus = CDF_OK;
1124   OFF_T xBytes;
1125   /****************************************************************************
1126   * Determine pad value.
1127   ****************************************************************************/
1128   if (!sX(ReadVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar,
1129 		    VDR_DATATYPE,&dataType,
1130 		    VDR_NUMELEMS,&numElems,
1131 		    VDR_FLAGS,&VDRflags,
1132 		    VDR_NULL),&pStatus)) return pStatus;
1133   padValue = (void *) cdf_AllocateMemory ((size_t) Var->NvalueBytes, NULL);
1134   if (padValue == NULL) return BAD_MALLOC;
1135   if (PADvalueBITset(VDRflags)) {
1136     if (!sX(ReadVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar,
1137 		      VDR_PADVALUE,padValue,
1138 		      VDR_NULL),&pStatus)) {
1139       cdf_FreeMemory (padValue, NULL);
1140       return pStatus;
1141     }
1142     if (!encode) {
1143       if (!sX(ConvertBuffer(CDF->encoding,HostDecoding(),
1144 			    CDF->negToPosFp0,dataType,
1145 			    numElems,padValue,padValue),&pStatus)) {
1146 	cdf_FreeMemory (padValue, NULL);
1147 	return pStatus;
1148       }
1149     }
1150   }
1151   else {
1152     DefaultPadValue (dataType, numElems, padValue);
1153     if (encode) {
1154       if (!sX(ConvertBuffer(HostEncoding(),CDF->encoding,
1155 			    CDF->negToPosFp0,dataType,
1156 			    numElems,padValue,padValue),&pStatus)) {
1157 	cdf_FreeMemory (padValue, NULL);
1158 	return pStatus;
1159       }
1160     }
1161   }
1162   /****************************************************************************
1163   * Try to allocate all of the records at once...
1164   ****************************************************************************/
1165   nValues = nRecords * Var->NphyRecValues;
1166   xBytes = (OFF_T) nValues * Var->NvalueBytes;
1167 #if defined(win32)
1168   if (xBytes < (OFF_T) ((1i64 << 31) - 1)) {
1169 #else
1170   if (xBytes < (OFF_T) ((1LL << 31) - 1)) {
1171 #endif
1172     nBytes = nValues * Var->NvalueBytes;
1173 #if LIMITof64K
1174     if (nBytes < 65536L) {
1175 #endif
1176       *buffer = (void *) cdf_AllocateMemory ((size_t) nBytes, NULL);
1177       if (*buffer != NULL) {
1178         for (valueN = 0, ptr = (Byte *) *buffer;
1179 	   valueN < nValues; valueN++, ptr += (size_t) Var->NvalueBytes) {
1180 	   memmove (ptr, padValue, (size_t) Var->NvalueBytes);
1181         }
1182         cdf_FreeMemory (padValue, NULL);
1183         *how = ALLrecordsATonce;
1184         return pStatus;
1185       }
1186 #if LIMITof64K
1187     }
1188 #endif
1189   }
1190   /****************************************************************************
1191   * Not enough memory for that, try allocating one record...
1192   ****************************************************************************/
1193 #if LIMITof64K
1194   if (Var->NphyRecBytes < 65536L) {
1195 #endif
1196     *buffer = (void *) cdf_AllocateMemory ((size_t) Var->NphyRecBytes, NULL);
1197     if (*buffer != NULL) {
1198       for (valueN = 0, ptr = (Byte *) *buffer;
1199 	   valueN < Var->NphyRecValues;
1200 	   valueN++, ptr += (size_t) Var->NvalueBytes) {
1201 	 memmove (ptr, padValue, (size_t) Var->NvalueBytes);
1202       }
1203       cdf_FreeMemory (padValue, NULL);
1204       *how = ONErecordATaTIME;
1205       return pStatus;
1206     }
1207 #if LIMITof64K
1208   }
1209 #endif
1210   /****************************************************************************
1211   * Not enough memory for that either, use the one allocated value...
1212   ****************************************************************************/
1213   *buffer = padValue;
1214   *how = ONEvalueATaTIME;
1215   return pStatus;
1216 }
1217 
1218 /******************************************************************************
1219 * ReadVarValues64.
1220 *   NOTE: If more than one record is being read, full records are assumed
1221 * and the `offset' must be zero.
1222 ******************************************************************************/
1223 
ReadVarValues64(CDF,Var,startRec,offset,nValues,buffer)1224 STATICforIDL CDFstatus ReadVarValues64 (CDF, Var, startRec, offset, nValues,
1225 				        buffer)
1226 struct CDFstruct *CDF;
1227 struct VarStruct *Var;
1228 Int32 startRec;         /* Physical record number at which to start reading. */
1229 Int32 offset;           /* Byte offset within (first) record at which to
1230 			   begin reading. */
1231 Int32 nValues;          /* Number of values to read. */
1232 void *buffer;
1233 {
1234   CDFstatus pStatus = CDF_OK; OFF_T tOffset; Logical fullRecord;
1235   Int32 numElems, firstRec, lastRec, lastRecInVVR, nPadValues;
1236   Int32 readTo, recCount, nBytes;
1237   /****************************************************************************
1238   * Determine first/last record(s) being read and if full physical record(s).
1239   ****************************************************************************/
1240   firstRec = startRec;
1241   if (nValues < Var->NphyRecValues) {
1242     fullRecord = FALSE;
1243     lastRec = startRec;
1244   }
1245   else {
1246     fullRecord = TRUE;
1247     lastRec = startRec + ((nValues - 1) / Var->NphyRecValues);
1248   }
1249   /****************************************************************************
1250   * Read value(s).
1251   ****************************************************************************/
1252   switch (Var->vType) {
1253     /**************************************************************************
1254     * Standard variable in a single-file CDF...
1255     **************************************************************************/
1256     case STANDARD_:
1257       if (fullRecord) {
1258 	/**********************************************************************
1259 	* Full record(s) - read from contiguous groups...
1260 	**********************************************************************/
1261 	Byte *tBuffer = buffer; Int32 recNum = firstRec;
1262 	while (recNum <= lastRec) {
1263 	  if (recNum <= Var->maxRec) {
1264 	    if (!sX(SearchForRecord64(CDF,Var->VDRoffset64,
1265 				      Var->zVar,recNum,
1266 				      NULL,&lastRecInVVR,
1267 				      NULL,NULL),&pStatus)) return pStatus;
1268 	    readTo = MINIMUMof3(Var->maxRec,lastRec,lastRecInVVR);
1269 	    recCount = readTo - recNum + 1;
1270 	    if (!sX(RecordByteOffset64(CDF,Var,
1271 				       recNum,
1272 				       &tOffset),&pStatus)) return pStatus;
1273 	    numElems = recCount * Var->NphyRecElems;
1274 	    if (!sX(ReadVarElems64(Var,CDF->fp,tOffset,
1275 				   numElems,tBuffer),&pStatus)) return pStatus;
1276 	  }
1277 	  else {
1278 	    recCount = lastRec - recNum + 1;
1279 	    nPadValues = recCount * Var->NphyRecValues;
1280 	    if (!sX(PadBuffer64(CDF,Var,
1281 			        nPadValues,
1282 			        tBuffer),&pStatus)) return pStatus;
1283 	    sX (VIRTUAL_RECORD_DATA, &pStatus);
1284 	  }
1285 	  recNum += recCount;
1286 	  tBuffer += (size_t) (recCount * Var->NphyRecBytes);
1287 	}
1288       }
1289       else {
1290 	/**********************************************************************
1291 	* Partial record...
1292 	**********************************************************************/
1293 	if (firstRec <= Var->maxRec) {
1294 	  if (!sX(RecordByteOffset64(CDF,Var,
1295 				     firstRec,
1296 				     &tOffset),&pStatus)) return pStatus;
1297 	  tOffset += (OFF_T) offset;
1298 	  numElems = nValues * Var->NvalueElems;
1299 	  if (!sX(ReadVarElems64(Var,CDF->fp,tOffset,
1300 			         numElems,buffer),&pStatus)) return pStatus;
1301 	}
1302 	else {
1303 	  if (!sX(PadBuffer64(CDF,Var,nValues,buffer),&pStatus)) return pStatus;
1304 	  sX (VIRTUAL_RECORD_DATA, &pStatus);
1305 	}
1306       }
1307       break;
1308     /**************************************************************************
1309     * Sparse records...
1310     **************************************************************************/
1311     case SPARSE_RECORDS_: {
1312       if (fullRecord) {
1313 	if (!sX(ReadSparseFull(CDF,Var,firstRec,
1314 			       lastRec,buffer),&pStatus)) return pStatus;
1315       }
1316       else {
1317 	if (!sX(ReadSparsePartial(CDF,Var,
1318 				  startRec,offset,
1319 				  nValues,buffer),&pStatus)) return pStatus;
1320       }
1321       break;
1322     }
1323     /**************************************************************************
1324     * Compressed variable...
1325     **************************************************************************/
1326     case COMPRESSED_:
1327     case SPARSE_COMPRESSED_RECORDS_: {
1328       /************************************************************************
1329       * Initialize staging area.  Note that the staging area is only
1330       * initialized if records have been written.  This prevents the
1331       * CORRUPTED_V3_CDF error code from being returned if an explicit
1332       * blocking factor has not been specified for the variable.
1333       ************************************************************************/
1334       if (Var->stage.areaOffset64 == (OFF_T) NO_OFFSET64 && Var->maxRec > NO_RECORD) {
1335 	if (Var->blockingFactor == 0) return CORRUPTED_V3_CDF;
1336 	nBytes = Var->blockingFactor * Var->NphyRecBytes;
1337 	if (!sX(InitVarStage64(CDF,Var,nBytes),&pStatus)) return pStatus;
1338       }
1339       /************************************************************************
1340       * If full record(s) or partial record...
1341       ************************************************************************/
1342       if (fullRecord) {
1343 	if (!sX(ReadCompressedFull(CDF,Var,firstRec,
1344 				   lastRec,buffer),&pStatus)) return pStatus;
1345       }
1346       else {
1347 	if (!sX(ReadCompressedPartial(CDF,Var,startRec,
1348 				      offset,nValues,
1349 				      buffer),&pStatus)) return pStatus;
1350       }
1351       break;
1352     }
1353     /**************************************************************************
1354     * Can't do sparse arrays yet...
1355     **************************************************************************/
1356     case SPARSE_ARRAYS_:
1357     case SPARSE_RECORDS_AND_ARRAYS_:
1358       return UNKNOWN_SPARSENESS;
1359     case IN_MULTI_:
1360       if (fullRecord) {
1361 	/********************************************************************
1362 	* Full record(s).
1363 	********************************************************************/
1364 	Byte *tBuffer = buffer;
1365 	if (firstRec <= Var->maxRec) {
1366 	  if (!sX(RecordByteOffset64(CDF,Var,
1367 				     firstRec,
1368 				     &tOffset),&pStatus)) return pStatus;
1369 	  recCount = MINIMUM(lastRec,Var->maxRec) - firstRec + 1;
1370 	  numElems = recCount * Var->NphyRecElems;
1371 	  if (!sX(ReadVarElems64(Var,Var->fp,tOffset,
1372 			         numElems,tBuffer),&pStatus)) return pStatus;
1373 	  tBuffer += (size_t) (recCount * Var->NphyRecBytes);
1374 	}
1375 	if (lastRec > Var->maxRec) {
1376 	  recCount = BOO(Var->maxRec < firstRec,
1377 			 lastRec - firstRec + 1,
1378 			 lastRec - Var->maxRec);
1379 	  nPadValues = recCount * Var->NphyRecValues;
1380 	  if (!sX(PadBuffer64(CDF,Var,
1381 			      nPadValues,
1382 			      tBuffer),&pStatus)) return pStatus;
1383 	  sX (VIRTUAL_RECORD_DATA, &pStatus);
1384 	}
1385       }
1386       else {
1387 	/********************************************************************
1388 	* Partial record.
1389 	********************************************************************/
1390 	if (firstRec <= Var->maxRec) {
1391 	  if (!sX(RecordByteOffset64(CDF,Var,
1392 				     firstRec,
1393 				     &tOffset),&pStatus)) return pStatus;
1394 	  tOffset += (OFF_T) offset;
1395 	  numElems = nValues * Var->NvalueElems;
1396 	  if (!sX(ReadVarElems64(Var,Var->fp,tOffset,
1397 			         numElems,buffer),&pStatus)) return pStatus;
1398 	}
1399 	else {
1400 	  if (!sX(PadBuffer64(CDF,Var,nValues,buffer),&pStatus)) return pStatus;
1401 	  sX (VIRTUAL_RECORD_DATA, &pStatus);
1402 	}
1403       }
1404       break;
1405   }
1406   return pStatus;
1407 }
1408 
1409 /******************************************************************************
1410 * ReadVarElems64.
1411 *   NOTE: On IBM PCs, it is assumed that the number of bytes being read
1412 * will not exceed 65535.
1413 ******************************************************************************/
1414 
ReadVarElems64(Var,fp,offset,numElems,buffer)1415 STATICforIDL CDFstatus ReadVarElems64 (Var, fp, offset, numElems, buffer)
1416 struct VarStruct *Var;
1417 vFILE *fp;
1418 OFF_T offset;
1419 Int32 numElems;
1420 void *buffer;
1421 {
1422   CDFstatus pStatus = CDF_OK; size_t nBytes;
1423   /****************************************************************************
1424   * Seek to the desired offset.
1425   ****************************************************************************/
1426   if (!SEEKv64(fp,offset,vSEEK_SET)) return VAR_READ_ERROR;
1427   /****************************************************************************
1428   * Read the value(s).
1429   ****************************************************************************/
1430   nBytes = (size_t) (numElems * Var->NelemBytes);
1431   if (!READv64(buffer,nBytes,1,fp)) return VAR_READ_ERROR;
1432   /****************************************************************************
1433   * Decode value(s).
1434   ****************************************************************************/
1435   if (!sX(DECODE(Var->DecodeFunction,buffer,numElems),&pStatus)) {
1436     return pStatus;
1437   }
1438   return pStatus;
1439 }
1440 
1441 /******************************************************************************
1442 * InitVarStage64.
1443 ******************************************************************************/
1444 
InitVarStage64(CDF,Var,nBytes)1445 STATICforIDL CDFstatus InitVarStage64 (CDF, Var, nBytes)
1446 struct CDFstruct *CDF;
1447 struct VarStruct *Var;
1448 Int32 nBytes;
1449 {
1450   if (CDF->stage.fp == NULL) {
1451     CDF->stage.fp = V_scratch (ScratchDirectory(CDF), "stg");
1452     if (CDF->stage.fp == NULL) return SCRATCH_CREATE_ERROR;
1453     if (!CACHEv64(CDF->stage.fp,CDF->stage.cacheSize)) {
1454       V_delete64 (CDF->stage.fp, NULL);
1455       CDF->stage.fp = NULL;
1456       return BAD_CACHE_SIZE;
1457     }
1458     CDF->stage.mark64 = (OFF_T) ZERO_OFFSET64;
1459   }
1460   Var->stage.areaOffset64 = CDF->stage.mark64;
1461   Var->stage.firstRec = NO_RECORD;
1462   Var->stage.lastRec = NO_RECORD;
1463   Var->stage.dotOffset64 = (OFF_T) NO_OFFSET64;
1464   Var->stage.modified = FALSE;
1465   CDF->stage.mark64 += nBytes;
1466   return CDF_OK;
1467 }
1468 
1469 /******************************************************************************
1470 * InitScratch64.
1471 ******************************************************************************/
1472 
InitScratch64(scratchDir,scratchFpH,cacheSize)1473 STATICforIDL CDFstatus InitScratch64 (scratchDir, scratchFpH, cacheSize)
1474 char *scratchDir;	/* Scratch directory to be used. */
1475 vFILE **scratchFpH;	/* Scratch file handle (pointer to pointer). */
1476 int cacheSize;		/* Number of cache buffers to request. */
1477 {
1478   if (*scratchFpH == NULL) {
1479     *scratchFpH = V_scratch (scratchDir, NULL);
1480     if (*scratchFpH == NULL) return SCRATCH_CREATE_ERROR;
1481     if (!CACHEv64(*scratchFpH,cacheSize)) {
1482       V_delete64 (*scratchFpH, NULL);
1483       *scratchFpH = NULL;
1484       return BAD_CACHE_SIZE;
1485     }
1486   }
1487   else {
1488     if (V_clear(*scratchFpH) != 0) return SCRATCH_READ_ERROR;
1489     if (!SEEKv64(*scratchFpH,(OFF_T)0,vSEEK_SET)) return SCRATCH_READ_ERROR;
1490   }
1491   return CDF_OK;
1492 }
1493 
1494 /******************************************************************************
1495 * FlushStage64.
1496 ******************************************************************************/
1497 
FlushStage64(CDF,Var)1498 STATICforIDL CDFstatus FlushStage64 (CDF, Var)
1499 struct CDFstruct *CDF;
1500 struct VarStruct *Var;
1501 {
1502   CDFstatus pStatus = CDF_OK;
1503   /****************************************************************************
1504   * Based on the variable type...
1505   ****************************************************************************/
1506   switch (Var->vType) {
1507     case SPARSE_RECORDS_: {
1508       Int32 nRecords, nBytes; struct AllocStruct alloc;
1509       OFF_T tOffset;
1510       /************************************************************************
1511       * First check if there are records to be flushed in the staging area.
1512       ************************************************************************/
1513       if (!Var->stage.modified) return pStatus;
1514       /************************************************************************
1515       * Allocate a new VVR.
1516       ************************************************************************/
1517       LoadAllocVVR64 (alloc, Var->stage.firstRec, Var->stage.lastRec, FALSE)
1518       if (!sX(AllocateRecords64(CDF,Var,alloc),&pStatus)) return pStatus;
1519       Var->maxAllocated = MAXIMUM(Var->maxAllocated,Var->stage.lastRec);
1520       /************************************************************************
1521       * Copy the records to the new VVR.
1522       ************************************************************************/
1523       if (!sX(RecordByteOffset64(CDF,Var,
1524 			         Var->stage.firstRec,
1525 			         &tOffset),&pStatus)) return pStatus;
1526       nRecords = Var->stage.lastRec - Var->stage.firstRec + 1;
1527       nBytes = nRecords * Var->NphyRecBytes;
1528       if (!sX(CopyBytes64(CDF->stage.fp,Var->stage.areaOffset64,
1529 		 	  SCRATCH_READ_ERROR,nBytes,CDF->fp,
1530 			  tOffset,CDF_WRITE_ERROR),&pStatus)) return pStatus;
1531       Var->maxWritten = MAXIMUM(Var->maxWritten,Var->stage.lastRec);
1532       /************************************************************************
1533       * Clear the staging area control.
1534       ************************************************************************/
1535       Var->stage.firstRec = NO_RECORD;
1536       Var->stage.lastRec = NO_RECORD;
1537       Var->stage.dotOffset64 = (OFF_T) NO_OFFSET64;
1538       Var->stage.modified = FALSE;
1539       break;
1540     }
1541     case COMPRESSED_:
1542     case SPARSE_COMPRESSED_RECORDS_: {
1543       Int32 nRecords;
1544       OFF_T cSize, xSize, irSize, uSize, newOffset;
1545       struct CVVRstruct64 CVVR; struct VVRstruct64 VVR; struct AllocStruct alloc;
1546       /************************************************************************
1547       * First check if there are records to be flushed in the staging area.
1548       ************************************************************************/
1549       if (!Var->stage.modified) return pStatus;
1550       /************************************************************************
1551       * Check if the scratch file is created/initialized.
1552       ************************************************************************/
1553       if (!sX(InitScratch64(ScratchDirectory(CDF),
1554 			    &(CDF->compressFp),
1555 			    CDF->compressCacheSize),&pStatus)) return pStatus;
1556       /************************************************************************
1557       * Compress the records in the stage.
1558       ************************************************************************/
1559       nRecords = Var->stage.lastRec - Var->stage.firstRec + 1;
1560       uSize = nRecords * Var->NphyRecBytes;
1561       if (!sX(Compress64(CDF->stage.fp,Var->stage.areaOffset64,
1562 		         uSize,SCRATCH_READ_ERROR,Var->cType,
1563 		         Var->cParms,CDF->compressFp,(OFF_T) ZERO_OFFSET64,
1564 		         &cSize,SCRATCH_WRITE_ERROR),&pStatus)) return pStatus;
1565       /************************************************************************
1566       * Does a VVR/CVVR for this block of records already exist?
1567       ************************************************************************/
1568       if (Var->stage.dotOffset64 != (OFF_T) NO_OFFSET64) {
1569 	/**********************************************************************
1570 	* Read the size of the existing VVR/CVVR.
1571 	**********************************************************************/
1572 	if (!sX(ReadIrSize64(CDF->fp,
1573 			     Var->stage.dotOffset64,
1574 			     &irSize),&pStatus)) return pStatus;
1575 	/**********************************************************************
1576 	* Will a CVVR fit?  Note that reserve space is only added to new CVVRs.
1577 	**********************************************************************/
1578 	if (CVVR_BASE_SIZE64 + cSize <= irSize) {
1579 	  LoadCVVRx64 (CVVR, irSize, cSize)
1580 	  if (!sX(WriteCVVR64(CDF->fp,Var->stage.dotOffset64,
1581 			      CVVR_RECORDx,&CVVR,
1582 			      CVVR_NULL),&pStatus)) return pStatus;
1583 	  if (!sX(CopyBytes64(CDF->compressFp,(OFF_T) ZERO_OFFSET64,
1584 			      SCRATCH_READ_ERROR,cSize,CDF->fp,
1585 			      Var->stage.dotOffset64 + CVVR_BASE_SIZE64,
1586 			      CDF_WRITE_ERROR),&pStatus)) return pStatus;
1587 	  Var->stage.modified = FALSE;
1588 	  return pStatus;
1589 	}
1590 	/**********************************************************************
1591 	* Will a VVR fit?
1592 	**********************************************************************/
1593 	if (VVR_BASE_SIZE64 + uSize <= irSize) {
1594 	  LoadVVRx64 (VVR, irSize)
1595 	  if (!sX(WriteVVR64(CDF->fp,Var->stage.dotOffset64,
1596 			     VVR_RECORDx,&VVR,
1597 			     VVR_NULL),&pStatus)) return pStatus;
1598 	  if (!sX(CopyBytes64(CDF->stage.fp,Var->stage.areaOffset64,
1599 			      SCRATCH_READ_ERROR,uSize,CDF->fp,
1600 			      Var->stage.dotOffset64 + VVR_BASE_SIZE64,
1601 			      CDF_WRITE_ERROR),&pStatus)) return pStatus;
1602 	  Var->stage.modified = FALSE;
1603 	  sX (DID_NOT_COMPRESS, &pStatus);
1604 	  return pStatus;
1605 	}
1606 	/**********************************************************************
1607 	* The existing VVR/CVVR will have to be resized.  Will a CVVR be
1608 	* smaller than a VVR?  Note that reserve space is not added to the
1609 	* size of the CVVR because a new one isn't being created.
1610 	**********************************************************************/
1611 	if (CVVR_BASE_SIZE64 + cSize < VVR_BASE_SIZE64 + uSize) {
1612 	  if (!sX(ResizeIR64(CDF,Var->stage.dotOffset64,
1613 			     CVVR_BASE_SIZE64 + cSize,
1614 			     &newOffset,TRUE,NULL),&pStatus)) return pStatus;
1615 	  LoadCVVRx64 (CVVR, CVVR_BASE_SIZE64 + cSize, cSize)
1616 	  if (!sX(WriteCVVR64(CDF->fp,newOffset,
1617 			      CVVR_RECORDx,&CVVR,
1618 			      CVVR_NULL),&pStatus)) return pStatus;
1619 	  if (!sX(CopyBytes64(CDF->compressFp,(OFF_T) ZERO_OFFSET64,
1620 			      SCRATCH_READ_ERROR,cSize,
1621 			      CDF->fp,newOffset + CVVR_BASE_SIZE64,
1622 			      CDF_WRITE_ERROR),&pStatus)) return pStatus;
1623 	}
1624 	else {
1625 	  if (!sX(ResizeIR64(CDF,Var->stage.dotOffset64,
1626 			     VVR_BASE_SIZE64 + uSize,
1627 			     &newOffset,TRUE,NULL),&pStatus)) return pStatus;
1628 	  LoadVVRx64 (VVR, VVR_BASE_SIZE64 + uSize)
1629 	  if (!sX(WriteVVR64(CDF->fp,newOffset,
1630 			     VVR_RECORDx,&VVR,
1631 			     VVR_NULL),&pStatus)) return pStatus;
1632 	  if (!sX(CopyBytes64(CDF->stage.fp,Var->stage.areaOffset64,
1633 			      SCRATCH_READ_ERROR,uSize,
1634 			      CDF->fp,newOffset + VVR_BASE_SIZE64,
1635 			      CDF_WRITE_ERROR),&pStatus)) return pStatus;
1636 	  sX (DID_NOT_COMPRESS, &pStatus);
1637 	}
1638 	if (!sX(ModIndexOffset64(CDF,Var,
1639 			         Var->stage.firstRec,
1640 			         Var->stage.lastRec,
1641 			         newOffset),&pStatus)) return pStatus;
1642 	Var->stage.dotOffset64 = newOffset;
1643 	Var->stage.modified = FALSE;
1644 	return pStatus;
1645       }
1646       /************************************************************************
1647       * A new VVR/CVVR will have to be created.  First calculate the reserve
1648       * size.
1649       ************************************************************************/
1650       if (Var->reservePct <= 0)
1651 	xSize = 0;
1652       else {
1653 	if (Var->reservePct <= 100) {
1654 	  Int32 tSize = (Int32) ((uSize * (Var->reservePct/100.0)) + 0.5);
1655 	  xSize = MAXIMUM(cSize,tSize) - cSize;
1656 	}
1657 	else {
1658 	  Int32 tSize = (Int32) ((cSize * (Var->reservePct/100.0)) + 0.5);
1659 	  xSize = tSize - cSize;
1660 	}
1661       }
1662       /************************************************************************
1663       * Will a CVVR be smaller than a VVR?
1664       ************************************************************************/
1665       if (CVVR_BASE_SIZE64 + cSize + xSize < VVR_BASE_SIZE64 + uSize) {
1666 	LoadAllocCVVR64 (alloc, Var->stage.firstRec, Var->stage.lastRec,
1667 		         cSize, xSize)
1668 	if (!sX(AllocateRecords64(CDF,Var,alloc),&pStatus)) return pStatus;
1669 	if (!sX(SearchForRecord64(CDF,Var->VDRoffset64,Var->zVar,
1670 				  Var->stage.firstRec,NULL,NULL,
1671 				  &newOffset,NULL),&pStatus)) return pStatus;
1672 	LoadCVVRx64 (CVVR, CVVR_BASE_SIZE64 + cSize + xSize, cSize)
1673 	if (!sX(WriteCVVR64(CDF->fp,newOffset,
1674 			    CVVR_RECORDx,&CVVR,
1675 			    CVVR_NULL),&pStatus)) return pStatus;
1676 	if (!sX(CopyBytes64(CDF->compressFp,(OFF_T) ZERO_OFFSET64,
1677 			    SCRATCH_READ_ERROR,cSize,
1678 			    CDF->fp,newOffset + CVVR_BASE_SIZE64,
1679 			    CDF_WRITE_ERROR),&pStatus)) return pStatus;
1680 	Var->stage.dotOffset64 = newOffset;
1681 	Var->stage.modified = FALSE;
1682 	return pStatus;
1683       }
1684       /************************************************************************
1685       * The CVVR will be too big - create a VVR.
1686       ************************************************************************/
1687       LoadAllocVVR64 (alloc, Var->stage.firstRec, Var->stage.lastRec, TRUE)
1688       if (!sX(AllocateRecords64(CDF,Var,alloc),&pStatus)) return pStatus;
1689       if (!sX(SearchForRecord64(CDF,Var->VDRoffset64,Var->zVar,
1690 				Var->stage.firstRec,NULL,NULL,
1691 				&newOffset,NULL),&pStatus)) return pStatus;
1692       LoadVVRx64 (VVR, VVR_BASE_SIZE64 + uSize)
1693       if (!sX(WriteVVR64(CDF->fp,newOffset,
1694 		         VVR_RECORDx,&VVR,
1695 		         VVR_NULL),&pStatus)) return pStatus;
1696       if (!sX(CopyBytes64(CDF->stage.fp,Var->stage.areaOffset64,
1697 			  SCRATCH_READ_ERROR,uSize,
1698 			  CDF->fp,newOffset + VVR_BASE_SIZE64,
1699 			  CDF_WRITE_ERROR),&pStatus)) return pStatus;
1700       Var->stage.dotOffset64 = newOffset;
1701       Var->stage.modified = FALSE;
1702       sX (DID_NOT_COMPRESS, &pStatus);
1703       return pStatus;
1704     }
1705     default:
1706       return CDF_INTERNAL_ERROR;
1707   }
1708   return pStatus;
1709 }
1710 
1711 /******************************************************************************
1712 * BringToStage.
1713 ******************************************************************************/
1714 
BringToStage(CDF,Var,recNum,found)1715 static CDFstatus BringToStage (CDF, Var, recNum, found)
1716 struct CDFstruct *CDF;
1717 struct VarStruct *Var;
1718 Int32 recNum;
1719 Logical *found;
1720 {
1721   CDFstatus pStatus = CDF_OK;
1722   /****************************************************************************
1723   * First check if record is already in the stage.
1724   ****************************************************************************/
1725   if (INCLUSIVE(Var->stage.firstRec,recNum,Var->stage.lastRec)) {
1726     ASSIGNnotNULL (found, TRUE)
1727     return pStatus;
1728   }
1729   /****************************************************************************
1730   * Then, based on variable type...
1731   ****************************************************************************/
1732   switch (Var->vType) {
1733     case COMPRESSED_:
1734     case SPARSE_COMPRESSED_RECORDS_: {
1735       Int32 firstRec, lastRec, nRecords; OFF_T uSize; Logical foundX;
1736       OFF_T offset;
1737       /************************************************************************
1738       * Determine if the record exists.
1739       ************************************************************************/
1740       if (!sX(SearchForRecord64(CDF,Var->VDRoffset64,Var->zVar,
1741 			        recNum,&firstRec,&lastRec,
1742 			        &offset,&foundX),&pStatus)) return pStatus;
1743       ASSIGNnotNULL (found, foundX)
1744       if (!foundX) return BOO(found == NULL,NO_SUCH_RECORD,pStatus);
1745       /************************************************************************
1746       * Flush the stage before...
1747       ************************************************************************/
1748       if (!sX(FlushStage64(CDF,Var),&pStatus)) return pStatus;
1749       /************************************************************************
1750       * ...decompressing the CVVR (or VVR if the records did not compress) to
1751       * the staging area.
1752       ************************************************************************/
1753       nRecords = lastRec - firstRec + 1;
1754       uSize = nRecords * Var->NphyRecBytes;
1755       if (!sX(DecompressToStage64(CDF,Var,
1756 				  offset,uSize),&pStatus)) return pStatus;
1757       /************************************************************************
1758       * Update staging control.
1759       ************************************************************************/
1760       Var->stage.firstRec = firstRec;
1761       Var->stage.lastRec = lastRec;
1762       Var->stage.dotOffset64 = offset;
1763       Var->stage.modified = FALSE;
1764       break;
1765     }
1766     default:
1767       return CDF_INTERNAL_ERROR;
1768   }
1769   return pStatus;
1770 }
1771 
1772 /******************************************************************************
1773 * CopyBytes64.
1774 ******************************************************************************/
1775 
CopyBytes64(iFp,iStart,iError,nBytes,oFp,oStart,oError)1776 STATICforIDL CDFstatus CopyBytes64 (iFp, iStart, iError, nBytes, oFp, oStart,
1777 				    oError)
1778 vFILE *iFp;
1779 OFF_T iStart;
1780 CDFstatus iError;
1781 OFF_T nBytes;
1782 vFILE *oFp;
1783 OFF_T oStart;
1784 CDFstatus oError;
1785 {
1786   Int32 nBlocks = (Int32) (nBytes / COPYblockSIZE);	/* Number of full blocks
1787 							   that can be copied. */
1788   Int32 lastCount = (Int32) (nBytes % COPYblockSIZE);	/* Number of bytes
1789 							   remaining to be copied
1790 							   after the full blocks
1791 							   have been copied. */
1792   Int32 i; Byte buffer[COPYblockSIZE];
1793   /****************************************************************************
1794   * If the copy is within the same file...
1795   ****************************************************************************/
1796   if (iFp == oFp) {
1797     /**************************************************************************
1798     * If the input group (of bytes) is before the output group start at the
1799     * end in case they overlap.
1800     **************************************************************************/
1801     if (iStart < oStart) {
1802       if (nBlocks > 0) {
1803 	OFF_T iOffset = iStart + (OFF_T) (nBytes - COPYblockSIZE);
1804 	OFF_T oOffset = oStart + (OFF_T) (nBytes - COPYblockSIZE);
1805 	for (i = 0; i < nBlocks; i++) {
1806 	   if (!SEEKv64(iFp,iOffset,vSEEK_SET)) return iError;
1807 	   if (!READv64(buffer,(size_t)COPYblockSIZE,(size_t)1,iFp)) return
1808 								   iError;
1809 	   if (!SEEKv64(oFp,oOffset,vSEEK_SET)) return oError;
1810 	   if (!WRITEv64(buffer,(size_t)COPYblockSIZE,(size_t)1,oFp)) return
1811 								    oError;
1812 	   iOffset -= (OFF_T) COPYblockSIZE;
1813 	   oOffset -= (OFF_T) COPYblockSIZE;
1814 	}
1815       }
1816       if (lastCount > 0) {
1817 	if (!SEEKv64(iFp,iStart,vSEEK_SET)) return iError;
1818 	if (!READv64(buffer,(size_t)lastCount,(size_t)1,iFp)) return iError;
1819 	if (!SEEKv64(oFp,oStart,vSEEK_SET)) return oError;
1820 	if (!WRITEv64(buffer,(size_t)lastCount,(size_t)1,oFp)) return oError;
1821       }
1822     }
1823     /**************************************************************************
1824     * If the input group (of bytes) is after the output group start at the
1825     * beginning in case they overlap.
1826     **************************************************************************/
1827     if (iStart > oStart) {
1828       OFF_T iOffset = iStart;
1829       OFF_T oOffset = oStart;
1830       if (nBlocks > 0) {
1831 	for (i = 0; i < nBlocks; i++) {
1832 	   if (!SEEKv64(iFp,iOffset,vSEEK_SET)) return iError;
1833 	   if (!READv64(buffer,(size_t)COPYblockSIZE,(size_t)1,iFp)) return
1834 								   iError;
1835 	   if (!SEEKv64(oFp,oOffset,vSEEK_SET)) return oError;
1836 	   if (!WRITEv64(buffer,(size_t)COPYblockSIZE,(size_t)1,oFp)) return
1837 								    oError;
1838 	   iOffset += (OFF_T) COPYblockSIZE;
1839 	   oOffset += (OFF_T) COPYblockSIZE;
1840 	}
1841       }
1842       if (lastCount > 0) {
1843 	if (!SEEKv64(iFp,iOffset,vSEEK_SET)) return iError;
1844 	if (!READv64(buffer,(size_t)lastCount,(size_t)1,iFp)) return iError;
1845 	if (!SEEKv64(oFp,oOffset,vSEEK_SET)) return oError;
1846 	if (!WRITEv64(buffer,(size_t)lastCount,(size_t)1,oFp)) return oError;
1847       }
1848     }
1849     /**************************************************************************
1850     * Offsets are the same - do nothing.
1851     **************************************************************************/
1852   }
1853   else {
1854     /**************************************************************************
1855     * Different files...
1856     **************************************************************************/
1857     if (!SEEKv64(iFp,iStart,vSEEK_SET)) return iError;
1858     if (!SEEKv64(oFp,oStart,vSEEK_SET)) return oError;
1859     for (i = 0; i < nBlocks; i++) {
1860        if (!READv64(buffer,(size_t)COPYblockSIZE,(size_t)1,iFp)) return iError;
1861        if (!WRITEv64(buffer,(size_t)COPYblockSIZE,(size_t)1,oFp)) return oError;
1862     }
1863     if (lastCount > 0) {
1864       if (!READv64(buffer,(size_t)lastCount,(size_t)1,iFp)) return iError;
1865       if (!WRITEv64(buffer,(size_t)lastCount,(size_t)1,oFp)) return oError;
1866     }
1867   }
1868   return CDF_OK;
1869 }
1870 
1871 /******************************************************************************
1872 * ModIndexOffset64.
1873 ******************************************************************************/
1874 
ModIndexOffset64(CDF,Var,firstRec,lastRec,newOffset)1875 STATICforIDL CDFstatus ModIndexOffset64 (CDF, Var, firstRec, lastRec, newOffset)
1876 struct CDFstruct *CDF;  /* Pointer to CDF. */
1877 struct VarStruct *Var;  /* Pointer to variable. */
1878 Int32 firstRec;         /* First record of entry. */
1879 Int32 lastRec;          /* Last record of entry. */
1880 OFF_T newOffset;        /* New VVR/CVVR/SVVR offset. */
1881 {
1882   CDFstatus pStatus = CDF_OK; OFF_T vxrOffset;
1883   /****************************************************************************
1884   * Read offset of first VXR...
1885   ****************************************************************************/
1886   if (!sX(ReadVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar,
1887 		    VDR_VXRHEAD,&vxrOffset,
1888 		    VDR_NULL),&pStatus)) return pStatus;
1889   /****************************************************************************
1890   * ...and start there.
1891   ****************************************************************************/
1892   if (!sX(ModIndexOffset_r_64(CDF->fp,vxrOffset,
1893 			      firstRec,lastRec,
1894 			      newOffset),&pStatus)) return pStatus;
1895   return pStatus;
1896 }
1897 
ModIndexOffset_r_64(fp,vxrOffset,firstRec,lastRec,newOffset)1898 static CDFstatus ModIndexOffset_r_64 (fp, vxrOffset, firstRec, lastRec, newOffset)
1899 vFILE *fp;              /* File pointer to dotCDF file. */
1900 OFF_T vxrOffset;        /* VXR at which to start. */
1901 Int32 firstRec;         /* First record of entry. */
1902 Int32 lastRec;          /* Last record of entry. */
1903 OFF_T newOffset;        /* New VVR/CVVR/SVVR offset. */
1904 {
1905   CDFstatus pStatus = CDF_OK;
1906   struct VXRstruct64 VXR; int entryN; Int32 irType;
1907   /****************************************************************************
1908   * While more VXRs...
1909   ****************************************************************************/
1910   while (vxrOffset != (OFF_T) ZERO_OFFSET64) {
1911     /**************************************************************************
1912     * Read the VXR.
1913     **************************************************************************/
1914     if (!sX(ReadVXR64(fp,vxrOffset,
1915 		      VXR_RECORD,&VXR,
1916 		      VXR_NULL),&pStatus)) return pStatus;
1917     /**************************************************************************
1918     * Search through index entries...
1919     **************************************************************************/
1920     for (entryN = 0; entryN < VXR.NusedEntries; entryN++) {
1921        if (VXR.First[entryN] <= firstRec && lastRec <= VXR.Last[entryN]) {
1922 	 if (!sX(ReadIrType64(fp,
1923 			      VXR.Offset[entryN],
1924 			      &irType),&pStatus)) return pStatus;
1925 	 if (irType == VXR_) return ModIndexOffset_r_64(fp,VXR.Offset[entryN],
1926 						        firstRec,lastRec,
1927 						        newOffset);
1928 	 if (VXR.First[entryN] == firstRec && lastRec == VXR.Last[entryN]) {
1929 	   VXR.Offset[entryN] = newOffset;
1930 	   if (!sX(WriteVXR64(fp,vxrOffset,
1931 			      VXR_RECORD,&VXR,
1932 			      VXR_NULL),&pStatus)) return pStatus;
1933 	   return pStatus;
1934 	 }
1935 	 return CDF_INTERNAL_ERROR;             /* or CORRUPTED_V3_CDF? */
1936        }
1937     }
1938     /**************************************************************************
1939     * Go to next VXR.
1940     **************************************************************************/
1941     vxrOffset = VXR.VXRnext;
1942   }
1943   /****************************************************************************
1944   * No more VXRs.
1945   ****************************************************************************/
1946   return CDF_INTERNAL_ERROR;
1947 }
1948 
1949 /******************************************************************************
1950 * WriteCompressedRecords.
1951 ******************************************************************************/
1952 
WriteCompressedRecords(CDF,Var,firstRec,lastRec,buffer,nValues,offset,fullRecord)1953 static CDFstatus WriteCompressedRecords (CDF, Var, firstRec, lastRec, buffer,
1954 					 nValues, offset, fullRecord)
1955 struct CDFstruct *CDF;  /* Pointer to CDF. */
1956 struct VarStruct *Var;  /* Pointer to variable. */
1957 Int32 firstRec;         /* First record being written. */
1958 Int32 lastRec;          /* Last record being written. */
1959 void *buffer;           /* Buffer of values. */
1960 Int32 nValues;          /* Number of values being written. */
1961 OFF_T offset;           /* If not full record(s), byte offset in record at
1962 			   which to write. */
1963 Logical fullRecord;     /* Full record(s) being written? */
1964 {
1965   CDFstatus pStatus = CDF_OK; Logical found;
1966   Int32 recCount, recordOffsetInStage, maxRecThisBlock;
1967   Int32 nextRec, writeTo, numElems; void *padBuffer; int how;
1968   Int32 recNum = firstRec; Byte *tBuffer = (Byte *) buffer;
1969   OFF_T tOffset;
1970   /****************************************************************************
1971   * From first to last record...
1972   ****************************************************************************/
1973   while (recNum <= lastRec) {
1974      /*************************************************************************
1975      * Check if this record is in the staging area.
1976      *************************************************************************/
1977      if (INCLUSIVE(Var->stage.firstRec,recNum,Var->stage.lastRec)) {
1978        recordOffsetInStage = recNum - Var->stage.firstRec;
1979        tOffset = Var->stage.areaOffset64;
1980        tOffset += (recordOffsetInStage * Var->NphyRecBytes);
1981        if (fullRecord) {
1982 	 if (Var->stage.dotOffset64 == (OFF_T) NO_OFFSET64) {
1983 	   maxRecThisBlock = Var->stage.firstRec + Var->blockingFactor - 1;
1984 	   if (!sX(NextRecord64(CDF,Var->VDRoffset64,
1985 			        Var->zVar,recNum,
1986 			        &nextRec,&found),&pStatus)) return pStatus;
1987 	   if (!found)
1988 	     writeTo = MINIMUM(maxRecThisBlock,lastRec);
1989 	   else {
1990 	     Int32 prevRecN = nextRec - 1;
1991 	     writeTo = MINIMUMof3(maxRecThisBlock,prevRecN,lastRec);
1992 	   }
1993 	 }
1994 	 else
1995 	   writeTo = MINIMUM(Var->stage.lastRec,lastRec);
1996 	 recCount = writeTo - recNum + 1;
1997 	 numElems = recCount * Var->NphyRecElems;
1998        }
1999        else {
2000 	 writeTo = recNum;
2001 	 recCount = 1;
2002 	 numElems = nValues * Var->NvalueElems;
2003 	 tOffset += offset;
2004        }
2005        if (!sX(WriteVarElems64(Var,CDF->stage.fp,
2006 			       tOffset,numElems,
2007 			       tBuffer),&pStatus)) return pStatus;
2008        Var->stage.lastRec = MAXIMUM(Var->stage.lastRec,writeTo);
2009        Var->stage.modified = TRUE;
2010        tBuffer += (size_t) (numElems * Var->NelemBytes);
2011        recNum += recCount;
2012        continue;
2013      }
2014      /*************************************************************************
2015      * Not in the staging area...check if this record is in an existing CVVR.
2016      *************************************************************************/
2017      if (!sX(BringToStage(CDF,Var,recNum,&found),&pStatus)) return pStatus;
2018      if (found) {
2019        recordOffsetInStage = recNum - Var->stage.firstRec;
2020        tOffset = Var->stage.areaOffset64;
2021        tOffset += (recordOffsetInStage * Var->NphyRecBytes);
2022        if (fullRecord) {
2023 	 writeTo = MINIMUM(Var->stage.lastRec,lastRec);
2024 	 recCount = writeTo - recNum + 1;
2025 	 numElems = recCount * Var->NphyRecElems;
2026        }
2027        else {
2028 	 writeTo = recNum;
2029 	 recCount = 1;
2030 	 numElems = nValues * Var->NvalueElems;
2031 	 tOffset += offset;
2032        }
2033        if (!sX(WriteVarElems64(Var,CDF->stage.fp,
2034 			       tOffset,numElems,
2035 			       tBuffer),&pStatus)) return pStatus;
2036        Var->stage.modified = TRUE;
2037        tBuffer += (size_t) (numElems * Var->NelemBytes);
2038        recNum += recCount;
2039        continue;
2040      }
2041      /*************************************************************************
2042      * Not in an existing CVVR...this record does not exist.  First check
2043      * if the record(s) can be added to the records in the stage.
2044      *************************************************************************/
2045      if (Var->stage.firstRec != NO_RECORD) {
2046        if (Var->stage.dotOffset64 == (OFF_T) NO_OFFSET64) {
2047 	 if (recNum == Var->stage.lastRec + 1) {
2048 	   maxRecThisBlock = Var->stage.firstRec + Var->blockingFactor - 1;
2049 	   if (recNum <= maxRecThisBlock) {
2050 	     recordOffsetInStage = recNum - Var->stage.firstRec;
2051 	     tOffset = Var->stage.areaOffset64;
2052 	     tOffset += (recordOffsetInStage * Var->NphyRecBytes);
2053 	     if (fullRecord) {
2054 	       if (!sX(NextRecord64(CDF,Var->VDRoffset64,
2055 				    Var->zVar,recNum,
2056 				    &nextRec,&found),&pStatus)) return pStatus;
2057 	       if (!found)
2058 		 writeTo = MINIMUM(maxRecThisBlock,lastRec);
2059 	       else {
2060 		 Int32 prevRecN = nextRec - 1;
2061 		 writeTo = MINIMUMof3(maxRecThisBlock,prevRecN,lastRec);
2062 	       }
2063 	       recCount = writeTo - recNum + 1;
2064 	       numElems = recCount * Var->NphyRecElems;
2065 	     }
2066 	     else {
2067 	       if (!sX(BuildPadBuffer64(CDF,Var,INT32_ONE,
2068 				        &how,&padBuffer,
2069 				        TRUE),&pStatus)) return pStatus;
2070 	       if (!sX(WritePadValues64(Var,CDF->stage.fp,
2071 				        tOffset,INT32_ONE,how,
2072 				        padBuffer),&pStatus)) return pStatus;
2073 	       cdf_FreeMemory (padBuffer, NULL);
2074 	       writeTo = recNum;
2075 	       recCount = 1;
2076 	       numElems = nValues * Var->NvalueElems;
2077 	       tOffset += offset;
2078 	     }
2079 	     if (!sX(WriteVarElems64(Var,CDF->stage.fp,
2080 				     tOffset,numElems,
2081 				     tBuffer),&pStatus)) return pStatus;
2082 	     Var->stage.lastRec = MAXIMUM(Var->stage.lastRec,writeTo);
2083 	     Var->stage.modified = TRUE;
2084 	     tBuffer += (size_t) (numElems * Var->NelemBytes);
2085 	     recNum += recCount;
2086 	     continue;
2087 	   }
2088 	 }
2089        }
2090      }
2091      /*************************************************************************
2092      * This record cannot be added to the block of records currently in
2093      * the staging area.  Start a new block of records.
2094      *************************************************************************/
2095      if (!sX(FlushStage64(CDF,Var),&pStatus)) return pStatus;
2096      tOffset = Var->stage.areaOffset64;
2097      if (fullRecord) {
2098        maxRecThisBlock = recNum + Var->blockingFactor - 1;
2099        if (!sX(NextRecord64(CDF,Var->VDRoffset64,Var->zVar,
2100 			    recNum,&nextRec,&found),&pStatus)) return pStatus;
2101        if (!found)
2102 	 writeTo = MINIMUM(maxRecThisBlock,lastRec);
2103        else {
2104 	 Int32 prevRecN = nextRec - 1;
2105 	 writeTo = MINIMUMof3(maxRecThisBlock,prevRecN,lastRec);
2106        }
2107        recCount = writeTo - recNum + 1;
2108        numElems = recCount * Var->NphyRecElems;
2109      }
2110      else {
2111        if (!sX(BuildPadBuffer64(CDF,Var,INT32_ONE,
2112 			        &how,&padBuffer,
2113 			        TRUE),&pStatus)) return pStatus;
2114        if (!sX(WritePadValues64(Var,CDF->stage.fp,
2115 			        tOffset,INT32_ONE,how,
2116 			        padBuffer),&pStatus)) return pStatus;
2117        cdf_FreeMemory (padBuffer, NULL);
2118        writeTo = recNum;
2119        recCount = 1;
2120        numElems = nValues * Var->NvalueElems;
2121        tOffset += offset;
2122      }
2123      if (!sX(WriteVarElems64(Var,CDF->stage.fp,
2124 			     tOffset,numElems,
2125 			     tBuffer),&pStatus)) return pStatus;
2126      Var->stage.firstRec = recNum;
2127      Var->stage.lastRec = writeTo;
2128      Var->stage.dotOffset64 = (OFF_T) NO_OFFSET64;
2129      Var->stage.modified = TRUE;
2130      tBuffer += (size_t) (numElems * Var->NelemBytes);
2131      recNum += recCount;
2132   }
2133   return pStatus;
2134 }
2135 
2136 /******************************************************************************
2137 * CalcCompressionPct64.
2138 ******************************************************************************/
2139 
CalcCompressionPct64(CDF,vdrOffset,zVar,cPct)2140 STATICforIDL CDFstatus CalcCompressionPct64 (CDF, vdrOffset, zVar, cPct)
2141 struct CDFstruct *CDF;
2142 OFF_T vdrOffset;
2143 Logical zVar;
2144 long *cPct;
2145 {
2146   CDFstatus pStatus = CDF_OK; OFF_T vxrOffset;
2147   OFF_T uTotal = 0, cTotal = 0; Int32 nPhyRecBytes;
2148   /****************************************************************************
2149   * Calculate the number of bytes per physical record.
2150   ****************************************************************************/
2151   if (!sX(CalcPhyRecBytes64(CDF,vdrOffset,
2152 			    zVar,&nPhyRecBytes),&pStatus)) return pStatus;
2153   /****************************************************************************
2154   * Read the offset of the first VXR (return 0% if no VXRs)...
2155   ****************************************************************************/
2156   if (!sX(ReadVDR64(CDF,CDF->fp,vdrOffset,zVar,
2157 		    VDR_VXRHEAD,&vxrOffset,
2158 		    VDR_NULL),&pStatus)) return pStatus;
2159   if (vxrOffset == (OFF_T) ZERO_OFFSET64) {
2160     *cPct = 0;
2161     return pStatus;
2162   }
2163   /****************************************************************************
2164   * ...and start there.
2165   ****************************************************************************/
2166   if (!sX(CalcCompressionPct_r_64(CDF->fp,vxrOffset,
2167 			          nPhyRecBytes,
2168 			          &uTotal,&cTotal),&pStatus)) return pStatus;
2169   /****************************************************************************
2170   * Calculate percentage.
2171   ****************************************************************************/
2172   *cPct = (long) (((100.0*cTotal) / uTotal) + 0.5);
2173   return pStatus;
2174 }
2175 
CalcCompressionPct_r_64(fp,vxrOffset,nPhyRecBytes,uTotal,cTotal)2176 static CDFstatus CalcCompressionPct_r_64 (fp, vxrOffset, nPhyRecBytes, uTotal,
2177 				          cTotal)
2178 vFILE *fp;
2179 OFF_T vxrOffset;
2180 Int32 nPhyRecBytes;
2181 OFF_T *uTotal;
2182 OFF_T *cTotal;
2183 {
2184   CDFstatus pStatus = CDF_OK; struct VXRstruct64 VXR; int entryN;
2185   Int32 nRecords, irType; OFF_T uSize, irSize;
2186   /****************************************************************************
2187   * While more VXRs...
2188   ****************************************************************************/
2189   while (vxrOffset != (OFF_T) ZERO_OFFSET64) {
2190     /**************************************************************************
2191     * Read the VXR.
2192     **************************************************************************/
2193     if (!sX(ReadVXR64(fp,vxrOffset,
2194 		      VXR_RECORD,&VXR,
2195 		      VXR_NULL),&pStatus)) return pStatus;
2196     /**************************************************************************
2197     * Scan entries...
2198     **************************************************************************/
2199     for (entryN = 0; entryN < VXR.NusedEntries; entryN++) {
2200        if (!sX(ReadIrType64(fp,VXR.Offset[entryN],&irType),&pStatus)) return
2201 								    pStatus;
2202        switch (irType) {
2203 	 case VXR_:
2204 	   if (!sX(CalcCompressionPct_r_64(fp,VXR.Offset[entryN],
2205 					   nPhyRecBytes,uTotal,
2206 					   cTotal),&pStatus)) return pStatus;
2207 	   break;
2208 	 case VVR_:
2209 	 case CVVR_:
2210 	   /*******************************************************************
2211 	   * Accumulate uncompressed size.
2212 	   *******************************************************************/
2213 	   nRecords = VXR.Last[entryN] - VXR.First[entryN] + 1;
2214 	   uSize = nRecords * nPhyRecBytes;
2215 	   *uTotal += uSize;
2216 	   /*******************************************************************
2217 	   * Accumulate compressed size.
2218 	   *******************************************************************/
2219 	   if (!sX(ReadIrSize64(fp,VXR.Offset[entryN],&irSize),&pStatus))
2220 								return pStatus;
2221 	   *cTotal += irSize - BOO(irType == CVVR_,
2222 				   CVVR_BASE_SIZE64,
2223 				   VVR_BASE_SIZE64);
2224 	   break;
2225 	 default:
2226 	   return CORRUPTED_V3_CDF;
2227        }
2228     }
2229     vxrOffset = VXR.VXRnext;
2230   }
2231   return pStatus;
2232 }
2233 
2234 /******************************************************************************
2235 * CalcPhyRecBytes64.
2236 ******************************************************************************/
2237 
CalcPhyRecBytes64(CDF,vdrOffset,zVar,nPhyRecBytes)2238 STATICforIDL CDFstatus CalcPhyRecBytes64 (CDF, vdrOffset, zVar, nPhyRecBytes)
2239 struct CDFstruct *CDF;
2240 OFF_T vdrOffset;
2241 Logical zVar;
2242 Int32 *nPhyRecBytes;
2243 {
2244   CDFstatus pStatus = CDF_OK; int dimN; Int32 dataType, numElems;
2245   Int32 numDims, dimSizes[CDF_MAX_DIMS], dimVarys[CDF_MAX_DIMS];
2246   if (!sX(CalcDimParms64(CDF,vdrOffset,zVar,
2247 		         &numDims,dimSizes,dimVarys),&pStatus)) return pStatus;
2248   if (!sX(ReadVDR64(CDF,CDF->fp,vdrOffset,zVar,
2249 		    VDR_DATATYPE,&dataType,
2250 		    VDR_NUMELEMS,&numElems,
2251 		    VDR_NULL),&pStatus)) return pStatus;
2252   *nPhyRecBytes = CDFelemSize((long)dataType) * numElems;
2253   for (dimN = 0; dimN < numDims; dimN++) {
2254      if (dimVarys[dimN]) *nPhyRecBytes *= dimSizes[dimN];
2255   }
2256   return pStatus;
2257 }
2258 
2259 /******************************************************************************
2260 * ReadSparseFull.
2261 ******************************************************************************/
2262 
ReadSparseFull(CDF,Var,firstRec,lastRec,buffer)2263 static CDFstatus ReadSparseFull (CDF, Var, firstRec, lastRec, buffer)
2264 struct CDFstruct *CDF;
2265 struct VarStruct *Var;
2266 Int32 firstRec;
2267 Int32 lastRec;
2268 void *buffer;
2269 {
2270   CDFstatus pStatus = CDF_OK; Logical found;
2271   Int32 readTo, recCount, numElems, recX, prevRecN;
2272   Int32 nextRec, padTo, nPadValues; OFF_T tOffset;
2273   Int32 recNum = firstRec;
2274   Byte *tBuffer = (Byte *) buffer;
2275   /****************************************************************************
2276   * While there are more records to be read/generated...
2277   ****************************************************************************/
2278   while (recNum <= lastRec) {
2279     /**************************************************************************
2280     * Is the record in the staging area?
2281     **************************************************************************/
2282     if (INCLUSIVE(Var->stage.firstRec,recNum,Var->stage.lastRec)) {
2283       readTo = MINIMUM(Var->stage.lastRec,lastRec);
2284       recCount = readTo - recNum + 1;
2285       numElems = recCount * Var->NphyRecElems;
2286       recX = recNum - Var->stage.firstRec;
2287       tOffset = Var->stage.areaOffset64 + (OFF_T) (recX * Var->NphyRecBytes);
2288       if (!sX(ReadVarElems64(Var,CDF->stage.fp,
2289 			     tOffset,numElems,tBuffer),&pStatus)) return pStatus;
2290       tBuffer += (size_t) (recCount * Var->NphyRecBytes);
2291       recNum += recCount;
2292       continue;
2293     }
2294     /**************************************************************************
2295     * Does the record exist and has been written to (not just allocated)?
2296     **************************************************************************/
2297     if (recNum <= Var->maxRec) {
2298       Int32 firstRecInVVR, lastRecInVVR;
2299       if (!sX(SearchForRecord64(CDF,Var->VDRoffset64,
2300 			        Var->zVar,recNum,
2301 			        &firstRecInVVR,
2302 			        &lastRecInVVR,
2303 			        &tOffset,&found),&pStatus)) return pStatus;
2304       if (found) {
2305 	readTo = MINIMUMof3(Var->maxRec,lastRec,lastRecInVVR);
2306 	recCount = readTo - recNum + 1;
2307 	numElems = recCount * Var->NphyRecElems;
2308 	recX = recNum - firstRecInVVR;
2309 	tOffset += VVR_BASE_SIZE64 + (OFF_T) (recX * Var->NphyRecBytes);
2310 	if (!sX(ReadVarElems64(Var,CDF->fp,tOffset,
2311 			       numElems,tBuffer),&pStatus)) return pStatus;
2312 	tBuffer += (size_t) (recCount * Var->NphyRecBytes);
2313 	recNum += recCount;
2314 	continue;
2315       }
2316     }
2317     /**************************************************************************
2318     * Determine which records need to be padded.
2319     **************************************************************************/
2320     if (recNum <= Var->maxRec) {
2321       if (!sX(NextRecord64(CDF,Var->VDRoffset64,Var->zVar,
2322 			   recNum,&nextRec,&found),&pStatus)) return pStatus;
2323       if (found) {
2324 	if (EXCLUSIVE(recNum,
2325 		      Var->stage.firstRec,
2326 		      nextRec)) nextRec = Var->stage.firstRec;
2327 	prevRecN = nextRec - 1;
2328 	padTo = MINIMUM(prevRecN,lastRec);
2329       }
2330       else {
2331 	prevRecN = Var->stage.firstRec - 1;
2332 	padTo = MINIMUM(prevRecN,lastRec);
2333       }
2334     }
2335     else
2336       padTo = lastRec;
2337     recCount = padTo - recNum + 1;
2338     /**************************************************************************
2339     * If sRecords.PREV...
2340     **************************************************************************/
2341     if (Var->prevIfMissing) {
2342       Int32 prevRec; Byte *destBuffer;
2343       if (!sX(PrevRecord64(CDF,Var->VDRoffset64,Var->zVar,
2344 			   MINIMUM(recNum,Var->maxRec),
2345 			   &prevRec,&found),&pStatus)) return pStatus;
2346       if (found) {
2347 	if (EXCLUSIVE(prevRec,Var->stage.lastRec,recNum)) {
2348 	  recX = Var->stage.lastRec - Var->stage.firstRec;
2349 	  tOffset = Var->stage.areaOffset64 + (OFF_T) (recX * Var->NphyRecBytes);
2350 	  if (!sX(ReadVarElems64(Var,CDF->stage.fp,
2351 			         tOffset,Var->NphyRecElems,
2352 			         tBuffer),&pStatus)) return pStatus;
2353 	}
2354 	else {
2355 	  if (!sX(RecordByteOffset64(CDF,Var,
2356 				     prevRec,
2357 				     &tOffset),&pStatus)) return pStatus;
2358 	  if (!sX(ReadVarElems64(Var,CDF->fp,tOffset,
2359 			         Var->NphyRecElems,
2360 			         tBuffer),&pStatus)) return pStatus;
2361 	}
2362 	destBuffer = tBuffer + ((size_t) Var->NphyRecBytes);
2363 	for (recX = 1; recX < recCount; recX++) {
2364 	   memmove (destBuffer, tBuffer, (size_t) Var->NphyRecBytes);
2365 	   destBuffer += (size_t) Var->NphyRecBytes;
2366 	}
2367 	sX (VIRTUAL_RECORD_DATA, &pStatus);
2368 	tBuffer += (size_t) (recCount * Var->NphyRecBytes);
2369 	recNum += recCount;
2370 	continue;
2371       }
2372       if (EXCLUSIVE(NO_RECORD,Var->stage.lastRec,recNum)) {
2373 	recX = Var->stage.lastRec - Var->stage.firstRec;
2374 	tOffset = Var->stage.areaOffset64 + (OFF_T) (recX * Var->NphyRecBytes);
2375 	if (!sX(ReadVarElems64(Var,CDF->stage.fp,
2376 			       tOffset,Var->NphyRecElems,
2377 			       tBuffer),&pStatus)) return pStatus;
2378 	destBuffer = tBuffer + ((size_t) Var->NphyRecBytes);
2379 	for (recX = 1; recX < recCount; recX++) {
2380 	   memmove (destBuffer, tBuffer, (size_t) Var->NphyRecBytes);
2381 	   destBuffer += (size_t) Var->NphyRecBytes;
2382 	}
2383 	sX (VIRTUAL_RECORD_DATA, &pStatus);
2384 	tBuffer += (size_t) (recCount * Var->NphyRecBytes);
2385 	recNum += recCount;
2386 	continue;
2387       }
2388     }
2389     /**************************************************************************
2390     * Pad with the variable's pad value.  This occurs if the variable is
2391     * sRecords.NO, sRecords.PAD, or if sRecords.PREV but a previous record
2392     * does not exist (in a VVR or the staging area).
2393     **************************************************************************/
2394     nPadValues = recCount * Var->NphyRecValues;
2395     if (!sX(PadBuffer64(CDF,Var,nPadValues,tBuffer),&pStatus)) return pStatus;
2396     sX (VIRTUAL_RECORD_DATA, &pStatus);
2397     tBuffer += (size_t) (recCount * Var->NphyRecBytes);
2398     recNum += recCount;
2399   }
2400   return pStatus;
2401 }
2402 
2403 /******************************************************************************
2404 * ReadSparsePartial.
2405 ******************************************************************************/
2406 
ReadSparsePartial(CDF,Var,recNum,offset,nValues,buffer)2407 static CDFstatus ReadSparsePartial (CDF, Var, recNum, offset, nValues, buffer)
2408 struct CDFstruct *CDF;
2409 struct VarStruct *Var;
2410 Int32 recNum;
2411 OFF_T offset;
2412 Int32 nValues;
2413 void *buffer;
2414 {
2415   CDFstatus pStatus = CDF_OK; Logical found;
2416   Int32 firstRec, prevRec; OFF_T tOffset;
2417   Int32 numElems = nValues * Var->NvalueElems;
2418   /****************************************************************************
2419   * If the record is in the staging area...
2420   ****************************************************************************/
2421   if (INCLUSIVE(Var->stage.firstRec,recNum,Var->stage.lastRec)) {
2422     tOffset = Var->stage.areaOffset64;
2423     tOffset += (OFF_T) (Var->NphyRecBytes * (recNum - Var->stage.firstRec));
2424     tOffset += offset;
2425     if (!sX(ReadVarElems64(Var,CDF->stage.fp,
2426 			   tOffset,numElems,buffer),&pStatus)) return pStatus;
2427     return pStatus;
2428   }
2429   /****************************************************************************
2430   * If the record exists and has been written (ie. not just allocated)...
2431   ****************************************************************************/
2432   if (recNum <= Var->maxRec) {
2433     if (!sX(SearchForRecord64(CDF,Var->VDRoffset64,
2434 			      Var->zVar,recNum,&firstRec,
2435 			      NULL,&tOffset,&found),&pStatus)) return pStatus;
2436     if (found) {
2437       tOffset += (OFF_T) VVR_BASE_SIZE64;
2438       tOffset += (OFF_T) Var->NphyRecBytes * (recNum - firstRec);
2439       tOffset += offset;
2440       if (!sX(ReadVarElems64(Var,CDF->fp,
2441 			     tOffset,numElems,buffer),&pStatus)) return pStatus;
2442       return pStatus;
2443     }
2444   }
2445   /****************************************************************************
2446   * If missing records are to be read from the previous record...
2447   ****************************************************************************/
2448   if (Var->prevIfMissing) {
2449     /**************************************************************************
2450     * Check if a previous record exists in a VVR.
2451     **************************************************************************/
2452     if (!sX(PrevRecord64(CDF,Var->VDRoffset64,Var->zVar,
2453 		         MINIMUM(recNum,Var->maxRec),
2454 		         &prevRec,&found),&pStatus)) return pStatus;
2455     /**************************************************************************
2456     * If so, also make sure that the last record in the staging area isn't
2457     * really the previous record to use.
2458     **************************************************************************/
2459     if (found) {
2460       if (EXCLUSIVE(prevRec,Var->stage.lastRec,recNum)) {
2461 	Int32 recNumInStage = Var->stage.lastRec - Var->stage.firstRec;
2462 	tOffset = Var->stage.areaOffset64;
2463 	tOffset += (OFF_T) Var->NphyRecBytes * recNumInStage;
2464 	tOffset += offset;
2465 	if (!sX(ReadVarElems64(Var,CDF->stage.fp,tOffset,
2466 			       numElems,buffer),&pStatus)) return pStatus;
2467       }
2468       else {
2469 	if (!sX(RecordByteOffset64(CDF,Var,
2470 				   prevRec,
2471 				   &tOffset),&pStatus)) return pStatus;
2472 	tOffset += offset;
2473 	if (!sX(ReadVarElems64(Var,CDF->fp,tOffset,
2474 			       numElems,buffer),&pStatus)) return pStatus;
2475       }
2476       sX (VIRTUAL_RECORD_DATA, &pStatus);
2477       return pStatus;
2478     }
2479     /**************************************************************************
2480     * A previous record does not exist in a VVR...check if the last record in
2481     * the staging area is the previous record.
2482     **************************************************************************/
2483     if (EXCLUSIVE(NO_RECORD,Var->stage.lastRec,recNum)) {
2484       Int32 recNumInStage = Var->stage.lastRec - Var->stage.firstRec;
2485       tOffset = Var->stage.areaOffset64;
2486       tOffset += (OFF_T) Var->NphyRecBytes * recNumInStage;
2487       tOffset += offset;
2488       if (!sX(ReadVarElems64(Var,CDF->stage.fp,
2489 			     tOffset,numElems,buffer),&pStatus)) return pStatus;
2490       sX (VIRTUAL_RECORD_DATA, &pStatus);
2491       return pStatus;
2492     }
2493   }
2494   /****************************************************************************
2495   * Pad the buffer with the variable's pad value.  Note that this is also done
2496   * if the variable is sRecords.PREV but a previous record does not exist.
2497   ****************************************************************************/
2498   if (!sX(PadBuffer64(CDF,Var,nValues,buffer),&pStatus)) return pStatus;
2499   sX (VIRTUAL_RECORD_DATA, &pStatus);
2500   return pStatus;
2501 }
2502 
2503 /******************************************************************************
2504 * ReadCompressedFull.
2505 ******************************************************************************/
2506 
ReadCompressedFull(CDF,Var,firstRec,lastRec,buffer)2507 static CDFstatus ReadCompressedFull (CDF, Var, firstRec, lastRec, buffer)
2508 struct CDFstruct *CDF;
2509 struct VarStruct *Var;
2510 Int32 firstRec;
2511 Int32 lastRec;
2512 void *buffer;
2513 {
2514   CDFstatus pStatus = CDF_OK; Logical found;
2515   Int32 readTo, recCount, numElems, recX, nextRec;
2516   Int32 recNum = firstRec, nPadValues, prevRec, padTo;
2517   Byte *tBuffer = (Byte *) buffer, *destBuffer;
2518   OFF_T tOffset;
2519   /****************************************************************************
2520   * While there are more records to be read/generated...
2521   ****************************************************************************/
2522   while (recNum <= lastRec) {
2523     /**************************************************************************
2524     * Try to bring the record to the staging area.
2525     **************************************************************************/
2526     if (!sX(BringToStage(CDF,Var,recNum,&found),&pStatus)) return pStatus;
2527     if (found) {
2528       readTo = MINIMUM(Var->stage.lastRec,lastRec);
2529       recCount = readTo - recNum + 1;
2530       numElems = recCount * Var->NphyRecElems;
2531       recX = recNum - Var->stage.firstRec;
2532       tOffset = Var->stage.areaOffset64 + (OFF_T) (recX * Var->NphyRecBytes);
2533       if (!sX(ReadVarElems64(Var,CDF->stage.fp,
2534 			     tOffset,numElems,tBuffer),&pStatus)) return pStatus;
2535       tBuffer += (size_t) (recCount * Var->NphyRecBytes);
2536       recNum += recCount;
2537       continue;
2538     }
2539     /**************************************************************************
2540     * Determine which records need to be padded.
2541     **************************************************************************/
2542     if (!sX(NextRecord64(CDF,Var->VDRoffset64,Var->zVar,
2543 		         recNum,&nextRec,&found),&pStatus)) return pStatus;
2544     if (found) {
2545       if (EXCLUSIVE(recNum,
2546 		    Var->stage.firstRec,
2547 		    nextRec)) nextRec = Var->stage.firstRec;
2548       prevRec = nextRec - 1;
2549       padTo = MINIMUM(prevRec,lastRec);
2550     }
2551     else
2552       padTo = BOO(Var->stage.firstRec > recNum,
2553 		  Var->stage.firstRec - 1,lastRec);
2554     recCount = padTo - recNum + 1;
2555     /**************************************************************************
2556     * If sRecords.PREV...
2557     **************************************************************************/
2558     if (Var->prevIfMissing) {
2559       if (!sX(PrevRecord64(CDF,Var->VDRoffset64,Var->zVar,
2560 			   recNum,&prevRec,&found),&pStatus)) return pStatus;
2561       if (!found) prevRec = NO_RECORD;
2562       if (EXCLUSIVE(prevRec,
2563 		    Var->stage.lastRec,
2564 		    recNum)) prevRec = Var->stage.lastRec;
2565       if (prevRec > NO_RECORD) {
2566 	if (!sX(BringToStage(CDF,Var,prevRec,NULL),&pStatus)) return pStatus;
2567 	recX = prevRec - Var->stage.firstRec;
2568 	tOffset = Var->stage.areaOffset64 + (OFF_T) (recX * Var->NphyRecBytes);
2569 	if (!sX(ReadVarElems64(Var,CDF->stage.fp,
2570 			       tOffset,Var->NphyRecElems,
2571 			       tBuffer),&pStatus)) return pStatus;
2572 	destBuffer = tBuffer + ((size_t) Var->NphyRecBytes);
2573 	for (recX = 1; recX < recCount; recX++) {
2574 	   memmove (destBuffer, tBuffer, (size_t) Var->NphyRecBytes);
2575 	   destBuffer += (size_t) Var->NphyRecBytes;
2576 	}
2577 	sX (VIRTUAL_RECORD_DATA, &pStatus);
2578 	tBuffer += (size_t) (recCount * Var->NphyRecBytes);
2579 	recNum += recCount;
2580 	continue;
2581       }
2582     }
2583     /**************************************************************************
2584     * Pad with the variable's pad value.  This occurs if the variable is
2585     * sRecords.NO, sRecords.PAD, or if sRecords.PREV but a previous record
2586     * does not exist (in a CVVR/VVR or the staging area).
2587     **************************************************************************/
2588     nPadValues = recCount * Var->NphyRecValues;
2589     if (!sX(PadBuffer64(CDF,Var,nPadValues,tBuffer),&pStatus)) return pStatus;
2590     sX (VIRTUAL_RECORD_DATA, &pStatus);
2591     tBuffer += (size_t) (recCount * Var->NphyRecBytes);
2592     recNum += recCount;
2593   }
2594   return pStatus;
2595 }
2596 
2597 /******************************************************************************
2598 * ReadCompressedPartial.
2599 ******************************************************************************/
2600 
ReadCompressedPartial(CDF,Var,recNum,offset,nValues,buffer)2601 static CDFstatus ReadCompressedPartial (CDF, Var, recNum, offset, nValues,
2602 					buffer)
2603 struct CDFstruct *CDF;
2604 struct VarStruct *Var;
2605 Int32 recNum;
2606 OFF_T offset;
2607 Int32 nValues;
2608 void *buffer;
2609 {
2610   CDFstatus pStatus = CDF_OK;
2611   Int32 numElems = nValues * Var->NvalueElems;
2612   Int32 prevRec, recX; Logical found;
2613   OFF_T tOffset;
2614   /****************************************************************************
2615   * Try to bring the record to the staging area.
2616   ****************************************************************************/
2617   if (!sX(BringToStage(CDF,Var,recNum,&found),&pStatus)) return pStatus;
2618   if (found) {
2619     tOffset = Var->stage.areaOffset64;
2620     tOffset += (OFF_T) Var->NphyRecBytes * (recNum - Var->stage.firstRec);
2621     tOffset += offset;
2622     if (!sX(ReadVarElems64(Var,CDF->stage.fp,
2623 			   tOffset,numElems,buffer),&pStatus)) return pStatus;
2624     return pStatus;
2625   }
2626   /****************************************************************************
2627   * If sRecords.PREV...
2628   ****************************************************************************/
2629   if (Var->prevIfMissing) {
2630     if (!sX(PrevRecord64(CDF,Var->VDRoffset64,
2631 		         Var->zVar,recNum,
2632 		         &prevRec,&found),&pStatus)) return pStatus;
2633     if (!found) prevRec = NO_RECORD;
2634     if (EXCLUSIVE(prevRec,
2635 		  Var->stage.lastRec,
2636 		  recNum)) prevRec = Var->stage.lastRec;
2637     if (prevRec > NO_RECORD) {
2638       if (!sX(BringToStage(CDF,Var,prevRec,NULL),&pStatus)) return pStatus;
2639       recX = Var->stage.lastRec - Var->stage.firstRec;
2640       tOffset = Var->stage.areaOffset64 + (OFF_T) (Var->NphyRecBytes * recX) +
2641 		offset;
2642       if (!sX(ReadVarElems64(Var,CDF->stage.fp,
2643 			     tOffset,numElems,buffer),&pStatus)) return pStatus;
2644       sX (VIRTUAL_RECORD_DATA, &pStatus);
2645       return pStatus;
2646     }
2647   }
2648   /****************************************************************************
2649   * Pad the buffer with the variable's pad value.  Note that this is also done
2650   * if the variable is sRecords.PREV but a previous record does not exist.
2651   ****************************************************************************/
2652   if (!sX(PadBuffer64(CDF,Var,nValues,buffer),&pStatus)) return pStatus;
2653   sX (VIRTUAL_RECORD_DATA, &pStatus);
2654   return pStatus;
2655 }
2656 
2657 /******************************************************************************
2658 * CheckLFS.
2659 ******************************************************************************/
2660 
CheckLFS(CDFname,isLFS,CDFfullName)2661 VISIBLE_PREFIX CDFstatus CheckLFS (CDFname, isLFS, CDFfullName)
2662 char *CDFname;
2663 Logical *isLFS;
2664 char *CDFfullName;
2665 {
2666   CDFstatus pStatus = CDF_OK;
2667 #if defined(win32) && (_FILE_OFFSET_BITS == 64)
2668   int fp;
2669 #else
2670   FILE *fp;
2671 #endif
2672   Int32 temp, magicNumber1;
2673   OFF_T length64 = (OFF_T) 0;
2674   Logical upper_case_ext, version_numbers, no_append;
2675   char CDFpathX[DU_MAX_PATH_LEN+1], CDFpathT[DU_MAX_PATH_LEN+1];
2676 
2677   if (CDFfullName != NULL) strcpyX (CDFfullName, CDFname, DU_MAX_PATH_LEN);
2678   /**************************************************************************
2679   * Open CDF file.
2680   **************************************************************************/
2681   if (strlen(CDFname) > (size_t) CDF_PATHNAME_LEN) {
2682     if (!sX(CDF_NAME_TRUNC,&pStatus)) return pStatus;
2683   }
2684   strcpyX (CDFpathT, CDFname, CDF_PATHNAME_LEN);
2685 #if STRIP_TRAILING_BLANKS_FROM_CDFPATH
2686   StripTrailingBlanks (CDFpathT);
2687 #endif
2688 #if defined(vms) || defined(dos)
2689   MakeUpperString (CDFpathT);
2690 #endif
2691   if (!ValidCDFname(CDFpathT)) return BAD_CDF_NAME;
2692   if (!sX(FindCDF(CDFpathT,&no_append,
2693                   &upper_case_ext,
2694                   &version_numbers),&pStatus)) return pStatus;
2695   BuildFilePath (CDFt, CDFpathT, no_append, upper_case_ext, version_numbers,
2696                  INT32_ZERO, CDFpathX);
2697 
2698 #if defined(win32) && (_FILE_OFFSET_BITS == 64)
2699   fp = FOPEN64 (CDFpathX, _O_RDONLY);
2700   if (fp == EOF) return CDF_OPEN_ERROR;
2701 #else
2702   fp = (FILE *) FOPEN64 (CDFpathX, READ_ONLY_a_mode);
2703   if (fp == NULL) return CDF_OPEN_ERROR;
2704 #endif
2705 
2706   if (FSEEK64(fp,(OFF_T)0,vSEEK_END) == EOF) {
2707     FCLOSE64 (fp);
2708     return CDF_OPEN_ERROR;
2709   }
2710   length64 = FTELL64 (fp);
2711 
2712   if (length64 == 0) /* A new one... Must be a LFS. */
2713     *isLFS = TRUE;
2714   else { /* Existing one... Check its magic number at the 1st 4-byte. */
2715     if (FSEEK64(fp,0,vSEEK_SET) == EOF) return CDF_OPEN_ERROR;
2716 
2717 #if defined(win32) && (_FILE_OFFSET_BITS == 64)
2718     if (FREAD64(fp,&magicNumber1,(unsigned int)4) != 4)
2719 #else
2720     if (FREAD64(&magicNumber1,(size_t)4,(size_t)1,fp) != 1)
2721 #endif
2722       return CDF_READ_ERROR;
2723 
2724 #ifndef NETWORKbyteORDERcpu
2725     temp = magicNumber1;
2726     REVERSE4bIO (&temp, &magicNumber1)
2727 #endif
2728     if (magicNumber1 == V3magicNUMBER_1)
2729       *isLFS = TRUE;
2730     else
2731       *isLFS = FALSE;
2732   }
2733   FCLOSE64 (fp);
2734   if (CDFfullName != NULL) strcpyX (CDFfullName, CDFpathX, DU_MAX_PATH_LEN);
2735   return pStatus;
2736 }
2737 
2738 /******************************************************************************
2739 * StrStrIgCaseX.
2740 ******************************************************************************/
2741 
StrStrIgCaseX(string,chkstring)2742 VISIBLE_PREFIX Logical StrStrIgCaseX (string, chkstring)
2743 char *string;
2744 char *chkstring;
2745 {
2746   int stringL = strlen(string);
2747   int chkstringL = strlen(chkstring);
2748   int i;
2749   if (stringL == 0 || chkstringL == 0) return FALSE;
2750   if (stringL != chkstringL) return FALSE;
2751   for (i = 0; i < stringL; i++) {
2752      if (MakeLower(chkstring[i]) != MakeLower(string[i])) return FALSE;
2753   }
2754   return TRUE;
2755 }
2756 
2757 /******************************************************************************
2758 *  Check if a given string ends with the provided substring, case sensitive.
2759 *  TRUE if s1 ends with s2.  Otherwise, FALSE is returned.
2760 ******************************************************************************/
2761 
EndsWith(s1,s2)2762 int EndsWith (s1, s2)
2763 char *s1;
2764 char *s2;
2765 {
2766     int  i;
2767     char *ps1, *ps2;
2768 
2769     if (strlen(s2) > strlen(s1))
2770         return FALSE;
2771 
2772     ps1 = s1 + strlen(s1) - strlen(s2);
2773     ps2 = s2;
2774 
2775     for (i=0; i < (int) strlen(s2); i++)
2776         if (*(ps1++) != *(ps2++))
2777             return FALSE;
2778 
2779     return TRUE;
2780 }
2781 
2782 /******************************************************************************
2783 *  Check if a given string ends with the provided substring, ignoring case.
2784 *  TRUE if s1 ends with s2.  Otherwise, FALSE is returned.
2785 ******************************************************************************/
2786 
EndsWithIgCase(s1,s2)2787 int EndsWithIgCase (s1, s2)
2788 char *s1;
2789 char *s2;
2790 {
2791     int  i;
2792     char *ps1, *ps2;
2793 
2794     if (strlen(s2) > strlen(s1))
2795         return FALSE;
2796 
2797     ps1 = s1 + strlen(s1) - strlen(s2);
2798     ps2 = s2;
2799 
2800     for (i=0; i < (int) strlen(s2); i++) {
2801         if (MakeLower(*ps1) != MakeLower(*ps2))
2802             return FALSE;
2803         ps1++;
2804         ps2++;
2805     }
2806     return TRUE;
2807 }
2808 
2809 /******************************************************************************
2810 *  Find the last occurence of a substring within a given string, case
2811 *  sensitive.  If the substring is found, it returns the offset where the
2812 *  substring is at in the original string. If the substring is not found, it
2813 *  returns -1.
2814 ******************************************************************************/
2815 
StrLaststr(s1,s2)2816 int StrLaststr (s1, s2)
2817 char *s1;
2818 char *s2;
2819 {
2820     char *sc2, *psc1, *ps1;
2821 
2822     if (*s2 == '\0')
2823         return -1;
2824 
2825     ps1 = s1 + strlen(s1);
2826 
2827     while(ps1 != s1) {
2828       --ps1;
2829       for (psc1 = ps1, sc2 = s2; ; )
2830           if (*(psc1++) != *(sc2++))
2831             break;
2832           else if (*sc2 == '\0')
2833             return (int) (ps1 - s1);
2834     }
2835     return -1;
2836 }
2837 
2838 /******************************************************************************
2839 *  Find the last occurence of a substring within a given string, ignoring case.
2840 *  If the substring is found, it returns the offset where the substring is at
2841 *  in the original string. If the substring is not found, it returns -1.
2842 ******************************************************************************/
2843 
StrLaststrIgCase(s1,s2)2844 int StrLaststrIgCase (s1, s2)
2845 char *s1;
2846 char *s2;
2847 {
2848     char *sc2, *psc1, *ps1;
2849 
2850     if (*s2 == '\0')
2851         return -1;
2852 
2853     ps1 = s1 + strlen(s1);
2854 
2855     while (ps1 != s1) {
2856       --ps1;
2857       for (psc1 = ps1, sc2 = s2; ; ) {
2858           if (MakeLower(*psc1) != MakeLower(*sc2))
2859             break;
2860           else if (*sc2 == '\0')
2861             return (int) (ps1 - s1);
2862           psc1++;
2863           sc2++;
2864       }
2865     }
2866     return -1;
2867 }
2868 
2869 /******************************************************************************
2870 *  Remove the ".cdf" file extension from the given file name if it's there.
2871 *  It ignores the case.
2872 *  Example:
2873 *      mydata.cdf => mydata
2874 ******************************************************************************/
2875 
RemoveCDFFileExtension(fileName,dstPath)2876 void RemoveCDFFileExtension (fileName, dstPath)
2877 char *fileName;         /* CDF file name. */
2878 char *dstPath;          /* The string holding file name without extension. */
2879 {
2880     int ptr = -1;
2881 
2882     strcpyX (dstPath, fileName, CDF_PATHNAME_LEN);
2883     if (EndsWithIgCase (dstPath, ".cdf")) {
2884       ptr = StrLaststrIgCase(dstPath, ".cdf");
2885       if (ptr != -1) ((char *) dstPath)[ptr] = (char) '\0';
2886     }
2887     return;
2888 }
2889 
2890 /******************************************************************************
2891 * CDFgetFileBackwardEnvVar.
2892 ******************************************************************************/
2893 
CDFgetFileBackwardEnvVar()2894 VISIBLE_PREFIX int CDFgetFileBackwardEnvVar ()
2895 {
2896   char *bk = NULL;
2897 #if defined(vms)
2898   bk = getenv("CDF$FILEBACKWARD");
2899 #else
2900   bk = getenv("CDF_FILEBACKWARD");
2901 #endif
2902   if (bk != NULL) {
2903     if (strlen(bk) == 0) return 0;
2904     if (StrStrIgCaseX(bk, "TRUE")) return 1;
2905   }
2906   return 0;
2907 }
2908 
2909 /******************************************************************************
2910 * CDFgetChecksumEnvVar.
2911 ******************************************************************************/
2912 
CDFgetChecksumEnvVar()2913 VISIBLE_PREFIX int CDFgetChecksumEnvVar ()
2914 {
2915   char *bk = NULL;
2916 #if defined(vms)
2917   bk = getenv("CDF$CHECKSUM");
2918 #else
2919   bk = getenv("CDF_CHECKSUM");
2920 #endif
2921   if (bk != NULL) {
2922     if (strlen(bk) == 0) return 0;
2923     if (StrStrIgCaseX(bk, "none") || StrStrIgCaseX(bk, "no")) return 0;
2924     if (StrStrIgCaseX(bk, "md5")) return 1;
2925   }
2926   return 0;
2927 }
2928 
2929 /******************************************************************************
2930 * ChecksumMethod.
2931 ******************************************************************************/
2932 
ChecksumMethod(Int32 flags)2933 VISIBLE_PREFIX long ChecksumMethod (Int32 flags)
2934 {
2935   int md5 = 0;
2936   int other = 0;
2937 
2938   if (!BITSET(flags,CDR_CHECKSUM_BIT)) return NONE_CHECKSUM;
2939   md5 = (int) BITSET(flags,CDR_CHECKSUM_MD5_BIT);
2940   other = (int) BITSET(flags,CDR_CHECKSUM_OTHER_BIT);
2941   if (md5 == 1) return MD5_CHECKSUM;
2942   else if (other == 1) return OTHER_CHECKSUM;
2943   return NONE_CHECKSUM;
2944 }
2945 
2946 /******************************************************************************
2947 * CDFsetValidate.
2948 ******************************************************************************/
2949 
CDFsetValidate(long validate)2950 VISIBLE_PREFIX void CDFsetValidate (long validate)
2951 {
2952   if (validate == VALIDATEFILEon) {
2953 #if !defined(vms)
2954 #if !defined(SOLARIS) && !defined(WIN32)
2955     setenv ("CDF_VALIDATE", "yes", 1);
2956 #else
2957     putenv ("CDF_VALIDATE=yes");
2958 #endif
2959 #else
2960     setenv ("CDF$VALIDATE", "yes", 1);
2961 #endif
2962   } else {
2963 #if !defined(vms)
2964 #if !defined(SOLARIS) && !defined(WIN32)
2965     setenv ("CDF_VALIDATE", "no", 1);
2966 #else
2967     putenv ("CDF_VALIDATE=no");
2968 #endif
2969 #else
2970     setenv ("CDF$VALIDATE", "no", 1);
2971 #endif
2972   }
2973 }
2974 
2975 /******************************************************************************
2976 * CDFgetValidate.
2977 * Return: 1 if not set or set to yes (the default)
2978 *         0 if set to no or none
2979 ******************************************************************************/
2980 
CDFgetValidate()2981 VISIBLE_PREFIX int CDFgetValidate ()
2982 {
2983   char *vad = NULL;
2984 #if defined(vms)
2985   vad = getenv("CDF$VALIDATE");
2986 #else
2987   vad = getenv("CDF_VALIDATE");
2988 #endif
2989   if (vad != NULL) {
2990     if (strlen(vad) == 0) return 0;
2991     if (StrStrIgCaseX(vad, "none") || StrStrIgCaseX(vad, "no")) return 0;
2992     if (StrStrIgCaseX(vad, "yes")) return 1;
2993   }
2994   return 1;
2995 }
2996 
2997 /******************************************************************************
2998 * CDFgetValidateDebug.
2999 * Return: 0 if not set or set to no or none (the default)
3000 *         1 if set to yes
3001 ******************************************************************************/
3002 
CDFgetValidateDebug()3003 VISIBLE_PREFIX int CDFgetValidateDebug ()
3004 {
3005   char *vad = NULL;
3006 #if defined(vms)
3007   vad = getenv("CDF$VALIDATE$DEBUG");
3008 #else
3009   vad = getenv("CDF_VALIDATE_DEBUG");
3010 #endif
3011   if (vad != NULL) {
3012     if (strlen(vad) == 0) return 0;
3013     if (StrStrIgCaseX(vad, "none") || StrStrIgCaseX(vad, "no")) return 0;
3014     if (StrStrIgCaseX(vad, "yes")) return 1;
3015   }
3016   return 0;
3017 }
3018 
3019