Esempio n. 1
0
int
nc_delete_mp(const char * path, int basepe)
{
	NC *ncp;
	int status;
	size_t chunk = 512;

	ncp = new_NC(&chunk);
	if(ncp == NULL)
		return NC_ENOMEM;
	
#if defined(LOCKNUMREC) /* && _CRAYMPP */
	if (status = NC_init_pe(ncp, basepe)) {
		return status;
	}
#else
	/*
	 * !_CRAYMPP, only pe 0 is valid
	 */
	if(basepe != 0)
		return NC_EINVAL;
#endif
	status = ncio_open(path, NC_NOWRITE,
		0, 0, &ncp->chunk,
		&ncp->nciop, 0);
	if(status)
		goto unwind_alloc;

	assert(ncp->flags == 0);

	status = nc_get_NC(ncp);
	if(status != NC_NOERR)
	{
		/* Not a netcdf file, don't delete */
		/* ??? is this the right semantic? what if it was just too big? */
		(void) ncio_close(ncp->nciop, 0);
	}
	else
	{
		/* ncio_close does the unlink */
		status = ncio_close(ncp->nciop, 1); /* ncio_close does the unlink */
	}

	ncp->nciop = NULL;
unwind_alloc:
	free_NC(ncp);
	return status;
}
Esempio n. 2
0
int
nc_close(int ncid)
{
	int status = NC_NOERR;
	NC *ncp; 

	status = NC_check_id(ncid, &ncp); 
	if(status != NC_NOERR)
		return status;

	if(NC_indef(ncp))
	{
		status = NC_endef(ncp, 0, 1, 0, 1); /* TODO: defaults */
		if(status != NC_NOERR )
		{
			(void) nc_abort(ncid);
			return status;
		}
	}
	else if(!NC_readonly(ncp))
	{
		status = NC_sync(ncp);
		/* flush buffers before any filesize comparisons */
		(void) ncp->nciop->sync(ncp->nciop);
	}

	/* 
	 * If file opened for writing and filesize is less than
	 * what it should be (due to previous use of NOFILL mode),
	 * pad it to correct size, as reported by NC_calcsize().
	 */
	if (status == ENOERR) {
	    off_t filesize; 	/* current size of open file */
	    off_t calcsize;	/* calculated file size, from header */
	    status = ncio_filesize(ncp->nciop, &filesize);
	    if(status != ENOERR)
		return status;
	    status = NC_calcsize(ncp, &calcsize);
	    if(status != NC_NOERR)
		return status;
	    if(filesize < calcsize && !NC_readonly(ncp)) {
		status = ncio_pad_length(ncp->nciop, calcsize);
		if(status != ENOERR)
		    return status;
	    }
	}

	(void) ncio_close(ncp->nciop, 0);
	ncp->nciop = NULL;

	del_from_NCList(ncp);

	free_NC(ncp);

	return status;
}
Esempio n. 3
0
/*
 * In data mode, same as ncclose.
 * In define mode, restore previous definition.
 * In create, remove the file.
 */
int
nc_abort(int ncid)
{
	int status;
	NC *ncp;
	int doUnlink = 0;

	status = NC_check_id(ncid, &ncp); 
	if(status != NC_NOERR)
		return status;

	doUnlink = NC_IsNew(ncp);

	if(ncp->old != NULL)
	{
		/* a plain redef, not a create */
		assert(!NC_IsNew(ncp));
		assert(fIsSet(ncp->flags, NC_INDEF));
		free_NC(ncp->old);
		ncp->old = NULL;
		fClr(ncp->flags, NC_INDEF);
	}
	else if(!NC_readonly(ncp))
	{
		status = NC_sync(ncp);
		if(status != NC_NOERR)
			return status;
	}


	(void) ncio_close(ncp->nciop, doUnlink);
	ncp->nciop = NULL;

	del_from_NCList(ncp);

	free_NC(ncp);

	return NC_NOERR;
}
Esempio n. 4
0
main(int ac, char *av[])
{
	char *path = "";
	ncio *nciop;
	char linebuf[128];
	off_t offset;
	size_t extent;
	void *vp;
	int status = ENOERR;
	int verbose = 0;
	int flags = 0;
	int create = 0;
	off_t igeto = 0;
	size_t igetsz = 0;
	size_t initialsz = 0;
	int doUnlink = 0;
	size_t sizehint = NC_SIZEHINT_DEFAULT;

	{
	extern int optind;
	extern int opterr;
	extern char *optarg;
	int ch;

	opterr = 1;

	while ((ch = getopt(ac, av, "vwcnLSUo:i:I:s:")) != EOF)
		switch (ch) {
		case 'v':
			verbose = 1;
			break;
		case 'w':
			flags |= NC_WRITE;
			break;
		case 'c':
			create = 1;
			break;
		case 'n':
			create = 1;
			flags |= NC_NOCLOBBER;
			break;
		case 'L':
			flags |= NC_LOCK;
			break;
		case 'S':
			flags |= NC_SHARE;
			break;
		case 'U':
			doUnlink = 1;
			break;
		case 'o':
			igeto = argscale(optarg, "igeto");
			break;
		case 'i':
			igetsz = argscale(optarg, "igetsz");
			break;
		case 'I':
			initialsz = argscale(optarg, "initialsz");
			break;
		case 's':
			sizehint = argscale(optarg, "sizehint");
			break;
		case '?':
			usage(av[0]);
			break;
		}

	/* last arg, the file name, is required */
	if(ac - optind <= 0)
		usage(av[0]) ;
	path = av[optind];


	}
	
	if(!create)
	{
		status = ncio_open(path, flags,
				igeto, igetsz, &sizehint,
				&nciop, &vp);
		if(status != ENOERR)
		{
			fprintf(stderr, "ncio_open: %s: %s\n",
				path, strerror(status));
			return(EXIT_FAILURE);
		}
	} else {
		status = ncio_create(path, flags, initialsz,
			igeto, igetsz, &sizehint,
			&nciop, &vp);
		if(status != ENOERR)
		{
			fprintf(stderr, "ncio_create: %s: %s\n",
				path, strerror(status));
			return(EXIT_FAILURE);
		}
	}

	while(fgets(linebuf, sizeof(linebuf), stdin) != NULL)
	{
		offset = 0;
		extent = 0;

		if(*linebuf == '#')
			continue; /* comment */
		if(sscanf(linebuf, "rel 0x%lx", &offset) == 1
			|| sscanf(linebuf, "rel %ld", &offset) == 1)
		{
			if(verbose)
				printf("- rel  %8ld\n", offset);
			if(!riu_pop(offset, 0))
				continue;
			status = nciop->rel(nciop, offset, 0);
			if(status)
			{
				fprintf(stderr, "- rel  error: %s\n",
					strerror(status));
				continue;
			}
		}
		else if(sscanf(linebuf, "relm 0x%lx", &offset) == 1
			|| sscanf(linebuf, "relm %ld", &offset) == 1)
		{
			if(verbose)
				printf("- relm %8ld\n", offset);
			if(!riu_pop(offset, 1))
				continue;
			status = nciop->rel(nciop, offset, RGN_MODIFIED);
			if(status)
			{
				fprintf(stderr, "- relm %8ld error: %s\n",
					offset, strerror(status));
				continue;
			}
		}
		else if(sscanf(linebuf, "get 0x%lx %ld", &offset, &extent) == 2
			|| sscanf(linebuf, "get %ld %ld", &offset, &extent) == 2)
		{
			if(verbose)
				printf("- get  %10ld %8ld\n", offset, extent);
			status = nciop->get(nciop, offset, extent, 0, &vp);
			if(status)
			{
				fprintf(stderr, "- get  error: %s\n",
					strerror(status));
				continue;
			}
			riu_push(offset, extent, vp);
		}
		else if(sscanf(linebuf, "getw 0x%lx %ld", &offset, &extent) == 2
			|| sscanf(linebuf, "getw %ld %ld", &offset, &extent) == 2)
		{
			if(verbose)
				printf("- getw %10ld %8ld\n", offset, extent);
			status = nciop->get(nciop, offset, extent, RGN_WRITE, &vp);
			if(status)
			{
				fprintf(stderr, "- getw  error: %s\n",
					strerror(status));
				continue;
			}
			riu_push(offset, extent, vp);
		}
		else if(strchr(linebuf, 'q') != NULL)
			break;
		else
			printf("???\n");
	}

	status = ncio_close(nciop, doUnlink);
	if(status != ENOERR)
	{
		fprintf(stderr, "ncio_close(%s): %s: %s\n",
			doUnlink ? "doUnlink" : "",
			path, strerror(status));
		return(EXIT_FAILURE);
	}

	return(EXIT_SUCCESS);
}
Esempio n. 5
0
/* 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 - pointer to sizehint parameter from nc__open or
   nc__create. This is used to set pxp->blksz.

   Here's what the man page has to say:

   "The argument referenced by chunksize controls a space versus time
   tradeoff, memory allocated in the netcdf library versus number of
   system calls.

   Because of internal requirements, the value may not be set to
   exactly the value requested. The actual value chosen is returned by reference.

   Using the value NC_SIZEHINT_DEFAULT causes the library to choose a
   default. How the system choses the default depends on the
   system. On many systems, the "preferred I/O block size" is
   available from the stat() system call, struct stat member
   st_blksize. If this is available it is used. Lacking that, twice
   the system pagesize is used. Lacking a call to discover the system
   pagesize, we just set default chunksize to 8192.

   The chunksize is a property of a given open netcdf descriptor ncid,
   it is not a persistent property of the netcdf dataset."

   nciopp - pointer to pointer that will get address of newly created
   and inited ncio struct.

   igetvpp - handle to pass back pointer to data from inital page
   read, if this were ever used, which it isn't.
*/
int
posixio_open(const char *path,
	int ioflags,
	off_t igeto, size_t igetsz, size_t *sizehintp,
	ncio **nciopp, void **const igetvpp)
{
	ncio *nciop;
	int oflags = fIsSet(ioflags, NC_WRITE) ? O_RDWR : O_RDONLY;
	int fd = -1;
	int status = 0;

	if(path == NULL || *path == 0)
		return EINVAL;

	nciop = ncio_px_new(path, ioflags);
	if(nciop == NULL)
		return ENOMEM;

//#ifdef O_BINARY
#if _MSC_VER
	fSet(oflags, O_BINARY);
#endif
#ifdef vms
	fd = open(path, oflags, 0, "ctx=stm");
#else
	fd = open(path, oflags, 0);
#endif
	if(fd < 0)
	{
		status = errno;
		goto unwind_new;
	}
	*((int *)&nciop->fd) = fd; /* cast away const */

	if(*sizehintp < NCIO_MINBLOCKSIZE)
	{
		/* Use default */
		*sizehintp = blksize(fd);
	}
	else if(*sizehintp >= NCIO_MAXBLOCKSIZE)
	{
		/* Use maximum allowed value */
		*sizehintp = NCIO_MAXBLOCKSIZE;
	}
	else
	{
		*sizehintp = M_RNDUP(*sizehintp);
	}

	if(fIsSet(nciop->ioflags, NC_SHARE))
		status = ncio_spx_init2(nciop, sizehintp);
	else
		status = ncio_px_init2(nciop, sizehintp, 0);

	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) close(fd); /* assert fd >= 0 */
	/*FALLTHRU*/
unwind_new:
	ncio_close(nciop,0);
	return status;
}
Esempio n. 6
0
/* Create a file, and the ncio struct to go with it. This funtion 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 - this eventually goes into pxp->blksz and is 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.
   igetvpp - pointer to pointer which will get the location of ?
*/
int
posixio_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;
	int oflags = (O_RDWR|O_CREAT);
	int fd;
	int status;

	if(initialsz < (size_t)igeto + igetsz)
		initialsz = (size_t)igeto + igetsz;

	fSet(ioflags, NC_WRITE);

	if(path == NULL || *path == 0)
		return EINVAL;

	nciop = ncio_px_new(path, ioflags);
	if(nciop == NULL)
		return ENOMEM;

	if(fIsSet(ioflags, NC_NOCLOBBER))
		fSet(oflags, O_EXCL);
	else
		fSet(oflags, O_TRUNC);
#ifdef O_BINARY
	fSet(oflags, O_BINARY);
#endif
#ifdef vms
	fd = open(path, oflags, NC_DEFAULT_CREAT_MODE, "ctx=stm");
#else
	/* Should we mess with the mode based on NC_SHARE ?? */
	fd = open(path, oflags, NC_DEFAULT_CREAT_MODE);
#endif
#if 0
	(void) fprintf(stderr, "ncio_create(): path=\"%s\"\n", path);
	(void) fprintf(stderr, "ncio_create(): oflags=0x%x\n", oflags);
#endif
	if(fd < 0)
	{
		status = errno;
		goto unwind_new;
	}
	*((int *)&nciop->fd) = fd; /* cast away const */

	if(*sizehintp < NCIO_MINBLOCKSIZE)
	{
		/* Use default */
		*sizehintp = blksize(fd);
	}
	else if(*sizehintp >= NCIO_MAXBLOCKSIZE)
	{
		/* Use maximum allowed value */
		*sizehintp = NCIO_MAXBLOCKSIZE;
	}
	else
	{
		*sizehintp = M_RNDUP(*sizehintp);
	}

	if(fIsSet(nciop->ioflags, NC_SHARE))
		status = ncio_spx_init2(nciop, sizehintp);
	else
		status = ncio_px_init2(nciop, sizehintp, 1);

	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) close(fd);
	/* ?? unlink */
	/*FALLTHRU*/
unwind_new:
	ncio_close(nciop,!fIsSet(ioflags, NC_NOCLOBBER));
	return status;
}
Esempio n. 7
0
/* 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;
}
Esempio n. 8
0
int
ffio_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_ffio_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_close(nciop,0);
	return status;
}
Esempio n. 9
0
int
nc__create_mp(const char * path, int ioflags, size_t initialsz, int basepe,
	size_t *chunksizehintp, int *ncid_ptr)
{
	NC *ncp;
	int status;
	void *xp = NULL;
	int sizeof_off_t = 0;

#if ALWAYS_NC_SHARE /* DEBUG */
	fSet(ioflags, NC_SHARE);
#endif

	ncp = new_NC(chunksizehintp);
	if(ncp == NULL)
		return NC_ENOMEM;

#if defined(LOCKNUMREC) /* && _CRAYMPP */
	if (status = NC_init_pe(ncp, basepe)) {
		return status;
	}
#else
	/*
	 * !_CRAYMPP, only pe 0 is valid
	 */
	if(basepe != 0)
		return NC_EINVAL;
#endif

	assert(ncp->flags == 0);

	/* Apply default create format. */
	if (default_create_format == NC_FORMAT_64BIT)
	  ioflags |= NC_64BIT_OFFSET;

	if (fIsSet(ioflags, NC_64BIT_OFFSET)) {
	  fSet(ncp->flags, NC_64BIT_OFFSET);
	  sizeof_off_t = 8;
	} else {
	  sizeof_off_t = 4;
	}

	assert(ncp->xsz == ncx_len_NC(ncp,sizeof_off_t));
	
	status = ncio_create(path, ioflags,
		initialsz,
		0, ncp->xsz, &ncp->chunk,
		&ncp->nciop, &xp);
	if(status != NC_NOERR)
	{
		/* translate error status */
		if(status == EEXIST)
			status = NC_EEXIST;
		goto unwind_alloc;
	}

	fSet(ncp->flags, NC_CREAT);

	if(fIsSet(ncp->nciop->ioflags, NC_SHARE))
	{
		/*
		 * NC_SHARE implies sync up the number of records as well.
		 * (File format version one.)
		 * Note that other header changes are not shared
		 * automatically.  Some sort of IPC (external to this package)
		 * would be used to trigger a call to nc_sync().
		 */
		fSet(ncp->flags, NC_NSYNC);
	}

	status = ncx_put_NC(ncp, &xp, sizeof_off_t, ncp->xsz);
	if(status != NC_NOERR)
		goto unwind_ioc;

	add_to_NCList(ncp);

	if(chunksizehintp != NULL)
		*chunksizehintp = ncp->chunk;
	*ncid_ptr = ncp->nciop->fd;
	return NC_NOERR;

unwind_ioc:
	(void) ncio_close(ncp->nciop, 1); /* N.B.: unlink */
	ncp->nciop = NULL;
	/*FALLTHRU*/
unwind_alloc:
	free_NC(ncp);
	return status;
}
Esempio n. 10
0
int
nc__open_mp(const char * path, int ioflags, int basepe,
	size_t *chunksizehintp, int *ncid_ptr)
{
	NC *ncp;
	int status;

#if ALWAYS_NC_SHARE /* DEBUG */
	fSet(ioflags, NC_SHARE);
#endif

	ncp = new_NC(chunksizehintp);
	if(ncp == NULL)
		return NC_ENOMEM;

#if defined(LOCKNUMREC) /* && _CRAYMPP */
	if (status = NC_init_pe(ncp, basepe)) {
		return status;
	}
#else
	/*
	 * !_CRAYMPP, only pe 0 is valid
	 */
	if(basepe != 0)
		return NC_EINVAL;
#endif

	status = ncio_open(path, ioflags,
		0, 0, &ncp->chunk,
		&ncp->nciop, 0);
	if(status)
		goto unwind_alloc;

	assert(ncp->flags == 0);

	if(fIsSet(ncp->nciop->ioflags, NC_SHARE))
	{
		/*
		 * NC_SHARE implies sync up the number of records as well.
		 * (File format version one.)
		 * Note that other header changes are not shared
		 * automatically.  Some sort of IPC (external to this package)
		 * would be used to trigger a call to nc_sync().
		 */
		fSet(ncp->flags, NC_NSYNC);
	}

	status = nc_get_NC(ncp);
	if(status != NC_NOERR)
		goto unwind_ioc;

	add_to_NCList(ncp);

	if(chunksizehintp != NULL)
		*chunksizehintp = ncp->chunk;
	*ncid_ptr = ncp->nciop->fd;
	return NC_NOERR;

unwind_ioc:
	(void) ncio_close(ncp->nciop, 0);
	ncp->nciop = NULL;
	/*FALLTHRU*/
unwind_alloc:
	free_NC(ncp);
	return status;
}