1 /******************************************************************************
2 *
3 * NSSDC/CDF CDF library miscellaneous functions, part 1.
4 *
5 * Version 1.3e, 18-Nov-97, Hughes STX.
6 *
7 * Modification history:
8 *
9 * V1.0 19-Dec-94, J Love Original version.
10 * V1.0a 29-Dec-94, J Love WriteBuffer: increment buffer pointer in the
11 * case where the memory allocation failed.
12 * V1.1 13-Jan-95, J Love Encode/decode changes. More cache-residency.
13 * Allow all possible extensions on all machines.
14 * V1.1a 19-Jan-95, J Love IRIX 6.x (64-bit).
15 * V1.1b 24-Feb-95, J Love Solaris 2.3 IDL i/f.
16 * V1.2 21-Mar-95, J Love POSIX.
17 * V1.2a 18-Apr-95, J Love More POSIX. MEMLOG_.
18 * V1.2b 19-Apr-95, J Love Memory functions moved to `cdfmem.c'.
19 * V1.2c 7-Sep-95, J Love Corrected status codes being returned. Try
20 * progressively smaller temporary buffers in
21 * `WriteVarElems'.
22 * V1.3 10-Sep-96, J Love CDF V2.6.
23 * V1.3a 21-Feb-97, J Love Removed RICE.
24 * V1.3b 28-Feb-97, J Love Windows NT for MS Visual C/C++ on an IBM PC.
25 * V1.3c 11-Sep-97, J Love Magic numbers are now uInt32.
26 * V1.3d 20-Oct-97, J Love Properly cast the uInt32 magic numbers. More
27 * Windows NT.
28 * V1.3e 18-Nov-97, J Love Even more Windows NT.
29 * V2.0 08/Apr-04, M liu Replaced VSTREAM.STATS with VSTREAM_STATS.
30 * V2.1 29-Jun-04, M Liu Added LFS (Large File Support > 2G).
31 *
32 ******************************************************************************/
33
34 #include "cdflib.h"
35 #include "cdflib64.h"
36 #include "cdfrev.h"
37
38 /******************************************************************************
39 * Max/MinLongLong.
40 ******************************************************************************/
41
MaxLongLong(a,b)42 VISIBLE_PREFIX OFF_T MaxLongLong (a, b)
43 OFF_T a;
44 OFF_T b;
45 {
46 return MAXIMUM64(a,b);
47 }
48
MinLongLong(a,b)49 VISIBLE_PREFIX OFF_T MinLongLong (a, b)
50 OFF_T a;
51 OFF_T b;
52 {
53 return MINIMUM64(a,b);
54 }
55
56 /******************************************************************************
57 * UpdateDotCDF64.
58 * If this routine is called when aborting a CDF, we cannot assume that
59 * the CDF structure is complete - it may have been only partially initialized
60 * when the CDF was aborted. If it is called to save the CDF without closing
61 * it, the data will be properly preserved.
62 ******************************************************************************/
63
UpdateDotCDF64(CDF)64 STATICforIDL CDFstatus UpdateDotCDF64 (CDF)
65 struct CDFstruct *CDF;
66 {
67 CDFstatus pStatus = CDF_OK; int varN; struct VarStruct *Var; Logical zVar;
68 /**************************************************************************
69 * Update r/zVariables depending on the variable type...
70 **************************************************************************/
71 for (zVar = 0; zVar <= 1; zVar++) {
72 if (BOO(zVar,CDF->zVars,CDF->rVars) != NULL) {
73 Int32 nVars = BOO(zVar,CDF->NzVars,CDF->NrVars);
74 for (varN = 0; varN < nVars; varN++) {
75 Var = BOO(zVar,CDF->zVars[varN],CDF->rVars[varN]);
76 if (Var != NULL) {
77 switch (Var->vType) {
78 case SPARSE_RECORDS_: {
79 if (!sX(FlushStage64(CDF,Var),&pStatus)) break;
80 /* No `break' is intentional. */
81 case STANDARD_:
82 if (Var->maxWritten < Var->maxAllocated) {
83 Int32 padFrom = Var->maxWritten + 1;
84 if (!sX(PadUnRecords64(CDF,Var,padFrom,
85 Var->maxAllocated),&pStatus)) break;
86 Var->maxWritten = Var->maxAllocated;
87 }
88 break;
89 }
90 case COMPRESSED_:
91 case SPARSE_COMPRESSED_RECORDS_:
92 if (!sX(FlushStage64(CDF,Var),&pStatus)) break;
93 break;
94 case SPARSE_ARRAYS_:
95 case SPARSE_RECORDS_AND_ARRAYS_:
96 sX (UNKNOWN_SPARSENESS, &pStatus);
97 break;
98 case IN_MULTI_:
99 break;
100 default:
101 sX (CDF_INTERNAL_ERROR, &pStatus);
102 break;
103 }
104 }
105 }
106 }
107 }
108 return pStatus;
109 }
110
111 /******************************************************************************
112 * CloseVarFiles64.
113 *
114 * Close the open variable files of the specified CDF. This routine closes all
115 * of the open variable files regardless of the number of errors detected.
116 *
117 * Because this routine is called when aborting a CDF, we cannot assume
118 * that the CDF structure is complete. Eg., it may have been only partially
119 * initialized when the CDF was aborted.
120 ******************************************************************************/
121
CloseVarFiles64(CDF)122 STATICforIDL CDFstatus CloseVarFiles64 (CDF)
123 struct CDFstruct *CDF;
124 {
125 CDFstatus pStatus = CDF_OK; struct VarStruct *Var; int varN;
126 /****************************************************************************
127 * If a multi-file CDF, close the variable files.
128 ****************************************************************************/
129 if (!CDF->singleFile) {
130 /**************************************************************************
131 * Close rVariable files. If the pointer to the rVariable is NULL, then
132 * the rVariable has yet to be initialized (and is obviously closed).
133 **************************************************************************/
134 if (CDF->rVars != NULL) {
135 for (varN = 0; varN < CDF->NrVars; varN++) {
136 Var = CDF->rVars[varN];
137 if (Var != NULL) {
138 if (Var->fp != NULL) {
139 if (!CLOSEv64(Var->fp,NULL,NULL)) sX (VAR_CLOSE_ERROR, &pStatus);
140 Var->fp = NULL;
141 }
142 }
143 }
144 }
145 /**************************************************************************
146 * Close zVariable files. If the pointer to the zVariable is NULL, then
147 * the zVariable has yet to be initialized (and is obviously closed).
148 **************************************************************************/
149 if (CDF->zVars != NULL) {
150 for (varN = 0; varN < CDF->NzVars; varN++) {
151 Var = CDF->zVars[varN];
152 if (Var != NULL) {
153 if (Var->fp != NULL) {
154 if (!CLOSEv64(Var->fp,NULL,NULL)) sX (VAR_CLOSE_ERROR, &pStatus);
155 Var->fp = NULL;
156 }
157 }
158 }
159 }
160 }
161 return pStatus;
162 }
163
164 /******************************************************************************
165 * WriteAccess64.
166 * Close and then reopen a CDF for read/write access (it was opened with
167 * read-only access initially). If the CDF is earlier than CDF V2.5, then
168 * some of the fields will have to be fixed and the CDR will be truncated for
169 * a shorter copyright length (unless the CDF is being deleted in which case
170 * it would be a waste of time to do these things).
171 ******************************************************************************/
172
WriteAccess64(CDF,forDelete,pStatus)173 STATICforIDL Logical WriteAccess64 (CDF, forDelete, pStatus)
174 struct CDFstruct *CDF;
175 Logical forDelete; /* Is the write access is needed to delete the CDF? */
176 CDFstatus *pStatus; /* Returned status. */
177 {
178 #if BUILD_READ_ONLY_DISTRIBUTION
179 *pStatus = READ_ONLY_DISTRIBUTION;
180 return FALSE;
181 #else
182 char pathName[DU_MAX_PATH_LEN+1]; vSTATS vStats;
183 /***************************************************************************
184 * Check if write access already.
185 ***************************************************************************/
186 if (CDF->status == READ_WRITE) return TRUE;
187 /***************************************************************************
188 * Check if this CDF is in read-only mode.
189 ***************************************************************************/
190 if (CDF->readOnly) {
191 *pStatus = READ_ONLY_MODE;
192 return FALSE;
193 }
194 /***************************************************************************
195 * Close (the possibly compressed) dotCDF file and the variable files (if
196 * a multi-file CDF). An uncompressed dotCDF file and any scratch files
197 * stay open.
198 ***************************************************************************/
199 if (!CLOSEv64(CDF->dotFp,NULL,&vStats)) {
200 CDF->dotFp = NULL;
201 AbortAccess64 (CDF, noUPDATE, noDELETE);
202 return FALSE;
203 }
204 CDF->dotFp = NULL;
205 AddTOvStats (&CDF->dotCDFvStats, &vStats);
206 #if defined(DEBUG)
207 DisplayVs (getenv("VSTREAM_STATS"), "DotCDF..", &vStats);
208 #endif
209 if (!sX(CloseVarFiles64(CDF),pStatus)) {
210 AbortAccess64 (CDF, noUPDATE, noDELETE);
211 return FALSE;
212 }
213 /***************************************************************************
214 * Open dotCDF file with read-write access. If read-write access not is
215 * allowed, try to return to read-only access. If reopening with read-only
216 * access fails, free CDF structures as if CDF had been closed.
217 ***************************************************************************/
218 BuildFilePath (CDFt, CDF->CDFname, CDF->no_append, CDF->upper_case_ext,
219 CDF->version_numbers, 0L, pathName);
220 CDF->dotFp = V_open64 (pathName, READ_PLUS_a_mode);
221 if (CDF->dotFp == NULL) {
222 CDF->dotFp = V_open64 (pathName, READ_ONLY_a_mode);
223 if (CDF->dotFp == NULL) {
224 AbortAccess64 (CDF, noUPDATE, noDELETE);
225 *pStatus = CDF_OPEN_ERROR;
226 return FALSE;
227 }
228 else {
229 CDF->status = READ_ONLY;
230 *pStatus = NO_WRITE_ACCESS; /* Don't return yet. */
231 }
232 }
233 else
234 CDF->status = READ_WRITE;
235 /***************************************************************************
236 * If the CDF is not compressed, reassign the "working" file pointer and
237 * reset the cache size (unless deleting). If the CDF is compressed, the
238 * cache size of the "working" file pointer does not have to be reset.
239 ***************************************************************************/
240 if (CDF->uDotFp == NULL) {
241 CDF->fp = CDF->dotFp;
242 if (!forDelete) {
243 if (!CACHEv64(CDF->fp,CDF->workingCacheSize)) {
244 *pStatus = BAD_CACHE_SIZE;
245 AbortAccess64 (CDF, noUPDATE, noDELETE);
246 return FALSE;
247 }
248 }
249 }
250 /***************************************************************************
251 * Fix various fields (if write access was obtained) unless write access
252 * was needed to delete the CDF.
253 ***************************************************************************/
254 if (CDF->status == READ_WRITE && !forDelete) {
255 Int32 versionNew = CDF_LIBRARY_VERSION,
256 releaseNew = CDF_LIBRARY_RELEASE,
257 incrementNew = CDF_LIBRARY_INCREMENT;
258 uInt32 magicNumber1 = V3magicNUMBER_1,
259 magicNumber2 = V3magicNUMBER_2u;
260 char copyRight[CDF_COPYRIGHT_LEN+1];
261 /*************************************************************************
262 * Update magic numbers.
263 *************************************************************************/
264 if (!SEEKv64(CDF->fp,(OFF_T)V3_MAGIC_OFFSET_1,vSEEK_SET)) {
265 AbortAccess64 (CDF, noUPDATE, noDELETE);
266 *pStatus = CDF_WRITE_ERROR;
267 return FALSE;
268 }
269 if (!Write32_64(CDF->fp,(Int32 *)&magicNumber1)) {
270 AbortAccess64 (CDF, noUPDATE, noDELETE);
271 *pStatus = CDF_WRITE_ERROR;
272 return FALSE;
273 }
274 if (!Write32_64(CDF->fp,(Int32 *)&magicNumber2)) {
275 AbortAccess64 (CDF, noUPDATE, noDELETE);
276 *pStatus = CDF_WRITE_ERROR;
277 return FALSE;
278 }
279 /*************************************************************************
280 * If a V2.0 CDF, correct the EOF field.
281 *************************************************************************/
282 if (CDF->badEOF) {
283 if (!sX(CorrectV20eof(CDF),pStatus)) {
284 AbortAccess64 (CDF, noUPDATE, noDELETE);
285 return FALSE;
286 }
287 CDF->badEOF = FALSE;
288 }
289 /*************************************************************************
290 * If a V2.0 CDF, correct the terminating offset fields. NOTE: Fix these
291 * fields before the other "fixing" routines (which may depend on these
292 * fields).
293 *************************************************************************/
294 if (CDF->badTerminatingOffsets) {
295 if (!sX(CorrectV20offsets(CDF),pStatus)) {
296 AbortAccess64 (CDF, noUPDATE, noDELETE);
297 return FALSE;
298 }
299 CDF->badTerminatingOffsets = FALSE;
300 }
301 /*************************************************************************
302 * If prior to CDF V2.1.1, then change the data type associated with the
303 * "EPOCH" rVariable/rEntries to CDF_EPOCH.
304 *************************************************************************/
305 if (CDF->fakeEPOCH) {
306 if (!sX(CorrectEPOCH(CDF),pStatus)) {
307 AbortAccess64 (CDF, noUPDATE, noDELETE);
308 return FALSE;
309 }
310 CDF->fakeEPOCH = FALSE;
311 }
312 /*************************************************************************
313 * If prior to CDF V2.5, then truncate the CDR for a shorter copyright
314 * field and shorten each VDR to reclaim the wasted space.
315 *************************************************************************/
316 if (CDF->wastedSpace) {
317 if (!sX(ShortenCDR(CDF),pStatus)) {
318 AbortAccess64 (CDF, noUPDATE, noDELETE);
319 return FALSE;
320 }
321 if (!sX(ShortenVDRs(CDF),pStatus)) {
322 AbortAccess64 (CDF, noUPDATE, noDELETE);
323 return FALSE;
324 }
325 CDF->wastedSpace = FALSE;
326 }
327 /*************************************************************************
328 * If prior to CDF V2.5, then convert all assumed scopes to definite
329 * scopes.
330 *************************************************************************/
331 if (CDF->assumedScopes) {
332 if (!sX(CorrectScopes(CDF),pStatus)) {
333 AbortAccess64 (CDF, noUPDATE, noDELETE);
334 return FALSE;
335 }
336 CDF->assumedScopes = FALSE;
337 }
338 /*************************************************************************
339 * Fix blocking factors for variables having a recVary of NOVARY.
340 *************************************************************************/
341 if (!sX(CorrectBlockingFactors64(CDF),pStatus)) {
342 AbortAccess64 (CDF, noUPDATE, noDELETE);
343 return FALSE;
344 }
345 /*************************************************************************
346 * Update version/release/increment.
347 *************************************************************************/
348 if (isLFS(CDF)) {
349 if (!sX(WriteCDR64(CDF->fp,V3_CDR_OFFSET64,
350 CDR_VERSION,&versionNew,
351 CDR_RELEASE,&releaseNew,
352 CDR_INCREMENT,&incrementNew,
353 CDR_NULL),pStatus)) {
354 AbortAccess64 (CDF, noUPDATE, noDELETE);
355 return FALSE;
356 }
357 }
358 /*************************************************************************
359 * Update copyright.
360 *************************************************************************/
361 CDFcopyRight (copyRight);
362 NulPad (copyRight, CDF_COPYRIGHT_LEN);
363 if (!sX(WriteCDR64(CDF->fp,V3_CDR_OFFSET64,
364 CDR_COPYRIGHT,copyRight,
365 CDR_NULL),pStatus)) {
366 AbortAccess64 (CDF, noUPDATE, noDELETE);
367 return FALSE;
368 }
369 }
370 /***************************************************************************
371 * Return based on whether or not write access was obtained.
372 ***************************************************************************/
373 return (CDF->status == READ_WRITE);
374 #endif
375 }
376
377 /******************************************************************************
378 * WriteBuffer64.
379 * Write occurs at current offset (assumed to have been set before this
380 * routine is called). On IBM PCs, it is assumed that `nBytes' will not
381 * exceed 65535.
382 ******************************************************************************/
383
WriteBuffer64(CDF,fp,dataType,numElems,buffer)384 STATICforIDL CDFstatus WriteBuffer64 (CDF, fp, dataType, numElems, buffer)
385 struct CDFstruct *CDF;
386 vFILE *fp;
387 Int32 dataType;
388 Int32 numElems;
389 void *buffer;
390 {
391 CDFstatus pStatus = CDF_OK;
392 size_t nElemBytes = CDFelemSize(dataType);
393 size_t nBytes = (size_t) (numElems * nElemBytes);
394 double eValue; Int32 elemN; Byte *ptr; void *tBuffer;
395 /****************************************************************************
396 * Try to encode/write entire buffer.
397 ****************************************************************************/
398 tBuffer = cdf_AllocateMemory (nBytes, NULL);
399 if (tBuffer != NULL) {
400 if (!sX(ConvertBuffer(HostEncoding(),CDF->encoding,CDF->negToPosFp0,
401 dataType,numElems,buffer,tBuffer),&pStatus)) {
402 cdf_FreeMemory (tBuffer, NULL);
403 return pStatus;
404 }
405 if (!WRITEv64(tBuffer,1,nBytes,fp)) {
406 cdf_FreeMemory (tBuffer, NULL);
407 return CDF_WRITE_ERROR;
408 }
409 cdf_FreeMemory (tBuffer, NULL);
410 return pStatus;
411 }
412 /****************************************************************************
413 * If that failed, encode/write one element at a time.
414 ****************************************************************************/
415 for (elemN = 0, ptr = buffer; elemN < numElems; elemN++, ptr += nElemBytes) {
416 if (!sX(ConvertBuffer(HostEncoding(),CDF->encoding,
417 CDF->negToPosFp0,dataType,1L,ptr,
418 &eValue),&pStatus)) return pStatus;
419 if (!WRITEv64(&eValue,1,nElemBytes,fp)) return CDF_WRITE_ERROR;
420 }
421 return pStatus;
422 }
423
424 /******************************************************************************
425 * UpdateMaxRec64.
426 ******************************************************************************/
427
UpdateMaxRec64(CDF,Var,recNum)428 STATICforIDL CDFstatus UpdateMaxRec64 (CDF, Var, recNum)
429 struct CDFstruct *CDF; /* In: Pointer to CDF. */
430 struct VarStruct *Var; /* In: Pointer to variable. */
431 Int32 recNum; /* In: Possible new maximum record number. */
432 {
433 CDFstatus pStatus = CDF_OK;
434 if (recNum > Var->maxRec) {
435 Var->maxRec = recNum;
436 if (!sX(WriteVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar,
437 VDR_MAXREC,&recNum,
438 VDR_NULL),&pStatus)) return pStatus;
439 }
440 if (!Var->zVar) {
441 if (recNum > CDF->rMaxRec) {
442 CDF->rMaxRec = recNum;
443 if (!sX(WriteGDR64(CDF->fp,CDF->GDRoffset64,
444 GDR_rMAXREC,&recNum,
445 GDR_NULL),&pStatus)) return pStatus;
446 }
447 }
448 return pStatus;
449 }
450
451 /******************************************************************************
452 * CalcDimParms64.
453 * Calculates a variable's number of dimensions, dimension sizes, and
454 * dimension variances depending on the current zMode.
455 ******************************************************************************/
456
CalcDimParms64(CDF,offset,zVar,numDimsP,dimSizesP,dimVarysP)457 STATICforIDL CDFstatus CalcDimParms64 (CDF, offset, zVar, numDimsP, dimSizesP,
458 dimVarysP)
459 struct CDFstruct *CDF; /* In: Pointer to CDF. */
460 OFF_T offset; /* In: Offset of VDR. */
461 Logical zVar; /* In: TRUE if a true zVariable. FALSE if a
462 true rVariable. */
463 Int32 *numDimsP; /* Out: Number of dimensions. */
464 Int32 dimSizesP[]; /* Out: Dimension sizes. */
465 Int32 dimVarysP[]; /* Out: Dimension variances. */
466 {
467 CDFstatus pStatus = CDF_OK; int dN;
468 Int32 tNumDims, tDimSizes[CDF_MAX_DIMS], tDimVarys[CDF_MAX_DIMS];
469 Int32 numDims, dimSizes[CDF_MAX_DIMS], dimVarys[CDF_MAX_DIMS];
470 /****************************************************************************
471 * Determine `true' parameters.
472 ****************************************************************************/
473 if (zVar) {
474 if (!sX(ReadVDR64(CDF,CDF->fp,offset,TRUE,
475 VDR_zNUMDIMS,&tNumDims,
476 VDR_zDIMSIZES,tDimSizes,
477 VDR_DIMVARYS,tDimVarys,
478 VDR_NULL),&pStatus)) return pStatus;
479 }
480 else {
481 if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64,
482 GDR_rNUMDIMS,&tNumDims,
483 GDR_rDIMSIZES,tDimSizes,
484 GDR_NULL),&pStatus)) {
485 return pStatus;
486 }
487 if (!sX(ReadVDR64(CDF,CDF->fp,offset,FALSE,
488 VDR_DIMVARYS,tDimVarys,
489 VDR_NULL),&pStatus)) return pStatus;
490 }
491 /****************************************************************************
492 * Determine parameters based on zMode and if r/zVariable.
493 ****************************************************************************/
494 if (CDF->zMode == zMODEon2 && !zVar) {
495 for (dN = 0, numDims = 0; dN < tNumDims; dN++) {
496 if (tDimVarys[dN]) {
497 dimSizes[(int)numDims] = tDimSizes[dN];
498 dimVarys[(int)numDims] = VARY;
499 numDims++;
500 }
501 }
502 }
503 else {
504 numDims = tNumDims;
505 for (dN = 0; dN < tNumDims; dN++) {
506 dimSizes[dN] = tDimSizes[dN];
507 dimVarys[dN] = tDimVarys[dN];
508 }
509 }
510 /****************************************************************************
511 * Assign those values requested.
512 ****************************************************************************/
513 ASSIGNnotNULL (numDimsP, numDims)
514 ASSIGNnotNULLarray (dimSizesP, numDims, dimSizes)
515 ASSIGNnotNULLarray (dimVarysP, numDims, dimVarys)
516 return pStatus;
517 }
518
519 /******************************************************************************
520 * WasteIR64.
521 ******************************************************************************/
522
WasteIR64(CDF,wasteOffset,size)523 STATICforIDL CDFstatus WasteIR64 (CDF, wasteOffset, size)
524 struct CDFstruct *CDF;
525 OFF_T wasteOffset;
526 OFF_T size;
527 {
528 CDFstatus pStatus = CDF_OK;
529 struct UIRstruct64 newUIR, firstUIR, tUIR, nextUIR;
530 OFF_T tOffset, nextOffset, UIRhead;
531 /****************************************************************************
532 * Begin initializing UIR.
533 ****************************************************************************/
534 newUIR.RecordSize = size;
535 newUIR.RecordType = UIR_;
536 /****************************************************************************
537 * Check that the internal record being wasted is big enough for the `next'
538 * and `previous' fields. If not, mark it as wasted but don't place it in
539 * the linked list of UIRs. Note that there will always be enough room for
540 * the `size' and `type' fields. If not, an internal logic error has occured.
541 ****************************************************************************/
542 if (size < UIR_BASE_SIZE64) {
543 if (size < UUIR_BASE_SIZE64) return CDF_INTERNAL_ERROR;
544 if (!sX(WriteUIR64(CDF->fp,wasteOffset,
545 UIR_RECORDSIZE,&(newUIR.RecordSize),
546 UIR_RECORDTYPE,&(newUIR.RecordType),
547 UIR_NULL),&pStatus)) return pStatus;
548 return pStatus;
549 }
550 /****************************************************************************
551 * Read offset of first UIR.
552 ****************************************************************************/
553 if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64,
554 GDR_UIRHEAD,&UIRhead,
555 GDR_NULL),&pStatus)) return pStatus;
556 /****************************************************************************
557 * Check if no UIRs exist yet.
558 ****************************************************************************/
559 if (UIRhead == 0) {
560 newUIR.NextUIR = 0;
561 newUIR.PrevUIR = 0;
562 if (!sX(WriteUIR64(CDF->fp,wasteOffset,
563 UIR_RECORD,&newUIR,
564 UIR_NULL),&pStatus)) return pStatus;
565 UIRhead = wasteOffset;
566 if (!sX(WriteGDR64(CDF->fp,CDF->GDRoffset64,
567 GDR_UIRHEAD,&UIRhead,
568 GDR_NULL),&pStatus)) return pStatus;
569 return pStatus;
570 }
571 /****************************************************************************
572 * At least one UIR exists, check if the new UIR is before the first UIR.
573 ****************************************************************************/
574 if (wasteOffset < UIRhead) {
575 if (!sX(ReadUIR64(CDF->fp,UIRhead,
576 UIR_RECORD,&firstUIR,
577 UIR_NULL),&pStatus)) return pStatus;
578 newUIR.NextUIR = UIRhead;
579 newUIR.PrevUIR = 0;
580 if (!sX(WriteUIR64(CDF->fp,wasteOffset,
581 UIR_RECORD,&newUIR,
582 UIR_NULL),&pStatus)) return pStatus;
583 firstUIR.PrevUIR = wasteOffset;
584 if (!sX(WriteUIR64(CDF->fp,UIRhead,
585 UIR_RECORD,&firstUIR,
586 UIR_NULL),&pStatus)) return pStatus;
587 UIRhead = wasteOffset;
588 if (!sX(WriteGDR64(CDF->fp,CDF->GDRoffset64,
589 GDR_UIRHEAD,&UIRhead,
590 GDR_NULL),&pStatus)) return pStatus;
591 return pStatus;
592 }
593 /****************************************************************************
594 * The new UIR is not before the first UIR. Scan the UIRs to find the point
595 * at which it should be inserted.
596 ****************************************************************************/
597 tOffset = UIRhead;
598 if (!sX(ReadUIR64(CDF->fp,tOffset,
599 UIR_RECORD,&tUIR,
600 UIR_NULL),&pStatus)) return pStatus;
601 while (tUIR.NextUIR != 0) {
602 if (wasteOffset < tUIR.NextUIR) {
603 nextOffset = tUIR.NextUIR;
604 if (!sX(ReadUIR64(CDF->fp,nextOffset,
605 UIR_RECORD,&nextUIR,
606 UIR_NULL),&pStatus)) return pStatus;
607 newUIR.NextUIR = tUIR.NextUIR;
608 newUIR.PrevUIR = tOffset;
609 if (!sX(WriteUIR64(CDF->fp,wasteOffset,
610 UIR_RECORD,&newUIR,
611 UIR_NULL),&pStatus)) return pStatus;
612 tUIR.NextUIR = wasteOffset;
613 if (!sX(WriteUIR64(CDF->fp,tOffset,
614 UIR_RECORD,&tUIR,
615 UIR_NULL),&pStatus)) return pStatus;
616 nextUIR.PrevUIR = wasteOffset;
617 if (!sX(WriteUIR64(CDF->fp,nextOffset,
618 UIR_RECORD,&nextUIR,
619 UIR_NULL),&pStatus)) return pStatus;
620 return pStatus;
621 }
622 tOffset = tUIR.NextUIR;
623 if (!sX(ReadUIR64(CDF->fp,tOffset,
624 UIR_RECORD,&tUIR,
625 UIR_NULL),&pStatus)) return pStatus;
626 }
627 /****************************************************************************
628 * The new UIR is going to be the last UIR.
629 ****************************************************************************/
630 newUIR.NextUIR = 0;
631 newUIR.PrevUIR = tOffset;
632 if (!sX(WriteUIR64(CDF->fp,wasteOffset,
633 UIR_RECORD,&newUIR,
634 UIR_NULL),&pStatus)) return pStatus;
635 tUIR.NextUIR = wasteOffset;
636 if (!sX(WriteUIR64(CDF->fp,tOffset,
637 UIR_RECORD,&tUIR,
638 UIR_NULL),&pStatus)) return pStatus;
639 return pStatus;
640 }
641
642 /******************************************************************************
643 * AllocateIR64.
644 ******************************************************************************/
645
AllocateIR64(CDF,size,offset)646 STATICforIDL CDFstatus AllocateIR64 (CDF, size, offset)
647 struct CDFstruct *CDF; /* In: Pointer to CDF. */
648 OFF_T size; /* In: Size of internal record (bytes). */
649 OFF_T *offset; /* Out: Offset of allocated internal record. */
650 {
651 CDFstatus pStatus = CDF_OK;
652 Int32 uir_ = UIR_;
653 OFF_T tSize, sOffset, eOffset, UIRhead, eof;
654 struct UIRstruct64 sUIR, eUIR;
655 /****************************************************************************
656 * Read EOF and offset of first UIR from GDR.
657 ****************************************************************************/
658 if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64,
659 GDR_UIRHEAD,&UIRhead,
660 GDR_EOF,&eof,
661 GDR_NULL),&pStatus)) return pStatus;
662 /****************************************************************************
663 * If UIRs exist, try to use one or more of them (if contiguous) for the new
664 * internal record.
665 ****************************************************************************/
666 if (UIRhead != 0) {
667 sOffset = UIRhead;
668 if (!sX(ReadUIR64(CDF->fp,sOffset,
669 UIR_RECORD,&sUIR,
670 UIR_NULL),&pStatus)) return pStatus;
671 eOffset = sOffset;
672 eUIR = sUIR;
673 tSize = sUIR.RecordSize;
674 for (;;) {
675 /***********************************************************************
676 * Check if the starting to ending UIRs are the exact size needed.
677 ***********************************************************************/
678 if (size == tSize) {
679 if (!sX(RemoveUIRs64(CDF,sOffset,eOffset),&pStatus)) return pStatus;
680 if (!sX(WriteIrSize64(CDF->fp,sOffset,&size),&pStatus)) return pStatus;
681 if (!sX(WriteIrType64(CDF->fp,sOffset,&uir_),&pStatus)) return pStatus;
682 *offset = sOffset;
683 return pStatus;
684 }
685 /***********************************************************************
686 * Check if the starting to ending UIRs are big enough for the new
687 * internal record and for a new UIR to fill the remaining space.
688 ***********************************************************************/
689 if (size + UIR_BASE_SIZE64 <= tSize) {
690 if (!sX(RemoveUIRs64(CDF,sOffset,eOffset),&pStatus)) return pStatus;
691 if (!sX(WasteIR64(CDF,sOffset+size,tSize-size),&pStatus)) {
692 return pStatus;
693 }
694 if (!sX(WriteIrSize64(CDF->fp,sOffset,&size),&pStatus)) return pStatus;
695 if (!sX(WriteIrType64(CDF->fp,sOffset,&uir_),&pStatus)) return pStatus;
696 *offset = sOffset;
697 return pStatus;
698 }
699 /***********************************************************************
700 * Check if the end of the UIRs has been reached. If so, check if the
701 * ending UIR is the last IR in the dotCDF file.
702 ***********************************************************************/
703 if (eUIR.NextUIR == 0) {
704 if (eOffset + (OFF_T) eUIR.RecordSize == eof) {
705 /*******************************************************************
706 * The ending UIR is the last internal record in the CDF. Check to
707 * see if after allocating the new internal record less than
708 * UIR_BASE_SIZE64 bytes will remain before the EOF. If so, waste an
709 * internal record at the location of those bytes so that a UIR is
710 * at the end (rather than stranded bytes).
711 *******************************************************************/
712 if (!sX(RemoveUIRs64(CDF,sOffset,eOffset),&pStatus)) return pStatus;
713 if (size < tSize) {
714 if (!sX(WasteIR64(CDF,sOffset+size,
715 UIR_BASE_SIZE64),&pStatus)) return pStatus;
716 eof = sOffset + (OFF_T) (size + UIR_BASE_SIZE64);
717 }
718 else
719 eof = sOffset + (OFF_T) size;
720 if (!sX(WriteGDR64(CDF->fp,CDF->GDRoffset64,
721 GDR_EOF,&eof,
722 GDR_NULL),&pStatus)) return pStatus;
723 if (!sX(WriteIrSize64(CDF->fp,
724 sOffset,
725 &size),&pStatus)) return pStatus;
726 if (!sX(WriteIrType64(CDF->fp,
727 sOffset,
728 &uir_),&pStatus)) return pStatus;
729 *offset = sOffset;
730 return pStatus;
731 }
732 else {
733 /*******************************************************************
734 * Non-UIRs follow the ending UIR. The new internal record will
735 * have to be allocated at the EOF.
736 *******************************************************************/
737 *offset = eof;
738 if (!sX(WriteIrSize64(CDF->fp,eof,&size),&pStatus)) return pStatus;
739 if (!sX(WriteIrType64(CDF->fp,eof,&uir_),&pStatus)) return pStatus;
740 eof += (OFF_T) size;
741 if (!sX(WriteGDR64(CDF->fp,CDF->GDRoffset64,
742 GDR_EOF,&eof,
743 GDR_NULL),&pStatus)) return pStatus;
744 return pStatus;
745 }
746 }
747 /***********************************************************************
748 * If the next UIR is contiguous with the ending UIR, make it the ending
749 * UIR. Otherwise, make the next UIR the starting and ending UIRs.
750 ***********************************************************************/
751 if (eOffset + eUIR.RecordSize == eUIR.NextUIR) {
752 eOffset = eUIR.NextUIR;
753 if (!sX(ReadUIR64(CDF->fp,eOffset,
754 UIR_RECORD,&eUIR,
755 UIR_NULL),&pStatus)) return pStatus;
756 tSize += eUIR.RecordSize;
757 }
758 else {
759 sOffset = eUIR.NextUIR;
760 if (!sX(ReadUIR64(CDF->fp,sOffset,
761 UIR_RECORD,&sUIR,
762 UIR_NULL),&pStatus)) return pStatus;
763 eOffset = sOffset;
764 eUIR = sUIR;
765 tSize = sUIR.RecordSize;
766 }
767 }
768 }
769 /****************************************************************************
770 * No UIRs exist. The new internal record will have to be allocated at the
771 * EOF.
772 ****************************************************************************/
773 *offset = eof;
774 if (!sX(WriteIrSize64(CDF->fp,eof,&size),&pStatus)) return pStatus;
775 if (!sX(WriteIrType64(CDF->fp,eof,&uir_),&pStatus)) return pStatus;
776 eof += size;
777 if (!sX(WriteGDR64(CDF->fp,CDF->GDRoffset64,
778 GDR_EOF,&eof,
779 GDR_NULL),&pStatus)) return pStatus;
780 return pStatus;
781 }
782
783 /******************************************************************************
784 * ResizeIR64.
785 ******************************************************************************/
786
ResizeIR64(CDF,curOffset,newSize,newOffset,move,success)787 STATICforIDL CDFstatus ResizeIR64 (CDF, curOffset, newSize, newOffset, move,
788 success)
789 struct CDFstruct *CDF;
790 OFF_T curOffset; /* In: Current offset of internal record. */
791 OFF_T newSize; /* In: New size of internal record. This may be
792 smaller or larger than the current size. */
793 OFF_T *newOffset; /* Out: New offset of internal record. This variable
794 is not modified if an error occurs or the internal
795 record cannot be extended (when `move' is FALSE). */
796 Logical move; /* In: TRUE if the internal record can be moved if
797 necessary. */
798 Logical *success; /* Out: TRUE if the internal record was successfully
799 extended (whether or not it had to be moved). */
800 {
801 CDFstatus pStatus = CDF_OK; OFF_T curSize;
802 OFF_T eof;
803 /****************************************************************************
804 * Determine current size of internal record.
805 ****************************************************************************/
806 if (!sX(ReadIrSize64(CDF->fp,curOffset,&curSize),&pStatus)) return pStatus;
807 /****************************************************************************
808 * Check sizes...
809 ****************************************************************************/
810 if (newSize > curSize) {
811 /**************************************************************************
812 * The internal record is growing. First check if it is the last one in
813 * the CDF.
814 **************************************************************************/
815 if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64,
816 GDR_EOF,&eof,
817 GDR_NULL),&pStatus)) return pStatus;
818 if (curOffset + (OFF_T) curSize == eof) {
819 /************************************************************************
820 * Last internal record. Simply extend the CDF.
821 ************************************************************************/
822 ASSIGNnotNULL (newOffset, curOffset)
823 eof += (OFF_T) (newSize - curSize);
824 if (!sX(WriteGDR64(CDF->fp,CDF->GDRoffset64,
825 GDR_EOF,&eof,
826 GDR_NULL),&pStatus)) return pStatus;
827 if (!sX(WriteIrSize64(CDF->fp,
828 curOffset,
829 &newSize),&pStatus)) return pStatus;
830 ASSIGNnotNULL (success, TRUE)
831 return pStatus;
832 }
833 else {
834 /************************************************************************
835 * Not the last internal record. If the internal record may be moved,
836 * first mark it as unused and then allocate a new internal record.
837 * Marking it unused first allows the possibility that if will be used
838 * as part of the allocated internal record. If the internal record can
839 * not be moved, check if unused records immediately follow.
840 ************************************************************************/
841 if (move) {
842 if (!sX(WasteIR64(CDF,curOffset,curSize),&pStatus)) return pStatus;
843 if (!sX(AllocateIR64(CDF,newSize,newOffset),&pStatus)) return pStatus;
844 ASSIGNnotNULL (success, TRUE)
845 return pStatus;
846 }
847 else {
848 Int32 irType;
849 OFF_T sOffset, eOffset, tSize, UIRhead;
850 struct UIRstruct64 sUIR, eUIR;
851 /**********************************************************************
852 * First check if there are any UIRs in the CDF. This is done because
853 * CDF V2.5.0* (alpha/beta) created UIRs without the next and previous
854 * UIR fields and didn't use the `UIRhead' field in the GDR. Because
855 * we don't want to use UIRs in those CDFs (because they are not the
856 * same as the current UIRs), this will keep us from doing so (because
857 * the `UIRhead' fields will always contain zero if a V2.5.0* CDF).
858 **********************************************************************/
859 if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64,
860 GDR_UIRHEAD,&UIRhead,
861 GDR_NULL),&pStatus)) return pStatus;
862 if (UIRhead == 0) {
863 ASSIGNnotNULL (success, FALSE)
864 return pStatus;
865 }
866 /**********************************************************************
867 * Read the internal record which immediately follows the internal
868 * record being resized. If it is a UIR make it the starting UIR.
869 * ---------------------------- DANGER ---------------------------------
870 * Don't try to read an entire UIR. First read only the record type
871 * field and check if it is UIR_. Then read the entire UIR. This is
872 * because the next internal record could be smaller than a UIR (or
873 * larger but not entirely written yet [eg. a VVR]).
874 **********************************************************************/
875 sOffset = curOffset + curSize;
876 if (!sX(ReadIrType64(CDF->fp,sOffset,&irType),&pStatus)) return pStatus;
877 if (irType != UIR_) {
878 ASSIGNnotNULL (success, FALSE)
879 return pStatus;
880 }
881 if (!sX(ReadUIR64(CDF->fp,sOffset,
882 UIR_RECORD,&sUIR,
883 UIR_NULL),&pStatus)) return pStatus;
884 tSize = curSize + sUIR.RecordSize;
885 eOffset = sOffset;
886 eUIR = sUIR;
887 for (;;) {
888 /*******************************************************************
889 * Check if the exact amount of available space has been found.
890 *******************************************************************/
891 if (newSize == tSize) {
892 if (!sX(RemoveUIRs64(CDF,sOffset,eOffset),&pStatus)) return pStatus;
893 if (!sX(WriteIrSize64(CDF->fp,
894 curOffset,
895 &newSize),&pStatus)) return pStatus;
896 ASSIGNnotNULL (newOffset, curOffset)
897 ASSIGNnotNULL (success, TRUE)
898 return pStatus;
899 }
900 /*******************************************************************
901 * Check if enough available space has been found to increase the
902 * internal record and then create a new UIR in the remaining space.
903 *******************************************************************/
904 if (newSize + UIR_BASE_SIZE64 <= tSize) {
905 if (!sX(RemoveUIRs64(CDF,sOffset,eOffset),&pStatus)) return pStatus;
906 if (!sX(WasteIR64(CDF,curOffset+newSize,tSize-newSize),&pStatus)) {
907 return pStatus;
908 }
909 if (!sX(WriteIrSize64(CDF->fp,
910 curOffset,
911 &newSize),&pStatus)) return pStatus;
912 ASSIGNnotNULL (newOffset, curOffset)
913 ASSIGNnotNULL (success, TRUE)
914 return pStatus;
915 }
916 /*******************************************************************
917 * Check if the end of the UIRs has been reached.
918 *******************************************************************/
919 if (eUIR.NextUIR == 0) {
920 /*****************************************************************
921 * If the ending UIR is at the EOF, then the internal record can
922 * be extended beyond the EOF or up to it with the creation of a
923 * new UIR at the very end.
924 *****************************************************************/
925 if (eOffset + (OFF_T) eUIR.RecordSize == eof) {
926 if (!sX(RemoveUIRs64(CDF,sOffset,eOffset),&pStatus)) return
927 pStatus;
928 if (newSize < tSize) {
929 if (!sX(WasteIR64(CDF,curOffset+newSize,
930 UIR_BASE_SIZE64),&pStatus)) return pStatus;
931 eof = curOffset + (OFF_T) (newSize + UIR_BASE_SIZE64);
932 }
933 else
934 eof = curOffset + (OFF_T) newSize;
935 if (!sX(WriteGDR64(CDF->fp,CDF->GDRoffset64,
936 GDR_EOF,&eof,
937 GDR_NULL),&pStatus)) return pStatus;
938 if (!sX(WriteIrSize64(CDF->fp,
939 curOffset,
940 &newSize),&pStatus)) return pStatus;
941 ASSIGNnotNULL (newOffset, curOffset)
942 ASSIGNnotNULL (success, TRUE)
943 return pStatus;
944 }
945 else {
946 ASSIGNnotNULL (success, FALSE)
947 return pStatus;
948 }
949 }
950 /*******************************************************************
951 * If the next UIR is contiguous with the ending UIR, make it the
952 * ending UIR.
953 *******************************************************************/
954 if (eOffset + eUIR.RecordSize == eUIR.NextUIR) {
955 eOffset = eUIR.NextUIR;
956 if (!sX(ReadUIR64(CDF->fp,eOffset,
957 UIR_RECORD,&eUIR,
958 UIR_NULL),&pStatus)) return pStatus;
959 tSize += eUIR.RecordSize;
960 }
961 else {
962 ASSIGNnotNULL (success, FALSE)
963 return pStatus;
964 }
965 }
966 }
967 }
968 }
969 else {
970 /**************************************************************************
971 * The internal record is shrinking. Check if it can be shrunk in place
972 * and a UIR created to occupy the extra space. If not, waste it and then
973 * allocate a new internal record (if moving it is allowed).
974 **************************************************************************/
975 if (newSize <= (curSize - UIR_BASE_SIZE64)) {
976 if (!sX(WasteIR64(CDF,curOffset + newSize,
977 curSize - newSize),&pStatus)) return pStatus;
978 if (!sX(WriteIrSize64(CDF->fp,
979 curOffset,
980 &newSize),&pStatus)) return pStatus;
981 ASSIGNnotNULL (newOffset, curOffset)
982 ASSIGNnotNULL (success, TRUE)
983 }
984 else {
985 if (move) {
986 if (!sX(WasteIR64(CDF,curOffset,curSize),&pStatus)) return pStatus;
987 if (!sX(AllocateIR64(CDF,newSize,newOffset),&pStatus)) return pStatus;
988 ASSIGNnotNULL (success, TRUE)
989 }
990 else {
991 ASSIGNnotNULL (success, FALSE)
992 }
993 }
994 return pStatus;
995 }
996 }
997
998 /******************************************************************************
999 * RemoveUIRs64.
1000 ******************************************************************************/
1001
RemoveUIRs64(CDF,sOffset,eOffset)1002 STATICforIDL CDFstatus RemoveUIRs64 (CDF, sOffset, eOffset)
1003 struct CDFstruct *CDF; /* In: Pointer to CDF. */
1004 OFF_T sOffset; /* In: Offset of starting UIR. */
1005 OFF_T eOffset; /* In: Offset of ending UIR. */
1006 {
1007 CDFstatus pStatus = CDF_OK;
1008 struct UIRstruct64 sUIR, eUIR;
1009 OFF_T UIRhead;
1010 if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64,
1011 GDR_UIRHEAD,&UIRhead,
1012 GDR_NULL),&pStatus)) return pStatus;
1013 if (!sX(ReadUIR64(CDF->fp,sOffset,
1014 UIR_RECORD,&sUIR,
1015 UIR_NULL),&pStatus)) return pStatus;
1016 if (!sX(ReadUIR64(CDF->fp,eOffset,
1017 UIR_RECORD,&eUIR,
1018 UIR_NULL),&pStatus)) return pStatus;
1019 if (UIRhead == sOffset) {
1020 UIRhead = eUIR.NextUIR;
1021 if (!sX(WriteGDR64(CDF->fp,CDF->GDRoffset64,
1022 GDR_UIRHEAD,&UIRhead,
1023 GDR_NULL),&pStatus)) return pStatus;
1024 }
1025 else {
1026 struct UIRstruct64 prevUIR;
1027 if (!sX(ReadUIR64(CDF->fp,sUIR.PrevUIR,
1028 UIR_RECORD,&prevUIR,
1029 UIR_NULL),&pStatus)) return pStatus;
1030 prevUIR.NextUIR = eUIR.NextUIR;
1031 if (!sX(WriteUIR64(CDF->fp,sUIR.PrevUIR,
1032 UIR_RECORD,&prevUIR,
1033 UIR_NULL),&pStatus)) return pStatus;
1034 }
1035 if (eUIR.NextUIR != 0) {
1036 struct UIRstruct64 nextUIR;
1037 if (!sX(ReadUIR64(CDF->fp,eUIR.NextUIR,
1038 UIR_RECORD,&nextUIR,
1039 UIR_NULL),&pStatus)) return pStatus;
1040 nextUIR.PrevUIR = sUIR.PrevUIR;
1041 if (!sX(WriteUIR64(CDF->fp,eUIR.NextUIR,
1042 UIR_RECORD,&nextUIR,
1043 UIR_NULL),&pStatus)) return pStatus;
1044 }
1045 return pStatus;
1046 }
1047
1048 /******************************************************************************
1049 * CorrectBlockingFactors64.
1050 * It is assumed that the last rVDR offset has already been fixed.
1051 ******************************************************************************/
1052
CorrectBlockingFactors64(CDF)1053 STATICforIDL CDFstatus CorrectBlockingFactors64 (CDF)
1054 struct CDFstruct *CDF;
1055 {
1056 CDFstatus pStatus = CDF_OK; Int32 nVars; OFF_T vdrOffset; int varN;
1057 Logical zVar; struct VDRstruct64 VDR; struct VarStruct **Vars, *Var;
1058 for (zVar = 0; zVar <= 1; zVar++) {
1059 Vars = BOO(zVar,CDF->zVars,CDF->rVars);
1060 nVars = BOO(zVar,CDF->NzVars,CDF->NrVars);
1061 for (varN = 0; varN < nVars; varN++) {
1062 Var = Vars[varN];
1063 if (Var == NULL) {
1064 if (!sX(FindVarByNumber64(CDF,(Int32)varN,
1065 zVar,&vdrOffset),&pStatus)) return pStatus;
1066 }
1067 else
1068 vdrOffset = Var->VDRoffset64;
1069 if (!sX(ReadVDR64(CDF,CDF->fp,vdrOffset,zVar,
1070 VDR_RECORD,&VDR,NULL,
1071 VDR_NULL),&pStatus)) return pStatus;
1072 if (!RECvaryBITset(VDR.Flags) && VDR.blockingFactor > 1) {
1073 VDR.blockingFactor = 1;
1074 if (!sX(WriteVDR64(CDF,CDF->fp,vdrOffset,zVar,
1075 VDR_RECORD,&VDR,NULL,
1076 VDR_NULL),&pStatus)) return pStatus;
1077 if (Var != NULL) {
1078 if (!sX(CalcBF64(CDF,Var),&pStatus)) return pStatus;
1079 }
1080 }
1081 }
1082 }
1083 return pStatus;
1084 }
1085
1086 /******************************************************************************
1087 * AbortAccess64.
1088 ******************************************************************************/
1089
AbortAccess64(CDF,updateCDF,deleteCDF)1090 STATICforIDL void AbortAccess64 (CDF, updateCDF, deleteCDF)
1091 struct CDFstruct *CDF;
1092 Logical updateCDF; /* Update "working" dotCDF file (if read/write
1093 access has been obtained)? */
1094 Logical deleteCDF; /* Delete CDF file(s)? */
1095 {
1096 /****************************************************************************
1097 * If the CDF is to be deleted do that first and then skip the updating and/or
1098 * closing of the CDF files.
1099 ****************************************************************************/
1100 if (deleteCDF) {
1101 DeleteCDFfiles (CDF);
1102 if (CDF->uDotFp != NULL) V_delete64 (CDF->uDotFp, NULL);
1103 }
1104 else {
1105 /**************************************************************************
1106 * Update the dotCDF file if requested, if the current access is read/write,
1107 * and if the "working" dotCDF file has not already been closed or deleted.
1108 **************************************************************************/
1109 if (CDF->status == READ_WRITE && updateCDF &&
1110 (CDF->fp == CDF->dotFp || CDF->fp == CDF->uDotFp)) UpdateDotCDF64 (CDF);
1111 /**************************************************************************
1112 * Close all of the CDF files if they are not already closed (or deleted).
1113 **************************************************************************/
1114 if (CDF->dotFp != NULL) V_close64 (CDF->dotFp, CDF, NULL);
1115 if (CDF->uDotFp != NULL) V_close64 (CDF->uDotFp, CDF, NULL);
1116 CloseVarFiles64 (CDF);
1117 }
1118 /****************************************************************************
1119 * Delete the scratch files that still exist.
1120 ****************************************************************************/
1121 if (CDF->stage.fp != NULL) V_delete64 (CDF->stage.fp, NULL);
1122 if (CDF->compressFp != NULL) V_delete64 (CDF->compressFp, NULL);
1123 /****************************************************************************
1124 * Free the memory used by the CDF.
1125 ****************************************************************************/
1126 FreeCDFid (CDF, TRUE);
1127 return;
1128 }
1129
1130 /******************************************************************************
1131 * DeleteCDFfiles64.
1132 * The files may be open or closed. This routine does not delete the
1133 * uncompressed dotCDF file (if one exists).
1134 ******************************************************************************/
1135
DeleteCDFfiles64(CDF)1136 STATICforIDL CDFstatus DeleteCDFfiles64 (CDF)
1137 struct CDFstruct *CDF;
1138 {
1139 char tmpFile[DU_MAX_PATH_LEN+1]; CDFstatus pStatus = CDF_OK;
1140 /**************************************************************************
1141 * Delete dotCDF file.
1142 **************************************************************************/
1143 if (CDF->dotFp == NULL) {
1144 BuildFilePath (CDFt, CDF->CDFname, CDF->no_append, CDF->upper_case_ext,
1145 CDF->version_numbers, INT32_ZERO, tmpFile);
1146 if (!DeleteFile(tmpFile)) sX (CDF_DELETE_ERROR, &pStatus);
1147 }
1148 else {
1149 if (!DELETEv64(CDF->dotFp,NULL)) sX (CDF_DELETE_ERROR, &pStatus);
1150 CDF->dotFp = NULL;
1151 }
1152 /**************************************************************************
1153 * Delete the variable files (if multi-file). Both rVariable and zVariable
1154 * files are deleted.
1155 **************************************************************************/
1156 if (!CDF->singleFile) {
1157 int varN;
1158 for (varN = 0; varN < CDF->NrVars; varN++) {
1159 struct VarStruct *Var = CDF->rVars[varN];
1160 if (Var != NULL) {
1161 if (Var->fp != NULL) {
1162 if (!DELETEv64(Var->fp,NULL)) sX (VAR_DELETE_ERROR, &pStatus);
1163 Var->fp = NULL;
1164 continue;
1165 }
1166 }
1167 BuildFilePath (Vt, CDF->CDFname, CDF->no_append, CDF->upper_case_ext,
1168 CDF->version_numbers, varN, tmpFile);
1169 if (!DeleteFile(tmpFile)) sX (VAR_DELETE_ERROR, &pStatus);
1170 }
1171 for (varN = 0; varN < CDF->NzVars; varN++) {
1172 struct VarStruct *Var = CDF->zVars[varN];
1173 if (Var != NULL) {
1174 if (Var->fp != NULL) {
1175 if (!DELETEv64(Var->fp,NULL)) sX (VAR_DELETE_ERROR, &pStatus);
1176 Var->fp = NULL;
1177 continue;
1178 }
1179 }
1180 BuildFilePath (Zt, CDF->CDFname, CDF->no_append, CDF->upper_case_ext,
1181 CDF->version_numbers, varN, tmpFile);
1182 if (!DeleteFile(tmpFile)) sX (VAR_DELETE_ERROR, &pStatus);
1183 }
1184 }
1185 return pStatus;
1186 }
1187
1188 /******************************************************************************
1189 * DeleteEntry64.
1190 ******************************************************************************/
1191
DeleteEntry64(CDF,aOffset,eOffset)1192 STATICforIDL CDFstatus DeleteEntry64 (CDF, aOffset, eOffset)
1193 struct CDFstruct *CDF;
1194 OFF_T aOffset;
1195 OFF_T eOffset;
1196 {
1197 CDFstatus pStatus = CDF_OK;
1198 struct ADRstruct64 ADR;
1199 struct AEDRstruct64 AEDR, AEDRt;
1200 OFF_T prevEntryOffset;
1201 Logical zEntry;
1202 /****************************************************************************
1203 * Read the ADR and the AEDR being deleted.
1204 ****************************************************************************/
1205 if (!sX(ReadADR64(CDF->fp,aOffset,
1206 ADR_RECORD,&ADR,
1207 ADR_NULL),&pStatus)) return pStatus;
1208 if (!sX(ReadAEDR64(CDF->fp,eOffset,
1209 AEDR_RECORD,&AEDR,NULL,
1210 AEDR_NULL),&pStatus)) return pStatus;
1211 zEntry = (AEDR.RecordType == AzEDR_);
1212 /****************************************************************************
1213 * Remove the AEDR from the list of entries.
1214 ****************************************************************************/
1215 if (!sX(FindPrevEntry64(CDF,aOffset,eOffset,
1216 zEntry,&prevEntryOffset),&pStatus)) return pStatus;
1217 if (prevEntryOffset == 0) {
1218 /**************************************************************************
1219 * The first entry on the linked list is being deleted. Point the ADR to
1220 * the entry being pointed to by the entry being deleted.
1221 **************************************************************************/
1222 if (zEntry)
1223 ADR.AzEDRhead = AEDR.AEDRnext;
1224 else
1225 ADR.AgrEDRhead = AEDR.AEDRnext;
1226 }
1227 else {
1228 /**************************************************************************
1229 * The entry being deleted is not the first entry on the linked list. Point
1230 * the previous entry to the entry pointed to by the entry being deleted.
1231 **************************************************************************/
1232 if (!sX(ReadAEDR64(CDF->fp,prevEntryOffset,
1233 AEDR_RECORD,&AEDRt,NULL,
1234 AEDR_NULL),&pStatus)) return pStatus;
1235 AEDRt.AEDRnext = AEDR.AEDRnext;
1236 if (!sX(WriteAEDR64(CDF,CDF->fp,prevEntryOffset,
1237 AEDR_RECORD,&AEDRt,NULL,
1238 AEDR_NULL),&pStatus)) return pStatus;
1239 }
1240 /****************************************************************************
1241 * Decrement the number of entries and recalculate the maximum entry (if
1242 * necessary).
1243 ****************************************************************************/
1244 if (zEntry)
1245 ADR.NzEntries--;
1246 else
1247 ADR.NgrEntries--;
1248 if (BOO(zEntry,ADR.MAXzEntry,ADR.MAXgrEntry) == AEDR.Num) {
1249 Int32 maxEntry = NO_ENTRY;
1250 OFF_T tOffset = BOO(zEntry,ADR.AzEDRhead,ADR.AgrEDRhead);
1251 while (tOffset != 0) {
1252 if (!sX(ReadAEDR64(CDF->fp,tOffset,
1253 AEDR_RECORD,&AEDRt,NULL,
1254 AEDR_NULL),&pStatus)) return pStatus;
1255 maxEntry = MaxInt32 (maxEntry, AEDRt.Num);
1256 tOffset = AEDRt.AEDRnext;
1257 }
1258 if (zEntry)
1259 ADR.MAXzEntry = maxEntry;
1260 else
1261 ADR.MAXgrEntry = maxEntry;
1262 }
1263 /****************************************************************************
1264 * Rewrite the ADR and waste the AEDR (of the entry being deleted).
1265 ****************************************************************************/
1266 if (!sX(WriteADR64(CDF->fp,aOffset,
1267 ADR_RECORD,&ADR,
1268 ADR_NULL),&pStatus)) return pStatus;
1269 if (!sX(WasteIR64(CDF,eOffset,AEDR.RecordSize),&pStatus)) return pStatus;
1270 return pStatus;
1271 }
1272
1273 /******************************************************************************
1274 * PadUnRecords64.
1275 * Pad all allocated records within the first/last record range. Note that
1276 * in the case of sparse records some of the records may not be allocated (and
1277 * should not be padded of course).
1278 ******************************************************************************/
1279
PadUnRecords64(CDF,Var,firstRec,lastRec)1280 STATICforIDL CDFstatus PadUnRecords64 (CDF, Var, firstRec, lastRec)
1281 struct CDFstruct *CDF;
1282 struct VarStruct *Var;
1283 Int32 firstRec;
1284 Int32 lastRec;
1285 {
1286 CDFstatus pStatus = CDF_OK; OFF_T offset; int how; void *buffer;
1287 Int32 recNum, nRecords, toRec, lastRecInVVR; Logical found;
1288 /****************************************************************************
1289 * Pad the records.
1290 * NOTE: Padding in a single-file CDF could be made more efficient by not
1291 * allocating/freeing the pad buffer over and over...
1292 ****************************************************************************/
1293 if (CDF->singleFile) {
1294 /**************************************************************************
1295 * Single-file...first determine the first allocated record to be padded.
1296 **************************************************************************/
1297 if (!sX(NextRecord64(CDF,Var->VDRoffset64,Var->zVar,
1298 firstRec,&recNum,&found),&pStatus)) return pStatus;
1299 if (!found) return pStatus;
1300 /**************************************************************************
1301 * While the first record to be padded is within the range...
1302 **************************************************************************/
1303 while (recNum <= lastRec) {
1304 if (!sX(RecordByteOffset64(CDF,Var,recNum,
1305 &offset),&pStatus)) return pStatus;
1306 if (!sX(SearchForRecord64(CDF,Var->VDRoffset64,
1307 Var->zVar,recNum,
1308 NULL,&lastRecInVVR,
1309 NULL,NULL),&pStatus)) return pStatus;
1310 toRec = MINIMUM(lastRec,lastRecInVVR);
1311 nRecords = toRec - recNum + 1;
1312 if (!sX(BuildPadBuffer64(CDF,Var,nRecords,
1313 &how,&buffer,TRUE),&pStatus)) return pStatus;
1314 if (!sX(WritePadValues64(Var,CDF->fp,offset,
1315 nRecords,how,buffer),&pStatus)) {
1316 cdf_FreeMemory (buffer, NULL);
1317 return pStatus;
1318 }
1319 cdf_FreeMemory (buffer, NULL);
1320 recNum += nRecords;
1321 /************************************************************************
1322 * Determine the next `first' record to be padded.
1323 ************************************************************************/
1324 if (!sX(NextRecord64(CDF,Var->VDRoffset64,Var->zVar,
1325 recNum,&recNum,&found),&pStatus)) return pStatus;
1326 if (!found) return pStatus;
1327 }
1328 }
1329 else {
1330 /**************************************************************************
1331 * Multi-file...
1332 **************************************************************************/
1333 if (!sX(RecordByteOffset64(CDF,Var,
1334 firstRec,
1335 &offset),&pStatus)) return pStatus;
1336 nRecords = lastRec - firstRec + 1;
1337 if (!sX(BuildPadBuffer64(CDF,Var,nRecords,
1338 &how,&buffer,TRUE),&pStatus)) return pStatus;
1339 if (!sX(WritePadValues64(Var,Var->fp,offset,nRecords,how,buffer),&pStatus)) {
1340 cdf_FreeMemory (buffer, NULL);
1341 return pStatus;
1342 }
1343 cdf_FreeMemory (buffer, NULL);
1344 }
1345 return pStatus;
1346 }
1347
1348 /******************************************************************************
1349 * WritePadValues64.
1350 * NOTE: It is assumed that the records are contiguous (in a single-file CDF)
1351 * and that on a DOS machine the buffer does not exceed 64K bytes. It is also
1352 * assumed that the values have already been encoded for the CDF.
1353 ******************************************************************************/
1354
WritePadValues64(Var,fp,offset,nRecords,how,buffer)1355 STATICforIDL CDFstatus WritePadValues64 (Var, fp, offset, nRecords, how, buffer)
1356 struct VarStruct *Var;
1357 vFILE *fp;
1358 OFF_T offset;
1359 Int32 nRecords;
1360 int how;
1361 void *buffer;
1362 {
1363 Int32 nBytes, nValues, recX, valueX;
1364 /****************************************************************************
1365 * Seek to desired offset.
1366 ****************************************************************************/
1367 if (!SEEKv64(fp,offset,vSEEK_SET)) return VAR_WRITE_ERROR;
1368 /****************************************************************************
1369 * Write records...
1370 ****************************************************************************/
1371 switch (how) {
1372 case ALLrecordsATonce:
1373 nBytes = nRecords * Var->NphyRecBytes;
1374 if (!WRITEv64(buffer,(size_t)nBytes,1,fp)) return VAR_WRITE_ERROR;
1375 break;
1376 case ONErecordATaTIME:
1377 for (recX = 0; recX < nRecords; recX++) {
1378 if (!WRITEv64(buffer,(size_t)Var->NphyRecBytes,1,fp)) {
1379 return VAR_WRITE_ERROR;
1380 }
1381 }
1382 break;
1383 case ONEvalueATaTIME:
1384 nValues = nRecords * Var->NphyRecValues;
1385 for (valueX = 0; valueX < nValues; valueX++) {
1386 if (!WRITEv64(buffer,(size_t)Var->NvalueBytes,1,fp)) {
1387 return VAR_WRITE_ERROR;
1388 }
1389 }
1390 break;
1391 }
1392 return CDF_OK;
1393 }
1394
1395