Example #1
0
/* ARGSUSED */
static int
px_double_buffer(ncio *const nciop, off_t to, off_t from,
                 size_t nbytes, int rflags)
{
  ncio_px *const pxp = (ncio_px *)nciop->pvt;
  int status = ENOERR;
  void *src;
  void *dest;
  (void)rflags;
  
#if INSTRUMENT
fprintf(stderr, "\tdouble_buffr %ld %ld %ld\n",
     (long)to, (long)from, (long)nbytes);
#endif
  status = px_get(nciop, pxp, to, nbytes, RGN_WRITE,
      &dest);
  if(status != ENOERR)
    return status;

  if(pxp->slave == NULL)
  {
    pxp->slave = (ncio_px *) malloc(sizeof(ncio_px));
    if(pxp->slave == NULL)
      return ENOMEM;

    pxp->slave->blksz = pxp->blksz;
    /* pos done below */
    pxp->slave->bf_offset = pxp->bf_offset; 
    pxp->slave->bf_extent = pxp->bf_extent;
    pxp->slave->bf_cnt = pxp->bf_cnt;
    pxp->slave->bf_base = malloc(2 * pxp->blksz);
    if(pxp->slave->bf_base == NULL)
      return ENOMEM;
    (void) memcpy(pxp->slave->bf_base, pxp->bf_base,
       pxp->bf_extent);
    pxp->slave->bf_rflags = 0;
    pxp->slave->bf_refcount = 0;
    pxp->slave->slave = NULL;
  }
  
  pxp->slave->pos = pxp->pos;
  status = px_get(nciop, pxp->slave, from, nbytes, 0,
      &src);
  if(status != ENOERR)
    return status;
  if(pxp->pos != pxp->slave->pos)
  {
    /* position changed, sync */
    pxp->pos = pxp->slave->pos;
  }

  (void) memcpy(dest, src, nbytes);

  (void)px_rel(pxp->slave, from, 0);
  (void)px_rel(pxp, to, RGN_MODIFIED);
  
  return status;
}
Example #2
0
/* This function indicates the file region starting at offset may be
   released.  Each read or write to the file is bracketed by a call to
   the "get" region function and a call to the "rel" region function.
   If you only read from the memory region, release it with a flag of
   0, if you modify the region, release it with a flag of
   RGN_MODIFIED.

   For POSIX system, without NC_SHARE, this becomes the rel function
   pointed to by the ncio rel function pointer. It mearly checks for
   file write permission, then calls px_rel to do everything.

   nciop - pointer to ncio struct.
   offset - num bytes from beginning of buffer to region to be
   released.
   rflags - only RGN_MODIFIED is relevent to this function, others ignored
*/
static int
ncio_px_rel(ncio *const nciop, off_t offset, int rflags)
{
	ncio_px *const pxp = (ncio_px *)nciop->pvt;

	if(fIsSet(rflags, RGN_MODIFIED) && !fIsSet(nciop->ioflags, NC_WRITE))
		return EPERM; /* attempt to write readonly file */

	return px_rel(pxp, offset, rflags);
}
Example #3
0
/* Like memmove(), safely move possibly overlapping data.

   Copy one region to another without making anything available to
   higher layers. May be just implemented in terms of get() and rel(),
   or may be tricky to be efficient. Only used in by nc_enddef()
   after redefinition.

   nciop - pointer to ncio struct with file info.
   to - src for move?
   from - dest for move?
   nbytes - number of bytes to move.
   rflags - One of the RGN_* flags defined in ncio.h. The only
   reasonable flag value is RGN_NOLOCK.
*/
static int
ncio_px_move(ncio *const nciop, off_t to, off_t from,
			size_t nbytes, int rflags)
{
	ncio_px *const pxp = (ncio_px *)nciop->pvt;
	int status = ENOERR;
	off_t lower;
	off_t upper;
	char *base;
	size_t diff;
	size_t extent;

	if(to == from)
		return ENOERR; /* NOOP */

	if(fIsSet(rflags, RGN_WRITE) && !fIsSet(nciop->ioflags, NC_WRITE))
		return EPERM; /* attempt to write readonly file */

	rflags &= RGN_NOLOCK; /* filter unwanted flags */

	if(to > from)
	{
		/* growing */
		lower = from;
		upper = to;
	}
	else
	{
		/* shrinking */
		lower = to;
		upper = from;
	}
	diff = (size_t)(upper - lower);
	extent = diff + nbytes;

#if INSTRUMENT
fprintf(stderr, "ncio_px_move %ld %ld %ld %ld %ld\n",
		 (long)to, (long)from, (long)nbytes, (long)lower, (long)extent);
#endif
	if(extent > pxp->blksz)
	{
		size_t remaining = nbytes;

if(to > from)
{
		off_t frm = from + nbytes;
		off_t toh = to + nbytes;
		for(;;)
		{
			size_t loopextent = MIN(remaining, pxp->blksz);
			frm -= loopextent;
			toh -= loopextent;

			status = px_double_buffer(nciop, toh, frm,
				 	loopextent, rflags) ;
			if(status != ENOERR)
				return status;
			remaining -= loopextent;

			if(remaining == 0)
				break; /* normal loop exit */
		}
}
else
{
		for(;;)
		{
			size_t loopextent = MIN(remaining, pxp->blksz);

			status = px_double_buffer(nciop, to, from,
				 	loopextent, rflags) ;
			if(status != ENOERR)
				return status;
			remaining -= loopextent;

			if(remaining == 0)
				break; /* normal loop exit */
			to += loopextent;
			from += loopextent;
		}
}
		return ENOERR;
	}

#if INSTRUMENT
fprintf(stderr, "\tncio_px_move small\n");
#endif
	status = px_get(nciop, pxp, 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) px_rel(pxp, lower, RGN_MODIFIED);

	return status;
}