/* Create a file, and the ncio struct to go with it. path - path of file to create. ioflags - flags from nc_create initialsz - From the netcdf man page: "The argument initialsize sets the initial size of the file at creation time." igeto - igetsz - sizehintp - the size of a page of data for buffered reads and writes. parameters - arbitrary data nciopp - pointer to a pointer that will get location of newly created and inited ncio struct. mempp - pointer to pointer to the initial memory read. */ int memio_create(const char* path, int ioflags, size_t initialsz, off_t igeto, size_t igetsz, size_t* sizehintp, void* parameters /*ignored*/, ncio* *nciopp, void** const mempp) { ncio* nciop; int fd; int status; NCMEMIO* memio = NULL; if(path == NULL ||* path == 0) return NC_EINVAL; status = memio_new(path, ioflags, initialsz, &nciop, &memio); if(status != NC_NOERR) return status; if(memio->persist) { /* Verify the file is writeable or does not exist*/ if(fileexists(path) && !fileiswriteable(path)) {status = EPERM; goto unwind_open;} } /* Allocate the memory for this file */ memio->memory = (char*)malloc((size_t)memio->alloc); if(memio->memory == NULL) {status = NC_ENOMEM; goto unwind_open;} memio->locked = 0; #ifdef DEBUG fprintf(stderr,"memio_create: initial memory: %lu/%lu\n",(unsigned long)memio->memory,(unsigned long)memio->alloc); #endif fd = nc__pseudofd(); *((int* )&nciop->fd) = fd; fSet(nciop->ioflags, NC_WRITE); /* Always writeable */ if(igetsz != 0) { status = nciop->get(nciop, igeto, igetsz, RGN_WRITE, mempp); if(status != NC_NOERR) goto unwind_open; } /* Pick a default sizehint */ if(sizehintp) *sizehintp = (size_t)pagesize; *nciopp = nciop; return NC_NOERR; unwind_open: memio_close(nciop,1); return status; }
/* This function opens the data file. It is only called from nc.c, from nc__open_mp and nc_delete_mp. path - path of data file. ioflags - flags passed into nc_open. igeto - looks like this function can do an initial page get, and igeto is going to be the offset for that. But it appears to be unused igetsz - the size in bytes of initial page get (a.k.a. extent). Not ever used in the library. sizehintp - the size of a page of data for buffered reads and writes. nciopp - pointer to pointer that will get address of newly created and inited ncio struct. mempp - pointer to pointer to the initial memory read. */ int memio_open(const char* path, int ioflags, off_t igeto, size_t igetsz, size_t* sizehintp, ncio* *nciopp, void** const mempp) { ncio* nciop; int fd; int status; int persist = (fIsSet(ioflags,NC_WRITE)?1:0); int oflags; NCMEMIO* memio = NULL; size_t sizehint; off_t filesize; if(path == NULL ||* path == 0) return EINVAL; assert(sizehintp != NULL); sizehint = *sizehintp; /* Open the file, but make sure we can write it if needed */ oflags = (persist ? O_RDWR : O_RDONLY); #ifdef O_BINARY fSet(oflags, O_BINARY); #endif oflags |= O_EXCL; #ifdef vms fd = open(path, oflags, 0, "ctx=stm"); #else fd = open(path, oflags, OPENMODE); #endif #ifdef DEBUG if(fd < 0) { fprintf(stderr,"open failed: file=%s err=",path); perror(""); } #endif if(fd < 0) {status = errno; goto unwind_open;} /* get current filesize = max(|file|,initialize)*/ filesize = lseek(fd,0,SEEK_END); if(filesize < 0) {status = errno; goto unwind_open;} /* move pointer back to beginning of file */ (void)lseek(fd,0,SEEK_SET); if(filesize < (off_t)sizehint) filesize = (off_t)sizehint; status = memio_new(path, ioflags, filesize, &nciop, &memio); if(status != NC_NOERR) return status; memio->size = filesize; memio->memory = (char*)malloc(memio->alloc); if(memio->memory == NULL) {status = NC_ENOMEM; goto unwind_open;} #ifdef DEBUG fprintf(stderr,"memio_open: initial memory: %lu/%lu\n",(unsigned long)memio->memory,(unsigned long)memio->alloc); #endif /* Read the file into the memio memory */ /* We need to do multiple reads because there is no guarantee that the amount read will be the full amount */ { off_t red = memio->size; char* pos = memio->memory; while(red > 0) { ssize_t count = read(fd, pos, red); if(count < 0) {close(fd); status = errno; goto unwind_open;} if(count == 0) {close(fd); status = NC_ENOTNC; goto unwind_open;} red -= count; pos += count; } } (void)close(fd); /* until memio_close() */ /* Use half the filesize as the blocksize */ sizehint = filesize/2; fd = nc__pseudofd(); *((int* )&nciop->fd) = fd; if(igetsz != 0) { status = nciop->get(nciop, igeto, igetsz, 0, mempp); if(status != NC_NOERR) goto unwind_open; } *sizehintp = sizehint; *nciopp = nciop; return NC_NOERR; unwind_open: memio_close(nciop,0); return status; }
/* Create a file, and the ncio struct to go with it. This function is only called from nc__create_mp. path - path of file to create. ioflags - flags from nc_create initialsz - From the netcdf man page: "The argument Iinitialsize sets the initial size of the file at creation time." igeto - igetsz - sizehintp - the size of a page of data for buffered reads and writes. nciopp - pointer to a pointer that will get location of newly created and inited ncio struct. mempp - pointer to pointer to the initial memory read. */ int memio_create(const char* path, int ioflags, size_t initialsz, off_t igeto, size_t igetsz, size_t* sizehintp, ncio* *nciopp, void** const mempp) { ncio* nciop; int fd; int status; NCMEMIO* memio = NULL; int persist = (ioflags & NC_WRITE?1:0); int oflags; if(path == NULL ||* path == 0) return NC_EINVAL; /* For diskless open has, the file must be classic version 1 or 2.*/ if(fIsSet(ioflags,NC_NETCDF4)) return NC_EDISKLESS; /* violates constraints */ status = memio_new(path, ioflags, initialsz, &nciop, &memio); if(status != NC_NOERR) return status; memio->size = 0; if(!persist) { memio->memory = (char*)malloc(memio->alloc); if(memio->memory == NULL) {status = NC_ENOMEM; goto unwind_open;} } else { /*persist */ /* Open the file, but make sure we can write it if needed */ oflags = (persist ? O_RDWR : O_RDONLY); #ifdef O_BINARY fSet(oflags, O_BINARY); #endif oflags |= (O_CREAT|O_TRUNC); if(fIsSet(ioflags,NC_NOCLOBBER)) oflags |= O_EXCL; #ifdef vms fd = open(path, oflags, 0, "ctx=stm"); #else fd = open(path, oflags, OPENMODE); #endif if(fd < 0) {status = errno; goto unwind_open;} (void)close(fd); /* will reopen at nc_close */ /* malloc memory */ memio->memory = (char*)malloc(memio->alloc); if(memio->memory == NULL) {status = NC_ENOMEM; goto unwind_open;} } /*!persist*/ #ifdef DEBUG fprintf(stderr,"memio_create: initial memory: %lu/%lu\n",(unsigned long)memio->memory,(unsigned long)memio->alloc); #endif fd = nc__pseudofd(); *((int* )&nciop->fd) = fd; fSet(nciop->ioflags, NC_WRITE); if(igetsz != 0) { status = nciop->get(nciop, igeto, igetsz, RGN_WRITE, mempp); if(status != NC_NOERR) goto unwind_open; } /* Pick a default sizehint */ if(sizehintp) *sizehintp = pagesize; *nciopp = nciop; return NC_NOERR; unwind_open: memio_close(nciop,1); return status; }
/* This function opens the data file. It is only called from nc.c, from nc__open_mp and nc_delete_mp. path - path of data file. ioflags - flags passed into nc_open. igeto - looks like this function can do an initial page get, and igeto is going to be the offset for that. But it appears to be unused igetsz - the size in bytes of initial page get (a.k.a. extent). Not ever used in the library. sizehintp - the size of a page of data for buffered reads and writes. nciopp - pointer to pointer that will get address of newly created and inited ncio struct. mempp - pointer to pointer to the initial memory read. */ int mmapio_open(const char* path, int ioflags, off_t igeto, size_t igetsz, size_t* sizehintp, void* parameters, ncio* *nciopp, void** const mempp) { ncio* nciop; int fd; int status; int persist = (fIsSet(ioflags,NC_WRITE)?1:0); int oflags; NCMMAPIO* mmapio = NULL; size_t sizehint; off_t filesize; if(path == NULL ||* path == 0) return EINVAL; assert(sizehintp != NULL); sizehint = *sizehintp; /* Open the file, but make sure we can write it if needed */ oflags = (persist ? O_RDWR : O_RDONLY); #ifdef O_BINARY fSet(oflags, O_BINARY); #endif oflags |= O_EXCL; #ifdef vms fd = open(path, oflags, 0, "ctx=stm"); #else fd = open(path, oflags, OPENMODE); #endif if(fd < 0) {status = errno; goto unwind_open;} /* get current filesize = max(|file|,initialize)*/ filesize = lseek(fd,0,SEEK_END); if(filesize < 0) {status = errno; goto unwind_open;} /* move pointer back to beginning of file */ (void)lseek(fd,0,SEEK_SET); if(filesize < (off_t)sizehint) filesize = (off_t)sizehint; status = mmapio_new(path, ioflags, filesize, &nciop, &mmapio); if(status != NC_NOERR) return status; mmapio->size = filesize; mmapio->mapfd = fd; mmapio->memory = (char*)mmap(NULL,mmapio->alloc, persist?(PROT_READ|PROT_WRITE):(PROT_READ), MAP_SHARED, mmapio->mapfd,0); #ifdef DEBUG fprintf(stderr,"mmapio_open: initial memory: %lu/%lu\n",(unsigned long)mmapio->memory,(unsigned long)mmapio->alloc); #endif /* Use half the filesize as the blocksize */ sizehint = filesize/2; /* sizehint must be multiple of 8 */ sizehint = (sizehint / 8) * 8; if(sizehint < 8) sizehint = 8; fd = nc__pseudofd(); *((int* )&nciop->fd) = fd; if(igetsz != 0) { status = nciop->get(nciop, igeto, igetsz, 0, mempp); if(status != NC_NOERR) goto unwind_open; } *sizehintp = sizehint; *nciopp = nciop; return NC_NOERR; unwind_open: mmapio_close(nciop,0); return status; }
/* Create a file, and the ncio struct to go with it. This function is only called from nc__create_mp. path - path of file to create. ioflags - flags from nc_create initialsz - From the netcdf man page: "The argument Iinitialsize sets the initial size of the file at creation time." igeto - igetsz - sizehintp - the size of a page of data for buffered reads and writes. nciopp - pointer to a pointer that will get location of newly created and inited ncio struct. mempp - pointer to pointer to the initial memory read. */ int mmapio_create(const char* path, int ioflags, size_t initialsz, off_t igeto, size_t igetsz, size_t* sizehintp, void* parameters, ncio* *nciopp, void** const mempp) { ncio* nciop; int fd; int status; NCMMAPIO* mmapio = NULL; int persist = (ioflags & NC_WRITE?1:0); int oflags; if(path == NULL ||* path == 0) return NC_EINVAL; /* For diskless open has, the file must be classic version 1 or 2.*/ if(fIsSet(ioflags,NC_NETCDF4)) return NC_EDISKLESS; /* violates constraints */ status = mmapio_new(path, ioflags, initialsz, &nciop, &mmapio); if(status != NC_NOERR) return status; mmapio->size = 0; if(!persist) { mmapio->mapfd = -1; mmapio->memory = (char*)mmap(NULL,mmapio->alloc, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, mmapio->mapfd,0); {mmapio->memory[0] = 0;} /* test writing of the mmap'd memory */ } else { /*persist */ /* Open the file, but make sure we can write it if needed */ oflags = (persist ? O_RDWR : O_RDONLY); #ifdef O_BINARY fSet(oflags, O_BINARY); #endif oflags |= (O_CREAT|O_TRUNC); if(fIsSet(ioflags,NC_NOCLOBBER)) oflags |= O_EXCL; #ifdef vms fd = open(path, oflags, 0, "ctx=stm"); #else fd = open(path, oflags, OPENMODE); #endif if(fd < 0) {status = errno; goto unwind_open;} mmapio->mapfd = fd; { /* Cause the output file to have enough allocated space */ lseek(fd,mmapio->alloc-1,SEEK_SET); /* cause file to appear */ write(fd,"",mmapio->alloc); lseek(fd,0,SEEK_SET); /* rewind */ } mmapio->memory = (char*)mmap(NULL,mmapio->alloc, PROT_READ|PROT_WRITE, MAP_SHARED, mmapio->mapfd,0); if(mmapio->memory == NULL) { return NC_EDISKLESS; } } /*!persist*/ #ifdef DEBUG fprintf(stderr,"mmap_create: initial memory: %lu/%lu\n",(unsigned long)mmapio->memory,(unsigned long)mmapio->alloc); #endif fd = nc__pseudofd(); *((int* )&nciop->fd) = fd; fSet(nciop->ioflags, NC_WRITE); if(igetsz != 0) { status = nciop->get(nciop, igeto, igetsz, RGN_WRITE, mempp); if(status != NC_NOERR) goto unwind_open; } /* Pick a default sizehint */ if(sizehintp) *sizehintp = pagesize; *nciopp = nciop; return NC_NOERR; unwind_open: mmapio_close(nciop,1); return status; }
/* This function opens the data file or inmemory data path - path of data file. ioflags - flags passed into nc_open. igeto - looks like this function can do an initial page get, and igeto is going to be the offset for that. But it appears to be unused igetsz - the size in bytes of initial page get (a.k.a. extent). Not ever used in the library. sizehintp - the size of a page of data for buffered reads and writes. parameters - arbitrary data nciopp - pointer to pointer that will get address of newly created and inited ncio struct. mempp - pointer to pointer to the initial memory read. */ int memio_open(const char* path, int ioflags, off_t igeto, size_t igetsz, size_t* sizehintp, void* parameters, ncio* *nciopp, void** const mempp) { ncio* nciop = NULL; int fd = -1; int status = NC_NOERR; size_t sizehint = 0; NC_memio meminfo; /* use struct to avoid worrying about free'ing it */ NCMEMIO* memio = NULL; size_t initialsize; /* Should be the case that diskless => inmemory but not converse */ int diskless = (fIsSet(ioflags,NC_DISKLESS)); int inmemory = fIsSet(ioflags,NC_INMEMORY); int locked = 0; assert(inmemory ? !diskless : 1); if(path == NULL || strlen(path) == 0) return NC_EINVAL; assert(sizehintp != NULL); sizehint = *sizehintp; memset(&meminfo,0,sizeof(meminfo)); if(inmemory) { /* parameters provide the memory chunk */ NC_memio* memparams = (NC_memio*)parameters; meminfo = *memparams; locked = fIsSet(meminfo.flags,NC_MEMIO_LOCKED); /* As a safeguard, if !locked and NC_WRITE is set, then we must take control of the incoming memory */ if(!locked && fIsSet(ioflags,NC_WRITE)) { memparams->memory = NULL; } } else { /* read the file into a chunk of memory*/ assert(diskless); status = readfile(path,&meminfo); if(status != NC_NOERR) {goto unwind_open;} } /* Fix up initial size */ initialsize = meminfo.size; /* create the NCMEMIO structure */ status = memio_new(path, ioflags, initialsize, &nciop, &memio); if(status != NC_NOERR) {goto unwind_open;} memio->locked = locked; /* Initialize the memio memory */ memio->memory = meminfo.memory; /* memio_new may have modified the allocated size, in which case, reallocate the memory unless the memory is locked. */ if(memio->alloc > meminfo.size) { if(memio->locked) memio->alloc = meminfo.size; /* force it back to what it was */ else { void* oldmem = memio->memory; memio->memory = reallocx(oldmem,memio->alloc,meminfo.size); if(memio->memory == NULL) {status = NC_ENOMEM; goto unwind_open;} } } #ifdef DEBUG fprintf(stderr,"memio_open: initial memory: %lu/%lu\n",(unsigned long)memio->memory,(unsigned long)memio->alloc); #endif if(memio->persist) { /* Verify the file is writeable and exists */ if(!fileexists(path)) {status = ENOENT; goto unwind_open;} if(!fileiswriteable(path)) {status = EACCES; goto unwind_open;} } /* Use half the filesize as the blocksize ; why? */ sizehint = (size_t)(memio->alloc/2); /* sizehint must be multiple of 8 */ sizehint = (sizehint / 8) * 8; if(sizehint < 8) sizehint = 8; fd = nc__pseudofd(); *((int* )&nciop->fd) = fd; if(igetsz != 0) { status = nciop->get(nciop, igeto, igetsz, 0, mempp); if(status != NC_NOERR) goto unwind_open; } if(sizehintp) *sizehintp = sizehint; if(nciopp) *nciopp = nciop; else {ncio_close(nciop,0);} return NC_NOERR; unwind_open: if(fd >= 0) close(fd); memio_close(nciop,0); return status; }