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