/* * Allocate a NC_string structure large enough * to hold slen characters. * Formerly NC_new_string(count, str) */ NC_string * new_NC_string(size_t slen, const char *str) { NC_string *ncstrp; size_t sz = M_RNDUP(sizeof(NC_string)) + slen + 1; #if 0 sz = _RNDUP(sz, X_ALIGN); #endif ncstrp = (NC_string *)malloc(sz); if( ncstrp == NULL ) return NULL; (void) memset(ncstrp, 0, sz); ncstrp->nchars = sz - M_RNDUP(sizeof(NC_string)) - 1; assert(ncstrp->nchars + 1 > slen); ncstrp->cp = (char *)ncstrp + M_RNDUP(sizeof(NC_string)); if(str != NULL && *str != 0) { (void) strncpy(ncstrp->cp, str, ncstrp->nchars +1); ncstrp->cp[ncstrp->nchars] = 0; } return(ncstrp); }
long long foo (foo_t *const pxp, long long offset, unsigned int extent) { long long blkoffset = _RNDDOWN(offset, (long long )pxp->blksz); unsigned int diff = (unsigned int)(offset - blkoffset); unsigned int blkextent = _RNDUP(diff + extent, pxp->blksz); if (pxp->blksz < blkextent) return -1LL; if (pxp->bf_cnt > pxp->blksz) pxp->bf_cnt = pxp->blksz; return blkoffset; }
/* * How much space will the xdr'd string take. * Formerly NC_xlen_string(cdfstr) */ static size_t ncx_len_NC_string(const NC_string *ncstrp, int version) { size_t sz = (version == 5) ? X_SIZEOF_INT64 : X_SIZEOF_INT; /* nchars */ assert(ncstrp != NULL); if(ncstrp->nchars != 0) { #if 0 assert(ncstrp->nchars % X_ALIGN == 0); sz += ncstrp->nchars; #else sz += _RNDUP(ncstrp->nchars, X_ALIGN); #endif } return sz; }
/* * How much space will the xdr'd string take. * Formerly NC_xlen_string(cdfstr) */ static size_t ncx_len_NC_string(const NC_string *ncstrp) { size_t sz = X_SIZEOF_SIZE_T; /* nchars */ assert(ncstrp != NULL); if(ncstrp->nchars != 0) { #if 0 assert(ncstrp->nchars % X_ALIGN == 0); sz += ncstrp->nchars; #else sz += _RNDUP(ncstrp->nchars, X_ALIGN); #endif } return sz; }
/* Read a NC_string from the header */ static int v1h_get_NC_string(v1hs *gsp, NC_string **ncstrpp) { int status; size_t nchars = 0; NC_string *ncstrp; status = v1h_get_size_t(gsp, &nchars); if(status != ENOERR) return status; ncstrp = new_NC_string(nchars, NULL); if(ncstrp == NULL) { return NC_ENOMEM; } #if 0 /* assert(ncstrp->nchars == nchars || ncstrp->nchars - nchars < X_ALIGN); */ assert(ncstrp->nchars % X_ALIGN == 0); status = check_v1hs(gsp, ncstrp->nchars); #else status = check_v1hs(gsp, _RNDUP(ncstrp->nchars, X_ALIGN)); #endif if(status != ENOERR) goto unwind_alloc; status = ncx_pad_getn_text((const void **)(&gsp->pos), nchars, ncstrp->cp); if(status != ENOERR) goto unwind_alloc; *ncstrpp = ncstrp; return ENOERR; unwind_alloc: free_NC_string(ncstrp); return status; }
/* Write a NC_string to the header */ static int v1h_put_NC_string(v1hs *psp, const NC_string *ncstrp) { int status; #if 0 assert(ncstrp->nchars % X_ALIGN == 0); #endif status = v1h_put_size_t(psp, &ncstrp->nchars); if(status != ENOERR) return status; status = check_v1hs(psp, _RNDUP(ncstrp->nchars, X_ALIGN)); if(status != ENOERR) return status; status = ncx_pad_putn_text(&psp->pos, ncstrp->nchars, ncstrp->cp); if(status != ENOERR) return status; return ENOERR; }
/* POSIX get. This will "make a region available." Since we're using buffered IO, this means that if needed, we'll fetch a new page from the file, otherwise, just return a pointer to what's in memory already. nciop - pointer to ncio struct, containing file info. pxp - pointer to ncio_px struct, which contains special metadate for posix files without NC_SHARE. offset - start byte of region to get. extent - how many bytes to read. rflags - One of the RGN_* flags defined in ncio.h. vpp - pointer to pointer that will recieve data. NOTES: * For blkoffset round offset down to the nearest pxp->blksz. This provides the offset (in bytes) to the beginning of the block that holds the current offset. * diff tells how far into the current block we are. * For blkextent round up to the number of bytes at the beginning of the next block, after the one that holds our current position, plus whatever extra (i.e. the extent) that we are about to grab. * The blkextent can't be more than twice the pxp->blksz. That's because the pxp->blksize is the sizehint, and in ncio_px_init2 the buffer (pointed to by pxp->bf-base) is allocated with 2 * *sizehintp. This is checked (unneccesarily) more than once in asserts. * If this is called on a newly opened file, pxp->bf_offset will be OFF_NONE and we'll jump to label pgin to immediately read in a page. */ static int px_get(ncio *const nciop, ncio_px *const pxp, off_t offset, size_t extent, int rflags, void **const vpp) { int status = ENOERR; const off_t blkoffset = _RNDDOWN(offset, (off_t)pxp->blksz); off_t diff = (size_t)(offset - blkoffset); off_t blkextent = _RNDUP(diff + extent, pxp->blksz); assert(extent != 0); assert(extent < X_INT_MAX); /* sanity check */ assert(offset >= 0); /* sanity check */ if(2 * pxp->blksz < blkextent) return E2BIG; /* TODO: temporary kludge */ if(pxp->bf_offset == OFF_NONE) { /* Uninitialized */ if(pxp->bf_base == NULL) { assert(pxp->bf_extent == 0); assert(blkextent <= 2 * pxp->blksz); pxp->bf_base = malloc(2 * pxp->blksz); if(pxp->bf_base == NULL) return ENOMEM; } goto pgin; } /* else */ assert(blkextent <= 2 * pxp->blksz); if(blkoffset == pxp->bf_offset) { /* hit */ if(blkextent > pxp->bf_extent) { /* page in upper */ void *const middle = (void *)((char *)pxp->bf_base + pxp->blksz); assert(pxp->bf_extent == pxp->blksz); status = px_pgin(nciop, pxp->bf_offset + (off_t)pxp->blksz, pxp->blksz, middle, &pxp->bf_cnt, &pxp->pos); if(status != ENOERR) return status; pxp->bf_extent = 2 * pxp->blksz; pxp->bf_cnt += pxp->blksz; } goto done; } /* else */ if(pxp->bf_extent > pxp->blksz && blkoffset == pxp->bf_offset + (off_t)pxp->blksz) { /* hit in upper half */ if(blkextent == pxp->blksz) { /* all in upper half, no fault needed */ diff += pxp->blksz; goto done; } /* else */ if(pxp->bf_cnt > pxp->blksz) { /* data in upper half */ void *const middle = (void *)((char *)pxp->bf_base + pxp->blksz); assert(pxp->bf_extent == 2 * pxp->blksz); if(fIsSet(pxp->bf_rflags, RGN_MODIFIED)) { /* page out lower half */ assert(pxp->bf_refcount <= 0); status = px_pgout(nciop, pxp->bf_offset, pxp->blksz, pxp->bf_base, &pxp->pos); if(status != ENOERR) return status; } pxp->bf_cnt -= pxp->blksz; /* copy upper half into lower half */ (void) memcpy(pxp->bf_base, middle, pxp->bf_cnt); } else /* added to fix nofill bug */ { assert(pxp->bf_extent == 2 * pxp->blksz); /* still have to page out lower half, if modified */ if(fIsSet(pxp->bf_rflags, RGN_MODIFIED)) { assert(pxp->bf_refcount <= 0); status = px_pgout(nciop, pxp->bf_offset, pxp->blksz, pxp->bf_base, &pxp->pos); if(status != ENOERR) return status; } } pxp->bf_offset = blkoffset; /* pxp->bf_extent = pxp->blksz; */ assert(blkextent == 2 * pxp->blksz); { /* page in upper */ void *const middle = (void *)((char *)pxp->bf_base + pxp->blksz); status = px_pgin(nciop, pxp->bf_offset + (off_t)pxp->blksz, pxp->blksz, middle, &pxp->bf_cnt, &pxp->pos); if(status != ENOERR) return status; pxp->bf_extent = 2 * pxp->blksz; pxp->bf_cnt += pxp->blksz; } goto done; } /* else */ if(blkoffset == pxp->bf_offset - (off_t)pxp->blksz) { /* wants the page below */ void *const middle = (void *)((char *)pxp->bf_base + pxp->blksz); size_t upper_cnt = 0; if(pxp->bf_cnt > pxp->blksz) { /* data in upper half */ assert(pxp->bf_extent == 2 * pxp->blksz); if(fIsSet(pxp->bf_rflags, RGN_MODIFIED)) { /* page out upper half */ assert(pxp->bf_refcount <= 0); status = px_pgout(nciop, pxp->bf_offset + (off_t)pxp->blksz, pxp->bf_cnt - pxp->blksz, middle, &pxp->pos); if(status != ENOERR) return status; } pxp->bf_cnt = pxp->blksz; pxp->bf_extent = pxp->blksz; } if(pxp->bf_cnt > 0) { /* copy lower half into upper half */ (void) memcpy(middle, pxp->bf_base, pxp->blksz); upper_cnt = pxp->bf_cnt; } /* read page below into lower half */ status = px_pgin(nciop, blkoffset, pxp->blksz, pxp->bf_base, &pxp->bf_cnt, &pxp->pos); if(status != ENOERR) return status; pxp->bf_offset = blkoffset; if(upper_cnt != 0) { pxp->bf_extent = 2 * pxp->blksz; pxp->bf_cnt = pxp->blksz + upper_cnt; } else { pxp->bf_extent = pxp->blksz; } goto done; } /* else */ /* no overlap */ if(fIsSet(pxp->bf_rflags, RGN_MODIFIED)) { assert(pxp->bf_refcount <= 0); status = px_pgout(nciop, pxp->bf_offset, pxp->bf_cnt, pxp->bf_base, &pxp->pos); if(status != ENOERR) return status; pxp->bf_rflags = 0; } pgin: status = px_pgin(nciop, blkoffset, blkextent, pxp->bf_base, &pxp->bf_cnt, &pxp->pos); if(status != ENOERR) return status; pxp->bf_offset = blkoffset; pxp->bf_extent = blkextent; done: extent += diff; if(pxp->bf_cnt < extent) pxp->bf_cnt = extent; assert(pxp->bf_cnt <= pxp->bf_extent); pxp->bf_rflags |= rflags; pxp->bf_refcount++; *vpp = (char *)pxp->bf_base + diff; return ENOERR; }