5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * CDDL HEADER START
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * The contents of this file are subject to the terms of the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Common Development and Distribution License (the "License").
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * You may not use this file except in compliance with the License.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * or http://www.opensolaris.org/os/licensing.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * See the License for the specific language governing permissions
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and limitations under the License.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * When distributing Covered Code, include this CDDL HEADER in each
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If applicable, add the following below this CDDL HEADER, with the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner]
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * CDDL HEADER END
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Use is subject to license terms.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Module: vfpops.c
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Synopsis: Implements virtual file protocol operations
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This module implements the "Virtual File protocol" operations. These
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * operations are intended to provide very fast access to file data,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * allowing a file to be accessed in very efficient ways with extremely
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * low-cpu intensive operations. If possible file data is mapped directly
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * into memory allowing the data to be accessed directly. If the data
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * cannot be mapped directly into memory, memory will be allocated and
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the file data read directly into memory. If that fails currently the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * file data is not accessible. Other methods of making the file could
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * be implemented in the future (e.g. stdio if all else fails).
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * In general any code that uses stdio to access a file can be changed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * to use the various "vfp" operations to access a file, with a resulting
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * increase in performance and decrease in cpu time required to access
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the file contents.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Public Methods:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpCheckpointFile - Create new VFP that checkpoints existing VFP
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpCheckpointOpen - open file, allocate storage, return pointer to VFP_T
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpClose - close file associated with vfp
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpDecCurrPtr - decrement current character pointer
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpGetBytesRemaining - get number of bytes remaining to read
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpGetCurrCharPtr - get pointer to current character
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpGetCurrPtrDelta - get number of bytes between current and specified char
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpGetFirstCharPtr - get pointer to first character
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpGetLastCharPtr - get pointer to last character
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpGetModifiedLen - get highest modified byte (length) contained in vfp
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpGetPath - get the path associated with the vfp
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpGetc - get current character and increment to next
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpGetcNoInc - get current character - do not increment
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpGets - get a string from the vfp into a fixed size buffer
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpIncCurrPtr - increment current character pointer
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpIncCurrPtrBy - increment current pointer by specified delta
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpOpen - open file on vfp
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpPutBytes - put fixed number of bytes to current character and increment
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpPutFormat - put format one arg to current character and increment
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpPutInteger - put integer to current character and increment
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpPutLong - put long to current character and increment
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpPutc - put current character and increment to next
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpPuts - put string to current character and increment
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpRewind - rewind file to first byte
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpSeekToEnd - seek to end of file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpSetCurrCharPtr - set pointer to current character
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpSetFlags - set flags that affect file access
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpSetSize - set size of file (for writing)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpTruncate - truncate file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpWriteToFile - write data contained in vfp to specified file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <stdio.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <limits.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <stdlib.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <string.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <strings.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <unistd.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <ctype.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <fcntl.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/types.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/stat.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/mman.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <errno.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <libintl.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "pkglib.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "pkgstrct.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "pkglocale.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * These are internal flags that occupy the high order byte of the VFPFLAGS_T
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * flags element of the vfp. These flags may only occupy the high order order
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * 16 bits of the 32-bit unsigned vfp "flags" object.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define _VFP_MMAP 0x00010000 /* mmap used */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define _VFP_MALLOC 0x00020000 /* malloc used */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define _VFP_WRITE 0x00040000 /* file opened for write */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define _VFP_READ 0x00080000 /* file opened for reading */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define _VFP_MODIFIED 0x00100000 /* contents are marked modified */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* path name given to "anonymous" (string) vfp */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define VFP_ANONYMOUS_PATH "<<string>>"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* minimum size file to mmap (64mb) */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define MIN_MMAP_SIZE (64*1024)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * *****************************************************************************
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * global external (public) functions
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * *****************************************************************************
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: vfpOpen
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Open file on vfp, allocate storage, return pointer to VFP_T
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * that can be used to access/modify file contents.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: VFP_T **r_vfp - pointer to pointer to VFP_T
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * char *a_path - path of file to open and associate with this VFP.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - if the path is (char *)NULL then no file is associated
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * with this VFP - this is a way to create a fixed length
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * string that can be manipulated with the VFP operators.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Before the VFP can be used "vfpSetSize" must be called
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * to set the size of the string buffer.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * char *a_mode - fopen mode to open the file with
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * VFPFLAGS_T a_flags - one or more flags to control the operation:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - VFP_NONE - no special flags
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - VFP_NEEDNOW - file data needed in memory now
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - VFP_SEQUENTIAL - memory will be sequentially accessed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - VFP_RANDOM - memory will be randomly accessed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - VFP_NOMMAP - do not use mmap to access file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - VFP_NOMALLOC - do not use malloc to buffer file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int == 0 - operation was successful
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != 0 - operation failed, errno contains reason
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Side Effects: r_vfp -- filled in with a pointer to a newly allocated vfp
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * which can be used with the various vfp functions.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * errno -- contains system error number if return is != 0
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandvfpOpen(VFP_T **r_vfp, char *a_path, char *a_mode, VFPFLAGS_T a_flags)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland FILE *fp = (FILE *)NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland VFP_T *vfp;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int lerrno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct stat statbuf;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int pagesize = getpagesize();
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* reset return VFP/FILE pointers */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (*r_vfp) = (VFP_T *)NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* allocate pre-zeroed vfp object */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp = (VFP_T *)calloc(sizeof (VFP_T), 1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (vfp == (VFP_T *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* create "string" vfp if no path specified */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_path == (char *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * no path specified - no open file associated with vfp
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * The vfp is initialized to all zeros - initialize just those
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * values that need to be non-zero.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpFlags = _VFP_MALLOC;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpPath = strdup(VFP_ANONYMOUS_PATH);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (*r_vfp) = vfp;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * path specified - associate open file with vfp;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * return an error if no path or mode specified
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_mode == (char *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = EFAULT; /* Bad address */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(vfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return an error if an empty path or mode specified */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((*a_path == '\0') || (*a_mode == '\0')) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = EINVAL; /* Invalid argument */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(vfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* open the file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland fp = fopen(a_path, a_mode);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (fp == (FILE *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland lerrno = errno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(vfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = lerrno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* Get the file size */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (fstat(fileno(fp), &statbuf) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland lerrno = errno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) fclose(fp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(vfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = lerrno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Obtain access to existing file contents:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * -> plan a: map contents file into memory
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * -> plan b: on failure just read into large buffer
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* attempt to mmap file if mmap is allowed */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpStart = MAP_FAILED; /* assume map failed if not allowed */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * if file is a regular file, and if mmap allowed,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and (malloc not forbidden or size is > minumum size to mmap)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((S_ISREG(statbuf.st_mode)) && (!(a_flags & VFP_NOMMAP)) &&
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ((a_flags & VFP_NOMALLOC) || statbuf.st_size > MIN_MMAP_SIZE)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *p;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* set size to current size of file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpMapSize = statbuf.st_size;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * compute proper size for mapping for the file contents;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * add in one extra page so falling off end when file size is
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * exactly modulo page size does not cause a page fault to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * guarantee that the end of the file contents will always
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * contain a '\0' null character.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpSize = (statbuf.st_size + pagesize +
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (pagesize-(statbuf.st_size % pagesize)));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * mmap allowed: mmap file into memory
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * first allocate space on top of which the mapping can be done;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * this way we can guarantee that if the mapping happens to be
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * an exact multiple of a page size, that there will be at least
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * one byte past the end of the mapping that can be accessed and
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * that is guaranteed to be zero.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* allocate backing space */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland p = (char *)memalign(pagesize, vfp->_vfpSize);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (p == (char *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpStart = MAP_FAILED;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* guarantee first byte after end of data is zero */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland p[vfp->_vfpMapSize] = '\0';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* map file on top of the backing space */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpStart = mmap(p, vfp->_vfpMapSize, PROT_READ,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland MAP_PRIVATE|MAP_FIXED, fileno(fp), (off_t)0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if mmap succeeded set mmap used flag in vfp */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (vfp->_vfpStart != MAP_FAILED) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpFlags |= _VFP_MMAP;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if map failed (or not allowed) attempt malloc (if allowed) */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((vfp->_vfpStart == MAP_FAILED) && (!(a_flags & VFP_NOMALLOC))) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* mmap failed - plan b: read directly into memory */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ssize_t rlen;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * compute proper size for allocating storage for file contents;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * add in one extra page so falling off end when file size is
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * exactly modulo page size does not cause a page fault to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * guarantee that the end of the file contents will always
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * contain a '\0' null character.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpSize = statbuf.st_size+pagesize;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* allocate buffer to hold file data */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpStart = memalign((size_t)pagesize, vfp->_vfpSize);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (vfp->_vfpStart == (char *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland lerrno = errno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) fclose(fp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(vfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = lerrno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* read the file into the buffer */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (statbuf.st_size != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland rlen = read(fileno(fp), vfp->_vfpStart,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland statbuf.st_size);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (rlen != statbuf.st_size) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland lerrno = errno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (lerrno == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland lerrno = EIO;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(vfp->_vfpStart);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) fclose(fp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(vfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = lerrno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* assure last byte+1 is null character */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ((char *)vfp->_vfpStart)[statbuf.st_size] = '\0';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* set malloc used flag in vfp */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpFlags |= _VFP_MALLOC;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if no starting address all read methods failed */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (vfp->_vfpStart == MAP_FAILED) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* no mmap() - no read() - cannot allocate memory */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) fclose(fp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(vfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = ENOMEM;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * initialize vfp contents
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* _vfpCurr -> next byte to read */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpCurr = (char *)vfp->_vfpStart;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* _vfpEnd -> last data byte */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpEnd = (((char *)vfp->_vfpStart) + statbuf.st_size)-1;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* _vfpHighWater -> last byte written */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpHighWater = (char *)vfp->_vfpEnd;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* _vfpFile -> associated FILE* object */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpFile = fp;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* set flags as appropriate */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) vfpSetFlags(vfp, a_flags);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* retain path name */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpPath = strdup(a_path ? a_path : "");
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* set read/write flags */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (*a_mode == 'w') {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpFlags |= _VFP_WRITE;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (*a_mode == 'r') {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpFlags |= _VFP_READ;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* set return vfp pointer */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (*r_vfp) = vfp;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* All OK */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: vfpClose
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Close an open vfp, causing any modified data to be written out
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * to the file associated with the vfp.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: VFP_T **r_vfp - pointer to pointer to VFP_T returned by vfpOpen
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int == 0 - operation was successful
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != 0 - operation failed, errno contains reason
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Side Effects: r_vfp is set to (VFP_T)NULL
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandvfpClose(VFP_T **r_vfp)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int ret;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int lerrno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland VFP_T *vfp;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return error if NULL VFP_T** provided */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (r_vfp == (VFP_T **)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = EFAULT;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* localize access to VFP_T */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp = *r_vfp;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return successful if NULL VFP_T* provided */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (vfp == (VFP_T *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* reset return VFP_T* handle */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *r_vfp = (VFP_T *)NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * if closing a file that is open for writing, commit all data if the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * backing memory is volatile and if there is a file open to write
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the data to.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (vfp->_vfpFlags & _VFP_WRITE) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((vfp->_vfpFlags & _VFP_MALLOC) &&
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (vfp->_vfpFile != (FILE *)NULL)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland size_t len;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* determine number of bytes to write */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland len = vfpGetModifiedLen(vfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if modified bytes present commit data to the file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (len > 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) vfpSafePwrite(fileno(vfp->_vfpFile),
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpStart, len, (off_t)0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* deallocate any allocated storage/mappings/etc */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (vfp->_vfpFlags & _VFP_MALLOC) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(vfp->_vfpStart);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else if (vfp->_vfpFlags & _VFP_MMAP) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* unmap the file mapping */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) munmap(vfp->_vfpStart, vfp->_vfpMapSize);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* free the backing allocation */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(vfp->_vfpStart);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* free up path */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(vfp->_vfpPath);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* close the file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ret = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (vfp->_vfpFile != (FILE *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ret = fclose(vfp->_vfpFile);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland lerrno = errno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* deallocate the vfp itself */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(vfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if the fclose() failed, return error and errno */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (ret != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = lerrno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: vfpSetFlags
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Modify operation of VFP according to flags specified
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to set flags
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * VFPFLAGS_T a_flags - one or more flags to control the operation:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - VFP_NEEDNOW - file data needed in memory now
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - VFP_SEQUENTIAL - file data sequentially accessed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - VFP_RANDOM - file data randomly accessed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Any other flags specified are silently ignored.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int == 0 - operation was successful
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != 0 - operation failed, errno contains reason
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandvfpSetFlags(VFP_T *a_vfp, VFPFLAGS_T a_flags)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return if no vfp specified */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_vfp == (VFP_T *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if file data mapped into memory, apply vm flags */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((a_vfp->_vfpSize != 0) && (a_vfp->_vfpFlags & _VFP_MMAP)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* mmap succeeded: properly advise vm system */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_flags & VFP_NEEDNOW) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* advise vm system data is needed now */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) madvise(a_vfp->_vfpStart, a_vfp->_vfpMapSize,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland MADV_WILLNEED);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_flags & VFP_SEQUENTIAL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* advise vm system data access is sequential */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) madvise(a_vfp->_vfpStart, a_vfp->_vfpSize,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland MADV_SEQUENTIAL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_flags & VFP_RANDOM) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* advise vm system data access is random */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) madvise(a_vfp->_vfpStart, a_vfp->_vfpSize,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland MADV_RANDOM);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: vfpRewind
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Reset default pointer for next read/write to start of file data
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to rewind
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: void
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Operation is always successful
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandvoid
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandvfpRewind(VFP_T *a_vfp)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return if no vfp specified */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_vfp == (VFP_T *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* set high water mark of last modified data */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_vfp->_vfpCurr > a_vfp->_vfpHighWater) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_vfp->_vfpHighWater = a_vfp->_vfpCurr;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* reset next character pointer to start of file data */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_vfp->_vfpCurr = a_vfp->_vfpStart;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: vfpSetSize
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Set size of in-memory image associated with VFP
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to set
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * size_t a_size - number of bytes to associatge with VFP
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int == 0 - operation was successful
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != 0 - operation failed, errno contains reason
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Side Effects:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Currently only a file that is in malloc()ed memory can
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * have its in-memory size changed.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * An error is returned If the file is mapped into memory.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * A file cannot be decreased in size - if the specified
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * size is less than the current size, the operation is
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * successful but no change in file size occurs.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If no file is associated with the VFP (no "name" was
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * given to vfpOpen) the first call to vfpSetSize allocates
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the initial size of the file data - effectively calling
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * "malloc" to allocate the initial memory for the file data.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Once an initial allocation has been made, subsequent calls
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * to vfpSetSize are effectively a "realloc" of the existing
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * file data.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * All existing file data is preserved.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandvfpSetSize(VFP_T *a_vfp, size_t a_size)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *np;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland size_t curSize;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return if no vfp specified */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_vfp == (VFP_T *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if malloc not used don't know how to set size right now */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (!(a_vfp->_vfpFlags & _VFP_MALLOC)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* adjust size to reflect extra page of data maintained */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_size += getpagesize();
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if size is not larger than current nothing to do */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_size <= a_vfp->_vfpSize) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* remember new size */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland curSize = a_vfp->_vfpSize;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_vfp->_vfpSize = a_size;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* allocate/reallocate memory as appropriate */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_vfp->_vfpStart != (char *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland np = (char *)realloc(a_vfp->_vfpStart, a_vfp->_vfpSize+1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (np == (char *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland np[curSize-1] = '\0';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland np = (char *)malloc(a_vfp->_vfpSize+1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (np == (char *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland np[0] = '\0';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* make sure last allocated byte is a null */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland np[a_vfp->_vfpSize] = '\0';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * adjust all pointers to account for buffer address change
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* _vfpCurr -> next byte to read */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_vfp->_vfpCurr = (char *)(((ptrdiff_t)a_vfp->_vfpCurr -
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (ptrdiff_t)a_vfp->_vfpStart) + np);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* _vfpHighWater -> last byte written */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_vfp->_vfpHighWater = (char *)(((ptrdiff_t)a_vfp->_vfpHighWater -
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (ptrdiff_t)a_vfp->_vfpStart) + np);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* _vfpEnd -> last data byte */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_vfp->_vfpEnd = (np + a_vfp->_vfpSize)-1;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* _vfpStart -> first data byte */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_vfp->_vfpStart = np;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: vfpTruncate
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Truncate data associated with VFP
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to truncate
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: void
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Operation is always successful.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Side Effects:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * In memory data associated with file is believed to be empty.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Actual memory associated with file is not affected.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If a file is associated with the VFP, it is truncated.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandvoid
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandvfpTruncate(VFP_T *a_vfp)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return if no vfp specified */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_vfp == (VFP_T *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * reset all pointers so that no data is associated with file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* current byte is start of data area */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_vfp->_vfpCurr = a_vfp->_vfpStart;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* last byte written is start of data area */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_vfp->_vfpHighWater = a_vfp->_vfpStart;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* current character is NULL */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *a_vfp->_vfpCurr = '\0';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if file associated with VFP, truncate actual file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_vfp->_vfpFile != (FILE *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) ftruncate(fileno(a_vfp->_vfpFile), 0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: vfpWriteToFile
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Write data associated with VFP to specified file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to write
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * char *a_path - path of file to write file data to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int == 0 - operation was successful
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != 0 - operation failed, errno contains reason
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandvfpWriteToFile(VFP_T *a_vfp, char *a_path)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int fd;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int lerrno = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland size_t len;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ssize_t result = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return if no vfp specified */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_vfp == (VFP_T *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = EFAULT;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* on buffer overflow generate error */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((a_vfp->_vfpOverflow != 0) || (vfpGetBytesAvailable(a_vfp) < 1)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = EFBIG;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* open file to write data to */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland fd = open(a_path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (fd < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* determine number of bytes to write */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland len = vfpGetModifiedLen(a_vfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * if there is data associated with the file, write it out;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * if an error occurs, close the file and return failure.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (len > 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland result = vfpSafeWrite(fd, a_vfp->_vfpStart, len);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (result != len) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* error comitting data - return failure */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland lerrno = errno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(fd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = lerrno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* close the file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) close(fd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* data committed to backing store - clear the modified flag */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) vfpClearModified(a_vfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return success */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: vfpCheckpointFile
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Create new VFP that checkpoints existing VFP, can be used by
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * subsequent call to vfpCheckpointOpen to open a file using the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * existing in-memory cache of the contents of the file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: VFP_T **r_cpVfp - pointer to pointer to VFP_T to be filled in
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * with "checkpointed file" VFP (backing store)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * VFP_T **a_vfp - pointer to pointer to VFP_T returned by vfpOpen
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * representing the VFP to checkpoint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * char *a_path - path to file that is the backing store for the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * in-memory data represented by a_vfp - used to verify
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * that the data in memory is not out of date with respect
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * to the backing store when vfpCheckpointOpen is called
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == (char *)NULL - use path associated with a_vfp
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * that is, the backing store file in use
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int == 0 - operation was successful
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - r_destVfp contains a pointer to a new VFP that
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * may be used in a subsequent call to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * vfpCheckpointOpen
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - the VFP referenced by *a_vfp is free()ed and
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * must no longer be referenced
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != 0 - operation failed, errno contains reason
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - the VFP referenced by *a_vfp is not affected;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the caller may continue to use it
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Notes: If the data of a VFP to checkpoint is mmap()ed then this method
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * returns failure - only malloc()ed data VFPs can be
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * checkpointed.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandvfpCheckpointFile(VFP_T **r_cpVfp, VFP_T **a_vfp, char *a_path)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland VFP_T *vfp; /* newly allocated checkpointed VFP */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland VFP_T *avfp; /* local -> to a_vfp */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct stat statbuf; /* stat(2) info for backing store */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return error if NULL VFP_T** to checkpoint provided */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (r_cpVfp == (VFP_T **)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = EFAULT;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* reset return checkpoint VFP pointer */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (*r_cpVfp) = (VFP_T *)NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return error if no VFP to checkpoint specified */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (a_vfp == (VFP_T **)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = EFAULT;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* localize reference to a_vfp */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland avfp = *a_vfp;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return error if no VFP to checkpoint specified */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (avfp == (VFP_T *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = EFAULT;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* on buffer overflow generate error */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((avfp->_vfpOverflow != 0) || (vfpGetBytesAvailable(avfp) < 1)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = EFBIG;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* no checkpointing is possible if the existing VFP is mmap()ed */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (avfp->_vfpFlags & _VFP_MMAP) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = EIO;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if no path specified, grab it from the VFP to checkpoint */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((a_path == (char *)NULL) || (*a_path == '\0')) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_path = avfp->_vfpPath;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* backing store required: if VFP is "string" then this is an error */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((a_path == (char *)NULL) ||
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland strcmp(a_path, VFP_ANONYMOUS_PATH) == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = EINVAL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* Get the VFP to checkpoint (backing store) file size */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (stat(a_path, &statbuf) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* allocate storage for checkpointed VFP (to return) */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp = (VFP_T *)malloc(sizeof (VFP_T));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (vfp == (VFP_T *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * close any file that is on the VFP to checkpoint (backing store);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * subsequent processes can modify the backing store data, and
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * then when vfpCheckpointOpen is called, either the in-memory
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * cached data will be used (if backing store unmodified) or else
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the in-memory data is released and the backing store is used.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (avfp->_vfpFile != (FILE *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) fclose(avfp->_vfpFile);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland avfp->_vfpFile = (FILE *)NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* free any path associated with VFP to checkpoint (backing store) */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (avfp->_vfpPath != (char *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(avfp->_vfpPath);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland avfp->_vfpPath = (char *)NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* copy contents of VFP to checkpoint to checkpointed VFP */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
4656d4747c8743290bfbe910c64cd75eb4e4af8dGarrett D'Amore (void) memcpy(vfp, avfp, sizeof (VFP_T));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* free contents of VFP to checkpoint */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(avfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* reset pointer to VFP that has been free'd */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *a_vfp = (VFP_T *)NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* remember path associated with the checkpointed VFP (backing store) */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpPath = strdup(a_path);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* save tokens that identify the backing store for the in-memory data */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpCkDev = statbuf.st_dev; /* devid holding st_ino inode */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpCkIno = statbuf.st_ino; /* backing store inode */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpCkMtime = statbuf.st_mtime; /* last data modification */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpCkSize = statbuf.st_size; /* backing store size (bytes) */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpCkStBlocks = statbuf.st_blocks; /* blocks allocated to file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* pass checkpointed VFP to caller */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (*r_cpVfp) = vfp;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* success! */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: vfpCheckpointOpen
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Open file on vfp, allocate storage, return pointer to VFP_T
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * that can be used to access/modify file contents. If a VFP_T to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a checkpointed VFP is passed in, and the in memory contents of
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the VFP are not out of date with respect to the backing store
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * file, use the existing in-memory contents - otherwise, discard
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the in-memory contents and reopen and reread the file.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: VFP_T **a_cpVfp - pointer to pointer to VFP_T that represents
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * checkpointed VFP to use to open the file IF the contents
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * of the backing store are identical to the in-memory data
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * VFP_T **r_vfp - pointer to pointer to VFP_T to open file on
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * char *a_path - path of file to open and associate with this VFP.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - if the path is (char *)NULL then no file is associated
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * with this VFP - this is a way to create a fixed length
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * string that can be manipulated with the VFP operators.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Before the VFP can be used "vfpSetSize" must be called
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * to set the size of the string buffer.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * char *a_mode - fopen mode to open the file with
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * VFPFLAGS_T a_flags - one or more flags to control the operation:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - VFP_NONE - no special flags
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - VFP_NEEDNOW - file data needed in memory now
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - VFP_SEQUENTIAL - memory will be sequentially accessed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - VFP_RANDOM - memory will be randomly accessed
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - VFP_NOMMAP - do not use mmap to access file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * - VFP_NOMALLOC - do not use malloc to buffer file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int == 0 - operation was successful
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != 0 - operation failed, errno contains reason
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Side Effects: r_vfp -- filled in with a pointer to a newly allocated vfp
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * which can be used with the various VFP functions.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_cpVfp -- contents reset to zero if used to open the file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * errno -- contains system error number if return is != 0
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandvfpCheckpointOpen(VFP_T **a_cpVfp, VFP_T **r_vfp, char *a_path,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *a_mode, VFPFLAGS_T a_flags)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland FILE *fp; /* backing store */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland VFP_T *cpVfp; /* local -> to a_cpVfp checkpointed VFP */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland VFP_T *vfp; /* new VFP open on checkpointed backing store */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct stat statbuf; /* stat(2) info on backing store */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * if no source VFP, or source VFP empty,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * or no backing store, just open file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((a_cpVfp == (VFP_T **)NULL) || (*a_cpVfp == (VFP_T *)NULL) ||
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ((*a_cpVfp)->_vfpStart == (char *)NULL)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) vfpClose(a_cpVfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (vfpOpen(r_vfp, a_path, a_mode, a_flags));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* localize access to checkpointed VFP_T (*a_cpVfp) */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland cpVfp = *a_cpVfp;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if no path specified, grab it from the checkpointed VFP */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((a_path == (char *)NULL) || (*a_path == '\0')) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_path = cpVfp->_vfpPath;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return error if no path specified and no path in checkpointed VFP */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((a_path == (char *)NULL) && (*a_path == '\0')) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = EINVAL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* if no backing store path, then just open file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (stat(a_path, &statbuf) != 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) vfpClose(a_cpVfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (vfpOpen(r_vfp, a_path, a_mode, a_flags));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * if backing store tokens do not match checkpointed VFP,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the backing store has been updated since the VFP was checkpointed;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * release the in-memory data, and open and read the backing store
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((statbuf.st_size != cpVfp->_vfpCkSize) ||
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (statbuf.st_mtime != cpVfp->_vfpCkMtime) ||
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (statbuf.st_blocks != cpVfp->_vfpCkStBlocks) ||
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (statbuf.st_ino != cpVfp->_vfpCkIno) ||
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (statbuf.st_dev != cpVfp->_vfpCkDev)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) vfpClose(a_cpVfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (vfpOpen(r_vfp, a_path, a_mode, a_flags));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * backing store has not been updated since the VFP was checkpointed;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * use the in-memory data without re-reading the backing store; open the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * backing store file (if no file already open on the checkpointed VFP)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * so there is an open file associated with the in-memory data
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland fp = cpVfp->_vfpFile;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (fp == (FILE *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland fp = fopen(a_path, a_mode);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (fp == (FILE *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int lerrno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland lerrno = errno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) vfpClose(a_cpVfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errno = lerrno;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (-1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* allocate new VFP object to return as open VFP */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp = (VFP_T *)malloc(sizeof (VFP_T));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (vfp == (VFP_T *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) vfpClose(a_cpVfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (vfpOpen(r_vfp, a_path, a_mode, a_flags));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* copy cached checkpointed VFP to new VFP to return */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) memcpy(vfp, cpVfp, sizeof (VFP_T));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * initialize VFP to return contents
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* FILE -> file opened on the VFPs backing store */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpFile = fp;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* release any existing path associated with the VFP */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (vfp->_vfpPath != (char *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(vfp->_vfpPath);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* path associated with the backing store for this VFP */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpPath = strdup(a_path);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * data pointers associated with in memory copy of backing store
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * (such as _vfpHighWater, _vfpEnd, _vfpStart, etc.)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * do not need to be modified because we are using the same backing
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * store as was checkpointed in cpVfp that is pointed to by vfp.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* _vfpCurr -> next byte to read */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland vfp->_vfpCurr = (char *)vfp->_vfpStart;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* free checkpointed VFP as it is now open on "vfp" */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) free(cpVfp);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* reset callers -> checkpointed VFP */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (*a_cpVfp) = (VFP_T *)NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* set return VFP pointer */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (*r_vfp) = vfp;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* success! */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: vfpClearModified
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Clear the "data is modified" indication from the VFP
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to clear
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the "data is modified" indication
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int - previous setting of "data is modified" indication
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == 0 - "data is modified" was NOT previously set
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != 0 - "data is modified" WAS previously set
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandvfpClearModified(VFP_T *a_vfp)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland VFPFLAGS_T flags;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* save current flags settings */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland flags = a_vfp->_vfpFlags;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* clear "data is modified" flag */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_vfp->_vfpFlags &= (~_VFP_MODIFIED);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return previous "data is modified" flag setting */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return ((flags & _VFP_MODIFIED) != 0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: vfpSetModified
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Set the "data is modified" indication from the VFP
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to set
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the "data is modified" indication
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int - previous setting of "data is modified" indication
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == 0 - "data is modified" was NOT previously set
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != 0 - "data is modified" WAS previously set
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandvfpSetModified(VFP_T *a_vfp)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland VFPFLAGS_T flags;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* save current flags settings */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland flags = a_vfp->_vfpFlags;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* set "data is modified" flag */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_vfp->_vfpFlags |= _VFP_MODIFIED;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return previous "data is modified" flag setting */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return ((flags & _VFP_MODIFIED) != 0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: vfpGetModified
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: Get the "data is modified" indication from the VFP
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to get
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the "data is modified" indication
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int - current setting of "data is modified" indication
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * == 0 - "data is modified" is NOT set
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * != 0 - "data is modified" IS set
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandvfpGetModified(VFP_T *a_vfp)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return current "data is modified" flag setting */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return ((a_vfp->_vfpFlags & _VFP_MODIFIED) != 0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: vfpSafeWrite
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: write data to open file safely
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: a_fildes - file descriptor to write data to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_buf - pointer to buffer containing data to write
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_nbyte - number of bytes to write to open file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * < 0 - error, errno set
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * >= 0 - success
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * NOTE: unlike write(2), vfpSafeWrite() handles partial writes, and will
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * ----- restart the write() until all bytes are written, or an error occurs.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandssize_t
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandvfpSafeWrite(int a_fildes, void *a_buf, size_t a_nbyte)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ssize_t r;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland size_t bytes = a_nbyte;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland for (;;) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* write bytes to file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland r = write(a_fildes, a_buf, a_nbyte);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return error on failure of write() */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (r < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* EAGAIN: try again */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errno == EAGAIN) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland continue;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* EINTR: interrupted - try again */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errno == EINTR) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland continue;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (r);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return total bytes written on success */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (r >= a_nbyte) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (bytes);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* partial write, adjust pointers, call write again */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_buf = (void *)((ptrdiff_t)a_buf + (ptrdiff_t)r);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_nbyte -= (size_t)r;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Name: vfpSafePwrite
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Description: write data to open file safely
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Arguments: a_fildes - file descriptor to write data to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_buf - pointer to buffer containing data to write
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_nbyte - number of bytes to write to open file
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * a_offset - offset into open file to write the first byte to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Returns: int
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * < 0 - error, errno set
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * >= 0 - success
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * NOTE: unlike pwrite(2), vfpSafePwrite() handles partial writes, and will
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * ----- restart the pwrite() until all bytes are written, or an error occurs.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandssize_t
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah WaterlandvfpSafePwrite(int a_fildes, void *a_buf, size_t a_nbyte, off_t a_offset)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ssize_t r;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland size_t bytes = a_nbyte;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland for (;;) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* write bytes to file */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland r = pwrite(a_fildes, a_buf, a_nbyte, a_offset);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return error on failure of write() */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (r < 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* EAGAIN: try again */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errno == EAGAIN) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland continue;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* EINTR: interrupted - try again */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errno == EINTR) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland continue;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (r);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* return total bytes written on success */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (r >= a_nbyte) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (bytes);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* partial write, adjust pointers, call write again */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_buf = (void *)((ptrdiff_t)a_buf + (ptrdiff_t)r);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_nbyte -= (size_t)r;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland a_offset += (off_t)r;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}