📄 ffio.c
字号:
ffp->bf_extent = *sizehintp; assert(ffp->bf_base == NULL); /* this is separate allocation because it may grow */ ffp->bf_base = malloc(ffp->bf_extent); if(ffp->bf_base == NULL) { ffp->bf_extent = 0; return ENOMEM; } /* else */ return ENOERR;}static voidncio_ffio_init(ncio *const nciop){ ncio_ffio *ffp = (ncio_ffio *)nciop->pvt; *((ncio_relfunc **)&nciop->rel) = ncio_ffio_rel; /* cast away const */ *((ncio_getfunc **)&nciop->get) = ncio_ffio_get; /* cast away const */ *((ncio_movefunc **)&nciop->move) = ncio_ffio_move; /* cast away const */ *((ncio_syncfunc **)&nciop->sync) = ncio_ffio_sync; /* cast away const */ *((ncio_freefunc **)&nciop->free) = ncio_ffio_free; /* cast away const */ ffp->pos = -1; ffp->bf_offset = OFF_NONE; ffp->bf_extent = 0; ffp->bf_cnt = 0; ffp->bf_base = NULL;}/* */static voidncio_free(ncio *nciop){ if(nciop == NULL) return; if(nciop->free != NULL) nciop->free(nciop->pvt); free(nciop);}static ncio *ncio_new(const char *path, int ioflags){ size_t sz_ncio = M_RNDUP(sizeof(ncio)); size_t sz_path = M_RNDUP(strlen(path) +1); size_t sz_ncio_pvt; ncio *nciop; #if ALWAYS_NC_SHARE /* DEBUG */ fSet(ioflags, NC_SHARE);#endif if(fIsSet(ioflags, NC_SHARE)) fprintf(stderr, "NC_SHARE not implemented for ffio\n"); sz_ncio_pvt = sizeof(ncio_ffio); nciop = (ncio *) malloc(sz_ncio + sz_path + sz_ncio_pvt); if(nciop == NULL) return NULL; nciop->ioflags = ioflags; *((int *)&nciop->fd) = -1; /* cast away const */ nciop->path = (char *) ((char *)nciop + sz_ncio); (void) strcpy((char *)nciop->path, path); /* cast away const */ /* cast away const */ *((void **)&nciop->pvt) = (void *)(nciop->path + sz_path); ncio_ffio_init(nciop); return nciop;}/* put all the FFIO assign specific code here * returns a pointer to an internal static char location * which may change when the function is called again * if the returned pointer is NULL this indicates that an error occured * check errno for the netCDF error value *//* prototype fortran subroutines */#ifdef __crayx1void ASNQFILE(const char *filename, const char *attribute, int *istat, int flen, int alen);void ASNFILE(const char *filename, const char *attribute, int *istat, int flen, int alen);#elsevoid ASNQFILE(_fcd filename, _fcd attribute, int *istat);void ASNFILE(_fcd filename, _fcd attribute, int *istat);#endif#define BUFLEN 256static const char *ncio_ffio_assign(const char *filename) { static char buffer[BUFLEN]; int istat;#ifndef __crayx1 _fcd fnp, fbp;#endif char *envstr; char *xtra_assign; char emptystr='\0';/* put things into known states */ memset(buffer,'\0',BUFLEN); errno = ENOERR;/* set up Fortran character pointers */#ifdef __crayx1 ASNQFILE(filename, buffer, &istat, strlen(filename)+1, BUFLEN);#else fnp = _cptofcd((char *)filename, strlen(filename)); fbp = _cptofcd(buffer, BUFLEN);/* see if the user has "assigned" to this file */ ASNQFILE(fnp, fbp, &istat);#endif if (istat == 0) { /* user has already specified an assign */ return buffer; } else if (istat > 0 || istat < -1) { /* error occured */ errno = EINVAL; return (const char *) NULL; } /* istat = -1 -> no assign for file */ envstr = getenv("NETCDF_FFIOSPEC"); if(envstr == (char *) NULL) { envstr = "bufa:336:2"; /* this should be macroized */ } /* Insertion by Olaf Heudecker, AWI-Bremerhaven, 12.8.1998 to allow more versatile FFIO-assigns */ /* this is unnecessary and could have been included * into the NETCDF_FFIOSPEC environment variable */ xtra_assign = getenv("NETCDF_XFFIOSPEC"); if(xtra_assign == (char *) NULL) { xtra_assign=&emptystr; } if (strlen(envstr)+strlen(xtra_assign) + 4 > BUFLEN) { /* Error: AssignCommand too long */ errno=E2BIG; return (const char *) NULL; } (void) sprintf(buffer,"-F %s %s", envstr,xtra_assign);#ifdef __crayx1 ASNFILE(filename, buffer, &istat, strlen(filename)+1, strlen(buffer)+1);#else fbp = _cptofcd(buffer, strlen(buffer)); ASNFILE(fnp, fbp, &istat);#endif if (istat == 0) { /* success */ return buffer; } else { /* error */ errno = EINVAL; return (const char *) NULL; }}/* Public below this point *//* TODO: Is this reasonable for this platform? */static const size_t NCIO_MINBLOCKSIZE = 256;static const size_t NCIO_MAXBLOCKSIZE = 268435456; /* sanity check, about X_SIZE_T_MAX/8 */intncio_create(const char *path, int ioflags, size_t initialsz, off_t igeto, size_t igetsz, size_t *sizehintp, ncio **nciopp, void **const igetvpp){ ncio *nciop; const char *ControlString; int oflags = (O_RDWR|O_CREAT|O_TRUNC); int fd; int status; struct ffsw stat; if(initialsz < (size_t)igeto + igetsz) initialsz = (size_t)igeto + igetsz; fSet(ioflags, NC_WRITE); if(path == NULL || *path == 0) return EINVAL; nciop = ncio_new(path, ioflags); if(nciop == NULL) return ENOMEM; if ((ControlString = ncio_ffio_assign(path)) == (const char *)NULL) { /* an error occured - just punt */ status = errno; goto unwind_new; }#ifdef NOFFFLUSH /* test whether the global layer is being called for * this file ... if so then can't call FFIO ffflush() * RKO 06/26/98 */ if (strstr(ControlString,"global") != (char *) NULL) { /* use no ffflush version */ *((ncio_syncfunc **)&nciop->sync) = ncio_ffio_sync_noffflush; }#endif if(fIsSet(ioflags, NC_NOCLOBBER)) fSet(oflags, O_EXCL); /* Orig: fd = ffopens(path, oflags, 0666, 0, &stat, ControlString); */ fd = ffopen(path, oflags, 0666, 0, &stat); if(fd < 0) { status = errno; goto unwind_new; } *((int *)&nciop->fd) = fd; /* cast away const */ if(*sizehintp < NCIO_MINBLOCKSIZE || *sizehintp > NCIO_MAXBLOCKSIZE) { /* Use default */ *sizehintp = blksize(fd); } else { *sizehintp = M_RNDUP(*sizehintp); } status = ncio_ffio_init2(nciop, sizehintp); if(status != ENOERR) goto unwind_open; if(initialsz != 0) { status = fgrow(fd, (off_t)initialsz); if(status != ENOERR) goto unwind_open; } if(igetsz != 0) { status = nciop->get(nciop, igeto, igetsz, RGN_WRITE, igetvpp); if(status != ENOERR) goto unwind_open; } *nciopp = nciop; return ENOERR;unwind_open: (void) ffclose(fd); /* ?? unlink */ /*FALLTHRU*/unwind_new: ncio_free(nciop); return status;}intncio_open(const char *path, int ioflags, off_t igeto, size_t igetsz, size_t *sizehintp, ncio **nciopp, void **const igetvpp){ ncio *nciop; const char *ControlString; int oflags = fIsSet(ioflags, NC_WRITE) ? O_RDWR : O_RDONLY; int fd; int status; struct ffsw stat; if(path == NULL || *path == 0) return EINVAL; nciop = ncio_new(path, ioflags); if(nciop == NULL) return ENOMEM; if ((ControlString = ncio_ffio_assign(path)) == (const char *)NULL) { /* an error occured - just punt */ status = errno; goto unwind_new; }#ifdef NOFFFLUSH /* test whether the global layer is being called for * this file ... if so then can't call FFIO ffflush() * RKO 06/26/98 */ if (strstr(ControlString,"global") != (char *) NULL) { /* use no ffflush version */ *((ncio_syncfunc **)&nciop->sync) = ncio_ffio_sync_noffflush; }#endif /* Orig: fd = ffopens(path, oflags, 0, 0, &stat, ControlString); */ fd = ffopen(path, oflags, 0, 0, &stat); if(fd < 0) { status = errno; goto unwind_new; } *((int *)&nciop->fd) = fd; /* cast away const */ if(*sizehintp < NCIO_MINBLOCKSIZE || *sizehintp > NCIO_MAXBLOCKSIZE) { /* Use default */ *sizehintp = blksize(fd); } else { *sizehintp = M_RNDUP(*sizehintp); } status = ncio_ffio_init2(nciop, sizehintp); if(status != ENOERR) goto unwind_open; if(igetsz != 0) { status = nciop->get(nciop, igeto, igetsz, 0, igetvpp); if(status != ENOERR) goto unwind_open; } *nciopp = nciop; return ENOERR;unwind_open: (void) ffclose(fd); /*FALLTHRU*/unwind_new: ncio_free(nciop); return status;}/* * Get file size in bytes. * Is use of ffseek() really necessary, or could we use standard fstat() call * and get st_size member? */intncio_filesize(ncio *nciop, off_t *filesizep){ off_t filesize, current, reset; if(nciop == NULL) return EINVAL; current = ffseek(nciop->fd, 0, SEEK_CUR); /* save current */ *filesizep = ffseek(nciop->fd, 0, SEEK_END); /* get size */ reset = ffseek(nciop->fd, current, SEEK_SET); /* reset */ if(reset != current) return EINVAL; return ENOERR;}/* * Sync any changes to disk, then extend file so its size is length. * This is only intended to be called before close, if the file is * open for writing and the actual size does not match the calculated * size, perhaps as the result of having been previously written in * NOFILL mode. */intncio_pad_length(ncio *nciop, off_t length){ int status = ENOERR; if(nciop == NULL) return EINVAL; if(!fIsSet(nciop->ioflags, NC_WRITE)) return EPERM; /* attempt to write readonly file */ status = nciop->sync(nciop); if(status != ENOERR) return status; status = fgrow2(nciop->fd, length); if(status != ENOERR) return errno; return ENOERR;}int ncio_close(ncio *nciop, int doUnlink){ /* * TODO: I believe this function is lacking the de-assignment of the * Fortran LUN assigned by ASNFILE in ncio_ffio_assign(...) -- SRE * 2002-07-10. */ int status = ENOERR; if(nciop == NULL) return EINVAL; status = nciop->sync(nciop); (void) ffclose(nciop->fd); if(doUnlink) (void) unlink(nciop->path); ncio_free(nciop); return status;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -