1 /******************************************************************************
2 *
3 * NSSDC/CDF Validate internal records in a CDF V2.* file
4 *
5 * Version 1.0, 15-Jul-08, Peort Systems.
6 *
7 * Modification history:
8 *
9 * V1.0 15-Jul-08, M Liu Original version.
10 *
11 ******************************************************************************/
12
13 #include "cdflib.h"
14
15 /******************************************************************************
16 * Local macro definitions.
17 ******************************************************************************/
18
19 #define CRE CDF_READ_ERROR
20 #define CV2C CORRUPTED_V2_CDF
21
22 /******************************************************************************
23 * Local function prototypes.
24 ******************************************************************************/
25
26 static CDFstatus QuitCDF PROTOARGs((char *why, int size, int num, void *value1, void *value2, Logical debug));
27 static CDFstatus ValidateCCR PROTOARGs((vFILE *fp, Int32 offset, Logical debug));
28 static CDFstatus ValidateCDR PROTOARGs((vFILE *fp, Int32 offset, Logical debug));
29 static CDFstatus ValidateGDR PROTOARGs((vFILE *fp, Int32 offset, Logical debug));
30 static CDFstatus ValidateVDR PROTOARGs((struct CDFstruct *CDF, vFILE *fp, Int32 offset, Logical zVar, Logical debug));
31 static CDFstatus ValidateVXR PROTOARGs((vFILE *fp, Int32 offset, Int32 lastRec, Logical debug));
32 static CDFstatus ValidateVVR PROTOARGs((vFILE *fp, Int32 offset, Logical debug));
33 static CDFstatus ValidateADR PROTOARGs((struct CDFstruct *CDF, vFILE *fp, Int32 offset, Logical debug));
34 static CDFstatus ValidateAEDR PROTOARGs((struct CDFstruct *CDF, vFILE *fp, Int32 offset, Int32 num, Int32 maxEntry, Logical zEntry, Logical debug));
35 static CDFstatus ValidateCPR PROTOARGs((vFILE *fp, Int32 offset, Logical debug));
36 static CDFstatus ValidateSPR PROTOARGs((vFILE *fp, Int32 offset, Logical debug));
37 static CDFstatus ValidateCVVR PROTOARGs((vFILE *fp, Int32 offset, Logical debug));
38 static CDFstatus ValidateUIR PROTOARGs((vFILE *fp, Int32 offset, Logical debug));
39 static CDFstatus ValidateAttributeLinks PROTOARGs((struct CDFstruct *CDF, vFILE *fp, Logical debug));
40 static CDFstatus ValidateAttributeEntryLink PROTOARGs((struct CDFstruct *CDF, vFILE *fp, Int32 num, Logical zEntry, Int32 AEDRhead, Int32 numEntries, Int32 maxEntry, Logical debug));
41 static CDFstatus ValidateVariableLinks PROTOARGs((struct CDFstruct *CDF, vFILE *fp, Logical zVar, Logical debug));
42 static CDFstatus ValidateVariableValueLinks PROTOARGs((struct CDFstruct *CDF, vFILE *fp, Int32 lastRec, Int32 headVXR, Logical debug));
43 static struct CDRstruct CDR;
44 static struct GDRstruct GDR;
45 static int rVars, zVars;
46 static int numAttrs;
47
48 /******************************************************************************
49 * ValidateCDF.
50 * Start to validate each internal record in a CDF file.
51 ******************************************************************************/
52
ValidateCDF(struct CDFstruct * CDF,vFILE * CDFfp,Int32 offset,Int32 fileSize,Logical debug)53 STATICforIDL CDFstatus ValidateCDF (struct CDFstruct *CDF, vFILE *CDFfp,
54 Int32 offset, Int32 fileSize,
55 Logical debug)
56 {
57 Int32 recordSize;
58 Int32 recordType;
59 CDFstatus status;
60
61 /****************************************************************************
62 * Read internal records from the beginning of the file until EOF (or illegal
63 * record) reached.
64 ****************************************************************************/
65 if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
66 for (;;) {
67 /*************************************************************************
68 * Read record size.
69 *************************************************************************/
70 offset = V_tell (CDFfp);
71 if (offset >= fileSize) break;
72 if (!Read32(CDFfp,&recordSize)) return CRE;
73 if (recordSize < 1 || recordSize > fileSize)
74 return QuitCDF ("CDF: an invalid internal record size",
75 4, 1, &recordSize, 0, debug);
76 /*************************************************************************
77 * Read record type.
78 *************************************************************************/
79 if (!Read32(CDFfp,&recordType)) return CRE;
80 /*************************************************************************
81 * Based on the record type...
82 *************************************************************************/
83 switch ((int)recordType) {
84 /**********************************************************************
85 * Compressed CDF Record (CCR).
86 **********************************************************************/
87 case CCR_: {
88 status = ValidateCCR (CDFfp, offset, debug);
89 if (status != CDF_OK) return status;
90 offset = offset + recordSize;
91 if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
92 break;
93 }
94 /**********************************************************************
95 * CDF Descriptor Record (CDR).
96 **********************************************************************/
97 case CDR_: {
98 numAttrs = rVars = zVars = 0;
99 status = ValidateCDR (CDFfp, offset, debug);
100 if (status != CDF_OK) return status;
101 status = ValidateGDR (CDFfp, CDR.GDRoffset, debug);
102 if (status != CDF_OK) return status;
103 offset = offset + recordSize;
104 if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
105 break;
106 }
107 /**********************************************************************
108 * Global Descriptor Record (GDR).
109 **********************************************************************/
110 case GDR_: {
111 offset = offset + recordSize;
112 if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
113 break;
114 }
115 /**********************************************************************
116 * Attribute Descriptor Record (ADR).
117 **********************************************************************/
118 case ADR_: {
119 ++numAttrs;
120 offset = offset + recordSize;
121 if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
122 break;
123 }
124 /**********************************************************************
125 * Attribute Entry Descriptor Record (AgrEDR or AzEDR).
126 **********************************************************************/
127 case AgrEDR_:
128 case AzEDR_: {
129 offset = offset + recordSize;
130 if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
131 break;
132 }
133 /**********************************************************************
134 * Variable Descriptor Record (rVDR or zVDR).
135 **********************************************************************/
136 case rVDR_:
137 case zVDR_: {
138 Logical zVar = (recordType == zVDR_);
139 if (zVar)
140 ++zVars;
141 else
142 ++rVars;
143 offset = offset + recordSize;
144 if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
145 break;
146 }
147 /**********************************************************************
148 * Variable indeX Record (VXR).
149 **********************************************************************/
150 case VXR_: {
151 offset = offset + recordSize;
152 if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
153 break;
154 }
155 /**********************************************************************
156 * Variable Values Record (VVR).
157 **********************************************************************/
158 case VVR_: {
159 status = ValidateVVR (CDFfp, offset, debug);
160 if (recordSize < VVR_BASE_SIZE)
161 return QuitCDF ("CDF: record size is invalid ",
162 4, 1, &recordSize, 0, debug);
163 offset = offset + recordSize;
164 if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
165 break;
166 }
167 /**********************************************************************
168 * Compressed Variable Values Record (CVVR).
169 **********************************************************************/
170 case CVVR_: {
171 status = ValidateCVVR (CDFfp, offset, debug);
172 if (status != CDF_OK) return status;
173 offset = offset + recordSize;
174 if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
175 break;
176 }
177 /**********************************************************************
178 * Compressed Parameters Record (CPR).
179 **********************************************************************/
180 case CPR_: {
181 offset = offset + recordSize;
182 if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
183 break;
184 }
185 /**********************************************************************
186 * Sparseness Parameters Record (SPR).
187 **********************************************************************/
188 case SPR_: {
189 /*
190 status = ValidateSPR (CDFfp, offset, debug);
191 if (status != CDF_OK) return status;
192 */
193 offset = offset + recordSize;
194 if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
195 break;
196 }
197 /**********************************************************************
198 * Unused internal record
199 **********************************************************************/
200 case UIR_: {
201 offset = offset + recordSize;
202 if (!SEEKv(CDFfp,offset,vSEEK_SET)) return CRE;
203 break;
204 }
205 /**********************************************************************
206 * Illegal record type.
207 **********************************************************************/
208 default: {
209 return QuitCDF ("CDF: an invalid internal record type",
210 4, 1, &recordType, 0, debug);
211 }
212 }
213 }
214 /****************************************************************************
215 * Check attribute links and their attribute entries.
216 ****************************************************************************/
217 if (GDR.NumAttr != numAttrs)
218 return QuitCDF ("CDF: number of attributes does not match: ",
219 4, 2, &GDR.NumAttr, &numAttrs, debug);
220 if (numAttrs > 0) {
221 status = ValidateAttributeLinks(CDF, CDFfp, debug);
222 if (status != CDF_OK) return status;
223 }
224 /****************************************************************************
225 * Check rVariable links and their data.
226 ****************************************************************************/
227 if (GDR.NrVars != rVars)
228 return QuitCDF ("CDF: number of rVariables does not match: ",
229 4, 2, &GDR.NrVars, &rVars, debug);
230 if (rVars > 0) {
231 status = ValidateVariableLinks(CDF, CDFfp, FALSE, debug);
232 if (status != CDF_OK) return status;
233 }
234 /****************************************************************************
235 * Check zVariable links and their data.
236 ****************************************************************************/
237 if (GDR.NzVars != zVars)
238 return QuitCDF ("CDF: number of zVariables does not match: ",
239 4, 2, &GDR.NzVars, &zVars, debug);
240 if (zVars > 0) {
241 status = ValidateVariableLinks(CDF, CDFfp, TRUE, debug);
242 if (status != CDF_OK) return status;
243 }
244 return CDF_OK;
245 }
246
247 /******************************************************************************
248 * ValidateCDR.
249 ******************************************************************************/
250
ValidateCDR(vFILE * fp,Int32 offset,Logical debug)251 CDFstatus ValidateCDR (vFILE *fp, Int32 offset, Logical debug)
252 {
253 Int32 actualEncoding;
254 /*
255 char copyRight[CDF_COPYRIGHT_LEN+1];
256 */
257 int i;
258 CDFstatus status;
259
260 if (debug)
261 printf(" Checking CDR...@%ld\n", offset);
262 status = ReadCDR (fp, offset,
263 CDR_RECORD, &CDR, NULL,
264 CDR_NULL);
265 if (status != CDF_OK) return status;
266 if (CDR.RecordType != CDR_)
267 return QuitCDF ("CDF: record type is invalid ",
268 4, 1, &(CDR.RecordType), 0, debug);
269 if (CDR.RecordSize < CDR_BASE_SIZE ||
270 (!PriorTo("2.5",CDR.Version,CDR.Release,CDR.Increment) &&
271 CDR.RecordSize > CDR_MAX_SIZE))
272 return QuitCDF ("CDF: record size is invalid ",
273 4, 1, &(CDR.RecordSize), 0, debug);
274 if (CDR.GDRoffset < 1)
275 return QuitCDF ("CDF: offset to GDR is invalid ",
276 4, 1, &(CDR.GDRoffset), 0, debug);
277 if (CDR.Version != 2)
278 return QuitCDF ("CDF: version number is invalid ",
279 4, 1, &(CDR.Version), 0, debug);
280 if (!ValidEncoding(CDR.Encoding,&actualEncoding))
281 return QuitCDF ("CDF: encoding is invalid ",
282 4, 1, &(CDR.Encoding), 0, debug);
283 /*
284 for (i = 0; i < strlen(copyRight); ++i)
285 if (!Printable(copyRight[i]))
286 return QuitCDF ("CDF: copyright is invalid ",
287 0, copyRight), 0, debug);
288 */
289 return CDF_OK;
290 }
291
292 /******************************************************************************
293 * ValidateGDR.
294 ******************************************************************************/
295
ValidateGDR(vFILE * fp,Int32 offset,Logical debug)296 CDFstatus ValidateGDR (vFILE *fp, Int32 offset, Logical debug)
297 {
298 int i;
299 CDFstatus status;
300
301 if (debug)
302 printf(" Checking GDR...@%ld\n", offset);
303 status = ReadGDR (fp, offset,
304 GDR_RECORD, &GDR,
305 GDR_NULL);
306 if (status != CDF_OK) return status;
307 if (GDR.RecordType != GDR_)
308 return QuitCDF ("CDF: record type is invalid ",
309 4, 1, &(GDR.RecordType), 0, debug);
310 if (GDR.RecordSize < GDR_BASE_SIZE ||
311 GDR.RecordSize > GDR_MAX_SIZE)
312 return QuitCDF ("CDF: record size is invalid ",
313 4, 1, &(GDR.RecordSize), 0, debug);
314 if (GDR.NrVars < 0 || (GDR.NrVars > 0 && GDR.rVDRhead < 1))
315 return QuitCDF ("CDF: NrVars or their link is invalid ",
316 4, 1, &(GDR.NrVars), 0, debug);
317 if (GDR.NumAttr < 0 || (GDR.NumAttr > 0 && GDR.ADRhead < 1))
318 return QuitCDF ("CDF: attribute numbers or their link is invalid ",
319 4, 1, &(GDR.NumAttr), 0, debug);
320 if (GDR.rMaxRec < -1)
321 return QuitCDF ("CDF: max rVars record is invalid ",
322 4, 1, &(GDR.rMaxRec), 0, debug);
323 if (GDR.rNumDims < 0 ||
324 GDR.rNumDims > CDF_MAX_DIMS)
325 return QuitCDF ("CDF: number of dimensions for rVars is invalid ",
326 4, 1, &(GDR.rNumDims), 0, debug);
327 if (GDR.NzVars < 0 || (GDR.NzVars > 0 && GDR.zVDRhead < 1))
328 return QuitCDF ("CDF: NzVars or their link is invalid ",
329 4, 1, &(GDR.NzVars), 0, debug);
330 if (GDR.UIRhead < 0)
331 return QuitCDF ("CDF: offset to UIR is invalid ",
332 4, 1, &(GDR.UIRhead), 0, debug);
333 for (i = 0; i < (int)GDR.rNumDims; ++i)
334 if (GDR.rDimSizes[i] < 1)
335 return QuitCDF ("CDF: dimensional size is invalid ",
336 4, 1, &(GDR.rDimSizes[i]), 0, debug);
337 return CDF_OK;
338 }
339
340 /******************************************************************************
341 * ValidateADR.
342 ******************************************************************************/
343
ValidateADR(struct CDFstruct * CDF,vFILE * fp,Int32 offset,Logical debug)344 CDFstatus ValidateADR (struct CDFstruct *CDF, vFILE *fp, Int32 offset,
345 Logical debug)
346 {
347 struct ADRstruct ADR;
348 CDFstatus status;
349
350 if (debug)
351 printf(" Checking ADR...@%ld\n", offset);
352 status = ReadADR (fp, offset,
353 ADR_RECORD, &ADR,
354 ADR_NULL);
355 if (status != CDF_OK) return status;
356 if (ADR.RecordType != ADR_)
357 return QuitCDF ("CDF: record type is invalid ",
358 4, 1, &(ADR.RecordType), 0, debug);
359
360 if (ADR.RecordSize < ADR_BASE_SIZE ||
361 ADR.RecordSize > ADR_MAX_SIZE)
362 return QuitCDF ("CDF: record size is invalid ",
363 4, 1, &(ADR.RecordSize), 0, debug);
364 if (ADR.ADRnext < 0 || ((ADR.Num < (GDR.NumAttr-1)) && ADR.ADRnext == 0))
365 return QuitCDF ("CDF: offset to next ADR is invalid ",
366 4, 1, &(ADR.ADRnext), 0, debug);
367 if (ADR.AgrEDRhead < 0 || (ADR.NgrEntries > 0 && ADR.AgrEDRhead == 0))
368 return QuitCDF ("CDF: record size is invalid ",
369 4, 1, &(ADR.AgrEDRhead), 0, debug);
370 /*
371 if ((ADR.Scope == GLOBAL_SCOPE) && (ADR.NzEntries > 0))
372 return QuitCDF ("CDF: attribute zEntries exist for a global attribute ",
373 4, 1, &(ADR.NzEntries), 0, debug);
374 */
375 if (!ValidAttrScope(ADR.Scope))
376 return QuitCDF ("CDF: scope is invalid ",
377 4, 1, &(ADR.Scope), 0, debug);
378 if (ADR.Num < 0 || ADR.Num > GDR.NumAttr)
379 return QuitCDF ("CDF: attribute number is invalid ",
380 4, 2, &(ADR.Num), &(GDR.NumAttr), debug);
381 if (ADR.NgrEntries < 0)
382 return QuitCDF ("CDF: number of g/rEntries is invalid ",
383 4, 1, &(ADR.NgrEntries), 0, debug);
384 /*
385 if ((ADR.Scope == VARIABLE_SCOPE) && (ADR.NgrEntries > CDF->NrVars))
386 return QuitCDF ("CDF: number of rEntries is invalid ",
387 4, 1, &(ADR.NgrEntries), 0, debug);
388 */
389 if (ADR.MAXgrEntry < -1)
390 return QuitCDF ("CDF: max g/rEntry is invalid ",
391 4, 1, &(ADR.MAXgrEntry), 0, debug);
392 if ((ADR.Scope == VARIABLE_SCOPE) && (ADR.MAXgrEntry < (ADR.NgrEntries-1)))
393 return QuitCDF ("CDF: max rEntry is invalid ",
394 4, 2, &(ADR.MAXgrEntry), &(ADR.NgrEntries), debug);
395 if (ADR.AzEDRhead < 0 || (ADR.NzEntries > 0 && ADR.AzEDRhead == 0))
396 return QuitCDF ("CD2: offset to next AzEDR is invalid ",
397 4, 1, &(ADR.AzEDRhead), 0, debug);
398 /*
399 if (ADR.NzEntries < 0 || ((ADR.Scope == VARIABLE_SCOPE) &&
400 (ADR.NzEntries > CDF->NzVars)))
401 return QuitCDF ("CDF: number of zEntries is invalid ",
402 4, 2, &(ADR.NzEntries), &(CDF->NzVars), debug);
403 if (ADR.MAXzEntry < -1 || ((ADR.Scope == VARIABLE_SCOPE) &&
404 (ADR.MAXzEntry > CDF->NzVars)))
405 return QuitCDF ("CDF: max zEntry is invalid ",
406 4, 2, &(ADR.MAXzEntry), &(CDF->NzVars), debug);
407 */
408 if ((ADR.Scope == VARIABLE_SCOPE) && (ADR.MAXzEntry < (ADR.NzEntries-1)))
409 return QuitCDF ("CDF: max zEntry is invalid ",
410 4, 2, &(ADR.MAXzEntry), &(ADR.NzEntries), debug);
411 if (!ValidAttrName(ADR.Name))
412 return QuitCDF ("CDF: attribute name is invalid ",
413 0, 1, ADR.Name, 0, debug);
414 return CDF_OK;
415 }
416
417 /******************************************************************************
418 * ValidateAEDR/AzEDR.
419 ******************************************************************************/
420
ValidateAEDR(struct CDFstruct * CDF,vFILE * fp,Int32 offset,Int32 num,Int32 maxEntry,Logical zEntry,Logical debug)421 CDFstatus ValidateAEDR (struct CDFstruct *CDF, vFILE *fp, Int32 offset,
422 Int32 num, Int32 maxEntry, Logical zEntry,
423 Logical debug)
424 {
425 struct AEDRstruct AEDR;
426 size_t nBytes;
427 CDFstatus status;
428
429 if (debug)
430 printf(" Checking AEDR...@%ld\n", offset);
431 status = ReadAEDR (fp, offset,
432 AEDR_RECORD, &AEDR, NULL,
433 AEDR_NULL);
434 if (status != CDF_OK) return status;
435 if ((!zEntry && AEDR.RecordType != AgrEDR_) ||
436 (zEntry && AEDR.RecordType != AzEDR_))
437 return QuitCDF ("CDF: record type is invalid ",
438 4, 1, &(AEDR.RecordType), 0, debug);
439 if (AEDR.RecordSize < AEDR_BASE_SIZE)
440 return QuitCDF ("CDF: record size is invalid ",
441 4, 1, &(AEDR.RecordSize), 0, debug);
442 if (AEDR.AEDRnext < 0)
443 return QuitCDF ("CDF: offset to next AEDR is invalid ",
444 4, 1, &(AEDR.AEDRnext), 0, debug);
445 /* Check for "AEDR.AttrNum != num" is not included as some CDFs fail this
446 check. Don't know why.... */
447 /* if (AEDR.AttrNum < 0 || AEDR.AttrNum > GDR.NumAttr || AEDR.AttrNum != num) */
448 /*
449 if (AEDR.AttrNum < 0 || AEDR.AttrNum > GDR.NumAttr)
450 return QuitCDF ("CDF: attribute number is invalid ",
451 4, 2, &(AEDR.AttrNum), &(GDR.NumAttr), debug);
452 */
453 if (!ValidDataType(AEDR.DataType))
454 return QuitCDF ("CDF: data type is invalid ",
455 4, 1, &(AEDR.DataType), 0, debug);
456 if (AEDR.Num < 0 || AEDR.Num > maxEntry)
457 return QuitCDF ("CDF: entry number is invalid ",
458 4, 2, &(AEDR.Num), &maxEntry, debug);
459 if (AEDR.AEDRnext < 0)
460 return QuitCDF ("CDF: next AEDR offset is invalid : ",
461 4, 1, &(AEDR.AEDRnext), 0, debug);
462 /*
463 if (zEntry && AEDR.EntryNum > GDR->NzVars)
464 return QuitCDF ("CDF: entry number is invalid ",
465 4, 2, &(AEDR.Num), &(GDR->NzVars), debug);
466 */
467 if (AEDR.NumElems < 1 ||
468 (STRINGdataType(AEDR.DataType) &&
469 AEDR.NumElems > (AEDR.RecordSize - AEDR_VALUE_OFFSET)))
470 return QuitCDF ("CDF: number of elements is invalid ",
471 4, 1, &(AEDR.NumElems), 0, debug);
472 nBytes = (size_t) (CDFelemSize(AEDR.DataType) * AEDR.NumElems);
473 if (nBytes < 1 ||
474 nBytes > (AEDR.RecordSize - AEDR_VALUE_OFFSET))
475 return QuitCDF ("CDF: entry value size is invalid ",
476 4, 1, &nBytes, 0, debug);
477 if (AEDR.RecordSize > (AEDR_MAX_SIZE + nBytes))
478 return QuitCDF ("CDF: record size is invalid ",
479 4, 1, &(AEDR.RecordSize), 0, debug);
480 return CDF_OK;
481 }
482
483 /******************************************************************************
484 * ValidateVDR/zVDR.
485 ******************************************************************************/
486
ValidateVDR(struct CDFstruct * CDF,vFILE * fp,Int32 offset,Logical zVar,Logical debug)487 CDFstatus ValidateVDR (struct CDFstruct *CDF, vFILE *fp, Int32 offset,
488 Logical zVar, Logical debug)
489 {
490 struct VDRstruct VDR;
491 void *padValue;
492 Int32 nDims, numVars;
493 int ix;
494 CDFstatus status;
495 size_t nBytes;
496
497 if (debug)
498 printf(" Checking VDR...@%ld\n", offset);
499 status = ReadVDR (CDF, fp, offset, zVar,
500 VDR_RECORD, &VDR, NULL,
501 VDR_NULL);
502 if (status != CDF_OK) return status;
503 if ((!zVar && VDR.RecordType != rVDR_) || (zVar && VDR.RecordType != zVDR_))
504 return QuitCDF ("CDF: record type is invalid ",
505 4, 1, &(VDR.RecordType), 0, debug);
506 if (VDR.RecordSize < (zVar ? zVDR_BASE_SIZE : rVDR_BASE_SIZE))
507 return QuitCDF ("CDF: record size is invalid ",
508 4, 1, &(VDR.RecordSize), 0, debug);
509 if (!ValidDataType(VDR.DataType))
510 return QuitCDF ("CDF: data type is invalid ",
511 4, 1, &(VDR.DataType), 0, debug);
512 if (VDR.MaxRec < -1)
513 return QuitCDF ("CDF: max record is invalid ",
514 4, 1, &(VDR.MaxRec), 0, debug);
515 if (VDR.NumElems < 1 || (!STRINGdataType(VDR.DataType) && VDR.NumElems != 1))
516 return QuitCDF ("CDF: number of elements is invalid ",
517 4, 1, &(VDR.NumElems), 0, debug);
518 if (zVar) numVars = CDF->NzVars;
519 else numVars = CDF->NrVars;
520 if (VDR.Num < 0 || VDR.Num > numVars)
521 return QuitCDF ("CDF: variable number is invalid ",
522 4, 2, &(VDR.Num), &numVars, debug);
523 if ((VDR.Num < (numVars-1)) && VDR.VDRnext < 1)
524 return QuitCDF ("CDF: offset to next VDR is invalid ",
525 4, 1, &(VDR.VDRnext), 0, debug);
526 if (VARcompressionBITset(VDR.Flags) && VDR.CPRorSPRoffset <= (int) NO_OFFSET)
527 return QuitCDF ("CDF: offset to CPRorSPR is invalid ",
528 4, 1, &(VDR.CPRorSPRoffset), 0, debug);
529 if (VDR.blockingFactor < 0)
530 return QuitCDF ("CDF: blocking factor is invalid ",
531 4, 1, &(VDR.blockingFactor), 0, debug);
532 if (!ValidVarName(VDR.Name))
533 return QuitCDF ("CDF: variable name is invalid ",
534 0, 1, VDR.Name, 0, debug);
535 if (zVar) {
536 if (VDR.zNumDims < 0 || VDR.zNumDims > CDF_MAX_DIMS)
537 return QuitCDF ("CDF: number of dimensions is invalid ",
538 4, 1, &(VDR.zNumDims), 0, debug);
539 for (ix = 0; ix < (int)VDR.zNumDims; ++ix)
540 if (VDR.zDimSizes[ix] < 1)
541 return QuitCDF ("CDF: dimensional size is invalid ",
542 4, 1, &(VDR.zDimSizes[ix]), 0, debug);
543 }
544 nBytes = (size_t) (CDFelemSize(VDR.DataType)*VDR.NumElems);
545 if (nBytes < 1)
546 return QuitCDF ("CDF: pad value size is invalid ",
547 4, 1, &nBytes, 0, debug);
548 if (VDR.RecordSize > ((zVar ? zVDR_MAX_SIZE : rVDR_MAX_SIZE) + nBytes +
549 (CDF->wastedSpace ? VDR_WASTED_SIZE : 0)))
550 return QuitCDF ("CDF: record size is invalid ",
551 4, 1, &(VDR.RecordSize), 0, debug);
552 return CDF_OK;
553 }
554
555 /******************************************************************************
556 * ValidateVXR.
557 ******************************************************************************/
558
ValidateVXR(vFILE * fp,Int32 offset,Int32 lastRec,Logical debug)559 CDFstatus ValidateVXR (vFILE *fp, Int32 offset, Int32 lastRec, Logical debug)
560 {
561 struct VXRstruct VXR;
562 int i;
563 Int32 irType;
564 CDFstatus status;
565
566 if (debug)
567 printf(" Checking VXR...@%ld\n", offset);
568 status = ReadVXR (fp, offset,
569 VXR_RECORD, &VXR,
570 VXR_NULL);
571 if (status != CDF_OK) return status;
572 if (VXR.RecordType != VXR_)
573 return QuitCDF ("CDF: record type is invalid ",
574 4, 1, &(VXR.RecordType), 0, debug);
575 if (VXR.RecordSize != (VXR_FIRSTREC_OFFSET + 12 * VXR.Nentries))
576 return QuitCDF ("CDF: record size is invalid ",
577 4, 1, &(VXR.RecordSize), 0, debug);
578 if (VXR.Nentries < 0 || VXR.Nentries > MAX_VXR_ENTRIES)
579 return QuitCDF ("CDF: number of entries is invalid ",
580 4, 1, &(VXR.Nentries), 0, debug);
581 if (VXR.NusedEntries < 0 || VXR.NusedEntries > VXR.Nentries)
582 return QuitCDF ("CDF: number of used entries is invalid ",
583 4, 2, &(VXR.NusedEntries), &(VXR.Nentries), debug);
584 if (VXR.VXRnext > 0) {
585 if (VXR.Last[VXR.NusedEntries-1] > lastRec)
586 return QuitCDF ("CDF: a variable last record does not match in a Variable Index Record: ",
587 4, 2, &(VXR.Last[VXR.NusedEntries-1]), &lastRec, debug);
588 status = ValidateVXR (fp, VXR.VXRnext, lastRec, debug);
589 if (status != CDF_OK) return status;
590 } else if (VXR.VXRnext < 0) {
591 return QuitCDF ("CDF: a link offset to next record is negative in a Variable Index Record: ",
592 4, 1, &(VXR.VXRnext), 0, debug);
593 }
594
595 for (i = 0; i < VXR.NusedEntries; ++i) {
596 if (VXR.First[i] < 0 || VXR.Last[i] < 0 || VXR.First[i] > VXR.Last[i])
597 return QuitCDF ("CDF: entry value for first/last is invalid ",
598 4, 2, &(VXR.First[i]), &(VXR.Last[i]), debug);
599 if (VXR.Offset[i] < 1)
600 return QuitCDF ("CDF: entry value for offset is invalid ",
601 4, 1, &(VXR.Offset[i]), 0, debug);
602
603 status = ReadIrType (fp, VXR.Offset[i], &irType);
604 if (status != CDF_OK) return status;
605 if (irType != VXR_ && irType != VVR_ && irType != CVVR_)
606 return QuitCDF ("CDF: entry value for offset is invalid ",
607 4, 1, &(VXR.Offset[i]), 0, debug);
608 if (irType == VXR_ && VXR.Offset[i] != offset) {
609 status = ValidateVXR (fp, VXR.Offset[i], lastRec, debug);
610 if (status != CDF_OK) return status;
611 }
612 }
613 return CDF_OK;
614 }
615
616 /******************************************************************************
617 * ValidateVVR.
618 ******************************************************************************/
619
ValidateVVR(vFILE * fp,Int32 offset,Logical debug)620 CDFstatus ValidateVVR (vFILE *fp, Int32 offset, Logical debug)
621 {
622 struct VVRstruct VVR;
623 CDFstatus status;
624
625 if (debug)
626 printf(" Checking VVR...@%ld\n", offset);
627 status = ReadVVR (fp, offset,
628 VVR_RECORDx, &VVR,
629 VVR_NULL);
630 if (status != CDF_OK) return status;
631 if (VVR.RecordType != VVR_)
632 return QuitCDF ("CDF: record type is invalid ",
633 4, 1, &(VVR.RecordType), 0, debug);
634 if (VVR.RecordSize < VVR_BASE_SIZE)
635 return QuitCDF ("CDF: record size is invalid for Variable Value Record",
636 4, 1, &(VVR.RecordSize), 0, debug);
637 return CDF_OK;
638 }
639
640 /******************************************************************************
641 * ValidateUIR.
642 ******************************************************************************/
643
ValidateUIR(vFILE * fp,Int32 offset,Logical debug)644 CDFstatus ValidateUIR (vFILE *fp, Int32 offset, Logical debug)
645 {
646 struct UIRstruct UIR;
647 CDFstatus status;
648
649 if (debug)
650 printf(" Checking UIR...@%ld\n", offset);
651 status = ReadUIR (fp, offset,
652 UIR_RECORD, &UIR,
653 UIR_NULL);
654 if (status != CDF_OK) return status;
655 if (UIR.RecordType != UIR_)
656 return QuitCDF ("CDF: record type is invalid ",
657 4, 1, &(UIR.RecordType), 0, debug);
658 if (UIR.RecordSize < UIR_BASE_SIZE)
659 return QuitCDF ("CDF: record size is invalid for Unused Internal Record",
660 4, 1, &(UIR.RecordSize), 0, debug);
661 if (UIR.NextUIR < 0)
662 return QuitCDF ("CDF: offset to next UIR is invalid for Unused Internal Record",
663 4, 1, &(UIR.NextUIR), 0, debug);
664 if (UIR.PrevUIR < 0)
665 return QuitCDF ("CDF: offset to previous UIR is invalid for Unused Internal Record",
666 4, 1, &(UIR.PrevUIR), 0, debug);
667 return CDF_OK;
668 }
669
670 /******************************************************************************
671 * ValidateCCR.
672 ******************************************************************************/
673
ValidateCCR(vFILE * fp,Int32 offset,Logical debug)674 CDFstatus ValidateCCR (vFILE *fp, Int32 offset, Logical debug)
675 {
676 struct CCRstruct CCR;
677 CDFstatus status;
678
679 if (debug)
680 printf(" Checking CCR...@%ld\n", offset);
681 status = ReadCCR (fp, offset,
682 CCR_RECORD, &CCR,
683 CCR_NULL);
684 if (status != CDF_OK) return status;
685 if (CCR.RecordType != CCR_)
686 return QuitCDF ("CDF: record type is invalid ",
687 4, 1, &(CCR.RecordType), 0, debug);
688 if (CCR.RecordSize < CCR_BASE_SIZE)
689 return QuitCDF ("CDF: record size is invalid ",
690 4, 1, &(CCR.RecordSize), 0, debug);
691 if (CCR.uSize < 0)
692 return QuitCDF ("CDF: uncompressed file size is invalid ",
693 4, 1, &(CCR.uSize), 0, debug);
694 if (CCR.CPRoffset < 0)
695 return QuitCDF ("CDF: offset to SPR is invalid ",
696 4, 1, &(CCR.CPRoffset), 0, debug);
697 return CDF_OK;
698 }
699
700 /******************************************************************************
701 * ValidateCPR.
702 ******************************************************************************/
703
ValidateCPR(vFILE * fp,Int32 offset,Logical debug)704 CDFstatus ValidateCPR (vFILE *fp, Int32 offset, Logical debug)
705 {
706 struct CPRstruct CPR;
707 int i;
708 CDFstatus status;
709 long cType, cParms[1];
710
711 if (debug)
712 printf(" Checking CPR...@%ld\n", offset);
713 status = ReadCPR (fp, offset,
714 CPR_RECORD, &CPR,
715 CPR_NULL);
716 if (status != CDF_OK) return status;
717 if (CPR.RecordType != CPR_)
718 return QuitCDF ("CDF: record type is invalid ",
719 4, 1, &(CPR.RecordType), 0, debug);
720 if (CPR.RecordSize != (CPR_BASE_SIZE + CPR.pCount * sizeof(Int32)))
721 return QuitCDF ("CDF: reocrd size is invalid ",
722 4, 1, &(CPR.RecordSize), 0, debug);
723 if (CPR.pCount != 1)
724 return QuitCDF ("CDF: compression parameter count is invalid ",
725 4, 1, &(CPR.pCount), 0, debug);
726 cType = (long) CPR.cType;
727 cParms[0] = (long) CPR.cParms[0];
728 if (ValidateCompression(cType, cParms) != CDF_OK)
729 return QuitCDF ("CDF: compression parameter is invalid ",
730 4, 1, &(CPR.cType), 0, debug);
731 return CDF_OK;
732 }
733
734 /******************************************************************************
735 * ValidateSPR.
736 ******************************************************************************/
737
ValidateSPR(vFILE * fp,Int32 offset,Logical debug)738 CDFstatus ValidateSPR (vFILE *fp, Int32 offset, Logical debug)
739 {
740 struct SPRstruct SPR;
741 CDFstatus status;
742
743 if (debug)
744 printf(" Checking SPR...@%ld\n", offset);
745 status = ReadSPR (fp, offset,
746 SPR_RECORD, &SPR,
747 SPR_NULL);
748 if (status != CDF_OK) return status;
749 if (SPR.RecordType != SPR_)
750 return QuitCDF ("CDF: record type is invalid ",
751 4, 1, &(SPR.RecordType), 0, debug);
752 if (SPR.RecordSize != (SPR_BASE_SIZE + SPR.pCount * sizeof(Int32)))
753 return QuitCDF ("CDF: record size is invalid ",
754 4, 1, &(SPR.RecordSize), 0, debug);
755 if (SPR.pCount < 1 || SPR.pCount > CDF_MAX_PARMS)
756 return QuitCDF ("CDF: sparseness parameter count is invalid ",
757 4, 1, &(SPR.pCount), 0, debug);
758 return CDF_OK;
759 }
760
761 /******************************************************************************
762 * ValidateCVVR.
763 ******************************************************************************/
764
ValidateCVVR(vFILE * fp,Int32 offset,Logical debug)765 CDFstatus ValidateCVVR (vFILE *fp, Int32 offset, Logical debug)
766 {
767 struct CVVRstruct CVVR;
768 CDFstatus status;
769
770 if (debug)
771 printf(" Checking CVVR...@%ld\n", offset);
772 status = ReadCVVR (fp, offset,
773 CVVR_RECORDx, &CVVR,
774 CVVR_NULL);
775 if (status != CDF_OK) return status;
776 if (CVVR.RecordSize < CVVR_BASE_SIZE)
777 return QuitCDF ("CDF: record size is invalid ",
778 4, 1, &(CVVR.RecordSize), 0, debug);
779 if (CVVR.cSize < 0)
780 return QuitCDF ("CDF: uncompressed records size is invalid ",
781 4, 1, &(CVVR.cSize), 0, debug);
782 return CDF_OK;
783 }
784
785 /******************************************************************************
786 * ValidateAttributeLinks.
787 ******************************************************************************/
788
ValidateAttributeLinks(struct CDFstruct * CDF,vFILE * fp,Logical debug)789 CDFstatus ValidateAttributeLinks (struct CDFstruct *CDF, vFILE *fp,
790 Logical debug)
791 {
792 CDFstatus status;
793 Int32 offset, nextADR, AgrEDRhead, AzEDRhead;
794 Int32 num, numgrEntries, maxgrEntry, numzEntries, maxzEntry, scope;
795 int ix, *visit;
796
797 visit = (int *) malloc(GDR.NumAttr * sizeof(Int32));
798 for (ix = 0; ix < GDR.NumAttr; ++ix)
799 visit[ix] = 0;
800 offset = GDR.ADRhead;
801 for (ix = 0; ix < GDR.NumAttr; ++ix) {
802 status = ValidateADR (CDF, fp, offset, debug);
803 if (status != CDF_OK) {
804 free (visit);
805 return status;
806 }
807 status = ReadADR (fp, offset,
808 ADR_NUM, &num,
809 ADR_ADRNEXT, &nextADR,
810 ADR_AgrEDRHEAD, &AgrEDRhead,
811 ADR_NgrENTRIES, &numgrEntries,
812 ADR_MAXgrENTRY, &maxgrEntry,
813 ADR_AzEDRHEAD, &AzEDRhead,
814 ADR_NzENTRIES, &numzEntries,
815 ADR_MAXzENTRY, &maxzEntry,
816 ADR_NULL);
817 if (numgrEntries > 0)
818 status = ValidateAttributeEntryLink (CDF, fp, num, FALSE, AgrEDRhead,
819 numgrEntries, maxgrEntry, debug);
820 if (status != CDF_OK) {
821 free (visit);
822 return status;
823 }
824 if (numzEntries > 0)
825 status = ValidateAttributeEntryLink (CDF, fp, num, TRUE, AzEDRhead,
826 numzEntries, maxzEntry, debug);
827 if (status != CDF_OK) {
828 free (visit);
829 return status;
830 }
831 visit[num] = 1;
832 offset = nextADR;
833 }
834 for (ix = 0; ix < GDR.NumAttr; ++ix) {
835 if (visit[ix] == 0) {
836 free (visit);
837 return QuitCDF ("CDF: an attribute unreachable in the attribute link: ",
838 4, 1, &ix, 0, debug);
839 }
840 }
841 free (visit);
842 return CDF_OK;
843 }
844
845 /******************************************************************************
846 * ValidateAttributeEntryLink.
847 ******************************************************************************/
848
ValidateAttributeEntryLink(struct CDFstruct * CDF,vFILE * fp,Int32 num,Logical zEntry,Int32 EDRhead,Int32 numEntries,Int32 maxEntry,Logical debug)849 CDFstatus ValidateAttributeEntryLink (struct CDFstruct *CDF, vFILE *fp,
850 Int32 num, Logical zEntry, Int32 EDRhead,
851 Int32 numEntries, Int32 maxEntry,
852 Logical debug)
853 {
854 CDFstatus status;
855 Int32 offset, nextAEDR;
856 Int32 entryNum, lastNum, *visits;
857 int ix, iy;
858
859 offset = EDRhead;
860 lastNum = 0;
861 visits = (Int32 *) cdf_AllocateMemory (numEntries * sizeof(Int32), NULL);
862 if (visits == NULL) return BAD_MALLOC;
863 for (ix = 0; ix < numEntries; ++ix)
864 visits[ix] = 0;
865 ix = 0;
866 while (offset != 0) {
867 status = ValidateAEDR (CDF, fp, offset, num, maxEntry, zEntry, debug);
868 if (status != CDF_OK) {
869 cdf_FreeMemory (visits, NULL);
870 return status;
871 }
872 status = ReadAEDR (fp, offset,
873 AEDR_NUM, &entryNum,
874 AEDR_AEDRNEXT, &nextAEDR,
875 AEDR_NULL);
876 if (ix > 0) {
877 for (iy = 0; iy < ix; ++iy) {
878 if (visits[iy] == entryNum) {
879 cdf_FreeMemory (visits, NULL);
880 return QuitCDF ("CDF: entry number is repeating in an attribute entry link: ",
881 4, 1, &entryNum, 0, debug);
882 }
883 }
884 }
885 if (ix == (int) numEntries) {
886 cdf_FreeMemory (visits, NULL);
887 return QuitCDF ("CDF: number of entries is more than maximum in an attribute entry link: ",
888 4, 1, &ix, 0, debug);
889 }
890 visits[ix] = entryNum;
891 ++ix;
892 if (lastNum < entryNum) lastNum = entryNum;
893 offset = nextAEDR;
894 }
895 if (lastNum != maxEntry) {
896 cdf_FreeMemory (visits, NULL);
897 return QuitCDF ("CDF: last entry number is not the maximum entry number in an attribute entry link: ",
898 4, 2, &lastNum, &maxEntry, debug);
899 }
900 cdf_FreeMemory (visits, NULL);
901 return CDF_OK;
902 }
903
904 /******************************************************************************
905 * ValidateVariableLinks.
906 ******************************************************************************/
907
ValidateVariableLinks(struct CDFstruct * CDF,vFILE * fp,Logical zVar,Logical debug)908 CDFstatus ValidateVariableLinks (struct CDFstruct *CDF, vFILE *fp,
909 Logical zVar, Logical debug)
910 {
911 CDFstatus status;
912 Int32 offset, headVXR, tailVXR, nextVDR, cprOffset;
913 Int32 num, lastRec, flags;
914 int ix, numVars, *visit;
915
916 numVars = (zVar ? GDR.NzVars : GDR.NrVars);
917 visit = (int *) cdf_AllocateMemory (numVars * sizeof(Int32), NULL);
918 if (visit == NULL) return BAD_MALLOC;
919 for (ix = 0; ix < numVars; ++ix)
920 visit[ix] = 0;
921 offset = (zVar ? GDR.zVDRhead : GDR.rVDRhead);
922 for (ix = 0; ix < numVars; ++ix) {
923 status = ValidateVDR (CDF, fp, offset, zVar, debug);
924 if (status != CDF_OK) {
925 cdf_FreeMemory (visit, NULL);
926 return status;
927 }
928 status = ReadVDR (CDF, fp, offset, zVar,
929 VDR_NUM, &num,
930 VDR_FLAGS, &flags,
931 VDR_MAXREC, &lastRec,
932 VDR_VDRNEXT, &nextVDR,
933 VDR_CPRorSPR, &cprOffset,
934 VDR_VXRHEAD, &headVXR,
935 VDR_VXRTAIL, &tailVXR,
936 VDR_NULL);
937 if (CDF->singleFile && lastRec > -1) {
938 status = ValidateVariableValueLinks (CDF, fp, lastRec, headVXR, debug);
939 if (status != CDF_OK) {
940 cdf_FreeMemory (visit, NULL);
941 return status;
942 }
943 }
944 /*
945 if (CDF->singleFile && (headVXR != tailVXR) && tailVXR > 0) {
946 status = ValidateVariableValueLinks (CDF, fp, lastRec, tailVXR, debug);
947 if (status != CDF_OK) {
948 cdf_FreeMemory (visit, NULL);
949 return status;
950 }
951 }
952 */
953 if (VARcompressionBITset(flags)) {
954 status = ValidateCPR (fp, cprOffset, debug);
955 if (status != CDF_OK) {
956 cdf_FreeMemory (visit, NULL);
957 return status;
958 }
959 }
960 visit[num] = 1;
961 offset = nextVDR;
962 }
963 for (ix = 0; ix < numVars; ++ix) {
964 if (visit[ix] == 0) {
965 cdf_FreeMemory (visit, NULL);
966 return QuitCDF ("CDF: a variable unreachable in variable link: ",
967 4, 1, &ix, 0, debug);
968 }
969 }
970 cdf_FreeMemory (visit, NULL);
971 if (offset != 0) {
972 status = ReadVDR (CDF, fp, offset, zVar,
973 VDR_NUM, &num,
974 VDR_VDRNEXT, &nextVDR,
975 VDR_NULL);
976 if (status == CDF_OK) {
977 if (num >= numVars)
978 return QuitCDF ("CDF: a variable unreachable in variable link: ",
979 4, 2, &num, &numVars, debug);
980 else
981 return QuitCDF ("CDF: a variable is repeated in variable link: ",
982 4, 2, &num, &numVars, debug);
983 }
984 }
985 return CDF_OK;
986 }
987
988 /******************************************************************************
989 * ValidateVariableValueLinks.
990 ******************************************************************************/
991
ValidateVariableValueLinks(struct CDFstruct * CDF,vFILE * fp,Int32 lastRec,Int32 headVXR,Logical debug)992 CDFstatus ValidateVariableValueLinks (struct CDFstruct *CDF, vFILE *fp,
993 Int32 lastRec, Int32 headVXR,
994 Logical debug)
995 {
996 CDFstatus status;
997
998 status = ValidateVXR (fp, headVXR, lastRec, debug);
999 if (status != CDF_OK) return status;
1000
1001 return CDF_OK;
1002 }
1003
1004 /******************************************************************************
1005 * QuitCDF.
1006 ******************************************************************************/
1007
QuitCDF(char * why,int size,int num,void * value1,void * value2,Logical debug)1008 CDFstatus QuitCDF (char *why, int size, int num, void *value1, void *value2,
1009 Logical debug)
1010 {
1011
1012 if (debug) {
1013 char text[101];
1014 strcpyX (text, why, 100);
1015 if (num == 2) {
1016 if (size == 4)
1017 sprintf (EofS(text), " (%ld vs %ld) ", (long) *(int *)value1,
1018 (long) *(int *)value2);
1019 else
1020 sprintf (EofS(text), " (%s vs %s) ", (char *)value1, (char *)value2);
1021 } else {
1022 if (size == 4)
1023 sprintf (EofS(text), " (%ld) ", (long) *(int *)value1);
1024 else
1025 sprintf (EofS(text), " (%s) ", (char *)value1);
1026 }
1027 printf ("ERROR...%s\n", text);
1028 }
1029 return CV2C;
1030 }
1031
1032