1 /******************************************************************************
2 *
3 *  NSSDC/CDF                                        Read from internal record.
4 *
5 *  Version 1.4a, 28-Feb-97, Hughes STX.
6 *
7 *  Modification history:
8 *
9 *   V1.0  30-Nov-94, J Love     Original version.
10 *   V1.1  30-Jan-95, J Love	`Read32s' now checks count.
11 *   V1.1a 24-Feb-95, J Love	Solaris 2.3 IDL i/f.
12 *   V1.2  26-May-95, J Love	CDF V2.4 compatibility mode.  What?
13 *   V1.3  14-Jun-95, J Love	Recursion!
14 *   V1.3a  4-Aug-95, J Love	More efficient `Read32' and `Read32s'.
15 *				CDFexport-related changes.
16 *   V1.4   3-Apr-96, J Love	CDF V2.6.
17 *   V1.4a 28-Feb-97, J Love	Windows NT for MS Visual C/C++ on an IBM PC.
18 *   V3.2  21-Jun-07, D Berger   Modified ReadGDR, ReadADR, and ReadAEDR, and
19 *                               added ReadADRList and ReadAEDRList to support
20 *                               perfomance enhancements for accessing metadata
21 *                               in READONLYon mode.
22 *   V3.2a 11-Apr-08, M Liu      Modified Read32s to eliminate the potential
23 *                               buffer overflow.
24 *   V3.3  28-Jul-08, M Liu      Modified to work with CDF file validation.
25 *   V3.3a 15-Sep-08, M Liu      Modified ReadAEDRList to pass in the number of
26 *                               entries to set up the list, not just the last
27 *                               entry number.
28 *
29 ******************************************************************************/
30 
31 #include "cdflib.h"
32 
33 /******************************************************************************
34 * Local macro definitions.
35 ******************************************************************************/
36 
37 #define CRE CDF_READ_ERROR
38 #define CV2C CORRUPTED_V2_CDF
39 
40 /******************************************************************************
41 * Read32.
42 ******************************************************************************/
43 
Read32(fp,value)44 VISIBLE_PREFIX Logical Read32 (fp, value)
45 vFILE *fp;
46 Int32 *value;
47 {
48 #if defined(NETWORKbyteORDERcpu)
49   if (!READv(value,(size_t)4,(size_t)1,fp)) return FALSE;
50 #else
51   Int32 temp;
52   if (!READv(&temp,(size_t)4,(size_t)1,fp)) return FALSE;
53   REVERSE4bIO (&temp, value)
54 #endif
55   return TRUE;
56 }
57 
58 /******************************************************************************
59 * Read32s.
60 ******************************************************************************/
61 
Read32s(fp,buffer,count)62 STATICforIDL Logical Read32s (fp, buffer, count)
63 vFILE *fp;
64 Int32 *buffer;
65 int count;
66 {
67 #define MAX_READ32s CDF_MAX_DIMS	/* This must be the maximum of
68 					   CDF_MAX_DIMS and MAX_VXR_ENTRIES
69 					   (and for any other uses of
70 					   `Read32s'). */
71 #if defined(NETWORKbyteORDERcpu)
72   if (count == 0) return TRUE;
73   if (count < 0 || count > MAX_READ32s) return FALSE;
74   if (!READv(buffer,(size_t)4,(size_t)count,fp)) return FALSE;
75 #else
76   int i; Int32 temp[MAX_READ32s];
77   if (count == 0) return TRUE;
78   if (count < 0 || count > MAX_READ32s) return FALSE;
79   if (!READv(temp,(size_t)4,(size_t)count,fp)) return FALSE;
80   for (i = 0; i < count; i++) {
81      REVERSE4bIO (&temp[i], &buffer[i])
82   }
83 #endif
84   return TRUE;
85 }
86 
87 /******************************************************************************
88 * ReadIrSize.
89 *   The size is always in the first 4-byte field.
90 ******************************************************************************/
91 
ReadIrSize(fp,offset,irSize)92 STATICforIDL CDFstatus ReadIrSize (fp, offset, irSize)
93 vFILE *fp;
94 Int32 offset;
95 Int32 *irSize;
96 {
97   if (!SEEKv(fp,(long)offset,vSEEK_SET)) return CRE;
98   if (!Read32(fp,irSize)) return CRE;
99   return CDF_OK;
100 }
101 
102 /******************************************************************************
103 * ReadIrType.
104 *   The type is always in the second 4-byte field.
105 ******************************************************************************/
106 
ReadIrType(fp,offset,irType)107 VISIBLE_PREFIX CDFstatus ReadIrType (fp, offset, irType)
108 vFILE *fp;
109 Int32 offset;
110 Int32 *irType;
111 {
112   long irTypeOffset = offset + sizeof(Int32);
113   if (!SEEKv(fp,irTypeOffset,vSEEK_SET)) return CRE;
114   if (!Read32(fp,irType)) return CRE;
115   return CDF_OK;
116 }
117 
118 /******************************************************************************
119 * ReadCDR.
120 *   Note that the length of the CDF copyright was decreased in CDF V2.5 (there
121 * were way too many characters allowed for).  When reading the copyright, only
122 * CDF_COPYRIGHT_LEN characters will be read.  This will be less than the
123 * actual number in CDFs prior to CDF V2.4 but is enough to include all of the
124 * characters that were used.  (The value of CDF_COPYRIGHT_LEN was decreased
125 * from CDF V2.4 to CDF V2.5.)
126 ******************************************************************************/
127 
128 #if defined(STDARG)
ReadCDR(vFILE * fp,Int32 offset,...)129 STATICforIDL CDFstatus ReadCDR (vFILE *fp, Int32 offset, ...)
130 #else
131 STATICforIDL CDFstatus ReadCDR (va_alist)
132 va_dcl
133 #endif
134 {
135   va_list ap; CDFstatus pStatus = CDF_OK;
136 #if defined(STDARG)
137   va_start (ap, offset);
138 #else
139   vFILE *fp; Int32 offset;
140   VA_START (ap);
141   fp = va_arg (ap, vFILE *);
142   offset = va_arg (ap, Int32);
143 #endif
144   for (;;) {
145      int field = va_arg (ap, int);
146      switch (field) {
147        case CDR_NULL:
148 	 va_end (ap);
149 	 return pStatus;
150        case CDR_RECORD: {
151 	 struct CDRstruct *CDR = va_arg (ap, struct CDRstruct *);
152 	 void *copyRight = va_arg (ap, char *);
153 	 if (!SEEKv(fp,(long)offset,vSEEK_SET)) return CRE;
154 	 if (!Read32(fp,&(CDR->RecordSize))) return CRE;
155 	 if (!Read32(fp,&(CDR->RecordType))) return CRE;
156 	 if (!Read32(fp,&(CDR->GDRoffset))) return CRE;
157 	 if (!Read32(fp,&(CDR->Version))) return CRE;
158 	 if (!Read32(fp,&(CDR->Release))) return CRE;
159 	 if (!Read32(fp,&(CDR->Encoding))) return CRE;
160 	 if (!Read32(fp,&(CDR->Flags))) return CRE;
161 	 if (!Read32(fp,&(CDR->rfuA))) return CRE;
162 	 if (!Read32(fp,&(CDR->rfuB))) return CRE;
163 	 if (!Read32(fp,&(CDR->Increment))) return CRE;
164 	 if (!Read32(fp,&(CDR->rfuD))) return CRE;
165 	 if (!Read32(fp,&(CDR->rfuE))) return CRE;
166 	 if (copyRight != NULL) {
167 	   if (!READv(copyRight,CDF_COPYRIGHT_LEN,1,fp)) return CRE;
168 	   NulPad (copyRight, CDF_COPYRIGHT_LEN);
169 	 }
170 	 break;
171        }
172        case CDR_COPYRIGHT: {
173 	 void *copyRight = va_arg (ap, char *);
174 	 long tOffset = offset + CDR_COPYRIGHT_OFFSET;
175 	 if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
176 	 if (!READv(copyRight,CDF_COPYRIGHT_LEN,1,fp)) return CRE;
177 	 NulPad (copyRight, CDF_COPYRIGHT_LEN);
178 	 break;
179        }
180        default: {
181 	 Int32 *buffer = va_arg (ap, Int32 *);
182 	 long tOffset = offset;
183 	 switch (field) {
184 	   case CDR_RECORDSIZE: tOffset += CDR_RECORDSIZE_OFFSET; break;
185 	   case CDR_RECORDTYPE: tOffset += CDR_RECORDTYPE_OFFSET; break;
186 	   case CDR_GDROFFSET: tOffset += CDR_GDROFFSET_OFFSET; break;
187 	   case CDR_VERSION: tOffset += CDR_VERSION_OFFSET; break;
188 	   case CDR_RELEASE: tOffset += CDR_RELEASE_OFFSET; break;
189 	   case CDR_ENCODING: tOffset += CDR_ENCODING_OFFSET; break;
190 	   case CDR_FLAGS: tOffset += CDR_FLAGS_OFFSET; break;
191 	   case CDR_INCREMENT: tOffset += CDR_INCREMENT_OFFSET; break;
192 	   default: return CDF_INTERNAL_ERROR;
193 	 }
194 	 if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
195 	 if (!Read32(fp,buffer)) return CRE;
196 	 break;
197        }
198      }
199   }
200 }
201 
202 /******************************************************************************
203 * ReadGDR.
204 ******************************************************************************/
205 
206 #if defined(STDARG)
ReadGDR(vFILE * fp,Int32 offset,...)207 STATICforIDL CDFstatus ReadGDR (vFILE *fp, Int32 offset, ...)
208 #else
209 STATICforIDL CDFstatus ReadGDR (va_alist)
210 va_dcl
211 #endif
212 {
213   long i;
214   long read_only_mode;
215   va_list ap; CDFstatus pStatus = CDF_OK;
216 #if defined(STDARG)
217   va_start (ap, offset);
218 #else
219   vFILE *fp; Int32 offset;
220   VA_START (ap);
221   fp = va_arg (ap, vFILE *);
222   offset = va_arg (ap, Int32);
223 #endif
224   /***************************************************************************
225   * Check read only mode. If it is invalid, it may have not been initialized -
226   * set it to off.
227   ***************************************************************************/
228   pStatus = CDFlib(CONFIRM_, CDF_READONLY_MODE_, &read_only_mode, NULL_);
229   if (pStatus != CDF_OK) return pStatus;
230   if (read_only_mode != READONLYon && read_only_mode != READONLYoff)
231   {
232       read_only_mode = READONLYoff;
233   };
234   /***************************************************************************
235   * If READONLYon, read the GDR into memory for future reference.
236   ***************************************************************************/
237   if (read_only_mode == READONLYon && fp->GDR == NULL)
238   {
239       fp->GDR = cdf_AllocateMemory(sizeof(struct GDRstruct), NULL);
240       if (fp->GDR == NULL) return CRE;
241       if (!SEEKv(fp,(long)offset,vSEEK_SET)) return CRE;
242       if (!Read32(fp,&(fp->GDR->RecordSize))) return CRE;
243       if (!Read32(fp,&(fp->GDR->RecordType))) return CRE;
244       if (!Read32(fp,&(fp->GDR->rVDRhead))) return CRE;
245       if (!Read32(fp,&(fp->GDR->zVDRhead))) return CRE;
246       if (!Read32(fp,&(fp->GDR->ADRhead))) return CRE;
247       if (!Read32(fp,&(fp->GDR->eof))) return CRE;
248       if (!Read32(fp,&(fp->GDR->NrVars))) return CRE;
249       if (!Read32(fp,&(fp->GDR->NumAttr))) return CRE;
250       if (!Read32(fp,&(fp->GDR->rMaxRec))) return CRE;
251       if (!Read32(fp,&(fp->GDR->rNumDims))) return CRE;
252       if (!Read32(fp,&(fp->GDR->NzVars))) return CRE;
253       if (!Read32(fp,&(fp->GDR->UIRhead))) return CRE;
254       if (!Read32(fp,&(fp->GDR->rfuC))) return CRE;
255       if (!Read32(fp,&(fp->GDR->rfuD))) return CRE;
256       if (!Read32(fp,&(fp->GDR->rfuE))) return CRE;
257       if (fp->GDR->rNumDims < 0 || fp->GDR->rNumDims > CDF_MAX_DIMS)
258         return CV2C;
259       if (!Read32s(fp,fp->GDR->rDimSizes,
260                    (int)fp->GDR->rNumDims)) return CRE;
261       pStatus = ReadADRList(fp);
262       if (pStatus != CDF_OK) return pStatus;
263   };
264   /**************************************************************************
265   * For whatever data is requested from the GDR, if READONLYon, get the data
266   * from the GDR in memory, otherwise read from the file/cache.
267   ***************************************************************************/
268   for (;;) {
269      int field = va_arg (ap, int);
270      switch (field) {
271        case GDR_NULL:
272 	 va_end (ap);
273 	 return pStatus;
274        case GDR_RECORD: {
275 	 struct GDRstruct *GDR = va_arg (ap, struct GDRstruct *);
276          if (read_only_mode == READONLYoff)
277          {
278              if (!SEEKv(fp,(long)offset,vSEEK_SET)) return CRE;
279              if (!Read32(fp,&(GDR->RecordSize))) return CRE;
280              if (!Read32(fp,&(GDR->RecordType))) return CRE;
281              if (!Read32(fp,&(GDR->rVDRhead))) return CRE;
282              if (!Read32(fp,&(GDR->zVDRhead))) return CRE;
283              if (!Read32(fp,&(GDR->ADRhead))) return CRE;
284              if (!Read32(fp,&(GDR->eof))) return CRE;
285              if (!Read32(fp,&(GDR->NrVars))) return CRE;
286              if (!Read32(fp,&(GDR->NumAttr))) return CRE;
287              if (!Read32(fp,&(GDR->rMaxRec))) return CRE;
288              if (!Read32(fp,&(GDR->rNumDims))) return CRE;
289              if (!Read32(fp,&(GDR->NzVars))) return CRE;
290              if (!Read32(fp,&(GDR->UIRhead))) return CRE;
291              if (!Read32(fp,&(GDR->rfuC))) return CRE;
292              if (!Read32(fp,&(GDR->rfuD))) return CRE;
293              if (!Read32(fp,&(GDR->rfuE))) return CRE;
294              if (GDR->rNumDims < 0 || GDR->rNumDims > CDF_MAX_DIMS)
295                break; /* return CV2C;  */
296              if (!Read32s(fp,GDR->rDimSizes,(int)GDR->rNumDims)) return CRE;
297          }
298          else
299          {
300              GDR->RecordSize = fp->GDR->RecordSize;
301              GDR->RecordType = fp->GDR->RecordType;
302              GDR->rVDRhead = fp->GDR->rVDRhead;
303              GDR->zVDRhead = fp->GDR->zVDRhead;
304              GDR->ADRhead = fp->GDR->ADRhead;
305              GDR->eof = fp->GDR->eof;
306              GDR->NrVars = fp->GDR->NrVars;
307              GDR->NumAttr = fp->GDR->NumAttr;
308              GDR->rMaxRec = fp->GDR->rMaxRec;
309              GDR->rNumDims = fp->GDR->rNumDims;
310              GDR->NzVars = fp->GDR->NzVars;
311              GDR->UIRhead = fp->GDR->UIRhead;
312              GDR->rfuC = fp->GDR->rfuC;
313              GDR->rfuD = fp->GDR->rfuD;
314              GDR->rfuE = fp->GDR->rfuE;
315              for (i = 0; i < GDR->rNumDims; i++)
316              {
317                  GDR->rDimSizes[i] = fp->GDR->rDimSizes[i];
318              };
319          }
320          break;
321        }
322        case GDR_rDIMSIZES: {
323 	 Int32 *rDimSizes = va_arg (ap, Int32 *); Int32 rNumDims; long tOffset;
324          if (read_only_mode == READONLYoff)
325          {
326 	     if (!sX(ReadGDR(fp,offset,
327                              GDR_rNUMDIMS,&rNumDims,
328                              GDR_NULL),&pStatus)) return pStatus;
329 	     tOffset = offset + GDR_rDIMSIZES_OFFSET;
330 	     if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
331              if (rNumDims < 0 || rNumDims > CDF_MAX_DIMS)
332                return CV2C;
333 	     if (!Read32s(fp,rDimSizes,(int)rNumDims)) return CRE;
334          }
335          else
336          {
337              for (i = 0; i < fp->GDR->rNumDims; i++)
338              {
339                  rDimSizes[i] = fp->GDR->rDimSizes[i];
340              };
341          }
342          break;
343        }
344        default: {
345 	 Int32 *buffer = va_arg (ap, Int32 *); long tOffset = offset;
346 	 switch (field) {
347 	   case GDR_RECORDSIZE: {
348                if (read_only_mode == READONLYoff)
349                {
350                    tOffset += GDR_RECORDSIZE_OFFSET;
351                }
352                else
353                {
354                    *buffer = fp->GDR->RecordSize;
355                };
356                break;
357            }
358 	   case GDR_RECORDTYPE: {
359                if (read_only_mode == READONLYoff)
360                {
361                    tOffset += GDR_RECORDTYPE_OFFSET;
362                }
363                else
364                {
365                    *buffer = fp->GDR->RecordType;
366                }
367                break;
368            }
369 	   case GDR_rVDRHEAD: {
370                if (read_only_mode == READONLYoff)
371                {
372                    tOffset += GDR_rVDRHEAD_OFFSET;
373                }
374                else
375                {
376                    *buffer = fp->GDR->rVDRhead;
377                }
378                break;
379            }
380 	   case GDR_zVDRHEAD: {
381                if (read_only_mode == READONLYoff)
382                {
383                    tOffset += GDR_zVDRHEAD_OFFSET;
384                }
385                else
386                {
387                    *buffer = fp->GDR->zVDRhead;
388                }
389                break;
390            }
391 	   case GDR_ADRHEAD: {
392                if (read_only_mode == READONLYoff)
393                {
394                    tOffset += GDR_ADRHEAD_OFFSET;
395                }
396                else
397                {
398                    *buffer = fp->GDR->ADRhead;
399                }
400                break;
401            }
402 	   case GDR_EOF: {
403                if (read_only_mode == READONLYoff)
404                {
405                    tOffset += GDR_EOF_OFFSET;
406                }
407                else
408                {
409                    *buffer = fp->GDR->eof;
410                }
411                break;
412            }
413 	   case GDR_NrVARS: {
414                if (read_only_mode == READONLYoff)
415                {
416                    tOffset += GDR_NrVARS_OFFSET;
417                }
418                else
419                {
420                    *buffer = fp->GDR->NrVars;
421                }
422                break;
423            }
424 	   case GDR_NUMATTR: {
425                if (read_only_mode == READONLYoff)
426                {
427                    tOffset += GDR_NUMATTR_OFFSET;
428                }
429                else
430                {
431                    *buffer = fp->GDR->NumAttr;
432                }
433                break;
434            }
435 	   case GDR_rMAXREC: {
436                if (read_only_mode == READONLYoff)
437                {
438                    tOffset += GDR_rMAXREC_OFFSET;
439                }
440                else
441                {
442                    *buffer = fp->GDR->rMaxRec;
443                }
444                break;
445            }
446 	   case GDR_rNUMDIMS: {
447                if (read_only_mode == READONLYoff)
448                {
449                    tOffset += GDR_rNUMDIMS_OFFSET;
450                }
451                else
452                {
453                    *buffer = fp->GDR->rNumDims;
454                }
455                break;
456            }
457 	   case GDR_NzVARS: {
458                if (read_only_mode == READONLYoff)
459                {
460                    tOffset += GDR_NzVARS_OFFSET;
461                }
462                else
463                {
464                    *buffer = fp->GDR->NzVars;
465                }
466                break;
467            }
468 	   case GDR_UIRHEAD: {
469                if (read_only_mode == READONLYoff)
470                {
471                    tOffset += GDR_UIRHEAD_OFFSET;
472                }
473                else
474                {
475                    *buffer = fp->GDR->UIRhead;
476                }
477                break;
478            }
479 	   default: return CDF_INTERNAL_ERROR;
480 	 }
481          if (read_only_mode == READONLYoff)
482          {
483 	     if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
484 	     if (!Read32(fp,buffer)) return CRE;
485          }
486 	 break;
487        }
488      }
489   }
490 }
491 
492 /******************************************************************************
493 * ReadADR.
494 ******************************************************************************/
495 
496 #if defined(STDARG)
ReadADR(vFILE * fp,Int32 offset,...)497 STATICforIDL CDFstatus ReadADR (vFILE *fp, Int32 offset, ...)
498 #else
499 STATICforIDL CDFstatus ReadADR (va_alist)
500 va_dcl
501 #endif
502 {
503   long read_only_mode;
504   va_list ap; CDFstatus pStatus = CDF_OK;
505 #if defined(STDARG)
506   va_start (ap, offset);
507 #else
508   vFILE *fp; Int32 offset;
509   VA_START (ap);
510   fp = va_arg (ap, vFILE *);
511   offset = va_arg (ap, Int32);
512 #endif
513   /***************************************************************************
514   * IF READONLYon, and there are no ADRs in memory or no attribute has been
515   * selected, return NO_ATTR_SELECTED. Note that reading of ADRs into memory
516   * is triggered the 1st time an ADR is selected.
517   ***************************************************************************/
518   pStatus = CDFlib(CONFIRM_, CDF_READONLY_MODE_, &read_only_mode, NULL_);
519   if (pStatus != CDF_OK) return pStatus;
520   if (read_only_mode == READONLYon && fp->CurADRIndex == RESERVED_ENTRYNUM)
521   {
522       return NO_ATTR_SELECTED;
523   };
524   /***************************************************************************
525   * For whatever ADR data is selected, if READONLYon, read the data from memory
526   * using CurADRIndex to select the correct ADR from the ADRList. Otherwise,
527   * read the data from the file/cache using the file offset.
528   ***************************************************************************/
529   for (;;) {
530      int field = va_arg (ap, int);
531      switch (field) {
532        case ADR_NULL:
533 	 va_end (ap);
534 	 return pStatus;
535        case ADR_RECORD: {
536 	 struct ADRstruct *ADR = va_arg (ap, struct ADRstruct *);
537          if (read_only_mode == READONLYoff)
538          {
539              if (!SEEKv(fp,(long)offset,vSEEK_SET)) return CRE;
540              if (!Read32(fp,&(ADR->RecordSize))) return CRE;
541              if (!Read32(fp,&(ADR->RecordType))) return CRE;
542              if (!Read32(fp,&(ADR->ADRnext))) return CRE;
543              if (!Read32(fp,&(ADR->AgrEDRhead))) return CRE;
544              if (!Read32(fp,&(ADR->Scope))) return CRE;
545              if (!Read32(fp,&(ADR->Num))) return CRE;
546              if (!Read32(fp,&(ADR->NgrEntries))) return CRE;
547              if (!Read32(fp,&(ADR->MAXgrEntry))) return CRE;
548              if (!Read32(fp,&(ADR->rfuA))) return CRE;
549              if (!Read32(fp,&(ADR->AzEDRhead))) return CRE;
550              if (!Read32(fp,&(ADR->NzEntries))) return CRE;
551              if (!Read32(fp,&(ADR->MAXzEntry))) return CRE;
552              if (!Read32(fp,&(ADR->rfuE))) return CRE;
553              if (!READv(ADR->Name,CDF_ATTR_NAME_LEN,1,fp)) return CRE;
554              NulPad (ADR->Name, CDF_ATTR_NAME_LEN);
555          }
556          else
557          {
558              ADR->RecordSize = fp->ADRList[fp->CurADRIndex]->RecordSize;
559              ADR->RecordType = fp->ADRList[fp->CurADRIndex]->RecordType;
560              ADR->ADRnext = fp->ADRList[fp->CurADRIndex]->ADRnext;
561              ADR->AgrEDRhead = fp->ADRList[fp->CurADRIndex]->AgrEDRhead;
562              ADR->Scope = fp->ADRList[fp->CurADRIndex]->Scope;
563              ADR->Num = fp->ADRList[fp->CurADRIndex]->Num;
564              ADR->NgrEntries = fp->ADRList[fp->CurADRIndex]->NgrEntries;
565              ADR->MAXgrEntry = fp->ADRList[fp->CurADRIndex]->MAXgrEntry;
566              ADR->rfuA = fp->ADRList[fp->CurADRIndex]->rfuA;
567              ADR->AzEDRhead = fp->ADRList[fp->CurADRIndex]->AzEDRhead;
568              ADR->NzEntries = fp->ADRList[fp->CurADRIndex]->NzEntries;
569              ADR->MAXzEntry = fp->ADRList[fp->CurADRIndex]->MAXzEntry;
570              ADR->rfuE = fp->ADRList[fp->CurADRIndex]->rfuE;
571              strcpy(ADR->Name, fp->ADRList[fp->CurADRIndex]->Name);
572          }
573          break;
574        }
575        case ADR_NAME: {
576 	 char *aName = va_arg (ap, char *);
577          if (read_only_mode == READONLYoff)
578          {
579 	     long tOffset = offset + ADR_NAME_OFFSET;
580 	     if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
581 	     if (!READv(aName,CDF_ATTR_NAME_LEN,1,fp)) return CRE;
582 	     NulPad (aName, CDF_ATTR_NAME_LEN);
583          }
584          else
585          {
586              strcpy(aName, fp->ADRList[fp->CurADRIndex]->Name);
587          }
588 	 break;
589        }
590        default: {
591 	 Int32 *buffer = va_arg (ap, Int32 *); long tOffset = offset;
592 	 switch (field) {
593 	   case ADR_RECORDSIZE: {
594                if (read_only_mode == READONLYoff)
595                {
596                    tOffset += ADR_RECORDSIZE_OFFSET;
597                }
598                else
599                {
600                    *buffer = fp->ADRList[fp->CurADRIndex]->RecordSize;
601                };
602                break;
603            }
604 	   case ADR_RECORDTYPE: {
605                if (read_only_mode == READONLYoff)
606                {
607                    tOffset += ADR_RECORDTYPE_OFFSET;
608                }
609                else
610                {
611                    *buffer = fp->ADRList[fp->CurADRIndex]->RecordType;
612                };
613                break;
614            }
615 	   case ADR_ADRNEXT: {
616                if (read_only_mode == READONLYoff)
617                {
618                    tOffset += ADR_ADRNEXT_OFFSET;
619                }
620                else
621                {
622                    *buffer = fp->ADRList[fp->CurADRIndex]->ADRnext;
623                };
624                break;
625            }
626 	   case ADR_AgrEDRHEAD: {
627                if (read_only_mode == READONLYoff)
628                {
629                    tOffset += ADR_AgrEDRHEAD_OFFSET;
630                }
631                else
632                {
633                    *buffer = fp->ADRList[fp->CurADRIndex]->AgrEDRhead;
634                };
635                break;
636            }
637 	   case ADR_SCOPE: {
638                if (read_only_mode == READONLYoff)
639                {
640                    tOffset += ADR_SCOPE_OFFSET;
641                }
642                else
643                {
644                    *buffer = fp->ADRList[fp->CurADRIndex]->Scope;
645                };
646                break;
647            }
648 	   case ADR_NUM: {
649                if (read_only_mode == READONLYoff)
650                {
651                    tOffset += ADR_NUM_OFFSET;
652                }
653                else
654                {
655                    *buffer = fp->ADRList[fp->CurADRIndex]->Num;
656                };
657                break;
658            }
659 	   case ADR_NgrENTRIES: {
660                if (read_only_mode == READONLYoff)
661                {
662                    tOffset += ADR_NgrENTRIES_OFFSET;
663                }
664                else
665                {
666                    *buffer = fp->ADRList[fp->CurADRIndex]->NgrEntries;
667                };
668                break;
669            }
670 	   case ADR_MAXgrENTRY: {
671                if (read_only_mode == READONLYoff)
672                {
673                    tOffset += ADR_MAXgrENTRY_OFFSET;
674                }
675                else
676                {
677                    *buffer = fp->ADRList[fp->CurADRIndex]->MAXgrEntry;
678                };
679                break;
680            }
681 	   case ADR_AzEDRHEAD: {
682                if (read_only_mode == READONLYoff)
683                {
684                    tOffset += ADR_AzEDRHEAD_OFFSET;
685                }
686                else
687                {
688                    *buffer = fp->ADRList[fp->CurADRIndex]->AzEDRhead;
689                };
690                break;
691            }
692 	   case ADR_NzENTRIES: {
693                if (read_only_mode == READONLYoff)
694                {
695                    tOffset += ADR_NzENTRIES_OFFSET;
696                }
697                else
698                {
699                    *buffer = fp->ADRList[fp->CurADRIndex]->NzEntries;
700                };
701                break;
702            }
703 	   case ADR_MAXzENTRY: {
704                if (read_only_mode == READONLYoff)
705                {
706                    tOffset += ADR_MAXzENTRY_OFFSET;
707                }
708                else
709                {
710                    *buffer = fp->ADRList[fp->CurADRIndex]->MAXzEntry;
711                };
712                break;
713            }
714 	   default: return CDF_INTERNAL_ERROR;
715 	 }
716          if (read_only_mode == READONLYoff) {
717 	     if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
718 	     if (!Read32(fp,buffer)) return CRE;
719          };
720 	 break;
721        }
722      }
723   }
724 }
725 
726 /******************************************************************************
727 * ReadAEDR/AzEDR.
728 *   If the entry value is being read, it is passed back in the encoding of the
729 * CDF (no decoding is performed).  The caller must decode the value (if that
730 * is necessary).
731 ******************************************************************************/
732 
733 #if defined(STDARG)
ReadAEDR(vFILE * fp,Int32 offset,...)734 STATICforIDL CDFstatus ReadAEDR (vFILE *fp, Int32 offset, ...)
735 #else
736 STATICforIDL CDFstatus ReadAEDR (va_alist)
737 va_dcl
738 #endif
739 {
740   long read_only_mode;
741   struct AEDRstructExt *CurAEDR;
742   va_list ap; CDFstatus pStatus = CDF_OK;
743 #if defined(STDARG)
744   va_start (ap, offset);
745 #else
746   vFILE *fp; Int32 offset;
747   VA_START (ap);
748   fp = va_arg (ap, vFILE *);
749   offset = va_arg (ap, Int32);
750 #endif
751   pStatus = CDFlib(CONFIRM_, CDF_READONLY_MODE_, &read_only_mode, NULL_);
752   if (pStatus != CDF_OK) return pStatus;
753   /***************************************************************************
754   * If READONLYon and either an attribute or an entry have not been selected,
755   * return the appropriate status. If they have been selected but there is no
756   * entry for the selected attribute, return NO_SUCH_ENTRY.  Note that for each
757   * attribute, entries are stored in an array which is indexed by the entry's
758   * number and if the selected entry number does not exist for the seleceted
759   * attribute, the entry list has a NULL pointer for that entry. Note also that
760   * the reading of ADRs and AEDRs into memory is triggered by the 1st time an
761   * ADR (or AEDR) is selected.
762   ***************************************************************************/
763   if (read_only_mode == READONLYon)
764   {
765       if (fp->CurADRIndex == RESERVED_ENTRYNUM)
766       {
767           return NO_ATTR_SELECTED;
768       }
769       else if (fp->CurAEDRIndex == RESERVED_ENTRYNUM)
770       {
771           return NO_ENTRY_SELECTED;
772       }
773       else if (fp->CURzEntrySel)
774       {
775           if (fp->ADRList[fp->CurADRIndex]->zAEDRList[fp->CurAEDRIndex] != NULL)
776           {
777               CurAEDR =
778                       fp->ADRList[fp->CurADRIndex]->zAEDRList[fp->CurAEDRIndex];
779           }
780           else
781           {
782               return NO_SUCH_ENTRY;
783           };
784       }
785       else
786       {
787           if (fp->ADRList[fp->CurADRIndex]->grAEDRList[fp->CurAEDRIndex] !=
788               NULL)
789           {
790               CurAEDR =
791                      fp->ADRList[fp->CurADRIndex]->grAEDRList[fp->CurAEDRIndex];
792           }
793           else
794           {
795               return NO_SUCH_ENTRY;
796           };
797       };
798   };
799   /***************************************************************************
800   * For whatever AEDR data is selected, if READONLYon, read the data from memory
801   * using CurADRIndex and CurAEDRIndex to select the correct AEDR from the
802   * AEDRList. Otherwise, read the data from the file/cache using the file
803   * offset.
804   ***************************************************************************/
805   for (;;) {
806      int field = va_arg (ap, int);
807      switch (field) {
808        case AEDR_NULL:
809 	 va_end (ap);
810 	 return pStatus;
811        case AEDR_RECORD: {
812 	 struct AEDRstruct *AEDR = va_arg (ap, struct AEDRstruct *);
813 	 void *value = va_arg (ap, void *); size_t nBytes;
814          if (read_only_mode == READONLYoff)
815          {
816              if (!SEEKv(fp,(long)offset,vSEEK_SET)) return CRE;
817              if (!Read32(fp,&(AEDR->RecordSize))) return CRE;
818              if (!Read32(fp,&(AEDR->RecordType))) return CRE;
819              if (!Read32(fp,&(AEDR->AEDRnext))) return CRE;
820              if (!Read32(fp,&(AEDR->AttrNum))) return CRE;
821              if (!Read32(fp,&(AEDR->DataType))) return CRE;
822              if (!Read32(fp,&(AEDR->Num))) return CRE;
823              if (!Read32(fp,&(AEDR->NumElems))) return CRE;
824              if (!Read32(fp,&(AEDR->rfuA))) return CRE;
825              if (!Read32(fp,&(AEDR->rfuB))) return CRE;
826              if (!Read32(fp,&(AEDR->rfuC))) return CRE;
827              if (!Read32(fp,&(AEDR->rfuD))) return CRE;
828              if (!Read32(fp,&(AEDR->rfuE))) return CRE;
829              if (value != NULL) {
830                  nBytes = (size_t) (CDFelemSize(AEDR->DataType) *
831                           AEDR->NumElems);
832                  if (!READv(value,nBytes,1,fp)) return CRE;
833              };
834          }
835          else
836          {
837              AEDR->RecordSize = CurAEDR->AEDR.RecordSize;
838              AEDR->RecordType = CurAEDR->AEDR.RecordType;
839              AEDR->AEDRnext = CurAEDR->AEDR.AEDRnext;
840              AEDR->AttrNum = CurAEDR->AEDR.AttrNum;
841              AEDR->DataType = CurAEDR->AEDR.DataType;
842              AEDR->Num = CurAEDR->AEDR.Num;
843              AEDR->NumElems = CurAEDR->AEDR.NumElems;
844              AEDR->rfuA = CurAEDR->AEDR.rfuA;
845              AEDR->rfuB = CurAEDR->AEDR.rfuB;
846              AEDR->rfuC = CurAEDR->AEDR.rfuC;
847              AEDR->rfuD = CurAEDR->AEDR.rfuD;
848              AEDR->rfuE = CurAEDR->AEDR.rfuE;
849              if (value != NULL) {
850                  memcpy(value, CurAEDR->Value, CurAEDR->ValueSize);
851              };
852          };
853          break;
854        }
855        case AEDR_VALUE: {
856 	 void *value = va_arg (ap, void *);
857          if (read_only_mode == READONLYoff)
858          {
859 	     size_t nBytes; Int32 dataType, numElems; long tOffset;
860 	     if (!sX(ReadAEDR(fp,offset,
861                               AEDR_DATATYPE,&dataType,
862                               AEDR_NUMELEMS,&numElems,
863                               AEDR_NULL),&pStatus)) return pStatus;
864 	     tOffset = offset + AEDR_VALUE_OFFSET;
865 	     if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
866 	     nBytes = (size_t) (CDFelemSize(dataType) * numElems);
867 	     if (!READv(value,nBytes,1,fp)) return CRE;
868          }
869          else
870          {
871              memcpy(value, CurAEDR->Value, CurAEDR->ValueSize);
872          };
873 	 break;
874        }
875        default: {
876 	 Int32 *buffer = va_arg (ap, Int32 *); long tOffset = offset;
877 	 switch (field) {
878 	   case AEDR_RECORDSIZE: {
879                if (read_only_mode == READONLYoff)
880                {
881                    tOffset += AEDR_RECORDSIZE_OFFSET;
882                }
883                else
884                {
885                    *buffer = CurAEDR->AEDR.RecordSize;
886                };
887                break;
888            }
889 	   case AEDR_RECORDTYPE: {
890                if (read_only_mode == READONLYoff)
891                {
892                    tOffset += AEDR_RECORDTYPE_OFFSET;
893                }
894                else
895                {
896                    *buffer = CurAEDR->AEDR.RecordType;
897                };
898                break;
899            }
900 	   case AEDR_AEDRNEXT: {
901                if (read_only_mode == READONLYoff)
902                {
903                    tOffset += AEDR_AEDRNEXT_OFFSET;
904                }
905                else
906                {
907                    *buffer = CurAEDR->AEDR.AEDRnext;
908                };
909                break;
910            }
911 	   case AEDR_ATTRNUM: {
912                if (read_only_mode == READONLYoff)
913                {
914                    tOffset += AEDR_ATTRNUM_OFFSET;
915                }
916                else
917                {
918                    *buffer = CurAEDR->AEDR.AttrNum;
919                };
920                break;
921            }
922 	   case AEDR_DATATYPE: {
923                if (read_only_mode == READONLYoff)
924                {
925                    tOffset += AEDR_DATATYPE_OFFSET;
926                }
927                else
928                {
929                    *buffer = CurAEDR->AEDR.DataType;
930                };
931                break;
932            }
933 	   case AEDR_NUM: {
934                if (read_only_mode == READONLYoff)
935                {
936                    tOffset += AEDR_NUM_OFFSET;
937                }
938                else
939                {
940                    *buffer = CurAEDR->AEDR.Num;
941                };
942                break;
943            }
944 	   case AEDR_NUMELEMS: {
945                if (read_only_mode == READONLYoff)
946                {
947                    tOffset += AEDR_NUMELEMS_OFFSET;
948                }
949                else
950                {
951                    *buffer = CurAEDR->AEDR.NumElems;
952                };
953                break;
954            }
955 	   default: return CDF_INTERNAL_ERROR;
956 	 }
957          if (read_only_mode == READONLYoff)
958          {
959 	     if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
960 	     if (!Read32(fp,buffer)) return CRE;
961          };
962 	 break;
963        }
964      }
965   }
966 }
967 
968 /******************************************************************************
969 * ReadVDR/zVDR.
970 *   If the pad value is being read, it is passed back in the encoding of the
971 * CDF (no decoding is performed).  The caller must decode the value (if that
972 * is necessary).
973 *   If this CDF contains wasted space in its VDRs, note that the offset for
974 * those fields after the wasted space is adjusted.
975 ******************************************************************************/
976 
977 #if defined(STDARG)
ReadVDR(struct CDFstruct * CDF,vFILE * fp,Int32 offset,Logical zVar,...)978 STATICforIDL CDFstatus ReadVDR (struct CDFstruct *CDF, vFILE *fp,
979 				Int32 offset, Logical zVar, ...)
980 #else
981 STATICforIDL CDFstatus ReadVDR (va_alist)
982 va_dcl
983 #endif
984 {
985   va_list ap; CDFstatus pStatus = CDF_OK;
986 #if defined(STDARG)
987   va_start (ap, zVar);
988 #else
989   struct CDFstruct *CDF; vFILE *fp; Int32 offset; Logical zVar;
990   VA_START (ap);
991   CDF = va_arg (ap, struct CDFstruct *);
992   fp = va_arg (ap, vFILE *);
993   offset = va_arg (ap, Int32);
994   zVar = va_arg (ap, Logical);
995 #endif
996   for (;;) {
997      int field = va_arg (ap, int);
998      switch (field) {
999        case VDR_NULL:
1000 	 va_end (ap);
1001 	 return pStatus;
1002        case VDR_RECORD: {
1003 	 struct VDRstruct *VDR = va_arg (ap, struct VDRstruct *);
1004 	 void *padValue = va_arg (ap, void *); Int32 nDims;
1005 	 if (!SEEKv(fp,(long)offset,vSEEK_SET)) return CRE;
1006 	 if (!Read32(fp,&(VDR->RecordSize))) return CRE;
1007 	 if (!Read32(fp,&(VDR->RecordType))) return CRE;
1008 	 if (!Read32(fp,&(VDR->VDRnext))) return CRE;
1009 	 if (!Read32(fp,&(VDR->DataType))) return CRE;
1010 	 if (!Read32(fp,&(VDR->MaxRec))) return CRE;
1011 	 if (!Read32(fp,&(VDR->VXRhead))) return CRE;
1012 	 if (!Read32(fp,&(VDR->VXRtail))) return CRE;
1013 	 if (!Read32(fp,&(VDR->Flags))) return CRE;
1014 	 if (!Read32(fp,&(VDR->sRecords))) return CRE;
1015 	 if (!Read32(fp,&(VDR->rfuB))) return CRE;
1016 	 if (!Read32(fp,&(VDR->rfuC))) return CRE;
1017 	 if (!Read32(fp,&(VDR->rfuF))) return CRE;
1018 	 if (CDF->wastedSpace) {
1019 	   if (!SEEKv(fp,(long)VDR_WASTED_SIZE,vSEEK_CUR)) return CRE;
1020 	 }
1021 	 if (!Read32(fp,&(VDR->NumElems))) return CRE;
1022 	 if (!Read32(fp,&(VDR->Num))) return CRE;
1023 	 if (!Read32(fp,&(VDR->CPRorSPRoffset))) return CRE;
1024 	 if (!Read32(fp,&(VDR->blockingFactor))) return CRE;
1025 	 if (!READv(VDR->Name,CDF_VAR_NAME_LEN,1,fp)) return CRE;
1026 	 NulPad (VDR->Name, CDF_VAR_NAME_LEN);
1027 	 if (zVar) {
1028 	   if (!Read32(fp,&(VDR->zNumDims))) return CRE;
1029            if (VDR->zNumDims < 0 || VDR->zNumDims > CDF_MAX_DIMS)
1030              return CV2C;
1031 	   if (!Read32s(fp,VDR->zDimSizes,(int)VDR->zNumDims)) return CRE;
1032 	 }
1033 	 if (zVar)
1034 	   nDims = VDR->zNumDims;
1035 	 else {
1036 	   long tOffset = V_tell (fp); Int32 GDRoffset;
1037 	   if (!sX(ReadCDR(fp,V2_CDR_OFFSET,
1038 			   CDR_GDROFFSET,&GDRoffset,
1039 			   CDR_NULL),&pStatus)) return pStatus;
1040 	   if (!sX(ReadGDR(fp,GDRoffset,
1041 			   GDR_rNUMDIMS,&nDims,
1042 			   GDR_NULL),&pStatus)) return pStatus;
1043 	   if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
1044 	 }
1045          if (nDims < 0 || nDims > CDF_MAX_DIMS)
1046            return CV2C;
1047 	 if (!Read32s(fp,VDR->DimVarys,(int)nDims)) return CRE;
1048 	 if (PADvalueBITset(VDR->Flags) && padValue != NULL) {
1049 	   size_t nBytes = (size_t) (CDFelemSize(VDR->DataType)*VDR->NumElems);
1050 	   if (!READv(padValue,nBytes,1,fp)) return CRE;
1051 	 }
1052 	 break;
1053        }
1054        case VDR_NAME: {
1055 	 char *vName = va_arg (ap, char *);
1056 	 long tOffset = offset + VDR_NAME_OFFSET;
1057 	 if (CDF->wastedSpace) tOffset += VDR_WASTED_SIZE;
1058 	 if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
1059 	 if (!READv(vName,CDF_VAR_NAME_LEN,1,fp)) return CRE;
1060 	 NulPad (vName, CDF_VAR_NAME_LEN);
1061 	 break;
1062        }
1063        case VDR_zNUMDIMS: {
1064 	 Int32 *numDims = va_arg (ap, Int32 *);
1065 	 long tOffset = offset + zVDR_zNUMDIMS_OFFSET +
1066 			BOO(CDF->wastedSpace,VDR_WASTED_SIZE,0);
1067 	 if (!zVar) return CDF_INTERNAL_ERROR;
1068 	 if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
1069 	 if (!Read32(fp,numDims)) return CRE;
1070 	 break;
1071        }
1072        case VDR_zDIMSIZES: {
1073 	 Int32 *zDimSizes = va_arg (ap, Int32 *);
1074 	 Int32 zNumDims; long tOffset;
1075 	 if (!zVar) return CDF_INTERNAL_ERROR;
1076 	 if (!sX(ReadVDR(CDF,fp,offset,zVar,
1077 			 VDR_zNUMDIMS,&zNumDims,
1078 			 VDR_NULL),&pStatus)) return pStatus;
1079 	 tOffset = offset + zVDR_zDIMSIZES_OFFSET +
1080 		   BOO(CDF->wastedSpace,VDR_WASTED_SIZE,0);
1081 	 if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
1082          if (zNumDims < 0 || zNumDims > CDF_MAX_DIMS)
1083            return CV2C;
1084 	 if (!Read32s(fp,zDimSizes,(int)zNumDims)) return CRE;
1085 	 break;
1086        }
1087        case VDR_DIMVARYS: {
1088 	 Int32 *dimVarys = va_arg (ap, Int32 *);
1089 	 Int32 nDims; long tOffset;
1090 	 if (zVar) {
1091 	   if (!sX(ReadVDR(CDF,fp,offset,zVar,
1092 			   VDR_zNUMDIMS,&nDims,
1093 			   VDR_NULL),&pStatus)) return pStatus;
1094 	   tOffset = offset + zVDR_DIMVARYS_OFFSETb + (nDims*sizeof(Int32)) +
1095 		     BOO(CDF->wastedSpace,VDR_WASTED_SIZE,0);
1096 	 }
1097 	 else {
1098 	   Int32 GDRoffset;
1099 	   if (!sX(ReadCDR(fp,V2_CDR_OFFSET,
1100 			   CDR_GDROFFSET,&GDRoffset,
1101 			   CDR_NULL),&pStatus)) return pStatus;
1102 	   if (!sX(ReadGDR(fp,GDRoffset,
1103 			   GDR_rNUMDIMS,&nDims,
1104 			   GDR_NULL),&pStatus)) return pStatus;
1105 	   tOffset = offset + rVDR_DIMVARYS_OFFSET +
1106 		     BOO(CDF->wastedSpace,VDR_WASTED_SIZE,0);
1107 	 }
1108          if (nDims < 0 || nDims > CDF_MAX_DIMS)
1109            return CV2C;
1110 	 if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
1111 	 if (!Read32s(fp,dimVarys,(int)nDims)) return CRE;
1112 	 break;
1113        }
1114        case VDR_PADVALUE: {
1115 	 void *padValue = va_arg (ap, void *);
1116 	 Int32 dataType, numElems; size_t nBytes; long tOffset;
1117 	 if (!sX(ReadVDR(CDF,fp,offset,zVar,
1118 			 VDR_DATATYPE,&dataType,
1119 			 VDR_NUMELEMS,&numElems,
1120 			 VDR_NULL),&pStatus)) return pStatus;
1121 	 if (zVar) {
1122 	   Int32 zNumDims;
1123 	   if (!sX(ReadVDR(CDF,fp,offset,zVar,
1124 			   VDR_zNUMDIMS,&zNumDims,
1125 			   VDR_NULL),&pStatus)) return pStatus;
1126 	   tOffset = offset + zVDR_PADVALUE_OFFSETb +
1127 		     (zNumDims*sizeof(Int32)) +
1128 		     (zNumDims*sizeof(Int32)) +
1129 		     BOO(CDF->wastedSpace,VDR_WASTED_SIZE,0);
1130 	 }
1131 	 else {
1132 	   Int32 rNumDims, GDRoffset;
1133 	   if (!sX(ReadCDR(fp,V2_CDR_OFFSET,
1134 			   CDR_GDROFFSET,&GDRoffset,
1135 			   CDR_NULL),&pStatus)) return pStatus;
1136 	   if (!sX(ReadGDR(fp,GDRoffset,
1137 			   GDR_rNUMDIMS,&rNumDims,
1138 			   GDR_NULL),&pStatus)) return pStatus;
1139 	   tOffset = offset + rVDR_PADVALUE_OFFSETb +
1140 		     (rNumDims*sizeof(Int32)) +
1141 		     BOO(CDF->wastedSpace,VDR_WASTED_SIZE,0);
1142 	 }
1143 	 if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
1144 	 nBytes = (size_t) (CDFelemSize(dataType) * numElems);
1145 	 if (!READv(padValue,nBytes,1,fp)) return CRE;
1146 	 break;
1147        }
1148        default: {
1149 	 Int32 *buffer = va_arg (ap, Int32 *); long tOffset = offset;
1150 	 switch (field) {
1151 	   case VDR_RECORDSIZE: tOffset += VDR_RECORDSIZE_OFFSET; break;
1152 	   case VDR_RECORDTYPE: tOffset += VDR_RECORDTYPE_OFFSET; break;
1153 	   case VDR_VDRNEXT: tOffset += VDR_VDRNEXT_OFFSET; break;
1154 	   case VDR_DATATYPE: tOffset += VDR_DATATYPE_OFFSET; break;
1155 	   case VDR_MAXREC: tOffset += VDR_MAXREC_OFFSET; break;
1156 	   case VDR_VXRHEAD: tOffset += VDR_VXRHEAD_OFFSET; break;
1157 	   case VDR_VXRTAIL: tOffset += VDR_VXRTAIL_OFFSET; break;
1158 	   case VDR_FLAGS: tOffset += VDR_FLAGS_OFFSET; break;
1159 	   case VDR_sRECORDS: tOffset += VDR_sRECORDS_OFFSET; break;
1160 	   case VDR_NUMELEMS:
1161 	     tOffset += (VDR_NUMELEMS_OFFSET +
1162 			 BOO(CDF->wastedSpace,VDR_WASTED_SIZE,0));
1163 	     break;
1164 	   case VDR_NUM:
1165 	     tOffset += (VDR_NUM_OFFSET +
1166 			 BOO(CDF->wastedSpace,VDR_WASTED_SIZE,0));
1167 	     break;
1168 	   case VDR_CPRorSPR:
1169 	     tOffset += (VDR_CPRorSPR_OFFSET +
1170 			 BOO(CDF->wastedSpace,VDR_WASTED_SIZE,0));
1171 	     break;
1172 	   case VDR_BLOCKING:
1173 	     tOffset += (VDR_BLOCKING_OFFSET +
1174 			 BOO(CDF->wastedSpace,VDR_WASTED_SIZE,0));
1175 	     break;
1176 	   default: return CDF_INTERNAL_ERROR;
1177 	 }
1178 	 if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
1179 	 if (!Read32(fp,buffer)) return CRE;
1180 	 break;
1181        }
1182      }
1183   }
1184 }
1185 
1186 /******************************************************************************
1187 * ReadVXR.
1188 ******************************************************************************/
1189 
1190 #if defined(STDARG)
ReadVXR(vFILE * fp,Int32 offset,...)1191 VISIBLE_PREFIX CDFstatus ReadVXR (vFILE *fp, Int32 offset, ...)
1192 #else
1193 VISIBLE_PREFIX CDFstatus ReadVXR (va_alist)
1194 va_dcl
1195 #endif
1196 {
1197   va_list ap; CDFstatus pStatus = CDF_OK;
1198 #if defined(STDARG)
1199   va_start (ap, offset);
1200 #else
1201   vFILE *fp; Int32 offset;
1202   VA_START (ap);
1203   fp = va_arg (ap, vFILE *);
1204   offset = va_arg (ap, Int32);
1205 #endif
1206   for (;;) {
1207      int field = va_arg (ap, int);
1208      switch (field) {
1209        case VXR_NULL:
1210 	 va_end (ap);
1211 	 return pStatus;
1212        case VXR_RECORD: {
1213 	 struct VXRstruct *VXR = va_arg (ap, struct VXRstruct *);
1214 	 if (!SEEKv(fp,(long)offset,vSEEK_SET)) return CRE;
1215 	 if (!Read32(fp,&(VXR->RecordSize))) return CRE;
1216 	 if (!Read32(fp,&(VXR->RecordType))) return CRE;
1217 	 if (!Read32(fp,&(VXR->VXRnext))) return CRE;
1218 	 if (!Read32(fp,&(VXR->Nentries))) return CRE;
1219 	 if (!Read32(fp,&(VXR->NusedEntries))) return CRE;
1220          if (VXR->Nentries < 0 || VXR->Nentries > MAX_VXR_ENTRIES)
1221            return CV2C;
1222 	 if (!Read32s(fp,VXR->First,(int)VXR->Nentries)) return CRE;
1223 	 if (!Read32s(fp,VXR->Last,(int)VXR->Nentries)) return CRE;
1224 	 if (!Read32s(fp,VXR->Offset,(int)VXR->Nentries)) return CRE;
1225 	 break;
1226        }
1227        case VXR_FIRSTREC:
1228        case VXR_LASTREC:
1229        case VXR_OFFSET: {
1230 	 Int32 *buffer = va_arg (ap, Int32 *), nEntries;
1231 	 long tOffset = offset + VXR_FIRSTREC_OFFSET;
1232 	 if (!sX(ReadVXR(fp,offset,
1233 			 VXR_NENTRIES,&nEntries,
1234 			 VXR_NULL),&pStatus)) return pStatus;
1235 	 switch (field) {
1236 	   case VXR_FIRSTREC: break;
1237 	   case VXR_LASTREC: tOffset += nEntries * sizeof(Int32); break;
1238 	   case VXR_OFFSET: tOffset += 2 * nEntries * sizeof(Int32); break;
1239 	   default: return CDF_INTERNAL_ERROR;
1240 	 }
1241 	 if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
1242          if (nEntries < 0 || nEntries > MAX_VXR_ENTRIES)
1243            return CV2C;
1244 	 if (!Read32s(fp,buffer,(int)nEntries)) return CRE;
1245 	 break;
1246        }
1247        default: {
1248 	 Int32 *buffer = va_arg (ap, Int32 *); long tOffset = offset;
1249 	 switch (field) {
1250 	   case VXR_RECORDSIZE: tOffset += VXR_RECORDSIZE_OFFSET; break;
1251 	   case VXR_RECORDTYPE: tOffset += VXR_RECORDTYPE_OFFSET; break;
1252 	   case VXR_VXRNEXT: tOffset += VXR_VXRNEXT_OFFSET; break;
1253 	   case VXR_NENTRIES: tOffset += VXR_NENTRIES_OFFSET; break;
1254 	   case VXR_NUSEDENTRIES: tOffset += VXR_NUSEDENTRIES_OFFSET; break;
1255 	   default: return CDF_INTERNAL_ERROR;
1256 	 }
1257 	 if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
1258 	 if (!Read32(fp,buffer)) return CRE;
1259 	 break;
1260        }
1261      }
1262   }
1263 }
1264 
1265 /******************************************************************************
1266 * ReadVVR.
1267 ******************************************************************************/
1268 
1269 #if defined(STDARG)
ReadVVR(vFILE * fp,Int32 offset,...)1270 STATICforIDL CDFstatus ReadVVR (vFILE *fp, Int32 offset, ...)
1271 #else
1272 STATICforIDL CDFstatus ReadVVR (va_alist)
1273 va_dcl
1274 #endif
1275 {
1276   va_list ap; CDFstatus pStatus = CDF_OK;
1277 #if defined(STDARG)
1278   va_start (ap, offset);
1279 #else
1280   vFILE *fp; Int32 offset;
1281   VA_START (ap);
1282   fp = va_arg (ap, vFILE *);
1283   offset = va_arg (ap, Int32);
1284 #endif
1285   for (;;) {
1286      int field = va_arg (ap, int);
1287      switch (field) {
1288        case VVR_NULL:
1289 	 va_end (ap);
1290 	 return pStatus;
1291        case VVR_RECORDx: {
1292 	 struct VVRstruct *VVR = va_arg (ap, struct VVRstruct *);
1293 	 if (!SEEKv(fp,(long)offset,vSEEK_SET)) return CRE;
1294 	 if (!Read32(fp,&(VVR->RecordSize))) return CRE;
1295 	 if (!Read32(fp,&(VVR->RecordType))) return CRE;
1296 	 break;
1297        }
1298        default: {
1299 	 Int32 *buffer = va_arg (ap, Int32 *); long tOffset = offset;
1300 	 switch (field) {
1301 	   case VVR_RECORDSIZE: tOffset += VVR_RECORDSIZE_OFFSET; break;
1302 	   case VVR_RECORDTYPE: tOffset += VVR_RECORDTYPE_OFFSET; break;
1303 	   default: return CDF_INTERNAL_ERROR;
1304 	 }
1305 	 if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
1306 	 if (!Read32(fp,buffer)) return CRE;
1307 	 break;
1308        }
1309      }
1310   }
1311 }
1312 
1313 /******************************************************************************
1314 * ReadUIR.
1315 ******************************************************************************/
1316 
1317 #if defined(STDARG)
ReadUIR(vFILE * fp,Int32 offset,...)1318 STATICforIDL CDFstatus ReadUIR (vFILE *fp, Int32 offset, ...)
1319 #else
1320 STATICforIDL CDFstatus ReadUIR (va_alist)
1321 va_dcl
1322 #endif
1323 {
1324   va_list ap; CDFstatus pStatus = CDF_OK;
1325 #if defined(STDARG)
1326   va_start (ap, offset);
1327 #else
1328   vFILE *fp; Int32 offset;
1329   VA_START (ap);
1330   fp = va_arg (ap, vFILE *);
1331   offset = va_arg (ap, Int32);
1332 #endif
1333   for (;;) {
1334      int field = va_arg (ap, int);
1335      switch (field) {
1336        case UIR_NULL:
1337 	 va_end (ap);
1338 	 return pStatus;
1339        case UIR_RECORD: {
1340 	 struct UIRstruct *UIR = va_arg (ap, struct UIRstruct *);
1341 	 if (!SEEKv(fp,(long)offset,vSEEK_SET)) return CRE;
1342 	 if (!Read32(fp,&(UIR->RecordSize))) return CRE;
1343 	 if (!Read32(fp,&(UIR->RecordType))) return CRE;
1344 	 if (!Read32(fp,&(UIR->NextUIR))) return CRE;
1345 	 if (!Read32(fp,&(UIR->PrevUIR))) return CRE;
1346 	 break;
1347        }
1348        default: {
1349 	 Int32 *buffer = va_arg (ap, Int32 *); long tOffset = offset;
1350 	 switch (field) {
1351 	   case UIR_RECORDSIZE: tOffset += UIR_RECORDSIZE_OFFSET; break;
1352 	   case UIR_RECORDTYPE: tOffset += UIR_RECORDTYPE_OFFSET; break;
1353 	   case UIR_NEXTUIR: tOffset += UIR_NEXTUIR_OFFSET; break;
1354 	   case UIR_PREVUIR: tOffset += UIR_PREVUIR_OFFSET; break;
1355 	   default: return CDF_INTERNAL_ERROR;
1356 	 }
1357 	 if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
1358 	 if (!Read32(fp,buffer)) return CRE;
1359 	 break;
1360        }
1361      }
1362   }
1363 }
1364 
1365 /******************************************************************************
1366 * ReadCCR.
1367 ******************************************************************************/
1368 
1369 #if defined(STDARG)
ReadCCR(vFILE * fp,Int32 offset,...)1370 STATICforIDL CDFstatus ReadCCR (vFILE *fp, Int32 offset, ...)
1371 #else
1372 STATICforIDL CDFstatus ReadCCR (va_alist)
1373 va_dcl
1374 #endif
1375 {
1376   va_list ap; CDFstatus pStatus = CDF_OK;
1377 #if defined(STDARG)
1378   va_start (ap, offset);
1379 #else
1380   vFILE *fp; Int32 offset;
1381   VA_START (ap);
1382   fp = va_arg (ap, vFILE *);
1383   offset = va_arg (ap, Int32);
1384 #endif
1385   for (;;) {
1386      int field = va_arg (ap, int);
1387      switch (field) {
1388        case CCR_NULL:
1389 	 va_end (ap);
1390 	 return pStatus;
1391        case CCR_RECORD: {
1392 	 struct CCRstruct *CCR = va_arg (ap, struct CCRstruct *);
1393 	 if (!SEEKv(fp,(long)offset,vSEEK_SET)) return CRE;
1394 	 if (!Read32(fp,&(CCR->RecordSize))) return CRE;
1395 	 if (!Read32(fp,&(CCR->RecordType))) return CRE;
1396 	 if (!Read32(fp,&(CCR->CPRoffset))) return CRE;
1397 	 if (!Read32(fp,&(CCR->uSize))) return CRE;
1398 	 if (!Read32(fp,&(CCR->rfuA))) return CRE;
1399 	 break;
1400        }
1401        default: {
1402 	 Int32 *buffer = va_arg (ap, Int32 *); long tOffset = offset;
1403 	 switch (field) {
1404 	   case CCR_RECORDSIZE: tOffset += CCR_RECORDSIZE_OFFSET; break;
1405 	   case CCR_RECORDTYPE: tOffset += CCR_RECORDTYPE_OFFSET; break;
1406 	   case CCR_CPROFFSET: tOffset += CCR_CPROFFSET_OFFSET; break;
1407 	   case CCR_USIZE: tOffset += CCR_USIZE_OFFSET; break;
1408 	   case CCR_RFUa: tOffset += CCR_RFUa_OFFSET; break;
1409 	   default: return CDF_INTERNAL_ERROR;
1410 	 }
1411 	 if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
1412 	 if (!Read32(fp,buffer)) return CRE;
1413 	 break;
1414        }
1415      }
1416   }
1417 }
1418 
1419 /******************************************************************************
1420 * ReadCPR.
1421 ******************************************************************************/
1422 
1423 #if defined(STDARG)
ReadCPR(vFILE * fp,Int32 offset,...)1424 STATICforIDL CDFstatus ReadCPR (vFILE *fp, Int32 offset, ...)
1425 #else
1426 STATICforIDL CDFstatus ReadCPR (va_alist)
1427 va_dcl
1428 #endif
1429 {
1430   va_list ap; CDFstatus pStatus = CDF_OK;
1431 #if defined(STDARG)
1432   va_start (ap, offset);
1433 #else
1434   vFILE *fp; Int32 offset;
1435   VA_START (ap);
1436   fp = va_arg (ap, vFILE *);
1437   offset = va_arg (ap, Int32);
1438 #endif
1439   for (;;) {
1440      int field = va_arg (ap, int);
1441      switch (field) {
1442        case CPR_NULL:
1443 	 va_end (ap);
1444 	 return pStatus;
1445        case CPR_RECORD: {
1446 	 struct CPRstruct *CPR = va_arg (ap, struct CPRstruct *); int i;
1447 	 if (!SEEKv(fp,(long)offset,vSEEK_SET)) return CRE;
1448 	 if (!Read32(fp,&(CPR->RecordSize))) return CRE;
1449 	 if (!Read32(fp,&(CPR->RecordType))) return CRE;
1450 	 if (!Read32(fp,&(CPR->cType))) return CRE;
1451 	 if (!Read32(fp,&(CPR->rfuA))) return CRE;
1452 	 if (!Read32(fp,&(CPR->pCount))) return CRE;
1453 	 if (CPR->pCount > CDF_MAX_PARMS) return TOO_MANY_PARMS;
1454 	 for (i = 0; i < CPR->pCount; i++) {
1455 	    if (!Read32(fp,&(CPR->cParms[i]))) return CRE;
1456 	 }
1457 	 break;
1458        }
1459        default: {
1460 	 Int32 *buffer = va_arg (ap, Int32 *); long tOffset = offset;
1461 	 switch (field) {
1462 	   case CPR_RECORDSIZE: tOffset += CPR_RECORDSIZE_OFFSET; break;
1463 	   case CPR_RECORDTYPE: tOffset += CPR_RECORDTYPE_OFFSET; break;
1464 	   case CPR_CTYPE: tOffset += CPR_CTYPE_OFFSET; break;
1465 	   case CPR_RFUa: tOffset += CPR_RFUa_OFFSET; break;
1466 	   case CPR_PCOUNT: tOffset += CPR_PCOUNT_OFFSET; break;
1467 	   case CPR_CPARM1: tOffset += CPR_CPARM1_OFFSET; break;
1468 	   case CPR_CPARM2: tOffset += CPR_CPARM2_OFFSET; break;
1469 	   case CPR_CPARM3: tOffset += CPR_CPARM3_OFFSET; break;
1470 	   case CPR_CPARM4: tOffset += CPR_CPARM4_OFFSET; break;
1471 	   case CPR_CPARM5: tOffset += CPR_CPARM5_OFFSET; break;
1472 	   default: return CDF_INTERNAL_ERROR;
1473 	 }
1474 	 if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
1475 	 if (!Read32(fp,buffer)) return CRE;
1476 	 break;
1477        }
1478      }
1479   }
1480 }
1481 
1482 /******************************************************************************
1483 * ReadSPR.
1484 ******************************************************************************/
1485 
1486 #if defined(STDARG)
ReadSPR(vFILE * fp,Int32 offset,...)1487 STATICforIDL CDFstatus ReadSPR (vFILE *fp, Int32 offset, ...)
1488 #else
1489 STATICforIDL CDFstatus ReadSPR (va_alist)
1490 va_dcl
1491 #endif
1492 {
1493   va_list ap; CDFstatus pStatus = CDF_OK;
1494 #if defined(STDARG)
1495   va_start (ap, offset);
1496 #else
1497   vFILE *fp; Int32 offset;
1498   VA_START (ap);
1499   fp = va_arg (ap, vFILE *);
1500   offset = va_arg (ap, Int32);
1501 #endif
1502   for (;;) {
1503      int field = va_arg (ap, int);
1504      switch (field) {
1505        case SPR_NULL:
1506 	 va_end (ap);
1507 	 return pStatus;
1508        case SPR_RECORD: {
1509 	 struct SPRstruct *SPR = va_arg (ap, struct SPRstruct *); int i;
1510 	 if (!SEEKv(fp,(long)offset,vSEEK_SET)) return CRE;
1511 	 if (!Read32(fp,&(SPR->RecordSize))) return CRE;
1512 	 if (!Read32(fp,&(SPR->RecordType))) return CRE;
1513 	 if (!Read32(fp,&(SPR->sArraysType))) return CRE;
1514 	 if (!Read32(fp,&(SPR->rfuA))) return CRE;
1515 	 if (!Read32(fp,&(SPR->pCount))) return CRE;
1516 	 if (SPR->pCount > CDF_MAX_PARMS) return TOO_MANY_PARMS;
1517 	 for (i = 0; i < SPR->pCount; i++) {
1518 	    if (!Read32(fp,&(SPR->sArraysParms[i]))) return CRE;
1519 	 }
1520 	 break;
1521        }
1522        default: {
1523 	 Int32 *buffer = va_arg (ap, Int32 *); long tOffset = offset;
1524 	 switch (field) {
1525 	   case SPR_RECORDSIZE: tOffset += SPR_RECORDSIZE_OFFSET; break;
1526 	   case SPR_RECORDTYPE: tOffset += SPR_RECORDTYPE_OFFSET; break;
1527 	   case SPR_STYPE: tOffset += SPR_STYPE_OFFSET; break;
1528 	   case SPR_RFUa: tOffset += SPR_RFUa_OFFSET; break;
1529 	   case SPR_PCOUNT: tOffset += SPR_PCOUNT_OFFSET; break;
1530 	   case SPR_SPARM1: tOffset += SPR_SPARM1_OFFSET; break;
1531 	   case SPR_SPARM2: tOffset += SPR_SPARM2_OFFSET; break;
1532 	   case SPR_SPARM3: tOffset += SPR_SPARM3_OFFSET; break;
1533 	   case SPR_SPARM4: tOffset += SPR_SPARM4_OFFSET; break;
1534 	   case SPR_SPARM5: tOffset += SPR_SPARM5_OFFSET; break;
1535 	   default: return CDF_INTERNAL_ERROR;
1536 	 }
1537 	 if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
1538 	 if (!Read32(fp,buffer)) return CRE;
1539 	 break;
1540        }
1541      }
1542   }
1543 }
1544 
1545 /******************************************************************************
1546 * ReadCVVR.
1547 ******************************************************************************/
1548 
1549 #if defined(STDARG)
ReadCVVR(vFILE * fp,Int32 offset,...)1550 STATICforIDL CDFstatus ReadCVVR (vFILE *fp, Int32 offset, ...)
1551 #else
1552 STATICforIDL CDFstatus ReadCVVR (va_alist)
1553 va_dcl
1554 #endif
1555 {
1556   va_list ap; CDFstatus pStatus = CDF_OK;
1557 #if defined(STDARG)
1558   va_start (ap, offset);
1559 #else
1560   vFILE *fp; Int32 offset;
1561   VA_START (ap);
1562   fp = va_arg (ap, vFILE *);
1563   offset = va_arg (ap, Int32);
1564 #endif
1565   for (;;) {
1566      int field = va_arg (ap, int);
1567      switch (field) {
1568        case CVVR_NULL:
1569 	 va_end (ap);
1570 	 return pStatus;
1571        case CVVR_RECORDx: {
1572 	 struct CVVRstruct *CVVR = va_arg (ap, struct CVVRstruct *);
1573 	 if (!SEEKv(fp,(long)offset,vSEEK_SET)) return CRE;
1574 	 if (!Read32(fp,&(CVVR->RecordSize))) return CRE;
1575 	 if (!Read32(fp,&(CVVR->RecordType))) return CRE;
1576 	 if (!Read32(fp,&(CVVR->rfuA))) return CRE;
1577 	 if (!Read32(fp,&(CVVR->cSize))) return CRE;
1578 	 break;
1579        }
1580        default: {
1581 	 Int32 *buffer = va_arg (ap, Int32 *); long tOffset = offset;
1582 	 switch (field) {
1583 	   case CVVR_RECORDSIZE: tOffset += CVVR_RECORDSIZE_OFFSET; break;
1584 	   case CVVR_RECORDTYPE: tOffset += CVVR_RECORDTYPE_OFFSET; break;
1585 	   case CVVR_RFUa: tOffset += CVVR_RFUa_OFFSET; break;
1586 	   case CVVR_CSIZE: tOffset += CVVR_CSIZE_OFFSET; break;
1587 	   default: return CDF_INTERNAL_ERROR;
1588 	 }
1589 	 if (!SEEKv(fp,tOffset,vSEEK_SET)) return CRE;
1590 	 if (!Read32(fp,buffer)) return CRE;
1591 	 break;
1592        }
1593      }
1594   }
1595 }
1596 
1597 /******************************************************************************
1598 * ReadADRList.
1599 * Reads metadata into memory for future reference in READONLYon mode.
1600 ******************************************************************************/
1601 
ReadADRList(vFILE * fp)1602 STATICforIDL CDFstatus ReadADRList (vFILE *fp)
1603 {
1604   Int32 nxtADR = fp->GDR->ADRhead;
1605   CDFstatus pStatus = CDF_OK;
1606   Int32 i;
1607 
1608   /**************************************************************************
1609   * Allocate memory for the list of ADRs
1610   ***************************************************************************/
1611   if (fp->GDR->NumAttr > 0)
1612   fp->ADRList = cdf_AllocateMemory(fp->GDR->NumAttr *
1613                                    sizeof(struct ADRstruct**), NULL);
1614   if (fp->GDR->NumAttr > 0 && fp->ADRList == NULL) return BAD_MALLOC;
1615   for (i = 0; i < fp->GDR->NumAttr; i++)
1616   {
1617       fp->ADRList[i] = cdf_AllocateMemory(sizeof(struct ADRstruct), NULL);
1618       if (fp->ADRList[i] == NULL) return BAD_MALLOC;
1619   };
1620   /***************************************************************************
1621   * Read the ADRs into the list
1622   ****************************************************************************/
1623   for (i = 0; i < fp->GDR->NumAttr; i++)
1624   {
1625       if (!SEEKv(fp,nxtADR,vSEEK_SET)) return CRE;
1626       if (!Read32(fp, &(fp->ADRList[i]->RecordSize))) return CRE;
1627       if (!Read32(fp,&(fp->ADRList[i]->RecordType))) return CRE;
1628       if (!Read32(fp,&nxtADR)) return CRE;
1629       fp->ADRList[i]->ADRnext = 0;
1630       if (!Read32(fp,&(fp->ADRList[i]->AgrEDRhead))) return CRE;
1631       if (!Read32(fp,&(fp->ADRList[i]->Scope))) return CRE;
1632       if (!Read32(fp,&(fp->ADRList[i]->Num))) return CRE;
1633       if (!Read32(fp,&(fp->ADRList[i]->NgrEntries))) return CRE;
1634       if (!Read32(fp,&(fp->ADRList[i]->MAXgrEntry))) return CRE;
1635       if (!Read32(fp,&(fp->ADRList[i]->rfuA))) return CRE;
1636       if (!Read32(fp,&(fp->ADRList[i]->AzEDRhead))) return CRE;
1637       if (!Read32(fp,&(fp->ADRList[i]->NzEntries))) return CRE;
1638       if (!Read32(fp,&(fp->ADRList[i]->MAXzEntry))) return CRE;
1639       if (!Read32(fp,&(fp->ADRList[i]->rfuE))) return CRE;
1640       if (!READv(fp->ADRList[i]->Name,CDF_ATTR_NAME_LEN,1,fp))
1641         return CRE;
1642       NulPad (fp->ADRList[i]->Name, CDF_ATTR_NAME_LEN);
1643       /***********************************************************************
1644       * Allocate memory for the lists of gAEDRs and zAEDRS associated with
1645       * this ADR and read the AEDRs into the lists.
1646       ***********************************************************************/
1647       pStatus = ReadAEDRList(fp, &(fp->ADRList[i]->grAEDRList),
1648                              fp->ADRList[i]->AgrEDRhead,
1649                              fp->ADRList[i]->NgrEntries,
1650                              fp->ADRList[i]->MAXgrEntry);
1651       if (pStatus != CDF_OK) return pStatus;
1652       pStatus = ReadAEDRList(fp, &(fp->ADRList[i]->zAEDRList),
1653                              fp->ADRList[i]->AzEDRhead,
1654                              fp->ADRList[i]->NzEntries,
1655                              fp->ADRList[i]->MAXzEntry);
1656       if (pStatus != CDF_OK) return pStatus;
1657   };
1658   return pStatus;
1659 }
1660 
1661 /******************************************************************************
1662 * ReadAEDRList.
1663 * Reads the set of entrys (zENTRYs or grENTRYs) associated with an attribute
1664 * into a list indexed by the entry number. If there is no entry for a particular
1665 * index (i.e., there is no entry for the associated variable/attribute
1666 * pair), the list entry is NULL.
1667 ******************************************************************************/
ReadAEDRList(vFILE * fp,struct AEDRstructExt *** AEDRList,Int32 AEDRHead,Int32 NumEntries,Int32 MaxEntry)1668 STATICforIDL CDFstatus ReadAEDRList (vFILE *fp,
1669                                      struct AEDRstructExt ***AEDRList,
1670                                      Int32 AEDRHead,
1671                                      Int32 NumEntries,
1672                                      Int32 MaxEntry)
1673 {
1674   CDFstatus pStatus = CDF_OK;
1675   Int32 NxtAEDR = AEDRHead;
1676   struct AEDRstructExt *TempAEDR;
1677   int iEntries;
1678   int i;
1679   /**************************************************************************
1680   * Allocate memory for the list and initialize each entry to NULL.
1681   **************************************************************************/
1682   if (MaxEntry >= 0) {
1683       *AEDRList = cdf_AllocateMemory((MaxEntry + 1) *
1684                                      sizeof(struct AEDRstructExt**), NULL);
1685       if (*AEDRList == NULL) return BAD_MALLOC;
1686   }
1687   else
1688   {
1689       *AEDRList = NULL;
1690       return pStatus;
1691   };
1692 
1693   for (i = 0; i <= MaxEntry; i++)
1694   {
1695       (*AEDRList)[i] = NULL;
1696   };
1697   iEntries = 0;
1698   /***************************************************************************
1699   * Allocate memory for each AEDR, read each AEDR, and assign them to the list
1700   * by entry number.
1701   ***************************************************************************/
1702   while (NxtAEDR != 0 && iEntries != NumEntries)
1703   {
1704       TempAEDR = cdf_AllocateMemory(sizeof(struct AEDRstructExt), NULL);
1705       if (TempAEDR == NULL) return BAD_MALLOC;
1706       if (!SEEKv(fp,NxtAEDR,vSEEK_SET)) return CRE;
1707       if (!Read32(fp,&(TempAEDR->AEDR.RecordSize))) return CRE;
1708       if (!Read32(fp,&(TempAEDR->AEDR.RecordType))) return CRE;
1709       if (!Read32(fp,&NxtAEDR)) return CRE;
1710       TempAEDR->AEDR.AEDRnext = 0;
1711       if (!Read32(fp,&(TempAEDR->AEDR.AttrNum))) return CRE;
1712       if (!Read32(fp,&(TempAEDR->AEDR.DataType))) return CRE;
1713       if (!Read32(fp,&(TempAEDR->AEDR.Num))) return CRE;
1714       if (!Read32(fp,&(TempAEDR->AEDR.NumElems))) return CRE;
1715       if (!Read32(fp,&(TempAEDR->AEDR.rfuA))) return CRE;
1716       if (!Read32(fp,&(TempAEDR->AEDR.rfuB))) return CRE;
1717       if (!Read32(fp,&(TempAEDR->AEDR.rfuC))) return CRE;
1718       if (!Read32(fp,&(TempAEDR->AEDR.rfuD))) return CRE;
1719       if (!Read32(fp,&(TempAEDR->AEDR.rfuE))) return CRE;
1720       TempAEDR->ValueSize = (CDFelemSize(TempAEDR->AEDR.DataType) *
1721                              TempAEDR->AEDR.NumElems);
1722       if (TempAEDR->ValueSize < 1) return CV2C;
1723       TempAEDR->Value = cdf_AllocateMemory(TempAEDR->ValueSize, NULL);
1724       if (TempAEDR->Value == NULL) return BAD_MALLOC;
1725       if (!READv(TempAEDR->Value,TempAEDR->ValueSize,1,fp)) return CRE;
1726       ++iEntries;
1727       if (TempAEDR->AEDR.Num < 0 || TempAEDR->AEDR.Num > MaxEntry)
1728         return CV2C;
1729       (*AEDRList)[TempAEDR->AEDR.Num] = TempAEDR;
1730   };
1731   return pStatus;
1732 }
1733 
1734