/* * Read just the numrecs member. * (A relatively expensive way to do things.) */ int read_numrecs(NC *ncp) { int status = NC_NOERR; const void *xp = NULL; size_t nrecs = NC_get_numrecs(ncp); assert(!NC_indef(ncp)); #define NC_NUMRECS_OFFSET 4 #define NC_NUMRECS_EXTENT 4 status = ncp->nciop->get(ncp->nciop, NC_NUMRECS_OFFSET, NC_NUMRECS_EXTENT, 0, (void **)&xp); /* cast away const */ if(status != NC_NOERR) return status; status = ncx_get_size_t(&xp, &nrecs); (void) ncp->nciop->rel(ncp->nciop, NC_NUMRECS_OFFSET, 0); if(status == NC_NOERR) { NC_set_numrecs(ncp, nrecs); fClr(ncp->flags, NC_NDIRTY); } return status; }
/* Read a size_t from the header */ static int v1h_get_size_t(v1hs *gsp, size_t *sp) { int status = check_v1hs(gsp, X_SIZEOF_SIZE_T); if(status != ENOERR) return status; return ncx_get_size_t((const void **)(&gsp->pos), sp); }
/* Read a size_t from the header */ static int v1h_get_size_t(v1hs *gsp, size_t *sp) { int status; if (gsp->version == 5) /* all integers in CDF-5 are 64 bits */ status = check_v1hs(gsp, X_SIZEOF_INT64); else status = check_v1hs(gsp, X_SIZEOF_SIZE_T); if(status != ENOERR) return status; if (gsp->version == 5) { long long tmp=0; status = ncx_get_int64((const void **)(&gsp->pos), &tmp); *sp = (size_t)tmp; return status; } else return ncx_get_size_t((const void **)(&gsp->pos), sp); }
/* Make the in-memory NC structure from reading the file header */ int nc_get_NC(NC3_INFO* ncp) { int status; v1hs gs; /* the get stream */ assert(ncp != NULL); /* Initialize stream gs */ gs.nciop = ncp->nciop; gs.offset = 0; /* beginning of file */ gs.extent = 0; gs.flags = 0; gs.version = 0; gs.base = NULL; gs.pos = gs.base; { /* * Come up with a reasonable stream read size. */ off_t filesize; size_t extent = ncp->xsz; if(extent <= ((fIsSet(ncp->flags, NC_64BIT_DATA))?MIN_NC5_XSZ:MIN_NC3_XSZ)) { status = ncio_filesize(ncp->nciop, &filesize); if(status) return status; if(filesize < sizeof(ncmagic)) { /* too small, not netcdf */ status = NC_ENOTNC; return status; } /* first time read */ extent = ncp->chunk; /* Protection for when ncp->chunk is huge; * no need to read hugely. */ if(extent > 4096) extent = 4096; if(extent > filesize) extent = filesize; } else if(extent > ncp->chunk) extent = ncp->chunk; /* * Invalidate the I/O buffers to force a read of the header * region. */ status = ncio_sync(gs.nciop); if(status) return status; status = fault_v1hs(&gs, extent); if(status) return status; } /* get the header from the stream gs */ { /* Get & check magic number */ schar magic[sizeof(ncmagic)]; (void) memset(magic, 0, sizeof(magic)); status = ncx_getn_schar_schar( (const void **)(&gs.pos), sizeof(magic), magic); if(status != ENOERR) goto unwind_get; if(memcmp(magic, ncmagic, sizeof(ncmagic)-1) != 0) { status = NC_ENOTNC; goto unwind_get; } /* Check version number in last byte of magic */ if (magic[sizeof(ncmagic)-1] == 0x1) { gs.version = 1; } else if (magic[sizeof(ncmagic)-1] == 0x2) { gs.version = 2; fSet(ncp->flags, NC_64BIT_OFFSET); /* Now we support version 2 file access on non-LFS systems -- rkr */ #if 0 if (sizeof(off_t) != 8) { fprintf(stderr, "NETCDF WARNING: Version 2 file on 32-bit system.\n"); } #endif } else if (magic[sizeof(ncmagic)-1] == 0x5) { gs.version = 5; fSet(ncp->flags, NC_64BIT_DATA); } else { status = NC_ENOTNC; goto unwind_get; } } { size_t nrecs = 0; if (gs.version == 5) { long long tmp = 0; status = ncx_get_int64((const void **)(&gs.pos), &tmp); nrecs = (size_t)tmp; } else status = ncx_get_size_t((const void **)(&gs.pos), &nrecs); if(status != ENOERR) goto unwind_get; NC_set_numrecs(ncp, nrecs); } assert((char *)gs.pos < (char *)gs.end); status = v1h_get_NC_dimarray(&gs, &ncp->dims); if(status != ENOERR) goto unwind_get; status = v1h_get_NC_attrarray(&gs, &ncp->attrs); if(status != ENOERR) goto unwind_get; status = v1h_get_NC_vararray(&gs, &ncp->vars); if(status != ENOERR) goto unwind_get; ncp->xsz = ncx_len_NC(ncp, (gs.version == 1) ? 4 : 8); status = NC_computeshapes(ncp); if(status != ENOERR) goto unwind_get; unwind_get: (void) rel_v1hs(&gs); return status; }