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