📄 ffio.c
字号:
/* * Copyright 1996, University Corporation for Atmospheric Research * See netcdf/COPYRIGHT file for copying and redistribution conditions. *//* $Id: ffio.c 2501 2007-11-20 02:33:29Z benkirk $ *//* addition by O. Heudecker, AWI-Bremerhaven, 12.3.1998 *//* added correction by John Sheldon and Hans Vahlenkamp 15.4.1998*/#include "ncconfig.h"#include <assert.h>#include <stdlib.h>#include <stdio.h> /* DEBUG */#include <errno.h>#ifndef ENOERR#define ENOERR 0#endif#include <fcntl.h>#include <ffio.h>#include <unistd.h>#include <string.h>/* Insertion by O. R. Heudecker, AWI-Bremerhaven 12.3.98 (1 line)*/#include <fortran.h>#include "ncio.h"#include "fbits.h"#include "rnd.h"#if !defined(NDEBUG) && !defined(X_INT_MAX)#define X_INT_MAX 2147483647#endif#if 0 /* !defined(NDEBUG) && !defined(X_ALIGN) */#define X_ALIGN 4#endif#define ALWAYS_NC_SHARE 0 /* DEBUG *//* Begin OS *//* * What is the preferred I/O block size? * (This becomes the default *sizehint == ncp->chunk in the higher layers.) * TODO: What is the the best answer here? */static size_tblksize(int fd){ struct ffc_stat_s sb; struct ffsw sw; if (fffcntl(fd, FC_STAT, &sb, &sw) > -1) {#ifdef __crayx1 if(sb.st_blksize > 0) return (size_t) sb.st_blksize;#else if(sb.st_oblksize > 0) return (size_t) sb.st_oblksize;#endif } /* else, silent in the face of error */ return (size_t) 32768;}/* * Sortof like ftruncate, except won't make the * file shorter. */static intfgrow(const int fd, const off_t len){ struct ffc_stat_s sb; struct ffsw sw; if (fffcntl(fd, FC_STAT, &sb, &sw) < 0) return errno; if (len < sb.st_size) return ENOERR; { const long dumb = 0; /* cache current position */ const off_t pos = ffseek(fd, 0, SEEK_CUR); if(pos < 0) return errno; if (ffseek(fd, len-sizeof(dumb), SEEK_SET) < 0) return errno; if(ffwrite(fd, (void *)&dumb, sizeof(dumb)) < 0) return errno; if (ffseek(fd, pos, SEEK_SET) < 0) return errno; } /* else */ return ENOERR;}/* * Sortof like ftruncate, except won't make the file shorter. Differs * from fgrow by only writing one byte at designated seek position, if * needed. */static intfgrow2(const int fd, const off_t len){ struct ffc_stat_s sb; struct ffsw sw; if (fffcntl(fd, FC_STAT, &sb, &sw) < 0) return errno; if (len <= sb.st_size) return ENOERR; { const char dumb = 0; /* we don't use ftruncate() due to problem with FAT32 file systems */ /* cache current position */ const off_t pos = ffseek(fd, 0, SEEK_CUR); if(pos < 0) return errno; if (ffseek(fd, len-1, SEEK_SET) < 0) return errno; if(ffwrite(fd, (void *)&dumb, sizeof(dumb)) < 0) return errno; if (ffseek(fd, pos, SEEK_SET) < 0) return errno; } return ENOERR;}/* End OS *//* Begin ffio */static intffio_pgout(ncio *const nciop, off_t const offset, const size_t extent, const void *const vp, off_t *posp){#ifdef X_ALIGN assert(offset % X_ALIGN == 0); assert(extent % X_ALIGN == 0);#endif if(*posp != offset) { if(ffseek(nciop->fd, offset, SEEK_SET) != offset) { return errno; } *posp = offset; } if(ffwrite(nciop->fd, vp, extent) != extent) { return errno; } *posp += extent; return ENOERR;}static intffio_pgin(ncio *const nciop, off_t const offset, const size_t extent, void *const vp, size_t *nreadp, off_t *posp){ int status; ssize_t nread;#ifdef X_ALIGN assert(offset % X_ALIGN == 0); assert(extent % X_ALIGN == 0);#endif if(*posp != offset) { if(ffseek(nciop->fd, offset, SEEK_SET) != offset) { status = errno; return status; } *posp = offset; } errno = 0; nread = ffread(nciop->fd, vp, extent); if(nread != extent) { status = errno; if(nread == -1 || status != ENOERR) return status; /* else it's okay we read 0. */ } *nreadp = nread; *posp += nread; return ENOERR;}/* */typedef struct ncio_ffio { off_t pos; /* buffer */ off_t bf_offset; size_t bf_extent; size_t bf_cnt; void *bf_base;} ncio_ffio;static intncio_ffio_rel(ncio *const nciop, off_t offset, int rflags){ ncio_ffio *ffp = (ncio_ffio *)nciop->pvt; int status = ENOERR; assert(ffp->bf_offset <= offset); assert(ffp->bf_cnt != 0); assert(ffp->bf_cnt <= ffp->bf_extent);#ifdef X_ALIGN assert(offset < ffp->bf_offset + X_ALIGN); assert(ffp->bf_cnt % X_ALIGN == 0 );#endif if(fIsSet(rflags, RGN_MODIFIED)) { if(!fIsSet(nciop->ioflags, NC_WRITE)) return EPERM; /* attempt to write readonly file */ status = ffio_pgout(nciop, ffp->bf_offset, ffp->bf_cnt, ffp->bf_base, &ffp->pos); /* if error, invalidate buffer anyway */ } ffp->bf_offset = OFF_NONE; ffp->bf_cnt = 0; return status;}static intncio_ffio_get(ncio *const nciop, off_t offset, size_t extent, int rflags, void **const vpp){ ncio_ffio *ffp = (ncio_ffio *)nciop->pvt; int status = ENOERR;#ifdef X_ALIGN size_t rem;#endif if(fIsSet(rflags, RGN_WRITE) && !fIsSet(nciop->ioflags, NC_WRITE)) return EPERM; /* attempt to write readonly file */ assert(extent != 0); assert(extent < X_INT_MAX); /* sanity check */ assert(ffp->bf_cnt == 0);#ifdef X_ALIGN /* round to seekable boundaries */ rem = offset % X_ALIGN; if(rem != 0) { offset -= rem; extent += rem; } { const size_t rndup = extent % X_ALIGN; if(rndup != 0) extent += X_ALIGN - rndup; } assert(offset % X_ALIGN == 0); assert(extent % X_ALIGN == 0);#endif if(ffp->bf_extent < extent) { if(ffp->bf_base != NULL) { free(ffp->bf_base); ffp->bf_base = NULL; ffp->bf_extent = 0; } assert(ffp->bf_extent == 0); ffp->bf_base = malloc(extent); if(ffp->bf_base == NULL) return ENOMEM; ffp->bf_extent = extent; } status = ffio_pgin(nciop, offset, extent, ffp->bf_base, &ffp->bf_cnt, &ffp->pos); if(status != ENOERR) return status; ffp->bf_offset = offset; if(ffp->bf_cnt < extent) { (void) memset((char *)ffp->bf_base + ffp->bf_cnt, 0, extent - ffp->bf_cnt); ffp->bf_cnt = extent; }#ifdef X_ALIGN *vpp = (char *)ffp->bf_base + rem;#else *vpp = (char *)ffp->bf_base;#endif return ENOERR;}static intncio_ffio_move(ncio *const nciop, off_t to, off_t from, size_t nbytes, int rflags){ int status = ENOERR; off_t lower = from; off_t upper = to; char *base; size_t diff = upper - lower; size_t extent = diff + nbytes; rflags &= RGN_NOLOCK; /* filter unwanted flags */ if(to == from) return ENOERR; /* NOOP */ if(to > from) { /* growing */ lower = from; upper = to; } else { /* shrinking */ lower = to; upper = from; } diff = upper - lower; extent = diff + nbytes; status = ncio_ffio_get(nciop, lower, extent, RGN_WRITE|rflags, (void **)&base); if(status != ENOERR) return status; if(to > from) (void) memmove(base + diff, base, nbytes); else (void) memmove(base, base + diff, nbytes); (void) ncio_ffio_rel(nciop, lower, RGN_MODIFIED); return status;}#ifdef NOFFFLUSH/* ncio_ffio_sync_noffflush is only needed if the FFIO global layer is * used, because it currently has a bug that causes the PEs to hang * RKO 06/26/98 */static intncio_ffio_sync_noffflush(ncio *const nciop){ struct ffc_stat_s si; /* for call to fffcntl() */ struct ffsw ffstatus; /* to return ffsw.sw_error */ /* run some innocuous ffio routine to get if any errno */ if(fffcntl(nciop->fd, FC_STAT, &si, &ffstatus) < 0) return ffstatus.sw_error; return ENOERR;}/* this tests to see if the global FFIO layer is being called for * returns ~0 if it is, else returns 0 */static intncio_ffio_global_test(const char *ControlString){ if (strstr(ControlString,"global") != (char *) NULL) { return ~0; } else { return 0; }}#endifstatic intncio_ffio_sync(ncio *const nciop){#ifdef __crayx1 struct ffsw stat; if(ffflush(nciop->fd,&stat) < 0)#else if(ffflush(nciop->fd) < 0)#endif return errno; return ENOERR;}static voidncio_ffio_free(void *const pvt){ ncio_ffio *ffp = (ncio_ffio *)pvt; if(ffp == NULL) return; if(ffp->bf_base != NULL) { free(ffp->bf_base); ffp->bf_base = NULL; ffp->bf_offset = OFF_NONE; ffp->bf_extent = 0; ffp->bf_cnt = 0; }}static intncio_ffio_init2(ncio *const nciop, size_t *sizehintp){ ncio_ffio *ffp = (ncio_ffio *)nciop->pvt; assert(nciop->fd >= 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -