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 13-Oct-06, M Liu Changed to allow upper and lower case CDF
31 * name to be used on win32.
32 *
33 ******************************************************************************/
34
35 #include "cdflib.h"
36 #include "cdflib64.h"
37 #include "cdfrev.h"
38
39 /******************************************************************************
40 * CorrectV20eof.
41 ******************************************************************************/
42
CorrectV20eof(CDF)43 STATICforIDL CDFstatus CorrectV20eof (CDF)
44 struct CDFstruct *CDF;
45 {
46 CDFstatus pStatus = CDF_OK;
47 Int32 eof = 0, size, vOffset, aOffset, eOffset, nAttrs, nEntries;
48 int varX, attrX, entryX;
49 /****************************************************************************
50 * Check if CDR is last internal record.
51 ****************************************************************************/
52 if (!sX(ReadCDR(CDF->fp,CDF->CDRoffset,
53 CDR_RECORDSIZE,&size,
54 CDR_NULL),&pStatus)) return pStatus;
55 eof = MaxInt32 (eof, CDF->CDRoffset + size);
56 /****************************************************************************
57 * Check if GDR is last internal record.
58 ****************************************************************************/
59 if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
60 GDR_RECORDSIZE,&size,
61 GDR_NULL),&pStatus)) return pStatus;
62 eof = MaxInt32 (eof, CDF->GDRoffset + size);
63 /****************************************************************************
64 * Scan through rVDRs checking if each is the last internal record. Note
65 * that V2.0 CDFs won't have zVDRs, VXRs, or VVRs.
66 ****************************************************************************/
67 if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
68 GDR_rVDRHEAD,&vOffset,
69 GDR_NULL),&pStatus)) return pStatus;
70 for (varX = 0; varX < CDF->NrVars; varX++) {
71 if (!sX(ReadVDR(CDF,CDF->fp,vOffset,FALSE,
72 VDR_RECORDSIZE,&size,
73 VDR_NULL),&pStatus)) return pStatus;
74 eof = MaxInt32 (eof, vOffset + size);
75 if (!sX(ReadVDR(CDF,CDF->fp,vOffset,FALSE,
76 VDR_VDRNEXT,&vOffset,
77 VDR_NULL),&pStatus)) return pStatus;
78 }
79 /****************************************************************************
80 * Scan through the ADRs checking if each is the last internal record.
81 ****************************************************************************/
82 if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
83 GDR_NUMATTR,&nAttrs,
84 GDR_ADRHEAD,&aOffset,
85 GDR_NULL),&pStatus)) return pStatus;
86 for (attrX = 0; attrX < nAttrs; attrX++) {
87 if (!sX(ReadADR(CDF->fp,aOffset,
88 ADR_RECORDSIZE,&size,
89 ADR_NULL),&pStatus)) return pStatus;
90 eof = MaxInt32 (eof, aOffset + size);
91 /*************************************************************************
92 * Scan through the ArEDRs checking if each is the last internal record.
93 * Note that V2.0 CDFs won't have AzEDRs.
94 *************************************************************************/
95 if (!sX(ReadADR(CDF->fp,aOffset,
96 ADR_AgrEDRHEAD,&eOffset,
97 ADR_NgrENTRIES,&nEntries,
98 ADR_NULL),&pStatus)) return pStatus;
99 for (entryX = 0; entryX < nEntries; entryX++) {
100 if (!sX(ReadAEDR(CDF->fp,eOffset,
101 AEDR_RECORDSIZE,&size,
102 AEDR_NULL),&pStatus)) return pStatus;
103 eof = MaxInt32 (eof, eOffset + size);
104 if (!sX(ReadAEDR(CDF->fp,eOffset,
105 AEDR_AEDRNEXT,&eOffset,
106 AEDR_NULL),&pStatus)) return pStatus;
107 }
108 if (!sX(ReadADR(CDF->fp,aOffset,
109 ADR_ADRNEXT,&aOffset,
110 ADR_NULL),&pStatus)) return pStatus;
111 }
112 /****************************************************************************
113 * Save correct EOF and return.
114 ****************************************************************************/
115 if (!sX(WriteGDR(CDF->fp,CDF->GDRoffset,
116 GDR_EOF,&eof,
117 GDR_NULL),&pStatus)) return pStatus;
118 return pStatus;
119 }
120
121 /******************************************************************************
122 * CorrectV20offsets.
123 ******************************************************************************/
124
CorrectV20offsets(CDF)125 STATICforIDL CDFstatus CorrectV20offsets (CDF)
126 struct CDFstruct *CDF;
127 {
128 CDFstatus pStatus = CDF_OK;
129 Int32 zero = 0, size, vOffset, aOffset, eOffset, nAttrs, nEntries;
130 int varX, attrX, entryX;
131 /****************************************************************************
132 * Scan through rVDRs fixing the next VDR field of the last one (setting it
133 * to an offset of zero). Note that V2.0 CDFs won't have zVDRs, VXRs, or
134 * VVRs.
135 ****************************************************************************/
136 if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
137 GDR_rVDRHEAD,&vOffset,
138 GDR_NULL),&pStatus)) return pStatus;
139 for (varX = 0; varX < CDF->NrVars; varX++) {
140 if (!sX(ReadVDR(CDF,CDF->fp,vOffset,FALSE,
141 VDR_RECORDSIZE,&size,
142 VDR_NULL),&pStatus)) return pStatus;
143 if (varX == CDF->NrVars - 1) {
144 if (!sX(WriteVDR(CDF,CDF->fp,vOffset,FALSE,
145 VDR_VDRNEXT,&zero,
146 VDR_NULL),&pStatus)) return pStatus;
147 }
148 else {
149 if (!sX(ReadVDR(CDF,CDF->fp,vOffset,FALSE,
150 VDR_VDRNEXT,&vOffset,
151 VDR_NULL),&pStatus)) return pStatus;
152 }
153 }
154 /****************************************************************************
155 * Scan through the ADRs fixing the next ADR field of the last one (setting
156 * it to an offset of zero).
157 ****************************************************************************/
158 if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
159 GDR_NUMATTR,&nAttrs,
160 GDR_ADRHEAD,&aOffset,
161 GDR_NULL),&pStatus)) return pStatus;
162 for (attrX = 0; attrX < nAttrs; attrX++) {
163 if (!sX(ReadADR(CDF->fp,aOffset,
164 ADR_RECORDSIZE,&size,
165 ADR_NULL),&pStatus)) return pStatus;
166 /*************************************************************************
167 * Scan through the ArEDRs fixing the next ArEDR field of the last one
168 * (setting it to an offset of zero). Note that V2.0 CDFs won't have
169 * AzEDRs.
170 *************************************************************************/
171 if (!sX(ReadADR(CDF->fp,aOffset,
172 ADR_AgrEDRHEAD,&eOffset,
173 ADR_NgrENTRIES,&nEntries,
174 ADR_NULL),&pStatus)) return pStatus;
175 for (entryX = 0; entryX < nEntries; entryX++) {
176 if (!sX(ReadAEDR(CDF->fp,eOffset,
177 AEDR_RECORDSIZE,&size,
178 AEDR_NULL),&pStatus)) return pStatus;
179 if (entryX == nEntries - 1) {
180 if (!sX(WriteAEDR(CDF,CDF->fp,eOffset,
181 AEDR_AEDRNEXT,&zero,
182 AEDR_NULL),&pStatus)) return pStatus;
183 }
184 else {
185 if (!sX(ReadAEDR(CDF->fp,eOffset,
186 AEDR_AEDRNEXT,&eOffset,
187 AEDR_NULL),&pStatus)) return pStatus;
188 }
189 }
190 if (attrX == nAttrs - 1) {
191 if (!sX(WriteADR(CDF->fp,aOffset,
192 ADR_ADRNEXT,&zero,
193 ADR_NULL),&pStatus)) return pStatus;
194 }
195 else {
196 if (!sX(ReadADR(CDF->fp,aOffset,
197 ADR_ADRNEXT,&aOffset,
198 ADR_NULL),&pStatus)) return pStatus;
199 }
200 }
201 return pStatus;
202 }
203
204 /******************************************************************************
205 * UpdateDotCDF.
206 * If this routine is called when aborting a CDF, we cannot assume that
207 * the CDF structure is complete - it may have been only partially initialized
208 * when the CDF was aborted. If it is called to save the CDF without closing
209 * it, the data will be properly preserved.
210 ******************************************************************************/
211
UpdateDotCDF(CDF)212 STATICforIDL CDFstatus UpdateDotCDF (CDF)
213 struct CDFstruct *CDF;
214 {
215 CDFstatus pStatus = CDF_OK; int varN; struct VarStruct *Var; Logical zVar;
216 /**************************************************************************
217 * Update r/zVariables depending on the variable type...
218 **************************************************************************/
219 for (zVar = 0; zVar <= 1; zVar++) {
220 if (BOO(zVar,CDF->zVars,CDF->rVars) != NULL) {
221 Int32 nVars = BOO(zVar,CDF->NzVars,CDF->NrVars);
222 for (varN = 0; varN < nVars; varN++) {
223 Var = BOO(zVar,CDF->zVars[varN],CDF->rVars[varN]);
224 if (Var != NULL) {
225 switch (Var->vType) {
226 case SPARSE_RECORDS_: {
227 if (!sX(FlushStage(CDF,Var),&pStatus)) break;
228 /* No `break' is intentional. */
229 case STANDARD_:
230 if (Var->maxWritten < Var->maxAllocated) {
231 Int32 padFrom = Var->maxWritten + 1;
232 if (!sX(PadUnRecords(CDF,Var,padFrom,
233 Var->maxAllocated),&pStatus)) break;
234 Var->maxWritten = Var->maxAllocated;
235 }
236 break;
237 }
238 case COMPRESSED_:
239 case SPARSE_COMPRESSED_RECORDS_:
240 if (!sX(FlushStage(CDF,Var),&pStatus)) break;
241 break;
242 case SPARSE_ARRAYS_:
243 case SPARSE_RECORDS_AND_ARRAYS_:
244 sX (UNKNOWN_SPARSENESS, &pStatus);
245 break;
246 case IN_MULTI_:
247 break;
248 default:
249 sX (CDF_INTERNAL_ERROR, &pStatus);
250 break;
251 }
252 }
253 }
254 }
255 }
256 return pStatus;
257 }
258
259 /******************************************************************************
260 * CloseVarFiles.
261 *
262 * Close the open variable files of the specified CDF. This routine closes all
263 * of the open variable files regardless of the number of errors detected.
264 *
265 * Because this routine is called when aborting a CDF, we cannot assume
266 * that the CDF structure is complete. Eg., it may have been only partially
267 * initialized when the CDF was aborted.
268 ******************************************************************************/
269
CloseVarFiles(CDF)270 STATICforIDL CDFstatus CloseVarFiles (CDF)
271 struct CDFstruct *CDF;
272 {
273 CDFstatus pStatus = CDF_OK; struct VarStruct *Var; int varN;
274 /****************************************************************************
275 * If a multi-file CDF, close the variable files.
276 ****************************************************************************/
277 if (!CDF->singleFile) {
278 /**************************************************************************
279 * Close rVariable files. If the pointer to the rVariable is NULL, then
280 * the rVariable has yet to be initialized (and is obviously closed).
281 **************************************************************************/
282 if (CDF->rVars != NULL) {
283 for (varN = 0; varN < CDF->NrVars; varN++) {
284 Var = CDF->rVars[varN];
285 if (Var != NULL) {
286 if (Var->fp != NULL) {
287 if (!CLOSEv(Var->fp,NULL,NULL)) sX (VAR_CLOSE_ERROR, &pStatus);
288 Var->fp = NULL;
289 }
290 }
291 }
292 }
293 /**************************************************************************
294 * Close zVariable files. If the pointer to the zVariable is NULL, then
295 * the zVariable has yet to be initialized (and is obviously closed).
296 **************************************************************************/
297 if (CDF->zVars != NULL) {
298 for (varN = 0; varN < CDF->NzVars; varN++) {
299 Var = CDF->zVars[varN];
300 if (Var != NULL) {
301 if (Var->fp != NULL) {
302 if (!CLOSEv(Var->fp,NULL,NULL)) sX (VAR_CLOSE_ERROR, &pStatus);
303 Var->fp = NULL;
304 }
305 }
306 }
307 }
308 }
309 return pStatus;
310 }
311
312 /******************************************************************************
313 * WriteAccess.
314 * Close and then reopen a CDF for read/write access (it was opened with
315 * read-only access initially). If the CDF is earlier than CDF V2.5, then
316 * some of the fields will have to be fixed and the CDR will be truncated for
317 * a shorter copyright length (unless the CDF is being deleted in which case
318 * it would be a waste of time to do these things).
319 ******************************************************************************/
320
WriteAccess(CDF,forDelete,pStatus)321 STATICforIDL Logical WriteAccess (CDF, forDelete, pStatus)
322 struct CDFstruct *CDF;
323 Logical forDelete; /* Is the write access is needed to delete the CDF? */
324 CDFstatus *pStatus; /* Returned status. */
325 {
326 #if BUILD_READ_ONLY_DISTRIBUTION
327 *pStatus = READ_ONLY_DISTRIBUTION;
328 return FALSE;
329 #else
330 char pathName[DU_MAX_PATH_LEN+1]; vSTATS vStats;
331 /***************************************************************************
332 * Check if write access already.
333 ***************************************************************************/
334 if (CDF->status == READ_WRITE) return TRUE;
335 /***************************************************************************
336 * Check if this CDF is in read-only mode.
337 ***************************************************************************/
338 if (CDF->readOnly) {
339 *pStatus = READ_ONLY_MODE;
340 return FALSE;
341 }
342 /***************************************************************************
343 * Close (the possibly compressed) dotCDF file and the variable files (if
344 * a multi-file CDF). An uncompressed dotCDF file and any scratch files
345 * stay open.
346 ***************************************************************************/
347 if (!CLOSEv(CDF->dotFp,NULL,&vStats)) {
348 CDF->dotFp = NULL;
349 AbortAccess (CDF, noUPDATE, noDELETE);
350 return FALSE;
351 }
352 CDF->dotFp = NULL;
353 AddTOvStats (&CDF->dotCDFvStats, &vStats);
354 #if defined(DEBUG)
355 DisplayVs (getenv("VSTREAM_STATS"), "DotCDF..", &vStats);
356 #endif
357 if (!sX(CloseVarFiles(CDF),pStatus)) {
358 AbortAccess (CDF, noUPDATE, noDELETE);
359 return FALSE;
360 }
361 /***************************************************************************
362 * Open dotCDF file with read-write access. If read-write access is not
363 * allowed, try to return to read-only access. If reopening with read-only
364 * access fails, free CDF structures as if CDF had been closed.
365 ***************************************************************************/
366 BuildFilePath (CDFt, CDF->CDFname, CDF->no_append, CDF->upper_case_ext,
367 CDF->version_numbers, 0L, pathName);
368 CDF->dotFp = V_open (pathName, READ_PLUS_a_mode);
369 if (CDF->dotFp == NULL) {
370 CDF->dotFp = V_open (pathName, READ_ONLY_a_mode);
371 if (CDF->dotFp == NULL) {
372 AbortAccess (CDF, noUPDATE, noDELETE);
373 *pStatus = CDF_OPEN_ERROR;
374 return FALSE;
375 }
376 else {
377 CDF->status = READ_ONLY;
378 *pStatus = NO_WRITE_ACCESS; /* Don't return yet. */
379 }
380 }
381 else
382 CDF->status = READ_WRITE;
383 /***************************************************************************
384 * If the CDF is not compressed, reassign the "working" file pointer and
385 * reset the cache size (unless deleting). If the CDF is compressed, the
386 * cache size of the "working" file pointer does not have to be reset.
387 ***************************************************************************/
388 if (CDF->uDotFp == NULL) {
389 CDF->fp = CDF->dotFp;
390 if (!forDelete) {
391 if (!CACHEv(CDF->fp,CDF->workingCacheSize)) {
392 *pStatus = BAD_CACHE_SIZE;
393 AbortAccess (CDF, noUPDATE, noDELETE);
394 return FALSE;
395 }
396 }
397 }
398 /***************************************************************************
399 * Fix various fields (if write access was obtained) unless write access
400 * was needed to delete the CDF.
401 ***************************************************************************/
402 if (CDF->status == READ_WRITE && !forDelete) {
403 Int32 versionNew = CDF_LIBRARY_VERSION,
404 releaseNew = CDF_LIBRARY_RELEASE,
405 incrementNew = CDF_LIBRARY_INCREMENT;
406 uInt32 magicNumber1 = V2magicNUMBER_1,
407 magicNumber2 = V2magicNUMBER_2u;
408 char copyRight[CDF_COPYRIGHT_LEN+1];
409 /*************************************************************************
410 * Update magic numbers.
411 *************************************************************************/
412 if (!SEEKv(CDF->fp,(long)V2_MAGIC_OFFSET_1,vSEEK_SET)) {
413 AbortAccess (CDF, noUPDATE, noDELETE);
414 *pStatus = CDF_WRITE_ERROR;
415 return FALSE;
416 }
417 if (!Write32(CDF->fp,(Int32 *)&magicNumber1)) {
418 AbortAccess (CDF, noUPDATE, noDELETE);
419 *pStatus = CDF_WRITE_ERROR;
420 return FALSE;
421 }
422 if (!Write32(CDF->fp,(Int32 *)&magicNumber2)) {
423 AbortAccess (CDF, noUPDATE, noDELETE);
424 *pStatus = CDF_WRITE_ERROR;
425 return FALSE;
426 }
427 /*************************************************************************
428 * If a V2.0 CDF, correct the EOF field.
429 *************************************************************************/
430 if (CDF->badEOF) {
431 if (!sX(CorrectV20eof(CDF),pStatus)) {
432 AbortAccess (CDF, noUPDATE, noDELETE);
433 return FALSE;
434 }
435 CDF->badEOF = FALSE;
436 }
437 /*************************************************************************
438 * If a V2.0 CDF, correct the terminating offset fields. NOTE: Fix these
439 * fields before the other "fixing" routines (which may depend on these
440 * fields).
441 *************************************************************************/
442 if (CDF->badTerminatingOffsets) {
443 if (!sX(CorrectV20offsets(CDF),pStatus)) {
444 AbortAccess (CDF, noUPDATE, noDELETE);
445 return FALSE;
446 }
447 CDF->badTerminatingOffsets = FALSE;
448 }
449 /*************************************************************************
450 * If prior to CDF V2.1.1, then change the data type associated with the
451 * "EPOCH" rVariable/rEntries to CDF_EPOCH.
452 *************************************************************************/
453 if (CDF->fakeEPOCH) {
454 if (!sX(CorrectEPOCH(CDF),pStatus)) {
455 AbortAccess (CDF, noUPDATE, noDELETE);
456 return FALSE;
457 }
458 CDF->fakeEPOCH = FALSE;
459 }
460 /*************************************************************************
461 * If prior to CDF V2.5, then truncate the CDR for a shorter copyright
462 * field and shorten each VDR to reclaim the wasted space.
463 *************************************************************************/
464 if (CDF->wastedSpace) {
465 if (!sX(ShortenCDR(CDF),pStatus)) {
466 AbortAccess (CDF, noUPDATE, noDELETE);
467 return FALSE;
468 }
469 if (!sX(ShortenVDRs(CDF),pStatus)) {
470 AbortAccess (CDF, noUPDATE, noDELETE);
471 return FALSE;
472 }
473 CDF->wastedSpace = FALSE;
474 }
475 /*************************************************************************
476 * If prior to CDF V2.5, then convert all assumed scopes to definite
477 * scopes.
478 *************************************************************************/
479 if (CDF->assumedScopes) {
480 if (!sX(CorrectScopes(CDF),pStatus)) {
481 AbortAccess (CDF, noUPDATE, noDELETE);
482 return FALSE;
483 }
484 CDF->assumedScopes = FALSE;
485 }
486 /*************************************************************************
487 * Fix blocking factors for variables having a recVary of NOVARY.
488 *************************************************************************/
489 if (!sX(CorrectBlockingFactors(CDF),pStatus)) {
490 AbortAccess (CDF, noUPDATE, noDELETE);
491 return FALSE;
492 }
493 /*************************************************************************
494 * Update version/release/increment - should never happen as for older
495 * versioned (V2.7 and older) CDFs, we want to keep its original data
496 * structure.
497 *************************************************************************/
498 if (isLFS(CDF)) { /* It should be false all the time. */
499 if (!sX(WriteCDR(CDF->fp,V2_CDR_OFFSET,
500 CDR_VERSION,&versionNew,
501 CDR_RELEASE,&releaseNew,
502 CDR_INCREMENT,&incrementNew,
503 CDR_NULL),pStatus)) {
504 AbortAccess (CDF, noUPDATE, noDELETE);
505 return FALSE;
506 }
507 }
508 /*************************************************************************
509 * Update copyright.
510 *************************************************************************/
511 CDFcopyRight (copyRight);
512 NulPad (copyRight, CDF_COPYRIGHT_LEN);
513 if (!sX(WriteCDR(CDF->fp,V2_CDR_OFFSET,
514 CDR_COPYRIGHT,copyRight,
515 CDR_NULL),pStatus)) {
516 AbortAccess (CDF, noUPDATE, noDELETE);
517 return FALSE;
518 }
519 }
520 /***************************************************************************
521 * Return based on whether or not write access was obtained.
522 ***************************************************************************/
523 return (CDF->status == READ_WRITE);
524 #endif
525 }
526
527 /******************************************************************************
528 * WriteBuffer.
529 * Write occurs at current offset (assumed to have been set before this
530 * routine is called). On IBM PCs, it is assumed that `nBytes' will not
531 * exceed 65535.
532 ******************************************************************************/
533
WriteBuffer(CDF,fp,dataType,numElems,buffer)534 STATICforIDL CDFstatus WriteBuffer (CDF, fp, dataType, numElems, buffer)
535 struct CDFstruct *CDF;
536 vFILE *fp;
537 Int32 dataType;
538 Int32 numElems;
539 void *buffer;
540 {
541 CDFstatus pStatus = CDF_OK;
542 size_t nElemBytes = CDFelemSize(dataType);
543 size_t nBytes = (size_t) (numElems * nElemBytes);
544 double eValue; Int32 elemN; Byte *ptr; void *tBuffer;
545 /****************************************************************************
546 * Try to encode/write entire buffer.
547 ****************************************************************************/
548 tBuffer = cdf_AllocateMemory (nBytes, NULL);
549 if (tBuffer != NULL) {
550 if (!sX(ConvertBuffer(HostEncoding(),CDF->encoding,CDF->negToPosFp0,
551 dataType,numElems,buffer,tBuffer),&pStatus)) {
552 cdf_FreeMemory (tBuffer, NULL);
553 return pStatus;
554 }
555 if (!WRITEv(tBuffer,1,nBytes,fp)) {
556 cdf_FreeMemory (tBuffer, NULL);
557 return CDF_WRITE_ERROR;
558 }
559 cdf_FreeMemory (tBuffer, NULL);
560 return pStatus;
561 }
562 /****************************************************************************
563 * If that failed, encode/write one element at a time.
564 ****************************************************************************/
565 for (elemN = 0, ptr = buffer; elemN < numElems; elemN++, ptr += nElemBytes) {
566 if (!sX(ConvertBuffer(HostEncoding(),CDF->encoding,
567 CDF->negToPosFp0,dataType,1L,ptr,
568 &eValue),&pStatus)) return pStatus;
569 if (!WRITEv(&eValue,1,nElemBytes,fp)) return CDF_WRITE_ERROR;
570 }
571 return pStatus;
572 }
573
574 /******************************************************************************
575 * NegativeZeroReal4.
576 * Checks for -0.0 (on any type computer). Assumed to be in host encoding.
577 ******************************************************************************/
578
NegativeZeroReal4(value)579 VISIBLE_PREFIX Logical NegativeZeroReal4 (value)
580 float *value;
581 {
582 #if defined(FP1cpu) || defined(FP2cpu)
583 return (*((uInt32 *) value) == (uInt32) 0x80000000);
584 #endif
585 #if defined(FP3cpu) || defined(FP4cpu)
586 /****************************************************************************
587 * On VAXes and DEC Alphas running OpenVMS/POSIXshell we're only interested
588 * in the sign bit and exponent.
589 ****************************************************************************/
590 return ((*((uInt32 *) value) & (uInt32) 0x0000FF80) == (uInt32) 0x00008000);
591 #endif
592 }
593
594 /******************************************************************************
595 * NegativeZeroReal8.
596 * Checks for -0.0 (on any type computer). Assumed to be in host encoding.
597 ******************************************************************************/
598
NegativeZeroReal8(value)599 VISIBLE_PREFIX Logical NegativeZeroReal8 (value)
600 double *value;
601 {
602 #if defined(FP1cpu)
603 return ((*((uInt32 *) value) == (uInt32) 0x80000000) &&
604 (*((uInt32 *) value+1) == (uInt32) 0x00000000));
605 #endif
606 #if defined(FP2cpu)
607 return ((*((uInt32 *) value) == (uInt32) 0x00000000) &&
608 (*((uInt32 *) value+1) == (uInt32) 0x80000000));
609 #endif
610 #if defined(FP3cpu)
611 /****************************************************************************
612 * On VAXes and DEC Alphas running OpenVMS/POSIXshell in D_FLOAT mode we're
613 * only interested in the sign bit and exponent (which are in the first
614 * longword [32-bit]).
615 ****************************************************************************/
616 return ((*((uInt32 *) value) & (uInt32) 0x0000FF80) == (uInt32) 0x00008000);
617 #endif
618 #if defined(FP4cpu)
619 /****************************************************************************
620 * On DEC Alphas running OpenVMS/POSIXshell in G_FLOAT mode we're only
621 * interested in the sign bit and exponent (which are in the first longword
622 * [32-bit]).
623 ****************************************************************************/
624 return ((*((uInt32 *) value) & (uInt32) 0x0000FFF0) == (uInt32) 0x00008000);
625 #endif
626 }
627
628 /******************************************************************************
629 * StripTrailingBlanks.
630 ******************************************************************************/
631
StripTrailingBlanks(string)632 STATICforIDL void StripTrailingBlanks (string)
633 char *string;
634 {
635 int i;
636 for (i = strlen(string) - 1; i >= 0 && string[i] == ' '; i--) {
637 string[i] = NUL;
638 }
639 return;
640 }
641
642 /******************************************************************************
643 * MakeUpperString.
644 * Convert string to upper-case.
645 ******************************************************************************/
646
MakeUpperString(string)647 VISIBLE_PREFIX void MakeUpperString (string)
648 char *string;
649 {
650 int i;
651 for (i = 0; string[i] != NUL; i++) {
652 string[i] = (char) MakeUpper((int)string[i]);
653 }
654 return;
655 }
656
657 /******************************************************************************
658 * MakeLowerString.
659 * Convert string to lower-case.
660 ******************************************************************************/
661
MakeLowerString(string)662 VISIBLE_PREFIX void MakeLowerString (string)
663 char *string;
664 {
665 int i;
666 for (i = 0; string[i] != NUL; i++) {
667 string[i] = (char) MakeLower((int)string[i]);
668 }
669 return;
670 }
671
672 /******************************************************************************
673 * SetBit32.
674 ******************************************************************************/
675
SetBit32(value,bit)676 STATICforIDL void SetBit32 (value, bit)
677 Int32 *value;
678 int bit;
679 {
680 *value = *value | (1 << bit);
681 return;
682 }
683
684 /******************************************************************************
685 * ClearBit32.
686 ******************************************************************************/
687
ClearBit32(value,bit)688 STATICforIDL void ClearBit32 (value, bit)
689 Int32 *value;
690 int bit;
691 {
692 *value = *value & ~(1 << bit);
693 return;
694 }
695
696 /******************************************************************************
697 * FindCDF.
698 * Tries various extensions on the specified CDF path to see if the CDF
699 * exists. The extensions tried are those which should be present on the
700 * various platforms plus the extensions which might be generated by a CD-ROM
701 * driver. Finally, the pathname is tried without an extension being added
702 * in case the CDF had been renamed with a different extension or no extension.
703 ******************************************************************************/
704
FindCDF(path,no_append,upper,version)705 STATICforIDL CDFstatus FindCDF (path, no_append, upper, version)
706 char *path; /* Base pathname. */
707 Logical *no_append; /* Should extensions/version numbers be appended? */
708 Logical *upper; /* Should extensions be upper case? */
709 Logical *version; /* Should a version number of `;1' be appended? */
710 {
711 char pathT[DU_MAX_PATH_LEN+1];
712
713 strcpyX (pathT, path, DU_MAX_PATH_LEN);
714 strcatX (pathT, ".cdf", DU_MAX_PATH_LEN);
715 if (IsReg(pathT)) {
716 *no_append = FALSE;
717 *upper = FALSE;
718 *version = FALSE;
719 return CDF_OK;
720 }
721
722 strcpyX (pathT, path, DU_MAX_PATH_LEN);
723 strcatX (pathT, ".CDF", DU_MAX_PATH_LEN);
724 if (IsReg(pathT)) {
725 *no_append = FALSE;
726 *upper = TRUE;
727 *version = FALSE;
728 return CDF_OK;
729 }
730
731 strcpyX (pathT, path, DU_MAX_PATH_LEN);
732 strcatX (pathT, ".cdf;1", DU_MAX_PATH_LEN);
733 if (IsReg(pathT)) {
734 *no_append = FALSE;
735 *upper = FALSE;
736 *version = TRUE;
737 return CDF_OK;
738 }
739
740 strcpyX (pathT, path, DU_MAX_PATH_LEN);
741 strcatX (pathT, ".CDF;1", DU_MAX_PATH_LEN);
742 if (IsReg(pathT)) {
743 *no_append = FALSE;
744 *upper = TRUE;
745 *version = TRUE;
746 return CDF_OK;
747 }
748
749 #if defined(unix) || defined(dos)
750 strcpyX (pathT, path, DU_MAX_PATH_LEN);
751 MakeUpperString (pathT);
752 strcatX (pathT, ".CDF", DU_MAX_PATH_LEN);
753 if (IsReg(pathT)) {
754 *no_append = FALSE;
755 *upper = TRUE;
756 *version = FALSE;
757 return CDF_OK;
758 }
759
760 strcpyX (pathT, path, DU_MAX_PATH_LEN);
761 MakeUpperString (pathT);
762 if (IsReg(pathT)) {
763 *no_append = TRUE;
764 *upper = TRUE;
765 *version = FALSE;
766 return CDF_OK;
767 }
768 #endif
769
770 if (IsReg(path)) {
771 *no_append = TRUE;
772 *upper = FALSE;
773 *version = FALSE;
774 return CDF_OK;
775 }
776
777 return NO_SUCH_CDF;
778 }
779
780 /******************************************************************************
781 * BuildFilePath.
782 ******************************************************************************/
783
BuildFilePath(fileType,pathBase,noAppend,upperCase,versionNumber,varN,pathX)784 STATICforIDL void BuildFilePath (fileType, pathBase, noAppend, upperCase,
785 versionNumber, varN, pathX)
786 int fileType; /* Type of file. */
787 char *pathBase; /* Base pathname. */
788 Logical noAppend; /* Should extensions/version numbers be appended? */
789 Logical upperCase; /* Should uppercase extensions be appended? */
790 Logical versionNumber; /* Should a version number of `;1' be appended? */
791 Int32 varN; /* Variable number. N/a if a `cdf' file. */
792 char pathX[DU_MAX_PATH_LEN+1];
793 /* The expanded path w/ extensions/version numbers. */
794 {
795 ExpandPath (pathBase, pathX);
796 if (!noAppend) {
797 switch (fileType) {
798 case CDFt:
799 strcatX (pathX, (upperCase ? ".CDF" : ".cdf"), DU_MAX_PATH_LEN);
800 break;
801 case Vt:
802 strcatX (pathX, (upperCase ? ".V" : ".v"), DU_MAX_PATH_LEN);
803 sprintf (EofS(pathX), "%d", varN);
804 break;
805 case Zt:
806 strcatX (pathX, (upperCase ? ".Z" : ".z"), DU_MAX_PATH_LEN);
807 sprintf (EofS(pathX), "%d", varN);
808 break;
809 }
810 strcatX (pathX, (versionNumber ? ";1" : ""), DU_MAX_PATH_LEN);
811 }
812 return;
813 }
814
815 /******************************************************************************
816 * NulPad.
817 * Pads with NUL characters to the length specified. Also NUL-terminates
818 * the string.
819 ******************************************************************************/
820
NulPad(string,length)821 STATICforIDL void NulPad (string, length)
822 char *string;
823 int length;
824 {
825 int i;
826 for (i = strlen(string); i < length; i++) string[i] = NUL;
827 string[length] = NUL;
828 return;
829 }
830
831 /******************************************************************************
832 * UpdateMaxRec.
833 ******************************************************************************/
834
UpdateMaxRec(CDF,Var,recNum)835 STATICforIDL CDFstatus UpdateMaxRec (CDF, Var, recNum)
836 struct CDFstruct *CDF; /* In: Pointer to CDF. */
837 struct VarStruct *Var; /* In: Pointer to variable. */
838 Int32 recNum; /* In: Possible new maximum record number. */
839 {
840 CDFstatus pStatus = CDF_OK;
841 if (recNum > Var->maxRec) {
842 Var->maxRec = recNum;
843 if (!sX(WriteVDR(CDF,CDF->fp,Var->VDRoffset,Var->zVar,
844 VDR_MAXREC,&recNum,
845 VDR_NULL),&pStatus)) return pStatus;
846 }
847 if (!Var->zVar) {
848 if (recNum > CDF->rMaxRec) {
849 CDF->rMaxRec = recNum;
850 if (!sX(WriteGDR(CDF->fp,CDF->GDRoffset,
851 GDR_rMAXREC,&recNum,
852 GDR_NULL),&pStatus)) return pStatus;
853 }
854 }
855 return pStatus;
856 }
857
858 /******************************************************************************
859 * CalcDimParms.
860 * Calculates a variable's number of dimensions, dimension sizes, and
861 * dimension variances depending on the current zMode.
862 ******************************************************************************/
863
CalcDimParms(CDF,offset,zVar,numDimsP,dimSizesP,dimVarysP)864 STATICforIDL CDFstatus CalcDimParms (CDF, offset, zVar, numDimsP, dimSizesP,
865 dimVarysP)
866 struct CDFstruct *CDF; /* In: Pointer to CDF. */
867 Int32 offset; /* In: Offset of VDR. */
868 Logical zVar; /* In: TRUE if a true zVariable. FALSE if a
869 true rVariable. */
870 Int32 *numDimsP; /* Out: Number of dimensions. */
871 Int32 dimSizesP[]; /* Out: Dimension sizes. */
872 Int32 dimVarysP[]; /* Out: Dimension variances. */
873 {
874 CDFstatus pStatus = CDF_OK; int dN;
875 Int32 tNumDims, tDimSizes[CDF_MAX_DIMS], tDimVarys[CDF_MAX_DIMS];
876 Int32 numDims, dimSizes[CDF_MAX_DIMS], dimVarys[CDF_MAX_DIMS];
877 /****************************************************************************
878 * Determine `true' parameters.
879 ****************************************************************************/
880 if (zVar) {
881 if (!sX(ReadVDR(CDF,CDF->fp,offset,TRUE,
882 VDR_zNUMDIMS,&tNumDims,
883 VDR_zDIMSIZES,tDimSizes,
884 VDR_DIMVARYS,tDimVarys,
885 VDR_NULL),&pStatus)) return pStatus;
886 }
887 else {
888 if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
889 GDR_rNUMDIMS,&tNumDims,
890 GDR_rDIMSIZES,tDimSizes,
891 GDR_NULL),&pStatus)) return pStatus;
892 if (!sX(ReadVDR(CDF,CDF->fp,offset,FALSE,
893 VDR_DIMVARYS,tDimVarys,
894 VDR_NULL),&pStatus)) return pStatus;
895 }
896 /****************************************************************************
897 * Determine parameters based on zMode and if r/zVariable.
898 ****************************************************************************/
899 if (CDF->zMode == zMODEon2 && !zVar) {
900 for (dN = 0, numDims = 0; dN < tNumDims; dN++) {
901 if (tDimVarys[dN]) {
902 dimSizes[(int)numDims] = tDimSizes[dN];
903 dimVarys[(int)numDims] = VARY;
904 numDims++;
905 }
906 }
907 }
908 else {
909 numDims = tNumDims;
910 for (dN = 0; dN < tNumDims; dN++) {
911 dimSizes[dN] = tDimSizes[dN];
912 dimVarys[dN] = tDimVarys[dN];
913 }
914 }
915 /****************************************************************************
916 * Assign those values requested.
917 ****************************************************************************/
918 ASSIGNnotNULL (numDimsP, numDims)
919 ASSIGNnotNULLarray (dimSizesP, numDims, dimSizes)
920 ASSIGNnotNULLarray (dimVarysP, numDims, dimVarys)
921 return pStatus;
922 }
923
924 /******************************************************************************
925 * NULterminateMAX.
926 * NUL-terminate a string but only if a NUL is not found before the maximum
927 * length is reached.
928 ******************************************************************************/
929
NULterminateMAX(string,maxLen)930 STATICforIDL void NULterminateMAX (string, maxLen)
931 char *string;
932 size_t maxLen;
933 {
934 int i;
935 for (i = 0; i < (int) maxLen; i++)
936 if (string[i] == NUL) return;
937 string[maxLen] = NUL;
938 return;
939 }
940
941 /******************************************************************************
942 * ClearBytes.
943 ******************************************************************************/
944
ClearBytes(buffer,firstByte,lastByte)945 VISIBLE_PREFIX void ClearBytes (buffer, firstByte, lastByte)
946 void *buffer;
947 int firstByte;
948 int lastByte;
949 {
950 int i;
951 for (i = firstByte; i <= lastByte; i++) ((Byte *)buffer)[i] = 0;
952 return;
953 }
954
955 /******************************************************************************
956 * WasteIR.
957 ******************************************************************************/
958
WasteIR(CDF,wasteOffset,size)959 STATICforIDL CDFstatus WasteIR (CDF, wasteOffset, size)
960 struct CDFstruct *CDF;
961 Int32 wasteOffset;
962 Int32 size;
963 {
964 CDFstatus pStatus = CDF_OK;
965 struct UIRstruct newUIR, firstUIR, tUIR, nextUIR;
966 Int32 tOffset, nextOffset, UIRhead;
967
968 /****************************************************************************
969 * Begin initializing UIR.
970 ****************************************************************************/
971 newUIR.RecordSize = size;
972 newUIR.RecordType = UIR_;
973 /****************************************************************************
974 * Check that the internal record being wasted is big enough for the `next'
975 * and `previous' fields. If not, mark it as wasted but don't place it in
976 * the linked list of UIRs. Note that there will always be enough room for
977 * the `size' and `type' fields. If not, an internal logic error has occured.
978 ****************************************************************************/
979 if (size < UIR_BASE_SIZE) {
980 if (size < UUIR_BASE_SIZE) return CDF_INTERNAL_ERROR;
981 if (!sX(WriteUIR(CDF->fp,wasteOffset,
982 UIR_RECORDSIZE,&(newUIR.RecordSize),
983 UIR_RECORDTYPE,&(newUIR.RecordType),
984 UIR_NULL),&pStatus)) return pStatus;
985 return pStatus;
986 }
987 /****************************************************************************
988 * Read offset of first UIR.
989 ****************************************************************************/
990 if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
991 GDR_UIRHEAD,&UIRhead,
992 GDR_NULL),&pStatus)) return pStatus;
993 /****************************************************************************
994 * Check if no UIRs exist yet.
995 ****************************************************************************/
996 if (UIRhead == 0) {
997 newUIR.NextUIR = 0;
998 newUIR.PrevUIR = 0;
999 if (!sX(WriteUIR(CDF->fp,wasteOffset,
1000 UIR_RECORD,&newUIR,
1001 UIR_NULL),&pStatus)) return pStatus;
1002 UIRhead = wasteOffset;
1003 if (!sX(WriteGDR(CDF->fp,CDF->GDRoffset,
1004 GDR_UIRHEAD,&UIRhead,
1005 GDR_NULL),&pStatus)) return pStatus;
1006 return pStatus;
1007 }
1008 /****************************************************************************
1009 * At least one UIR exists, check if the new UIR is before the first UIR.
1010 ****************************************************************************/
1011 if (wasteOffset < UIRhead) {
1012 if (!sX(ReadUIR(CDF->fp,UIRhead,
1013 UIR_RECORD,&firstUIR,
1014 UIR_NULL),&pStatus)) return pStatus;
1015 newUIR.NextUIR = UIRhead;
1016 newUIR.PrevUIR = 0;
1017 if (!sX(WriteUIR(CDF->fp,wasteOffset,
1018 UIR_RECORD,&newUIR,
1019 UIR_NULL),&pStatus)) return pStatus;
1020 firstUIR.PrevUIR = wasteOffset;
1021 if (!sX(WriteUIR(CDF->fp,UIRhead,
1022 UIR_RECORD,&firstUIR,
1023 UIR_NULL),&pStatus)) return pStatus;
1024 UIRhead = wasteOffset;
1025 if (!sX(WriteGDR(CDF->fp,CDF->GDRoffset,
1026 GDR_UIRHEAD,&UIRhead,
1027 GDR_NULL),&pStatus)) return pStatus;
1028 return pStatus;
1029 }
1030 /****************************************************************************
1031 * The new UIR is not before the first UIR. Scan the UIRs to find the point
1032 * at which it should be inserted.
1033 ****************************************************************************/
1034 tOffset = UIRhead;
1035 if (!sX(ReadUIR(CDF->fp,tOffset,
1036 UIR_RECORD,&tUIR,
1037 UIR_NULL),&pStatus)) return pStatus;
1038 while (tUIR.NextUIR != 0) {
1039 if (wasteOffset < tUIR.NextUIR) {
1040 nextOffset = tUIR.NextUIR;
1041 if (!sX(ReadUIR(CDF->fp,nextOffset,
1042 UIR_RECORD,&nextUIR,
1043 UIR_NULL),&pStatus)) return pStatus;
1044 newUIR.NextUIR = tUIR.NextUIR;
1045 newUIR.PrevUIR = tOffset;
1046 if (!sX(WriteUIR(CDF->fp,wasteOffset,
1047 UIR_RECORD,&newUIR,
1048 UIR_NULL),&pStatus)) return pStatus;
1049 tUIR.NextUIR = wasteOffset;
1050 if (!sX(WriteUIR(CDF->fp,tOffset,
1051 UIR_RECORD,&tUIR,
1052 UIR_NULL),&pStatus)) return pStatus;
1053 nextUIR.PrevUIR = wasteOffset;
1054 if (!sX(WriteUIR(CDF->fp,nextOffset,
1055 UIR_RECORD,&nextUIR,
1056 UIR_NULL),&pStatus)) return pStatus;
1057 return pStatus;
1058 }
1059 tOffset = tUIR.NextUIR;
1060 if (!sX(ReadUIR(CDF->fp,tOffset,
1061 UIR_RECORD,&tUIR,
1062 UIR_NULL),&pStatus)) return pStatus;
1063 }
1064 /****************************************************************************
1065 * The new UIR is going to be the last UIR.
1066 ****************************************************************************/
1067 newUIR.NextUIR = 0;
1068 newUIR.PrevUIR = tOffset;
1069 if (!sX(WriteUIR(CDF->fp,wasteOffset,
1070 UIR_RECORD,&newUIR,
1071 UIR_NULL),&pStatus)) return pStatus;
1072 tUIR.NextUIR = wasteOffset;
1073 if (!sX(WriteUIR(CDF->fp,tOffset,
1074 UIR_RECORD,&tUIR,
1075 UIR_NULL),&pStatus)) return pStatus;
1076 return pStatus;
1077 }
1078
1079 /******************************************************************************
1080 * AllocateIR.
1081 ******************************************************************************/
1082
AllocateIR(CDF,size,offset)1083 STATICforIDL CDFstatus AllocateIR (CDF, size, offset)
1084 struct CDFstruct *CDF; /* In: Pointer to CDF. */
1085 Int32 size; /* In: Size of internal record (bytes). */
1086 Int32 *offset; /* Out: Offset of allocated internal record. */
1087 {
1088 CDFstatus pStatus = CDF_OK;
1089 Int32 sOffset, eOffset, tSize, UIRhead, eof, uir_ = UIR_;
1090 struct UIRstruct sUIR, eUIR;
1091 /****************************************************************************
1092 * Read EOF and offset of first UIR from GDR.
1093 ****************************************************************************/
1094 if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
1095 GDR_UIRHEAD,&UIRhead,
1096 GDR_EOF,&eof,
1097 GDR_NULL),&pStatus)) return pStatus;
1098 /****************************************************************************
1099 * If UIRs exist, try to use one or more of them (if contiguous) for the new
1100 * internal record.
1101 ****************************************************************************/
1102 if (UIRhead != 0) {
1103 sOffset = UIRhead;
1104 if (!sX(ReadUIR(CDF->fp,sOffset,
1105 UIR_RECORD,&sUIR,
1106 UIR_NULL),&pStatus)) return pStatus;
1107 eOffset = sOffset;
1108 eUIR = sUIR;
1109 tSize = sUIR.RecordSize;
1110 for (;;) {
1111 /***********************************************************************
1112 * Check if the starting to ending UIRs are the exact size needed.
1113 ***********************************************************************/
1114 if (size == tSize) {
1115 if (!sX(RemoveUIRs(CDF,sOffset,eOffset),&pStatus)) return pStatus;
1116 if (!sX(WriteIrSize(CDF->fp,sOffset,&size),&pStatus)) return pStatus;
1117 if (!sX(WriteIrType(CDF->fp,sOffset,&uir_),&pStatus)) return pStatus;
1118 *offset = sOffset;
1119 return pStatus;
1120 }
1121 /***********************************************************************
1122 * Check if the starting to ending UIRs are big enough for the new
1123 * internal record and for a new UIR to fill the remaining space.
1124 ***********************************************************************/
1125 if (size + UIR_BASE_SIZE <= tSize) {
1126 if (!sX(RemoveUIRs(CDF,sOffset,eOffset),&pStatus)) return pStatus;
1127 if (!sX(WasteIR(CDF,sOffset+size,tSize-size),&pStatus)) {
1128 return pStatus;
1129 }
1130 if (!sX(WriteIrSize(CDF->fp,sOffset,&size),&pStatus)) return pStatus;
1131 if (!sX(WriteIrType(CDF->fp,sOffset,&uir_),&pStatus)) return pStatus;
1132 *offset = sOffset;
1133 return pStatus;
1134 }
1135 /***********************************************************************
1136 * Check if the end of the UIRs has been reached. If so, check if the
1137 * ending UIR is the last IR in the dotCDF file.
1138 ***********************************************************************/
1139 if (eUIR.NextUIR == 0) {
1140 if (eOffset + eUIR.RecordSize == eof) {
1141 /*******************************************************************
1142 * The ending UIR is the last internal record in the CDF. Check to
1143 * see if after allocating the new internal record less than
1144 * UIR_BASE_SIZE bytes will remain before the EOF. If so, waste an
1145 * internal record at the location of those bytes so that a UIR is
1146 * at the end (rather than stranded bytes).
1147 *******************************************************************/
1148 if (!sX(RemoveUIRs(CDF,sOffset,eOffset),&pStatus)) return pStatus;
1149 if (size < tSize) {
1150 if (!sX(WasteIR(CDF,sOffset+size,
1151 UIR_BASE_SIZE),&pStatus)) return pStatus;
1152 eof = sOffset + size + UIR_BASE_SIZE;
1153 }
1154 else
1155 eof = sOffset + size;
1156 if (!sX(WriteGDR(CDF->fp,CDF->GDRoffset,
1157 GDR_EOF,&eof,
1158 GDR_NULL),&pStatus)) return pStatus;
1159 if (!sX(WriteIrSize(CDF->fp,
1160 sOffset,
1161 &size),&pStatus)) return pStatus;
1162 if (!sX(WriteIrType(CDF->fp,
1163 sOffset,
1164 &uir_),&pStatus)) return pStatus;
1165 *offset = sOffset;
1166 return pStatus;
1167 }
1168 else {
1169 /*******************************************************************
1170 * Non-UIRs follow the ending UIR. The new internal record will
1171 * have to be allocated at the EOF.
1172 *******************************************************************/
1173 *offset = eof;
1174 if (!sX(WriteIrSize(CDF->fp,eof,&size),&pStatus)) return pStatus;
1175 if (!sX(WriteIrType(CDF->fp,eof,&uir_),&pStatus)) return pStatus;
1176 eof += size;
1177 if (!sX(WriteGDR(CDF->fp,CDF->GDRoffset,
1178 GDR_EOF,&eof,
1179 GDR_NULL),&pStatus)) return pStatus;
1180 return pStatus;
1181 }
1182 }
1183 /***********************************************************************
1184 * If the next UIR is contiguous with the ending UIR, make it the ending
1185 * UIR. Otherwise, make the next UIR the starting and ending UIRs.
1186 ***********************************************************************/
1187 if (eOffset + eUIR.RecordSize == eUIR.NextUIR) {
1188 eOffset = eUIR.NextUIR;
1189 if (!sX(ReadUIR(CDF->fp,eOffset,
1190 UIR_RECORD,&eUIR,
1191 UIR_NULL),&pStatus)) return pStatus;
1192 tSize += eUIR.RecordSize;
1193 }
1194 else {
1195 sOffset = eUIR.NextUIR;
1196 if (!sX(ReadUIR(CDF->fp,sOffset,
1197 UIR_RECORD,&sUIR,
1198 UIR_NULL),&pStatus)) return pStatus;
1199 eOffset = sOffset;
1200 eUIR = sUIR;
1201 tSize = sUIR.RecordSize;
1202 }
1203 }
1204 }
1205 /****************************************************************************
1206 * No UIRs exist. The new internal record will have to be allocated at the
1207 * EOF.
1208 ****************************************************************************/
1209 *offset = eof;
1210 if (!sX(WriteIrSize(CDF->fp,eof,&size),&pStatus)) return pStatus;
1211 if (!sX(WriteIrType(CDF->fp,eof,&uir_),&pStatus)) return pStatus;
1212 eof += size;
1213 if (!sX(WriteGDR(CDF->fp,CDF->GDRoffset,
1214 GDR_EOF,&eof,
1215 GDR_NULL),&pStatus)) return pStatus;
1216 return pStatus;
1217 }
1218
1219 /******************************************************************************
1220 * ResizeIR.
1221 ******************************************************************************/
1222
ResizeIR(CDF,curOffset,newSize,newOffset,move,success)1223 STATICforIDL CDFstatus ResizeIR (CDF, curOffset, newSize, newOffset, move,
1224 success)
1225 struct CDFstruct *CDF;
1226 Int32 curOffset; /* In: Current offset of internal record. */
1227 Int32 newSize; /* In: New size of internal record. This may be
1228 smaller or larger than the current size. */
1229 Int32 *newOffset; /* Out: New offset of internal record. This variable
1230 is not modified if an error occurs or the internal
1231 record cannot be extended (when `move' is FALSE). */
1232 Logical move; /* In: TRUE if the internal record can be moved if
1233 necessary. */
1234 Logical *success; /* Out: TRUE if the internal record was successfully
1235 extended (whether or not it had to be moved). */
1236 {
1237 CDFstatus pStatus = CDF_OK; Int32 curSize; Int32 eof;
1238 /****************************************************************************
1239 * Determine current size of internal record.
1240 ****************************************************************************/
1241 if (!sX(ReadIrSize(CDF->fp,curOffset,&curSize),&pStatus)) return pStatus;
1242 /****************************************************************************
1243 * Check sizes...
1244 ****************************************************************************/
1245 if (newSize > curSize) {
1246 /**************************************************************************
1247 * The internal record is growing. First check if it is the last one in
1248 * the CDF.
1249 **************************************************************************/
1250 if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
1251 GDR_EOF,&eof,
1252 GDR_NULL),&pStatus)) return pStatus;
1253 if (curOffset + curSize == eof) {
1254 /************************************************************************
1255 * Last internal record. Simply extend the CDF.
1256 ************************************************************************/
1257 ASSIGNnotNULL (newOffset, curOffset)
1258 eof += (newSize - curSize);
1259 if (!sX(WriteGDR(CDF->fp,CDF->GDRoffset,
1260 GDR_EOF,&eof,
1261 GDR_NULL),&pStatus)) return pStatus;
1262 if (!sX(WriteIrSize(CDF->fp,
1263 curOffset,
1264 &newSize),&pStatus)) return pStatus;
1265 ASSIGNnotNULL (success, TRUE)
1266 return pStatus;
1267 }
1268 else {
1269 /************************************************************************
1270 * Not the last internal record. If the internal record may be moved,
1271 * first mark it as unused and then allocate a new internal record.
1272 * Marking it unused first allows the possibility that if will be used
1273 * as part of the allocated internal record. If the internal record can
1274 * not be moved, check if unused records immediately follow.
1275 ************************************************************************/
1276 if (move) {
1277 if (!sX(WasteIR(CDF,curOffset,curSize),&pStatus)) return pStatus;
1278 if (!sX(AllocateIR(CDF,newSize,newOffset),&pStatus)) return pStatus;
1279 ASSIGNnotNULL (success, TRUE)
1280 return pStatus;
1281 }
1282 else {
1283 Int32 sOffset, eOffset, tSize, UIRhead, irType;
1284 struct UIRstruct sUIR, eUIR;
1285 /**********************************************************************
1286 * First check if there are any UIRs in the CDF. This is done because
1287 * CDF V2.5.0* (alpha/beta) created UIRs without the next and previous
1288 * UIR fields and didn't use the `UIRhead' field in the GDR. Because
1289 * we don't want to use UIRs in those CDFs (because they are not the
1290 * same as the current UIRs), this will keep us from doing so (because
1291 * the `UIRhead' fields will always contain zero if a V2.5.0* CDF).
1292 **********************************************************************/
1293 if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
1294 GDR_UIRHEAD,&UIRhead,
1295 GDR_NULL),&pStatus)) return pStatus;
1296 if (UIRhead == 0) {
1297 ASSIGNnotNULL (success, FALSE)
1298 return pStatus;
1299 }
1300 /**********************************************************************
1301 * Read the internal record which immediately follows the internal
1302 * record being resized. If it is a UIR make it the starting UIR.
1303 * ---------------------------- DANGER ---------------------------------
1304 * Don't try to read an entire UIR. First read only the record type
1305 * field and check if it is UIR_. Then read the entire UIR. This is
1306 * because the next internal record could be smaller than a UIR (or
1307 * larger but not entirely written yet [eg. a VVR]).
1308 **********************************************************************/
1309 sOffset = curOffset + curSize;
1310 if (!sX(ReadIrType(CDF->fp,sOffset,&irType),&pStatus)) return pStatus;
1311 if (irType != UIR_) {
1312 ASSIGNnotNULL (success, FALSE)
1313 return pStatus;
1314 }
1315 if (!sX(ReadUIR(CDF->fp,sOffset,
1316 UIR_RECORD,&sUIR,
1317 UIR_NULL),&pStatus)) return pStatus;
1318 tSize = curSize + sUIR.RecordSize;
1319 eOffset = sOffset;
1320 eUIR = sUIR;
1321 for (;;) {
1322 /*******************************************************************
1323 * Check if the exact amount of available space has been found.
1324 *******************************************************************/
1325 if (newSize == tSize) {
1326 if (!sX(RemoveUIRs(CDF,sOffset,eOffset),&pStatus)) return pStatus;
1327 if (!sX(WriteIrSize(CDF->fp,
1328 curOffset,
1329 &newSize),&pStatus)) return pStatus;
1330 ASSIGNnotNULL (newOffset, curOffset)
1331 ASSIGNnotNULL (success, TRUE)
1332 return pStatus;
1333 }
1334 /*******************************************************************
1335 * Check if enough available space has been found to increase the
1336 * internal record and then create a new UIR in the remaining space.
1337 *******************************************************************/
1338 if (newSize + UIR_BASE_SIZE <= tSize) {
1339 if (!sX(RemoveUIRs(CDF,sOffset,eOffset),&pStatus)) return pStatus;
1340 if (!sX(WasteIR(CDF,curOffset+newSize,tSize-newSize),&pStatus)) {
1341 return pStatus;
1342 }
1343 if (!sX(WriteIrSize(CDF->fp,
1344 curOffset,
1345 &newSize),&pStatus)) return pStatus;
1346 ASSIGNnotNULL (newOffset, curOffset)
1347 ASSIGNnotNULL (success, TRUE)
1348 return pStatus;
1349 }
1350 /*******************************************************************
1351 * Check if the end of the UIRs has been reached.
1352 *******************************************************************/
1353 if (eUIR.NextUIR == 0) {
1354 /*****************************************************************
1355 * If the ending UIR is at the EOF, then the internal record can
1356 * be extended beyond the EOF or up to it with the creation of a
1357 * new UIR at the very end.
1358 *****************************************************************/
1359 if (eOffset + eUIR.RecordSize == eof) {
1360 if (!sX(RemoveUIRs(CDF,sOffset,eOffset),&pStatus)) return
1361 pStatus;
1362 if (newSize < tSize) {
1363 if (!sX(WasteIR(CDF,curOffset+newSize,
1364 UIR_BASE_SIZE),&pStatus)) return pStatus;
1365 eof = curOffset + newSize + UIR_BASE_SIZE;
1366 }
1367 else
1368 eof = curOffset + newSize;
1369 if (!sX(WriteGDR(CDF->fp,CDF->GDRoffset,
1370 GDR_EOF,&eof,
1371 GDR_NULL),&pStatus)) return pStatus;
1372 if (!sX(WriteIrSize(CDF->fp,
1373 curOffset,
1374 &newSize),&pStatus)) return pStatus;
1375 ASSIGNnotNULL (newOffset, curOffset)
1376 ASSIGNnotNULL (success, TRUE)
1377 return pStatus;
1378 }
1379 else {
1380 ASSIGNnotNULL (success, FALSE)
1381 return pStatus;
1382 }
1383 }
1384 /*******************************************************************
1385 * If the next UIR is contiguous with the ending UIR, make it the
1386 * ending UIR.
1387 *******************************************************************/
1388 if (eOffset + eUIR.RecordSize == eUIR.NextUIR) {
1389 eOffset = eUIR.NextUIR;
1390 if (!sX(ReadUIR(CDF->fp,eOffset,
1391 UIR_RECORD,&eUIR,
1392 UIR_NULL),&pStatus)) return pStatus;
1393 tSize += eUIR.RecordSize;
1394 }
1395 else {
1396 ASSIGNnotNULL (success, FALSE)
1397 return pStatus;
1398 }
1399 }
1400 }
1401 }
1402 }
1403 else {
1404 /**************************************************************************
1405 * The internal record is shrinking. Check if it can be shrunk in place
1406 * and a UIR created to occupy the extra space. If not, waste it and then
1407 * allocate a new internal record (if moving it is allowed).
1408 **************************************************************************/
1409 if (newSize <= (curSize - UIR_BASE_SIZE)) {
1410 if (!sX(WasteIR(CDF,curOffset + newSize,
1411 curSize - newSize),&pStatus)) return pStatus;
1412 if (!sX(WriteIrSize(CDF->fp,
1413 curOffset,
1414 &newSize),&pStatus)) return pStatus;
1415 ASSIGNnotNULL (newOffset, curOffset)
1416 ASSIGNnotNULL (success, TRUE)
1417 }
1418 else {
1419 if (move) {
1420 if (!sX(WasteIR(CDF,curOffset,curSize),&pStatus)) return pStatus;
1421 if (!sX(AllocateIR(CDF,newSize,newOffset),&pStatus)) return pStatus;
1422 ASSIGNnotNULL (success, TRUE)
1423 }
1424 else {
1425 ASSIGNnotNULL (success, FALSE)
1426 }
1427 }
1428 return pStatus;
1429 }
1430 }
1431
1432 /******************************************************************************
1433 * RemoveUIRs.
1434 ******************************************************************************/
1435
RemoveUIRs(CDF,sOffset,eOffset)1436 STATICforIDL CDFstatus RemoveUIRs (CDF, sOffset, eOffset)
1437 struct CDFstruct *CDF; /* In: Pointer to CDF. */
1438 Int32 sOffset; /* In: Offset of starting UIR. */
1439 Int32 eOffset; /* In: Offset of ending UIR. */
1440 {
1441 CDFstatus pStatus = CDF_OK;
1442 struct UIRstruct sUIR, eUIR;
1443 Int32 UIRhead;
1444 if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
1445 GDR_UIRHEAD,&UIRhead,
1446 GDR_NULL),&pStatus)) return pStatus;
1447 if (!sX(ReadUIR(CDF->fp,sOffset,
1448 UIR_RECORD,&sUIR,
1449 UIR_NULL),&pStatus)) return pStatus;
1450 if (!sX(ReadUIR(CDF->fp,eOffset,
1451 UIR_RECORD,&eUIR,
1452 UIR_NULL),&pStatus)) return pStatus;
1453 if (UIRhead == sOffset) {
1454 UIRhead = eUIR.NextUIR;
1455 if (!sX(WriteGDR(CDF->fp,CDF->GDRoffset,
1456 GDR_UIRHEAD,&UIRhead,
1457 GDR_NULL),&pStatus)) return pStatus;
1458 }
1459 else {
1460 struct UIRstruct prevUIR;
1461 if (!sX(ReadUIR(CDF->fp,sUIR.PrevUIR,
1462 UIR_RECORD,&prevUIR,
1463 UIR_NULL),&pStatus)) return pStatus;
1464 prevUIR.NextUIR = eUIR.NextUIR;
1465 if (!sX(WriteUIR(CDF->fp,sUIR.PrevUIR,
1466 UIR_RECORD,&prevUIR,
1467 UIR_NULL),&pStatus)) return pStatus;
1468 }
1469 if (eUIR.NextUIR != 0) {
1470 struct UIRstruct nextUIR;
1471 if (!sX(ReadUIR(CDF->fp,eUIR.NextUIR,
1472 UIR_RECORD,&nextUIR,
1473 UIR_NULL),&pStatus)) return pStatus;
1474 nextUIR.PrevUIR = sUIR.PrevUIR;
1475 if (!sX(WriteUIR(CDF->fp,eUIR.NextUIR,
1476 UIR_RECORD,&nextUIR,
1477 UIR_NULL),&pStatus)) return pStatus;
1478 }
1479 return pStatus;
1480 }
1481
1482 /******************************************************************************
1483 * PriorTo.
1484 ******************************************************************************/
1485
PriorTo(spec,version,release,increment)1486 VISIBLE_PREFIX Logical PriorTo (spec, version, release, increment)
1487 char *spec;
1488 Int32 version;
1489 Int32 release;
1490 Int32 increment;
1491 {
1492 int ver, rel, incr;
1493 switch (sscanf(spec,"%d.%d.%d",&ver,&rel,&incr)) {
1494 case 1:
1495 if (version < ver) return TRUE;
1496 break;
1497 case 2:
1498 if (version < ver) return TRUE;
1499 if (version == ver && release < rel) return TRUE;
1500 break;
1501 case 3:
1502 if (version < ver) return TRUE;
1503 if (version == ver && release < rel) return TRUE;
1504 if (version == ver && release == rel && increment < incr) return TRUE;
1505 break;
1506 }
1507 return FALSE;
1508 }
1509
1510 /******************************************************************************
1511 * ShortenCDR.
1512 ******************************************************************************/
1513
ShortenCDR(CDF)1514 STATICforIDL CDFstatus ShortenCDR (CDF)
1515 struct CDFstruct *CDF;
1516 {
1517 CDFstatus pStatus = CDF_OK;
1518 Int32 offset, oldRecordSize, newRecordSize, nBytes;
1519 if (!sX(ReadCDR(CDF->fp,CDF->CDRoffset,
1520 CDR_RECORDSIZE,&oldRecordSize,
1521 CDR_NULL),&pStatus))
1522 return pStatus;
1523 newRecordSize = CDR_BASE_SIZE + CDF_COPYRIGHT_LEN;
1524 if (!sX(WriteCDR(CDF->fp,V2_CDR_OFFSET,
1525 CDR_RECORDSIZE,&newRecordSize,
1526 CDR_NULL),&pStatus)) return pStatus;
1527 offset = CDF->CDRoffset + newRecordSize;
1528 nBytes = oldRecordSize - newRecordSize;
1529 if (!sX(WasteIR(CDF,offset,nBytes),&pStatus)) return pStatus;
1530 return pStatus;
1531 }
1532
1533 /******************************************************************************
1534 * CorrectScopes.
1535 * It is assumed that the last ADR offset has already been fixed.
1536 ******************************************************************************/
1537
CorrectScopes(CDF)1538 STATICforIDL CDFstatus CorrectScopes (CDF)
1539 struct CDFstruct *CDF;
1540 {
1541 Int32 tOffset, attrScope;
1542 CDFstatus pStatus = CDF_OK;
1543 /****************************************************************************
1544 * Read the offset of the first ADR from the GDR.
1545 ****************************************************************************/
1546 if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
1547 GDR_ADRHEAD,&tOffset,
1548 GDR_NULL),&pStatus)) return pStatus;
1549 /****************************************************************************
1550 * Read the ADRs correcting each assumed scope.
1551 ****************************************************************************/
1552 while (tOffset != 0) {
1553 if (!sX(ReadADR(CDF->fp,tOffset,
1554 ADR_SCOPE,&attrScope,
1555 ADR_NULL),&pStatus)) return pStatus;
1556 switch (attrScope) {
1557 case GLOBALscopeASSUMED:
1558 attrScope = GLOBAL_SCOPE;
1559 if (!sX(WriteADR(CDF->fp,tOffset,
1560 ADR_SCOPE,&attrScope,
1561 ADR_NULL),&pStatus)) return pStatus;
1562 break;
1563 case VARIABLEscopeASSUMED:
1564 attrScope = VARIABLE_SCOPE;
1565 if (!sX(WriteADR(CDF->fp,tOffset,
1566 ADR_SCOPE,&attrScope,
1567 ADR_NULL),&pStatus)) return pStatus;
1568 break;
1569 }
1570 if (!sX(ReadADR(CDF->fp,tOffset,
1571 ADR_ADRNEXT,&tOffset,
1572 ADR_NULL),&pStatus)) return pStatus;
1573 }
1574 return pStatus;
1575 }
1576
1577 /******************************************************************************
1578 * ShortenVDRs.
1579 * It is assumed that the last rVDR offset has already been fixed.
1580 ******************************************************************************/
1581
ShortenVDRs(CDF)1582 STATICforIDL CDFstatus ShortenVDRs (CDF)
1583 struct CDFstruct *CDF;
1584 {
1585 Int32 vOffset, nextOffset, recordSize, nTailBytes;
1586 void *tBuffer;
1587 Int32 tOffset;
1588 CDFstatus pStatus = CDF_OK;
1589 int i;
1590 for (i = 0; i < 2; i++) {
1591 Logical zVar = (i == 0);
1592 /*************************************************************************
1593 * Read the offset of the first rVDR from the GDR.
1594 *************************************************************************/
1595 if (!sX(ReadGDR(CDF->fp,CDF->GDRoffset,
1596 BOO(zVar,GDR_zVDRHEAD,GDR_rVDRHEAD),&vOffset,
1597 GDR_NULL),&pStatus)) return pStatus;
1598 /*************************************************************************
1599 * Read the rVDRs shortening each.
1600 *************************************************************************/
1601 while (vOffset != ZERO_OFFSET) {
1602 if (!sX(ReadVDR(CDF,CDF->fp,vOffset,zVar,
1603 VDR_VDRNEXT,&nextOffset,
1604 VDR_RECORDSIZE,&recordSize,
1605 VDR_NULL),&pStatus)) return pStatus;
1606 nTailBytes = recordSize - VDR_WASTED_OFFSET - VDR_WASTED_SIZE;
1607 recordSize -= VDR_WASTED_SIZE;
1608 if (!sX(WriteVDR(CDF,CDF->fp,vOffset,zVar,
1609 VDR_RECORDSIZE,&recordSize,
1610 VDR_NULL),&pStatus)) return pStatus;
1611 tBuffer = cdf_AllocateMemory ((size_t) nTailBytes, NULL);
1612 if (tBuffer != NULL) {
1613 tOffset = vOffset + VDR_WASTED_OFFSET + VDR_WASTED_SIZE;
1614 if (!SEEKv(CDF->fp,tOffset,vSEEK_SET)) return CDF_READ_ERROR;
1615 if (!READv(tBuffer,(size_t)nTailBytes,1,CDF->fp)) return
1616 CDF_READ_ERROR;
1617 tOffset = vOffset + VDR_WASTED_OFFSET;
1618 if (!SEEKv(CDF->fp,tOffset,vSEEK_SET)) return CDF_WRITE_ERROR;
1619 if (!WRITEv(tBuffer,(size_t)nTailBytes,1,CDF->fp)) return
1620 CDF_WRITE_ERROR;
1621 cdf_FreeMemory (tBuffer, NULL);
1622 }
1623 else {
1624 Int32 oldOffset = vOffset + VDR_WASTED_OFFSET + VDR_WASTED_SIZE,
1625 newOffset = vOffset + VDR_WASTED_OFFSET, byteX;
1626 Byte tByte;
1627 for (byteX = 0; byteX < nTailBytes; byteX++) {
1628 if (!SEEKv(CDF->fp,oldOffset,vSEEK_SET)) return CDF_READ_ERROR;
1629 if (!READv(&tByte,1,1,CDF->fp)) return CDF_READ_ERROR;
1630 if (!SEEKv(CDF->fp,newOffset,vSEEK_SET)) return CDF_WRITE_ERROR;
1631 if (!WRITEv(&tByte,1,1,CDF->fp)) return CDF_WRITE_ERROR;
1632 oldOffset++;
1633 newOffset++;
1634 }
1635 }
1636 if (!sX(WasteIR(CDF,vOffset+recordSize,VDR_WASTED_SIZE),&pStatus)) {
1637 return pStatus;
1638 }
1639 vOffset = nextOffset;
1640 }
1641 }
1642 return pStatus;
1643 }
1644
1645 /******************************************************************************
1646 * CorrectBlockingFactors.
1647 * It is assumed that the last rVDR offset has already been fixed.
1648 ******************************************************************************/
1649
CorrectBlockingFactors(CDF)1650 STATICforIDL CDFstatus CorrectBlockingFactors (CDF)
1651 struct CDFstruct *CDF;
1652 {
1653 CDFstatus pStatus = CDF_OK; Int32 nVars, vdrOffset; int varN;
1654 Logical zVar; struct VDRstruct VDR; struct VarStruct **Vars, *Var;
1655 for (zVar = 0; zVar <= 1; zVar++) {
1656 Vars = BOO(zVar,CDF->zVars,CDF->rVars);
1657 nVars = BOO(zVar,CDF->NzVars,CDF->NrVars);
1658 for (varN = 0; varN < nVars; varN++) {
1659 Var = Vars[varN];
1660 if (Var == NULL) {
1661 if (!sX(FindVarByNumber(CDF,(Int32)varN,
1662 zVar,&vdrOffset),&pStatus)) return pStatus;
1663 }
1664 else
1665 vdrOffset = Var->VDRoffset;
1666 if (!sX(ReadVDR(CDF,CDF->fp,vdrOffset,zVar,
1667 VDR_RECORD,&VDR,NULL,
1668 VDR_NULL),&pStatus)) return pStatus;
1669 if (!RECvaryBITset(VDR.Flags) && VDR.blockingFactor > 1) {
1670 VDR.blockingFactor = 1;
1671 if (!sX(WriteVDR(CDF,CDF->fp,vdrOffset,zVar,
1672 VDR_RECORD,&VDR,NULL,
1673 VDR_NULL),&pStatus)) return pStatus;
1674 if (Var != NULL) {
1675 if (!sX(CalcBF(CDF,Var),&pStatus)) return pStatus;
1676 }
1677 }
1678 }
1679 }
1680 return pStatus;
1681 }
1682
1683 /******************************************************************************
1684 * CorrectEPOCH.
1685 ******************************************************************************/
1686
CorrectEPOCH(CDF)1687 STATICforIDL CDFstatus CorrectEPOCH (CDF)
1688 struct CDFstruct *CDF;
1689 {
1690 CDFstatus tStatus, pStatus = CDF_OK;
1691 Int32 dataType, vNum, vOffset, aOffset, eOffset;
1692 Logical zVar;
1693 int i;
1694 /****************************************************************************
1695 * Search for EPOCH rVariable.
1696 ****************************************************************************/
1697 tStatus = FindVarByName (CDF, "EPOCH", &vOffset, &zVar, NULL);
1698 switch (tStatus) {
1699 case CDF_OK:
1700 if (!sX(ReadVDR(CDF,CDF->fp,vOffset,zVar,
1701 VDR_NUM,&vNum,
1702 VDR_DATATYPE,&dataType,
1703 VDR_NULL),&pStatus)) return pStatus;
1704 if (FLOAT8dataType(dataType)) dataType = CDF_EPOCH;
1705 if (!sX(WriteVDR(CDF,CDF->fp,vOffset,zVar,
1706 VDR_DATATYPE,&dataType,
1707 VDR_NULL),&pStatus)) return pStatus;
1708 /************************************************************************
1709 * Search for associated VALIDMIN/VALIDMAX/SCALEMIN/SCALEMAX rEntries.
1710 ************************************************************************/
1711 for (i = 0; i < 4; i++) {
1712 char aName[8+1];
1713 switch (i) {
1714 case 0: strcpy (aName, "VALIDMIN"); break;
1715 case 1: strcpy (aName, "VALIDMAX"); break;
1716 case 2: strcpy (aName, "SCALEMIN"); break;
1717 case 3: strcpy (aName, "SCALEMAX"); break;
1718 }
1719 tStatus = FindAttrByName (CDF,aName,&aOffset);
1720 switch (tStatus) {
1721 case CDF_OK:
1722 tStatus = FindEntryByNumber (CDF, aOffset, zVar, vNum,
1723 &eOffset); /* We can do this since
1724 only rVariables will
1725 exist. */
1726 switch (tStatus) {
1727 case CDF_OK:
1728 if (!sX(ReadAEDR(CDF->fp,eOffset,
1729 AEDR_DATATYPE,&dataType,
1730 AEDR_NULL),&pStatus)) return pStatus;
1731 if (FLOAT8dataType(dataType)) dataType = CDF_EPOCH;
1732 if (!sX(WriteAEDR(CDF,CDF->fp,eOffset,
1733 AEDR_DATATYPE,&dataType,
1734 AEDR_NULL),&pStatus)) return pStatus;
1735 break;
1736 case NO_SUCH_ENTRY:
1737 break;
1738 default:
1739 return tStatus;
1740 }
1741 break;
1742 case NO_SUCH_ATTR:
1743 break;
1744 default:
1745 return tStatus;
1746 }
1747 }
1748 break;
1749 case NO_SUCH_VAR:
1750 break;
1751 default:
1752 return tStatus;
1753 }
1754 return pStatus;
1755 }
1756
1757 /******************************************************************************
1758 * DeleteFile.
1759 ******************************************************************************/
1760
DeleteFile(path)1761 STATICforIDL Logical DeleteFile (path)
1762 char *path;
1763 {
1764 #if defined(vms)
1765 char tPath[DU_MAX_PATH_LEN+1];
1766 strcpyX (tPath, path, DU_MAX_PATH_LEN);
1767 strcatX (tPath, ";0", DU_MAX_PATH_LEN); /* Only most recent is deleted. */
1768 return (delete(tPath) == 0);
1769 #endif
1770 #if defined(unix) || defined(dos)
1771 return (unlink(path) == 0);
1772 #endif
1773 #if defined(mac) || defined(posixSHELL) || defined(win32)
1774 return (remove(path) == 0);
1775 #endif
1776 }
1777
1778 /******************************************************************************
1779 * KillAbortedCDF.
1780 ******************************************************************************/
1781
KillAbortedCDF(CDF,Cur)1782 STATICforIDL void KillAbortedCDF (CDF, Cur)
1783 struct CDFstruct *CDF;
1784 struct CurStruct *Cur;
1785 {
1786 CDF->magic = KILLEDid_MAGIC_NUMBER;
1787 cdf_FreeMemory (CDF, NULL);
1788 Cur->cdf = NULL;
1789 return;
1790 }
1791
1792 /******************************************************************************
1793 * AbortAccess.
1794 ******************************************************************************/
1795
AbortAccess(CDF,updateCDF,deleteCDF)1796 STATICforIDL void AbortAccess (CDF, updateCDF, deleteCDF)
1797 struct CDFstruct *CDF;
1798 Logical updateCDF; /* Update "working" dotCDF file (if read/write
1799 access has been obtained)? */
1800 Logical deleteCDF; /* Delete CDF file(s)? */
1801 {
1802 /****************************************************************************
1803 * If the CDF is to be deleted do that first and then skip the updating and/or
1804 * closing of the CDF files.
1805 ****************************************************************************/
1806 if (deleteCDF) {
1807 DeleteCDFfiles (CDF);
1808 if (CDF->uDotFp != NULL) V_delete (CDF->uDotFp, NULL);
1809 }
1810 else {
1811 /**************************************************************************
1812 * Update the dotCDF file if requested, if the current access is read/write,
1813 * and if the "working" dotCDF file has not already been closed or deleted.
1814 **************************************************************************/
1815 if (CDF->status == READ_WRITE && updateCDF &&
1816 (CDF->fp == CDF->dotFp || CDF->fp == CDF->uDotFp)) UpdateDotCDF (CDF);
1817 /**************************************************************************
1818 * Close all of the CDF files if they are not already closed (or deleted).
1819 **************************************************************************/
1820 if (CDF->dotFp != NULL) V_close (CDF->dotFp, CDF, NULL);
1821 if (CDF->uDotFp != NULL) V_close (CDF->uDotFp, CDF, NULL);
1822 CloseVarFiles (CDF);
1823 }
1824 /****************************************************************************
1825 * Delete the scratch files that still exist.
1826 ****************************************************************************/
1827 if (CDF->stage.fp != NULL) V_delete (CDF->stage.fp, NULL);
1828 if (CDF->compressFp != NULL) V_delete (CDF->compressFp, NULL);
1829 /****************************************************************************
1830 * Free the memory used by the CDF.
1831 ****************************************************************************/
1832 FreeCDFid (CDF, TRUE);
1833 return;
1834 }
1835
1836 /******************************************************************************
1837 * DeleteCDFfiles.
1838 * The files may be open or closed. This routine does not delete the
1839 * uncompressed dotCDF file (if one exists).
1840 ******************************************************************************/
1841
DeleteCDFfiles(CDF)1842 STATICforIDL CDFstatus DeleteCDFfiles (CDF)
1843 struct CDFstruct *CDF;
1844 {
1845 char tmpFile[DU_MAX_PATH_LEN+1]; CDFstatus pStatus = CDF_OK;
1846 /**************************************************************************
1847 * Delete dotCDF file.
1848 **************************************************************************/
1849 if (CDF->dotFp == NULL) {
1850 BuildFilePath (CDFt, CDF->CDFname, CDF->no_append, CDF->upper_case_ext,
1851 CDF->version_numbers, INT32_ZERO, tmpFile);
1852 if (!DeleteFile(tmpFile)) sX (CDF_DELETE_ERROR, &pStatus);
1853 }
1854 else {
1855 if (!DELETEv(CDF->dotFp,NULL)) sX (CDF_DELETE_ERROR, &pStatus);
1856 CDF->dotFp = NULL;
1857 }
1858 /**************************************************************************
1859 * Delete the variable files (if multi-file). Both rVariable and zVariable
1860 * files are deleted.
1861 **************************************************************************/
1862 if (!CDF->singleFile) {
1863 int varN;
1864 for (varN = 0; varN < CDF->NrVars; varN++) {
1865 struct VarStruct *Var = CDF->rVars[varN];
1866 if (Var != NULL) {
1867 if (Var->fp != NULL) {
1868 if (!DELETEv(Var->fp,NULL)) sX (VAR_DELETE_ERROR, &pStatus);
1869 Var->fp = NULL;
1870 continue;
1871 }
1872 }
1873 BuildFilePath (Vt, CDF->CDFname, CDF->no_append, CDF->upper_case_ext,
1874 CDF->version_numbers, varN, tmpFile);
1875 if (!DeleteFile(tmpFile)) sX (VAR_DELETE_ERROR, &pStatus);
1876 }
1877 for (varN = 0; varN < CDF->NzVars; varN++) {
1878 struct VarStruct *Var = CDF->zVars[varN];
1879 if (Var != NULL) {
1880 if (Var->fp != NULL) {
1881 if (!DELETEv(Var->fp,NULL)) sX (VAR_DELETE_ERROR, &pStatus);
1882 Var->fp = NULL;
1883 continue;
1884 }
1885 }
1886 BuildFilePath (Zt, CDF->CDFname, CDF->no_append, CDF->upper_case_ext,
1887 CDF->version_numbers, varN, tmpFile);
1888 if (!DeleteFile(tmpFile)) sX (VAR_DELETE_ERROR, &pStatus);
1889 }
1890 }
1891 return pStatus;
1892 }
1893
1894 /******************************************************************************
1895 * DeleteEntry.
1896 ******************************************************************************/
1897
DeleteEntry(CDF,aOffset,eOffset)1898 STATICforIDL CDFstatus DeleteEntry (CDF, aOffset, eOffset)
1899 struct CDFstruct *CDF;
1900 Int32 aOffset;
1901 Int32 eOffset;
1902 {
1903 CDFstatus pStatus = CDF_OK;
1904 struct ADRstruct ADR;
1905 struct AEDRstruct AEDR, AEDRt;
1906 Int32 prevEntryOffset;
1907 Logical zEntry;
1908 /****************************************************************************
1909 * Read the ADR and the AEDR being deleted.
1910 ****************************************************************************/
1911 if (!sX(ReadADR(CDF->fp,aOffset,
1912 ADR_RECORD,&ADR,
1913 ADR_NULL),&pStatus)) return pStatus;
1914 if (!sX(ReadAEDR(CDF->fp,eOffset,
1915 AEDR_RECORD,&AEDR,NULL,
1916 AEDR_NULL),&pStatus)) return pStatus;
1917 zEntry = (AEDR.RecordType == AzEDR_);
1918 /****************************************************************************
1919 * Remove the AEDR from the list of entries.
1920 ****************************************************************************/
1921 if (!sX(FindPrevEntry(CDF,aOffset,eOffset,
1922 zEntry,&prevEntryOffset),&pStatus)) return pStatus;
1923 if (prevEntryOffset == 0) {
1924 /**************************************************************************
1925 * The first entry on the linked list is being deleted. Point the ADR to
1926 * the entry being pointed to by the entry being deleted.
1927 **************************************************************************/
1928 if (zEntry)
1929 ADR.AzEDRhead = AEDR.AEDRnext;
1930 else
1931 ADR.AgrEDRhead = AEDR.AEDRnext;
1932 }
1933 else {
1934 /**************************************************************************
1935 * The entry being deleted is not the first entry on the linked list. Point
1936 * the previous entry to the entry pointed to by the entry being deleted.
1937 **************************************************************************/
1938 if (!sX(ReadAEDR(CDF->fp,prevEntryOffset,
1939 AEDR_RECORD,&AEDRt,NULL,
1940 AEDR_NULL),&pStatus)) return pStatus;
1941 AEDRt.AEDRnext = AEDR.AEDRnext;
1942 if (!sX(WriteAEDR(CDF,CDF->fp,prevEntryOffset,
1943 AEDR_RECORD,&AEDRt,NULL,
1944 AEDR_NULL),&pStatus)) return pStatus;
1945 }
1946 /****************************************************************************
1947 * Decrement the number of entries and recalculate the maximum entry (if
1948 * necessary).
1949 ****************************************************************************/
1950 if (zEntry)
1951 ADR.NzEntries--;
1952 else
1953 ADR.NgrEntries--;
1954 if (BOO(zEntry,ADR.MAXzEntry,ADR.MAXgrEntry) == AEDR.Num) {
1955 Int32 maxEntry = NO_ENTRY;
1956 Int32 tOffset = BOO(zEntry,ADR.AzEDRhead,ADR.AgrEDRhead);
1957 while (tOffset != 0) {
1958 if (!sX(ReadAEDR(CDF->fp,tOffset,
1959 AEDR_RECORD,&AEDRt,NULL,
1960 AEDR_NULL),&pStatus)) return pStatus;
1961 maxEntry = MaxInt32 (maxEntry, AEDRt.Num);
1962 tOffset = AEDRt.AEDRnext;
1963 }
1964 if (zEntry)
1965 ADR.MAXzEntry = maxEntry;
1966 else
1967 ADR.MAXgrEntry = maxEntry;
1968 }
1969 /****************************************************************************
1970 * Rewrite the ADR and waste the AEDR (of the entry being deleted).
1971 ****************************************************************************/
1972 if (!sX(WriteADR(CDF->fp,aOffset,
1973 ADR_RECORD,&ADR,
1974 ADR_NULL),&pStatus)) return pStatus;
1975 if (!sX(WasteIR(CDF,eOffset,AEDR.RecordSize),&pStatus)) return pStatus;
1976 return pStatus;
1977 }
1978
1979 /******************************************************************************
1980 * CtoPstr/PtoCstr.
1981 ******************************************************************************/
1982
1983 #if defined(MPW_C)
CtoPstr(string)1984 STATICforIDL unsigned char *CtoPstr (string)
1985 char *string;
1986 {
1987 size_t length = MINIMUM(strlen(string),255);
1988 if (length > 0) memmove (&string[1], string, length);
1989 string[0] = (char) length;
1990 return ((unsigned char *) string);
1991 }
1992 #endif
1993
1994 #if defined(MPW_C)
PtoCstr(string)1995 STATICforIDL char *PtoCstr (string)
1996 unsigned char *string;
1997 {
1998 size_t length = (size_t) string[0];
1999 if (length > 0) memmove (string, &string[1], length);
2000 string[length] = (unsigned char) NUL;
2001 return ((char *) string);
2002 }
2003 #endif
2004
2005 /******************************************************************************
2006 * PadUnRecords.
2007 * Pad all allocated records within the first/last record range. Note that
2008 * in the case of sparse records some of the records may not be allocated (and
2009 * should not be padded of course).
2010 ******************************************************************************/
2011
PadUnRecords(CDF,Var,firstRec,lastRec)2012 STATICforIDL CDFstatus PadUnRecords (CDF, Var, firstRec, lastRec)
2013 struct CDFstruct *CDF;
2014 struct VarStruct *Var;
2015 Int32 firstRec;
2016 Int32 lastRec;
2017 {
2018 CDFstatus pStatus = CDF_OK; Int32 offset; int how; void *buffer;
2019 Int32 recNum, nRecords, toRec, lastRecInVVR; Logical found;
2020 /****************************************************************************
2021 * Pad the records.
2022 * NOTE: Padding in a single-file CDF could be made more efficient by not
2023 * allocating/freeing the pad buffer over and over...
2024 ****************************************************************************/
2025 if (CDF->singleFile) {
2026 /**************************************************************************
2027 * Single-file...first determine the first allocated record to be padded.
2028 **************************************************************************/
2029 if (!sX(NextRecord(CDF,Var->VDRoffset,Var->zVar,
2030 firstRec,&recNum,&found),&pStatus)) return pStatus;
2031 if (!found) return pStatus;
2032 /**************************************************************************
2033 * While the first record to be padded is within the range...
2034 **************************************************************************/
2035 while (recNum <= lastRec) {
2036 if (!sX(RecordByteOffset(CDF,Var,recNum,
2037 &offset),&pStatus)) return pStatus;
2038 if (!sX(SearchForRecord(CDF,Var->VDRoffset,
2039 Var->zVar,recNum,
2040 NULL,&lastRecInVVR,
2041 NULL,NULL),&pStatus)) return pStatus;
2042 toRec = MINIMUM(lastRec,lastRecInVVR);
2043 nRecords = toRec - recNum + 1;
2044 if (!sX(BuildPadBuffer(CDF,Var,nRecords,
2045 &how,&buffer,TRUE),&pStatus)) return pStatus;
2046 if (!sX(WritePadValues(Var,CDF->fp,offset,
2047 nRecords,how,buffer),&pStatus)) {
2048 cdf_FreeMemory (buffer, NULL);
2049 return pStatus;
2050 }
2051 cdf_FreeMemory (buffer, NULL);
2052 recNum += nRecords;
2053 /************************************************************************
2054 * Determine the next `first' record to be padded.
2055 ************************************************************************/
2056 if (!sX(NextRecord(CDF,Var->VDRoffset,Var->zVar,
2057 recNum,&recNum,&found),&pStatus)) return pStatus;
2058 if (!found) return pStatus;
2059 }
2060 }
2061 else {
2062 /**************************************************************************
2063 * Multi-file...
2064 **************************************************************************/
2065 if (!sX(RecordByteOffset(CDF,Var,
2066 firstRec,
2067 &offset),&pStatus)) return pStatus;
2068 nRecords = lastRec - firstRec + 1;
2069 if (!sX(BuildPadBuffer(CDF,Var,nRecords,
2070 &how,&buffer,TRUE),&pStatus)) return pStatus;
2071 if (!sX(WritePadValues(Var,Var->fp,offset,nRecords,how,buffer),&pStatus)) {
2072 cdf_FreeMemory (buffer, NULL);
2073 return pStatus;
2074 }
2075 cdf_FreeMemory (buffer, NULL);
2076 }
2077 return pStatus;
2078 }
2079
2080 /******************************************************************************
2081 * WritePadValues.
2082 * NOTE: It is assumed that the records are contiguous (in a single-file CDF)
2083 * and that on a DOS machine the buffer does not exceed 64K bytes. It is also
2084 * assumed that the values have already been encoded for the CDF.
2085 ******************************************************************************/
2086
WritePadValues(Var,fp,offset,nRecords,how,buffer)2087 STATICforIDL CDFstatus WritePadValues (Var, fp, offset, nRecords, how, buffer)
2088 struct VarStruct *Var;
2089 vFILE *fp;
2090 Int32 offset;
2091 Int32 nRecords;
2092 int how;
2093 void *buffer;
2094 {
2095 Int32 nBytes, nValues, recX, valueX;
2096 /****************************************************************************
2097 * Seek to desired offset.
2098 ****************************************************************************/
2099 if (!SEEKv(fp,(long)offset,vSEEK_SET)) return VAR_WRITE_ERROR;
2100 /****************************************************************************
2101 * Write records...
2102 ****************************************************************************/
2103 switch (how) {
2104 case ALLrecordsATonce:
2105 nBytes = nRecords * Var->NphyRecBytes;
2106 if (!WRITEv(buffer,(size_t)nBytes,1,fp)) return VAR_WRITE_ERROR;
2107 break;
2108 case ONErecordATaTIME:
2109 for (recX = 0; recX < nRecords; recX++) {
2110 if (!WRITEv(buffer,(size_t)Var->NphyRecBytes,1,fp)) {
2111 return VAR_WRITE_ERROR;
2112 }
2113 }
2114 break;
2115 case ONEvalueATaTIME:
2116 nValues = nRecords * Var->NphyRecValues;
2117 for (valueX = 0; valueX < nValues; valueX++) {
2118 if (!WRITEv(buffer,(size_t)Var->NvalueBytes,1,fp)) {
2119 return VAR_WRITE_ERROR;
2120 }
2121 }
2122 break;
2123 }
2124 return CDF_OK;
2125 }
2126
2127 /******************************************************************************
2128 * MinInt/Int32/Long.
2129 * These are used to avoid double evaluation in macro expansions (eg. MINIMUM).
2130 ******************************************************************************/
2131
MinInt(a,b)2132 VISIBLE_PREFIX int MinInt (a, b)
2133 int a;
2134 int b;
2135 {
2136 return MINIMUM(a,b);
2137 }
2138
MinInt32(a,b)2139 VISIBLE_PREFIX Int32 MinInt32 (a, b)
2140 Int32 a;
2141 Int32 b;
2142 {
2143 return MINIMUM(a,b);
2144 }
2145
MinLong(a,b)2146 VISIBLE_PREFIX long MinLong (a, b)
2147 long a;
2148 long b;
2149 {
2150 return MINIMUM(a,b);
2151 }
2152
2153 /******************************************************************************
2154 * MaxInt/Int32/Long.
2155 * These are used to avoid double evaluation in macro expansions (eg. MAXIMUM).
2156 ******************************************************************************/
2157
MaxInt(a,b)2158 VISIBLE_PREFIX int MaxInt (a, b)
2159 int a;
2160 int b;
2161 {
2162 return MAXIMUM(a,b);
2163 }
2164
MaxInt32(a,b)2165 VISIBLE_PREFIX Int32 MaxInt32 (a, b)
2166 Int32 a;
2167 Int32 b;
2168 {
2169 return MAXIMUM(a,b);
2170 }
2171
MaxLong(a,b)2172 VISIBLE_PREFIX long MaxLong (a, b)
2173 long a;
2174 long b;
2175 {
2176 return MAXIMUM(a,b);
2177 }
2178
2179 /******************************************************************************
2180 * AddTOvStats.
2181 ******************************************************************************/
2182
AddTOvStats(vStatsTO,vStats)2183 STATICforIDL void AddTOvStats (vStatsTO, vStats)
2184 vSTATS *vStatsTO; /* If NULL, do nothing. */
2185 vSTATS *vStats; /* If NULL, initialize (to zero). */
2186 {
2187 if (vStatsTO != NULL) {
2188 if (vStats == NULL) {
2189 vStatsTO->nBuffers = 0;
2190 vStatsTO->maxBuffers = 0;
2191 vStatsTO->nV_reads = 0;
2192 vStatsTO->nV_writes = 0;
2193 vStatsTO->nPageIns = 0;
2194 vStatsTO->nPageOuts = 0;
2195 vStatsTO->nBlockReads = 0;
2196 vStatsTO->nBlockWrites = 0;
2197 }
2198 else {
2199 vStatsTO->nBuffers = MAXIMUM(vStatsTO->nBuffers,vStats->nBuffers);
2200 vStatsTO->maxBuffers = MAXIMUM(vStatsTO->maxBuffers,vStats->maxBuffers);
2201 vStatsTO->nV_reads += vStats->nV_reads;
2202 vStatsTO->nV_writes += vStats->nV_writes;
2203 vStatsTO->nPageIns += vStats->nPageIns;
2204 vStatsTO->nPageOuts += vStats->nPageOuts;
2205 vStatsTO->nBlockReads += vStats->nBlockReads;
2206 vStatsTO->nBlockWrites += vStats->nBlockWrites;
2207 }
2208 }
2209 return;
2210 }
2211
2212 /******************************************************************************
2213 * DisplayVs.
2214 ******************************************************************************/
2215
2216 #if defined(DEBUG)
DisplayVs(toWhere,label,vStats)2217 STATICforIDL void DisplayVs (toWhere, label, vStats)
2218 char *toWhere;
2219 char *label;
2220 vSTATS *vStats;
2221 {
2222 if (toWhere != NULL) {
2223 FILE *fp = BOO(strcmp(toWhere,"STDOUT"),FOPEN(toWhere,"a"),stdout);
2224 if (fp == NULL) return;
2225 fprintf (fp, "%s", label);
2226 fprintf (fp, "..BUF:%03ldu/%03ldx", vStats->nBuffers, vStats->maxBuffers);
2227 fprintf (fp, " V_:%06ldr/%06ldw", vStats->nV_reads, vStats->nV_writes);
2228 fprintf (fp, " PAGE:%05ldi/%05ldo", vStats->nPageIns, vStats->nPageOuts);
2229 fprintf (fp, " BLK:%05ldr/%05ldw",
2230 vStats->nBlockReads, vStats->nBlockWrites);
2231 fprintf (fp, "\n");
2232 if (fp != stdout) fclose (fp);
2233 }
2234 return;
2235 }
2236 #endif
2237