15c51f124SMoriah Waterland /*
25c51f124SMoriah Waterland * CDDL HEADER START
35c51f124SMoriah Waterland *
45c51f124SMoriah Waterland * The contents of this file are subject to the terms of the
55c51f124SMoriah Waterland * Common Development and Distribution License (the "License").
65c51f124SMoriah Waterland * You may not use this file except in compliance with the License.
75c51f124SMoriah Waterland *
85c51f124SMoriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c51f124SMoriah Waterland * or http://www.opensolaris.org/os/licensing.
105c51f124SMoriah Waterland * See the License for the specific language governing permissions
115c51f124SMoriah Waterland * and limitations under the License.
125c51f124SMoriah Waterland *
135c51f124SMoriah Waterland * When distributing Covered Code, include this CDDL HEADER in each
145c51f124SMoriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155c51f124SMoriah Waterland * If applicable, add the following below this CDDL HEADER, with the
165c51f124SMoriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying
175c51f124SMoriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner]
185c51f124SMoriah Waterland *
195c51f124SMoriah Waterland * CDDL HEADER END
205c51f124SMoriah Waterland */
215c51f124SMoriah Waterland
225c51f124SMoriah Waterland /*
235c51f124SMoriah Waterland * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
245c51f124SMoriah Waterland * Use is subject to license terms.
255c51f124SMoriah Waterland */
265c51f124SMoriah Waterland
275c51f124SMoriah Waterland
285c51f124SMoriah Waterland
295c51f124SMoriah Waterland /*
305c51f124SMoriah Waterland * Module: vfpops.c
315c51f124SMoriah Waterland * Synopsis: Implements virtual file protocol operations
325c51f124SMoriah Waterland * Description:
335c51f124SMoriah Waterland *
345c51f124SMoriah Waterland * This module implements the "Virtual File protocol" operations. These
355c51f124SMoriah Waterland * operations are intended to provide very fast access to file data,
365c51f124SMoriah Waterland * allowing a file to be accessed in very efficient ways with extremely
375c51f124SMoriah Waterland * low-cpu intensive operations. If possible file data is mapped directly
385c51f124SMoriah Waterland * into memory allowing the data to be accessed directly. If the data
395c51f124SMoriah Waterland * cannot be mapped directly into memory, memory will be allocated and
405c51f124SMoriah Waterland * the file data read directly into memory. If that fails currently the
415c51f124SMoriah Waterland * file data is not accessible. Other methods of making the file could
425c51f124SMoriah Waterland * be implemented in the future (e.g. stdio if all else fails).
435c51f124SMoriah Waterland *
445c51f124SMoriah Waterland * In general any code that uses stdio to access a file can be changed
455c51f124SMoriah Waterland * to use the various "vfp" operations to access a file, with a resulting
465c51f124SMoriah Waterland * increase in performance and decrease in cpu time required to access
475c51f124SMoriah Waterland * the file contents.
485c51f124SMoriah Waterland *
495c51f124SMoriah Waterland * Public Methods:
505c51f124SMoriah Waterland *
515c51f124SMoriah Waterland * vfpCheckpointFile - Create new VFP that checkpoints existing VFP
525c51f124SMoriah Waterland * vfpCheckpointOpen - open file, allocate storage, return pointer to VFP_T
535c51f124SMoriah Waterland * vfpClose - close file associated with vfp
545c51f124SMoriah Waterland * vfpDecCurrPtr - decrement current character pointer
555c51f124SMoriah Waterland * vfpGetBytesRemaining - get number of bytes remaining to read
565c51f124SMoriah Waterland * vfpGetCurrCharPtr - get pointer to current character
575c51f124SMoriah Waterland * vfpGetCurrPtrDelta - get number of bytes between current and specified char
585c51f124SMoriah Waterland * vfpGetFirstCharPtr - get pointer to first character
595c51f124SMoriah Waterland * vfpGetLastCharPtr - get pointer to last character
605c51f124SMoriah Waterland * vfpGetModifiedLen - get highest modified byte (length) contained in vfp
615c51f124SMoriah Waterland * vfpGetPath - get the path associated with the vfp
625c51f124SMoriah Waterland * vfpGetc - get current character and increment to next
635c51f124SMoriah Waterland * vfpGetcNoInc - get current character - do not increment
645c51f124SMoriah Waterland * vfpGets - get a string from the vfp into a fixed size buffer
655c51f124SMoriah Waterland * vfpIncCurrPtr - increment current character pointer
665c51f124SMoriah Waterland * vfpIncCurrPtrBy - increment current pointer by specified delta
675c51f124SMoriah Waterland * vfpOpen - open file on vfp
685c51f124SMoriah Waterland * vfpPutBytes - put fixed number of bytes to current character and increment
695c51f124SMoriah Waterland * vfpPutFormat - put format one arg to current character and increment
705c51f124SMoriah Waterland * vfpPutInteger - put integer to current character and increment
715c51f124SMoriah Waterland * vfpPutLong - put long to current character and increment
725c51f124SMoriah Waterland * vfpPutc - put current character and increment to next
735c51f124SMoriah Waterland * vfpPuts - put string to current character and increment
745c51f124SMoriah Waterland * vfpRewind - rewind file to first byte
755c51f124SMoriah Waterland * vfpSeekToEnd - seek to end of file
765c51f124SMoriah Waterland * vfpSetCurrCharPtr - set pointer to current character
775c51f124SMoriah Waterland * vfpSetFlags - set flags that affect file access
785c51f124SMoriah Waterland * vfpSetSize - set size of file (for writing)
795c51f124SMoriah Waterland * vfpTruncate - truncate file
805c51f124SMoriah Waterland * vfpWriteToFile - write data contained in vfp to specified file
815c51f124SMoriah Waterland */
825c51f124SMoriah Waterland
835c51f124SMoriah Waterland #include <stdio.h>
845c51f124SMoriah Waterland #include <limits.h>
855c51f124SMoriah Waterland #include <stdlib.h>
865c51f124SMoriah Waterland #include <string.h>
875c51f124SMoriah Waterland #include <strings.h>
885c51f124SMoriah Waterland #include <unistd.h>
895c51f124SMoriah Waterland #include <ctype.h>
905c51f124SMoriah Waterland #include <fcntl.h>
915c51f124SMoriah Waterland #include <sys/types.h>
925c51f124SMoriah Waterland #include <sys/stat.h>
935c51f124SMoriah Waterland #include <sys/mman.h>
945c51f124SMoriah Waterland #include <errno.h>
955c51f124SMoriah Waterland #include <libintl.h>
965c51f124SMoriah Waterland #include "pkglib.h"
975c51f124SMoriah Waterland #include "pkgstrct.h"
985c51f124SMoriah Waterland #include "pkglocale.h"
995c51f124SMoriah Waterland
1005c51f124SMoriah Waterland /*
1015c51f124SMoriah Waterland * These are internal flags that occupy the high order byte of the VFPFLAGS_T
1025c51f124SMoriah Waterland * flags element of the vfp. These flags may only occupy the high order order
1035c51f124SMoriah Waterland * 16 bits of the 32-bit unsigned vfp "flags" object.
1045c51f124SMoriah Waterland */
1055c51f124SMoriah Waterland
1065c51f124SMoriah Waterland #define _VFP_MMAP 0x00010000 /* mmap used */
1075c51f124SMoriah Waterland #define _VFP_MALLOC 0x00020000 /* malloc used */
1085c51f124SMoriah Waterland #define _VFP_WRITE 0x00040000 /* file opened for write */
1095c51f124SMoriah Waterland #define _VFP_READ 0x00080000 /* file opened for reading */
1105c51f124SMoriah Waterland #define _VFP_MODIFIED 0x00100000 /* contents are marked modified */
1115c51f124SMoriah Waterland
1125c51f124SMoriah Waterland /* path name given to "anonymous" (string) vfp */
1135c51f124SMoriah Waterland
1145c51f124SMoriah Waterland #define VFP_ANONYMOUS_PATH "<<string>>"
1155c51f124SMoriah Waterland
1165c51f124SMoriah Waterland /* minimum size file to mmap (64mb) */
1175c51f124SMoriah Waterland
1185c51f124SMoriah Waterland #define MIN_MMAP_SIZE (64*1024)
1195c51f124SMoriah Waterland
1205c51f124SMoriah Waterland /*
1215c51f124SMoriah Waterland * *****************************************************************************
1225c51f124SMoriah Waterland * global external (public) functions
1235c51f124SMoriah Waterland * *****************************************************************************
1245c51f124SMoriah Waterland */
1255c51f124SMoriah Waterland
1265c51f124SMoriah Waterland /*
1275c51f124SMoriah Waterland * Name: vfpOpen
1285c51f124SMoriah Waterland * Description: Open file on vfp, allocate storage, return pointer to VFP_T
1295c51f124SMoriah Waterland * that can be used to access/modify file contents.
1305c51f124SMoriah Waterland * Arguments: VFP_T **r_vfp - pointer to pointer to VFP_T
1315c51f124SMoriah Waterland * char *a_path - path of file to open and associate with this VFP.
1325c51f124SMoriah Waterland * - if the path is (char *)NULL then no file is associated
1335c51f124SMoriah Waterland * with this VFP - this is a way to create a fixed length
1345c51f124SMoriah Waterland * string that can be manipulated with the VFP operators.
1355c51f124SMoriah Waterland * Before the VFP can be used "vfpSetSize" must be called
1365c51f124SMoriah Waterland * to set the size of the string buffer.
1375c51f124SMoriah Waterland * char *a_mode - fopen mode to open the file with
1385c51f124SMoriah Waterland * VFPFLAGS_T a_flags - one or more flags to control the operation:
1395c51f124SMoriah Waterland * - VFP_NONE - no special flags
1405c51f124SMoriah Waterland * - VFP_NEEDNOW - file data needed in memory now
1415c51f124SMoriah Waterland * - VFP_SEQUENTIAL - memory will be sequentially accessed
1425c51f124SMoriah Waterland * - VFP_RANDOM - memory will be randomly accessed
1435c51f124SMoriah Waterland * - VFP_NOMMAP - do not use mmap to access file
1445c51f124SMoriah Waterland * - VFP_NOMALLOC - do not use malloc to buffer file
1455c51f124SMoriah Waterland * Returns: int == 0 - operation was successful
1465c51f124SMoriah Waterland * != 0 - operation failed, errno contains reason
1475c51f124SMoriah Waterland * Side Effects: r_vfp -- filled in with a pointer to a newly allocated vfp
1485c51f124SMoriah Waterland * which can be used with the various vfp functions.
1495c51f124SMoriah Waterland * errno -- contains system error number if return is != 0
1505c51f124SMoriah Waterland */
1515c51f124SMoriah Waterland
1525c51f124SMoriah Waterland int
vfpOpen(VFP_T ** r_vfp,char * a_path,char * a_mode,VFPFLAGS_T a_flags)1535c51f124SMoriah Waterland vfpOpen(VFP_T **r_vfp, char *a_path, char *a_mode, VFPFLAGS_T a_flags)
1545c51f124SMoriah Waterland {
1555c51f124SMoriah Waterland FILE *fp = (FILE *)NULL;
1565c51f124SMoriah Waterland VFP_T *vfp;
1575c51f124SMoriah Waterland int lerrno;
1585c51f124SMoriah Waterland struct stat statbuf;
1595c51f124SMoriah Waterland int pagesize = getpagesize();
1605c51f124SMoriah Waterland
1615c51f124SMoriah Waterland /* reset return VFP/FILE pointers */
1625c51f124SMoriah Waterland
1635c51f124SMoriah Waterland (*r_vfp) = (VFP_T *)NULL;
1645c51f124SMoriah Waterland
1655c51f124SMoriah Waterland /* allocate pre-zeroed vfp object */
1665c51f124SMoriah Waterland
1675c51f124SMoriah Waterland vfp = (VFP_T *)calloc(sizeof (VFP_T), 1);
1685c51f124SMoriah Waterland if (vfp == (VFP_T *)NULL) {
1695c51f124SMoriah Waterland return (-1);
1705c51f124SMoriah Waterland }
1715c51f124SMoriah Waterland
1725c51f124SMoriah Waterland /* create "string" vfp if no path specified */
1735c51f124SMoriah Waterland
1745c51f124SMoriah Waterland if (a_path == (char *)NULL) {
1755c51f124SMoriah Waterland /*
1765c51f124SMoriah Waterland * no path specified - no open file associated with vfp
1775c51f124SMoriah Waterland * The vfp is initialized to all zeros - initialize just those
1785c51f124SMoriah Waterland * values that need to be non-zero.
1795c51f124SMoriah Waterland */
1805c51f124SMoriah Waterland
1815c51f124SMoriah Waterland vfp->_vfpFlags = _VFP_MALLOC;
1825c51f124SMoriah Waterland vfp->_vfpPath = strdup(VFP_ANONYMOUS_PATH);
1835c51f124SMoriah Waterland (*r_vfp) = vfp;
1845c51f124SMoriah Waterland return (0);
1855c51f124SMoriah Waterland }
1865c51f124SMoriah Waterland
1875c51f124SMoriah Waterland /*
1885c51f124SMoriah Waterland * path specified - associate open file with vfp;
1895c51f124SMoriah Waterland * return an error if no path or mode specified
1905c51f124SMoriah Waterland */
1915c51f124SMoriah Waterland
1925c51f124SMoriah Waterland if (a_mode == (char *)NULL) {
1935c51f124SMoriah Waterland errno = EFAULT; /* Bad address */
1945c51f124SMoriah Waterland (void) free(vfp);
1955c51f124SMoriah Waterland return (-1);
1965c51f124SMoriah Waterland }
1975c51f124SMoriah Waterland
1985c51f124SMoriah Waterland /* return an error if an empty path or mode specified */
1995c51f124SMoriah Waterland
2005c51f124SMoriah Waterland if ((*a_path == '\0') || (*a_mode == '\0')) {
2015c51f124SMoriah Waterland errno = EINVAL; /* Invalid argument */
2025c51f124SMoriah Waterland (void) free(vfp);
2035c51f124SMoriah Waterland return (-1);
2045c51f124SMoriah Waterland }
2055c51f124SMoriah Waterland
2065c51f124SMoriah Waterland /* open the file */
2075c51f124SMoriah Waterland
2085c51f124SMoriah Waterland fp = fopen(a_path, a_mode);
2095c51f124SMoriah Waterland if (fp == (FILE *)NULL) {
2105c51f124SMoriah Waterland lerrno = errno;
2115c51f124SMoriah Waterland (void) free(vfp);
2125c51f124SMoriah Waterland errno = lerrno;
2135c51f124SMoriah Waterland return (-1);
2145c51f124SMoriah Waterland }
2155c51f124SMoriah Waterland
2165c51f124SMoriah Waterland /* Get the file size */
2175c51f124SMoriah Waterland
2185c51f124SMoriah Waterland if (fstat(fileno(fp), &statbuf) != 0) {
2195c51f124SMoriah Waterland lerrno = errno;
2205c51f124SMoriah Waterland (void) fclose(fp);
2215c51f124SMoriah Waterland (void) free(vfp);
2225c51f124SMoriah Waterland errno = lerrno;
2235c51f124SMoriah Waterland return (-1);
2245c51f124SMoriah Waterland }
2255c51f124SMoriah Waterland
2265c51f124SMoriah Waterland /*
2275c51f124SMoriah Waterland * Obtain access to existing file contents:
2285c51f124SMoriah Waterland * -> plan a: map contents file into memory
2295c51f124SMoriah Waterland * -> plan b: on failure just read into large buffer
2305c51f124SMoriah Waterland */
2315c51f124SMoriah Waterland
2325c51f124SMoriah Waterland /* attempt to mmap file if mmap is allowed */
2335c51f124SMoriah Waterland
2345c51f124SMoriah Waterland vfp->_vfpStart = MAP_FAILED; /* assume map failed if not allowed */
2355c51f124SMoriah Waterland
2365c51f124SMoriah Waterland /*
2375c51f124SMoriah Waterland * if file is a regular file, and if mmap allowed,
2385c51f124SMoriah Waterland * and (malloc not forbidden or size is > minumum size to mmap)
2395c51f124SMoriah Waterland */
2405c51f124SMoriah Waterland
2415c51f124SMoriah Waterland if ((S_ISREG(statbuf.st_mode)) && (!(a_flags & VFP_NOMMAP)) &&
2425c51f124SMoriah Waterland ((a_flags & VFP_NOMALLOC) || statbuf.st_size > MIN_MMAP_SIZE)) {
2435c51f124SMoriah Waterland char *p;
2445c51f124SMoriah Waterland /* set size to current size of file */
2455c51f124SMoriah Waterland
2465c51f124SMoriah Waterland vfp->_vfpMapSize = statbuf.st_size;
2475c51f124SMoriah Waterland
2485c51f124SMoriah Waterland /*
2495c51f124SMoriah Waterland * compute proper size for mapping for the file contents;
2505c51f124SMoriah Waterland * add in one extra page so falling off end when file size is
2515c51f124SMoriah Waterland * exactly modulo page size does not cause a page fault to
2525c51f124SMoriah Waterland * guarantee that the end of the file contents will always
2535c51f124SMoriah Waterland * contain a '\0' null character.
2545c51f124SMoriah Waterland */
2555c51f124SMoriah Waterland
2565c51f124SMoriah Waterland vfp->_vfpSize = (statbuf.st_size + pagesize +
2575c51f124SMoriah Waterland (pagesize-(statbuf.st_size % pagesize)));
2585c51f124SMoriah Waterland
2595c51f124SMoriah Waterland /*
2605c51f124SMoriah Waterland * mmap allowed: mmap file into memory
2615c51f124SMoriah Waterland * first allocate space on top of which the mapping can be done;
2625c51f124SMoriah Waterland * this way we can guarantee that if the mapping happens to be
2635c51f124SMoriah Waterland * an exact multiple of a page size, that there will be at least
2645c51f124SMoriah Waterland * one byte past the end of the mapping that can be accessed and
2655c51f124SMoriah Waterland * that is guaranteed to be zero.
2665c51f124SMoriah Waterland */
2675c51f124SMoriah Waterland
2685c51f124SMoriah Waterland /* allocate backing space */
2695c51f124SMoriah Waterland
2705c51f124SMoriah Waterland p = (char *)memalign(pagesize, vfp->_vfpSize);
2715c51f124SMoriah Waterland if (p == (char *)NULL) {
2725c51f124SMoriah Waterland vfp->_vfpStart = MAP_FAILED;
2735c51f124SMoriah Waterland } else {
2745c51f124SMoriah Waterland /* guarantee first byte after end of data is zero */
2755c51f124SMoriah Waterland
2765c51f124SMoriah Waterland p[vfp->_vfpMapSize] = '\0';
2775c51f124SMoriah Waterland
2785c51f124SMoriah Waterland /* map file on top of the backing space */
2795c51f124SMoriah Waterland
2805c51f124SMoriah Waterland vfp->_vfpStart = mmap(p, vfp->_vfpMapSize, PROT_READ,
2815c51f124SMoriah Waterland MAP_PRIVATE|MAP_FIXED, fileno(fp), (off_t)0);
2825c51f124SMoriah Waterland
2835c51f124SMoriah Waterland /* if mmap succeeded set mmap used flag in vfp */
2845c51f124SMoriah Waterland
2855c51f124SMoriah Waterland if (vfp->_vfpStart != MAP_FAILED) {
2865c51f124SMoriah Waterland vfp->_vfpFlags |= _VFP_MMAP;
2875c51f124SMoriah Waterland }
2885c51f124SMoriah Waterland }
2895c51f124SMoriah Waterland }
2905c51f124SMoriah Waterland
2915c51f124SMoriah Waterland /* if map failed (or not allowed) attempt malloc (if allowed) */
2925c51f124SMoriah Waterland
2935c51f124SMoriah Waterland if ((vfp->_vfpStart == MAP_FAILED) && (!(a_flags & VFP_NOMALLOC))) {
2945c51f124SMoriah Waterland /* mmap failed - plan b: read directly into memory */
2955c51f124SMoriah Waterland ssize_t rlen;
2965c51f124SMoriah Waterland
2975c51f124SMoriah Waterland /*
2985c51f124SMoriah Waterland * compute proper size for allocating storage for file contents;
2995c51f124SMoriah Waterland * add in one extra page so falling off end when file size is
3005c51f124SMoriah Waterland * exactly modulo page size does not cause a page fault to
3015c51f124SMoriah Waterland * guarantee that the end of the file contents will always
3025c51f124SMoriah Waterland * contain a '\0' null character.
3035c51f124SMoriah Waterland */
3045c51f124SMoriah Waterland
3055c51f124SMoriah Waterland vfp->_vfpSize = statbuf.st_size+pagesize;
3065c51f124SMoriah Waterland
3075c51f124SMoriah Waterland /* allocate buffer to hold file data */
3085c51f124SMoriah Waterland
3095c51f124SMoriah Waterland vfp->_vfpStart = memalign((size_t)pagesize, vfp->_vfpSize);
3105c51f124SMoriah Waterland if (vfp->_vfpStart == (char *)NULL) {
3115c51f124SMoriah Waterland lerrno = errno;
3125c51f124SMoriah Waterland (void) fclose(fp);
3135c51f124SMoriah Waterland (void) free(vfp);
3145c51f124SMoriah Waterland errno = lerrno;
3155c51f124SMoriah Waterland return (-1);
3165c51f124SMoriah Waterland }
3175c51f124SMoriah Waterland
3185c51f124SMoriah Waterland /* read the file into the buffer */
3195c51f124SMoriah Waterland
3205c51f124SMoriah Waterland if (statbuf.st_size != 0) {
3215c51f124SMoriah Waterland rlen = read(fileno(fp), vfp->_vfpStart,
3225c51f124SMoriah Waterland statbuf.st_size);
3235c51f124SMoriah Waterland if (rlen != statbuf.st_size) {
3245c51f124SMoriah Waterland lerrno = errno;
3255c51f124SMoriah Waterland if (lerrno == 0) {
3265c51f124SMoriah Waterland lerrno = EIO;
3275c51f124SMoriah Waterland }
3285c51f124SMoriah Waterland (void) free(vfp->_vfpStart);
3295c51f124SMoriah Waterland (void) fclose(fp);
3305c51f124SMoriah Waterland (void) free(vfp);
3315c51f124SMoriah Waterland errno = lerrno;
3325c51f124SMoriah Waterland return (-1);
3335c51f124SMoriah Waterland }
3345c51f124SMoriah Waterland
3355c51f124SMoriah Waterland /* assure last byte+1 is null character */
3365c51f124SMoriah Waterland
3375c51f124SMoriah Waterland ((char *)vfp->_vfpStart)[statbuf.st_size] = '\0';
3385c51f124SMoriah Waterland }
3395c51f124SMoriah Waterland
3405c51f124SMoriah Waterland /* set malloc used flag in vfp */
3415c51f124SMoriah Waterland
3425c51f124SMoriah Waterland vfp->_vfpFlags |= _VFP_MALLOC;
3435c51f124SMoriah Waterland }
3445c51f124SMoriah Waterland
3455c51f124SMoriah Waterland /* if no starting address all read methods failed */
3465c51f124SMoriah Waterland
3475c51f124SMoriah Waterland if (vfp->_vfpStart == MAP_FAILED) {
3485c51f124SMoriah Waterland /* no mmap() - no read() - cannot allocate memory */
3495c51f124SMoriah Waterland (void) fclose(fp);
3505c51f124SMoriah Waterland (void) free(vfp);
3515c51f124SMoriah Waterland errno = ENOMEM;
3525c51f124SMoriah Waterland return (-1);
3535c51f124SMoriah Waterland }
3545c51f124SMoriah Waterland
3555c51f124SMoriah Waterland /*
3565c51f124SMoriah Waterland * initialize vfp contents
3575c51f124SMoriah Waterland */
3585c51f124SMoriah Waterland
3595c51f124SMoriah Waterland /* _vfpCurr -> next byte to read */
3605c51f124SMoriah Waterland vfp->_vfpCurr = (char *)vfp->_vfpStart;
3615c51f124SMoriah Waterland
3625c51f124SMoriah Waterland /* _vfpEnd -> last data byte */
3635c51f124SMoriah Waterland vfp->_vfpEnd = (((char *)vfp->_vfpStart) + statbuf.st_size)-1;
3645c51f124SMoriah Waterland
3655c51f124SMoriah Waterland /* _vfpHighWater -> last byte written */
3665c51f124SMoriah Waterland vfp->_vfpHighWater = (char *)vfp->_vfpEnd;
3675c51f124SMoriah Waterland
3685c51f124SMoriah Waterland /* _vfpFile -> associated FILE* object */
3695c51f124SMoriah Waterland vfp->_vfpFile = fp;
3705c51f124SMoriah Waterland
3715c51f124SMoriah Waterland /* set flags as appropriate */
3725c51f124SMoriah Waterland
3735c51f124SMoriah Waterland (void) vfpSetFlags(vfp, a_flags);
3745c51f124SMoriah Waterland
3755c51f124SMoriah Waterland /* retain path name */
3765c51f124SMoriah Waterland
3775c51f124SMoriah Waterland vfp->_vfpPath = strdup(a_path ? a_path : "");
3785c51f124SMoriah Waterland
3795c51f124SMoriah Waterland /* set read/write flags */
3805c51f124SMoriah Waterland
3815c51f124SMoriah Waterland if (*a_mode == 'w') {
3825c51f124SMoriah Waterland vfp->_vfpFlags |= _VFP_WRITE;
3835c51f124SMoriah Waterland }
3845c51f124SMoriah Waterland
3855c51f124SMoriah Waterland if (*a_mode == 'r') {
3865c51f124SMoriah Waterland vfp->_vfpFlags |= _VFP_READ;
3875c51f124SMoriah Waterland }
3885c51f124SMoriah Waterland
3895c51f124SMoriah Waterland /* set return vfp pointer */
3905c51f124SMoriah Waterland
3915c51f124SMoriah Waterland (*r_vfp) = vfp;
3925c51f124SMoriah Waterland
3935c51f124SMoriah Waterland /* All OK */
3945c51f124SMoriah Waterland
3955c51f124SMoriah Waterland return (0);
3965c51f124SMoriah Waterland }
3975c51f124SMoriah Waterland
3985c51f124SMoriah Waterland /*
3995c51f124SMoriah Waterland * Name: vfpClose
4005c51f124SMoriah Waterland * Description: Close an open vfp, causing any modified data to be written out
4015c51f124SMoriah Waterland * to the file associated with the vfp.
4025c51f124SMoriah Waterland * Arguments: VFP_T **r_vfp - pointer to pointer to VFP_T returned by vfpOpen
4035c51f124SMoriah Waterland * Returns: int == 0 - operation was successful
4045c51f124SMoriah Waterland * != 0 - operation failed, errno contains reason
4055c51f124SMoriah Waterland * Side Effects: r_vfp is set to (VFP_T)NULL
4065c51f124SMoriah Waterland */
4075c51f124SMoriah Waterland
4085c51f124SMoriah Waterland int
vfpClose(VFP_T ** r_vfp)4095c51f124SMoriah Waterland vfpClose(VFP_T **r_vfp)
4105c51f124SMoriah Waterland {
4115c51f124SMoriah Waterland int ret;
4125c51f124SMoriah Waterland int lerrno;
4135c51f124SMoriah Waterland VFP_T *vfp;
4145c51f124SMoriah Waterland
4155c51f124SMoriah Waterland /* return error if NULL VFP_T** provided */
4165c51f124SMoriah Waterland
4175c51f124SMoriah Waterland if (r_vfp == (VFP_T **)NULL) {
4185c51f124SMoriah Waterland errno = EFAULT;
4195c51f124SMoriah Waterland return (-1);
4205c51f124SMoriah Waterland }
4215c51f124SMoriah Waterland
4225c51f124SMoriah Waterland /* localize access to VFP_T */
4235c51f124SMoriah Waterland
4245c51f124SMoriah Waterland vfp = *r_vfp;
4255c51f124SMoriah Waterland
4265c51f124SMoriah Waterland /* return successful if NULL VFP_T* provided */
4275c51f124SMoriah Waterland
4285c51f124SMoriah Waterland if (vfp == (VFP_T *)NULL) {
4295c51f124SMoriah Waterland return (0);
4305c51f124SMoriah Waterland }
4315c51f124SMoriah Waterland
4325c51f124SMoriah Waterland /* reset return VFP_T* handle */
4335c51f124SMoriah Waterland
4345c51f124SMoriah Waterland *r_vfp = (VFP_T *)NULL;
4355c51f124SMoriah Waterland
4365c51f124SMoriah Waterland /*
4375c51f124SMoriah Waterland * if closing a file that is open for writing, commit all data if the
4385c51f124SMoriah Waterland * backing memory is volatile and if there is a file open to write
4395c51f124SMoriah Waterland * the data to.
4405c51f124SMoriah Waterland */
4415c51f124SMoriah Waterland
4425c51f124SMoriah Waterland if (vfp->_vfpFlags & _VFP_WRITE) {
4435c51f124SMoriah Waterland if ((vfp->_vfpFlags & _VFP_MALLOC) &&
4445c51f124SMoriah Waterland (vfp->_vfpFile != (FILE *)NULL)) {
4455c51f124SMoriah Waterland size_t len;
4465c51f124SMoriah Waterland
4475c51f124SMoriah Waterland /* determine number of bytes to write */
4485c51f124SMoriah Waterland len = vfpGetModifiedLen(vfp);
4495c51f124SMoriah Waterland
4505c51f124SMoriah Waterland /* if modified bytes present commit data to the file */
4515c51f124SMoriah Waterland if (len > 0) {
4525c51f124SMoriah Waterland (void) vfpSafePwrite(fileno(vfp->_vfpFile),
4535c51f124SMoriah Waterland vfp->_vfpStart, len, (off_t)0);
4545c51f124SMoriah Waterland }
4555c51f124SMoriah Waterland }
4565c51f124SMoriah Waterland }
4575c51f124SMoriah Waterland
4585c51f124SMoriah Waterland /* deallocate any allocated storage/mappings/etc */
4595c51f124SMoriah Waterland
4605c51f124SMoriah Waterland if (vfp->_vfpFlags & _VFP_MALLOC) {
4615c51f124SMoriah Waterland (void) free(vfp->_vfpStart);
4625c51f124SMoriah Waterland } else if (vfp->_vfpFlags & _VFP_MMAP) {
4635c51f124SMoriah Waterland /* unmap the file mapping */
4645c51f124SMoriah Waterland
4655c51f124SMoriah Waterland (void) munmap(vfp->_vfpStart, vfp->_vfpMapSize);
4665c51f124SMoriah Waterland
4675c51f124SMoriah Waterland /* free the backing allocation */
4685c51f124SMoriah Waterland
4695c51f124SMoriah Waterland (void) free(vfp->_vfpStart);
4705c51f124SMoriah Waterland }
4715c51f124SMoriah Waterland
4725c51f124SMoriah Waterland /* free up path */
4735c51f124SMoriah Waterland
4745c51f124SMoriah Waterland (void) free(vfp->_vfpPath);
4755c51f124SMoriah Waterland
4765c51f124SMoriah Waterland /* close the file */
4775c51f124SMoriah Waterland
4785c51f124SMoriah Waterland ret = 0;
4795c51f124SMoriah Waterland if (vfp->_vfpFile != (FILE *)NULL) {
4805c51f124SMoriah Waterland ret = fclose(vfp->_vfpFile);
4815c51f124SMoriah Waterland lerrno = errno;
4825c51f124SMoriah Waterland }
4835c51f124SMoriah Waterland
4845c51f124SMoriah Waterland /* deallocate the vfp itself */
4855c51f124SMoriah Waterland
4865c51f124SMoriah Waterland (void) free(vfp);
4875c51f124SMoriah Waterland
4885c51f124SMoriah Waterland /* if the fclose() failed, return error and errno */
4895c51f124SMoriah Waterland
4905c51f124SMoriah Waterland if (ret != 0) {
4915c51f124SMoriah Waterland errno = lerrno;
4925c51f124SMoriah Waterland return (-1);
4935c51f124SMoriah Waterland }
4945c51f124SMoriah Waterland
4955c51f124SMoriah Waterland return (0);
4965c51f124SMoriah Waterland }
4975c51f124SMoriah Waterland
4985c51f124SMoriah Waterland /*
4995c51f124SMoriah Waterland * Name: vfpSetFlags
5005c51f124SMoriah Waterland * Description: Modify operation of VFP according to flags specified
5015c51f124SMoriah Waterland * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to set flags
5025c51f124SMoriah Waterland * VFPFLAGS_T a_flags - one or more flags to control the operation:
5035c51f124SMoriah Waterland * - VFP_NEEDNOW - file data needed in memory now
5045c51f124SMoriah Waterland * - VFP_SEQUENTIAL - file data sequentially accessed
5055c51f124SMoriah Waterland * - VFP_RANDOM - file data randomly accessed
5065c51f124SMoriah Waterland * Any other flags specified are silently ignored.
5075c51f124SMoriah Waterland * Returns: int == 0 - operation was successful
5085c51f124SMoriah Waterland * != 0 - operation failed, errno contains reason
5095c51f124SMoriah Waterland */
5105c51f124SMoriah Waterland
5115c51f124SMoriah Waterland int
vfpSetFlags(VFP_T * a_vfp,VFPFLAGS_T a_flags)5125c51f124SMoriah Waterland vfpSetFlags(VFP_T *a_vfp, VFPFLAGS_T a_flags)
5135c51f124SMoriah Waterland {
5145c51f124SMoriah Waterland /* return if no vfp specified */
5155c51f124SMoriah Waterland
5165c51f124SMoriah Waterland if (a_vfp == (VFP_T *)NULL) {
5175c51f124SMoriah Waterland return (0);
5185c51f124SMoriah Waterland }
5195c51f124SMoriah Waterland
5205c51f124SMoriah Waterland /* if file data mapped into memory, apply vm flags */
5215c51f124SMoriah Waterland
5225c51f124SMoriah Waterland if ((a_vfp->_vfpSize != 0) && (a_vfp->_vfpFlags & _VFP_MMAP)) {
5235c51f124SMoriah Waterland /* mmap succeeded: properly advise vm system */
5245c51f124SMoriah Waterland
5255c51f124SMoriah Waterland if (a_flags & VFP_NEEDNOW) {
5265c51f124SMoriah Waterland /* advise vm system data is needed now */
5275c51f124SMoriah Waterland (void) madvise(a_vfp->_vfpStart, a_vfp->_vfpMapSize,
5285c51f124SMoriah Waterland MADV_WILLNEED);
5295c51f124SMoriah Waterland }
5305c51f124SMoriah Waterland if (a_flags & VFP_SEQUENTIAL) {
5315c51f124SMoriah Waterland /* advise vm system data access is sequential */
5325c51f124SMoriah Waterland (void) madvise(a_vfp->_vfpStart, a_vfp->_vfpSize,
5335c51f124SMoriah Waterland MADV_SEQUENTIAL);
5345c51f124SMoriah Waterland }
5355c51f124SMoriah Waterland if (a_flags & VFP_RANDOM) {
5365c51f124SMoriah Waterland /* advise vm system data access is random */
5375c51f124SMoriah Waterland (void) madvise(a_vfp->_vfpStart, a_vfp->_vfpSize,
5385c51f124SMoriah Waterland MADV_RANDOM);
5395c51f124SMoriah Waterland }
5405c51f124SMoriah Waterland }
5415c51f124SMoriah Waterland
5425c51f124SMoriah Waterland return (0);
5435c51f124SMoriah Waterland }
5445c51f124SMoriah Waterland
5455c51f124SMoriah Waterland /*
5465c51f124SMoriah Waterland * Name: vfpRewind
5475c51f124SMoriah Waterland * Description: Reset default pointer for next read/write to start of file data
5485c51f124SMoriah Waterland * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to rewind
5495c51f124SMoriah Waterland * Returns: void
5505c51f124SMoriah Waterland * Operation is always successful
5515c51f124SMoriah Waterland */
5525c51f124SMoriah Waterland
5535c51f124SMoriah Waterland void
vfpRewind(VFP_T * a_vfp)5545c51f124SMoriah Waterland vfpRewind(VFP_T *a_vfp)
5555c51f124SMoriah Waterland {
5565c51f124SMoriah Waterland /* return if no vfp specified */
5575c51f124SMoriah Waterland
5585c51f124SMoriah Waterland if (a_vfp == (VFP_T *)NULL) {
5595c51f124SMoriah Waterland return;
5605c51f124SMoriah Waterland }
5615c51f124SMoriah Waterland
5625c51f124SMoriah Waterland /* set high water mark of last modified data */
5635c51f124SMoriah Waterland
5645c51f124SMoriah Waterland if (a_vfp->_vfpCurr > a_vfp->_vfpHighWater) {
5655c51f124SMoriah Waterland a_vfp->_vfpHighWater = a_vfp->_vfpCurr;
5665c51f124SMoriah Waterland }
5675c51f124SMoriah Waterland
5685c51f124SMoriah Waterland /* reset next character pointer to start of file data */
5695c51f124SMoriah Waterland
5705c51f124SMoriah Waterland a_vfp->_vfpCurr = a_vfp->_vfpStart;
5715c51f124SMoriah Waterland }
5725c51f124SMoriah Waterland
5735c51f124SMoriah Waterland /*
5745c51f124SMoriah Waterland * Name: vfpSetSize
5755c51f124SMoriah Waterland * Description: Set size of in-memory image associated with VFP
5765c51f124SMoriah Waterland * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to set
5775c51f124SMoriah Waterland * size_t a_size - number of bytes to associatge with VFP
5785c51f124SMoriah Waterland * Returns: int == 0 - operation was successful
5795c51f124SMoriah Waterland * != 0 - operation failed, errno contains reason
5805c51f124SMoriah Waterland * Side Effects:
5815c51f124SMoriah Waterland * Currently only a file that is in malloc()ed memory can
5825c51f124SMoriah Waterland * have its in-memory size changed.
5835c51f124SMoriah Waterland * An error is returned If the file is mapped into memory.
5845c51f124SMoriah Waterland * A file cannot be decreased in size - if the specified
5855c51f124SMoriah Waterland * size is less than the current size, the operation is
5865c51f124SMoriah Waterland * successful but no change in file size occurs.
5875c51f124SMoriah Waterland * If no file is associated with the VFP (no "name" was
5885c51f124SMoriah Waterland * given to vfpOpen) the first call to vfpSetSize allocates
5895c51f124SMoriah Waterland * the initial size of the file data - effectively calling
5905c51f124SMoriah Waterland * "malloc" to allocate the initial memory for the file data.
5915c51f124SMoriah Waterland * Once an initial allocation has been made, subsequent calls
5925c51f124SMoriah Waterland * to vfpSetSize are effectively a "realloc" of the existing
5935c51f124SMoriah Waterland * file data.
5945c51f124SMoriah Waterland * All existing file data is preserved.
5955c51f124SMoriah Waterland */
5965c51f124SMoriah Waterland
5975c51f124SMoriah Waterland int
vfpSetSize(VFP_T * a_vfp,size_t a_size)5985c51f124SMoriah Waterland vfpSetSize(VFP_T *a_vfp, size_t a_size)
5995c51f124SMoriah Waterland {
6005c51f124SMoriah Waterland char *np;
6015c51f124SMoriah Waterland size_t curSize;
6025c51f124SMoriah Waterland
6035c51f124SMoriah Waterland /* return if no vfp specified */
6045c51f124SMoriah Waterland
6055c51f124SMoriah Waterland if (a_vfp == (VFP_T *)NULL) {
6065c51f124SMoriah Waterland return (0);
6075c51f124SMoriah Waterland }
6085c51f124SMoriah Waterland
6095c51f124SMoriah Waterland /* if malloc not used don't know how to set size right now */
6105c51f124SMoriah Waterland
6115c51f124SMoriah Waterland if (!(a_vfp->_vfpFlags & _VFP_MALLOC)) {
6125c51f124SMoriah Waterland return (-1);
6135c51f124SMoriah Waterland }
6145c51f124SMoriah Waterland
6155c51f124SMoriah Waterland /* adjust size to reflect extra page of data maintained */
6165c51f124SMoriah Waterland
6175c51f124SMoriah Waterland a_size += getpagesize();
6185c51f124SMoriah Waterland
6195c51f124SMoriah Waterland /* if size is not larger than current nothing to do */
6205c51f124SMoriah Waterland
6215c51f124SMoriah Waterland if (a_size <= a_vfp->_vfpSize) {
6225c51f124SMoriah Waterland return (0);
6235c51f124SMoriah Waterland }
6245c51f124SMoriah Waterland
6255c51f124SMoriah Waterland /* remember new size */
6265c51f124SMoriah Waterland
6275c51f124SMoriah Waterland curSize = a_vfp->_vfpSize;
6285c51f124SMoriah Waterland a_vfp->_vfpSize = a_size;
6295c51f124SMoriah Waterland
6305c51f124SMoriah Waterland /* allocate/reallocate memory as appropriate */
6315c51f124SMoriah Waterland
6325c51f124SMoriah Waterland if (a_vfp->_vfpStart != (char *)NULL) {
6335c51f124SMoriah Waterland np = (char *)realloc(a_vfp->_vfpStart, a_vfp->_vfpSize+1);
6345c51f124SMoriah Waterland if (np == (char *)NULL) {
6355c51f124SMoriah Waterland return (-1);
6365c51f124SMoriah Waterland }
6375c51f124SMoriah Waterland np[curSize-1] = '\0';
6385c51f124SMoriah Waterland } else {
6395c51f124SMoriah Waterland np = (char *)malloc(a_vfp->_vfpSize+1);
6405c51f124SMoriah Waterland if (np == (char *)NULL) {
6415c51f124SMoriah Waterland return (-1);
6425c51f124SMoriah Waterland }
6435c51f124SMoriah Waterland np[0] = '\0';
6445c51f124SMoriah Waterland }
6455c51f124SMoriah Waterland
6465c51f124SMoriah Waterland /* make sure last allocated byte is a null */
6475c51f124SMoriah Waterland
6485c51f124SMoriah Waterland np[a_vfp->_vfpSize] = '\0';
6495c51f124SMoriah Waterland
6505c51f124SMoriah Waterland /*
6515c51f124SMoriah Waterland * adjust all pointers to account for buffer address change
6525c51f124SMoriah Waterland */
6535c51f124SMoriah Waterland
6545c51f124SMoriah Waterland /* _vfpCurr -> next byte to read */
6555c51f124SMoriah Waterland a_vfp->_vfpCurr = (char *)(((ptrdiff_t)a_vfp->_vfpCurr -
6565c51f124SMoriah Waterland (ptrdiff_t)a_vfp->_vfpStart) + np);
6575c51f124SMoriah Waterland
6585c51f124SMoriah Waterland /* _vfpHighWater -> last byte written */
6595c51f124SMoriah Waterland a_vfp->_vfpHighWater = (char *)(((ptrdiff_t)a_vfp->_vfpHighWater -
6605c51f124SMoriah Waterland (ptrdiff_t)a_vfp->_vfpStart) + np);
6615c51f124SMoriah Waterland
6625c51f124SMoriah Waterland /* _vfpEnd -> last data byte */
6635c51f124SMoriah Waterland a_vfp->_vfpEnd = (np + a_vfp->_vfpSize)-1;
6645c51f124SMoriah Waterland
6655c51f124SMoriah Waterland /* _vfpStart -> first data byte */
6665c51f124SMoriah Waterland a_vfp->_vfpStart = np;
6675c51f124SMoriah Waterland
6685c51f124SMoriah Waterland return (0);
6695c51f124SMoriah Waterland }
6705c51f124SMoriah Waterland
6715c51f124SMoriah Waterland /*
6725c51f124SMoriah Waterland * Name: vfpTruncate
6735c51f124SMoriah Waterland * Description: Truncate data associated with VFP
6745c51f124SMoriah Waterland * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to truncate
6755c51f124SMoriah Waterland * Returns: void
6765c51f124SMoriah Waterland * Operation is always successful.
6775c51f124SMoriah Waterland * Side Effects:
6785c51f124SMoriah Waterland * In memory data associated with file is believed to be empty.
6795c51f124SMoriah Waterland * Actual memory associated with file is not affected.
6805c51f124SMoriah Waterland * If a file is associated with the VFP, it is truncated.
6815c51f124SMoriah Waterland */
6825c51f124SMoriah Waterland
6835c51f124SMoriah Waterland void
vfpTruncate(VFP_T * a_vfp)6845c51f124SMoriah Waterland vfpTruncate(VFP_T *a_vfp)
6855c51f124SMoriah Waterland {
6865c51f124SMoriah Waterland /* return if no vfp specified */
6875c51f124SMoriah Waterland
6885c51f124SMoriah Waterland if (a_vfp == (VFP_T *)NULL) {
6895c51f124SMoriah Waterland return;
6905c51f124SMoriah Waterland }
6915c51f124SMoriah Waterland
6925c51f124SMoriah Waterland /*
6935c51f124SMoriah Waterland * reset all pointers so that no data is associated with file
6945c51f124SMoriah Waterland */
6955c51f124SMoriah Waterland
6965c51f124SMoriah Waterland /* current byte is start of data area */
6975c51f124SMoriah Waterland
6985c51f124SMoriah Waterland a_vfp->_vfpCurr = a_vfp->_vfpStart;
6995c51f124SMoriah Waterland
7005c51f124SMoriah Waterland /* last byte written is start of data area */
7015c51f124SMoriah Waterland
7025c51f124SMoriah Waterland a_vfp->_vfpHighWater = a_vfp->_vfpStart;
7035c51f124SMoriah Waterland
7045c51f124SMoriah Waterland /* current character is NULL */
7055c51f124SMoriah Waterland
7065c51f124SMoriah Waterland *a_vfp->_vfpCurr = '\0';
7075c51f124SMoriah Waterland
7085c51f124SMoriah Waterland /* if file associated with VFP, truncate actual file */
7095c51f124SMoriah Waterland
7105c51f124SMoriah Waterland if (a_vfp->_vfpFile != (FILE *)NULL) {
7115c51f124SMoriah Waterland (void) ftruncate(fileno(a_vfp->_vfpFile), 0);
7125c51f124SMoriah Waterland }
7135c51f124SMoriah Waterland }
7145c51f124SMoriah Waterland
7155c51f124SMoriah Waterland /*
7165c51f124SMoriah Waterland * Name: vfpWriteToFile
7175c51f124SMoriah Waterland * Description: Write data associated with VFP to specified file
7185c51f124SMoriah Waterland * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to write
7195c51f124SMoriah Waterland * char *a_path - path of file to write file data to
7205c51f124SMoriah Waterland * Returns: int == 0 - operation was successful
7215c51f124SMoriah Waterland * != 0 - operation failed, errno contains reason
7225c51f124SMoriah Waterland */
7235c51f124SMoriah Waterland
7245c51f124SMoriah Waterland int
vfpWriteToFile(VFP_T * a_vfp,char * a_path)7255c51f124SMoriah Waterland vfpWriteToFile(VFP_T *a_vfp, char *a_path)
7265c51f124SMoriah Waterland {
7275c51f124SMoriah Waterland int fd;
7285c51f124SMoriah Waterland int lerrno = 0;
7295c51f124SMoriah Waterland size_t len;
7305c51f124SMoriah Waterland ssize_t result = 0;
7315c51f124SMoriah Waterland
7325c51f124SMoriah Waterland /* return if no vfp specified */
7335c51f124SMoriah Waterland
7345c51f124SMoriah Waterland if (a_vfp == (VFP_T *)NULL) {
7355c51f124SMoriah Waterland errno = EFAULT;
7365c51f124SMoriah Waterland return (-1);
7375c51f124SMoriah Waterland }
7385c51f124SMoriah Waterland
7395c51f124SMoriah Waterland /* on buffer overflow generate error */
7405c51f124SMoriah Waterland
7415c51f124SMoriah Waterland if ((a_vfp->_vfpOverflow != 0) || (vfpGetBytesAvailable(a_vfp) < 1)) {
7425c51f124SMoriah Waterland errno = EFBIG;
7435c51f124SMoriah Waterland return (-1);
7445c51f124SMoriah Waterland }
7455c51f124SMoriah Waterland
7465c51f124SMoriah Waterland /* open file to write data to */
7475c51f124SMoriah Waterland
7485c51f124SMoriah Waterland fd = open(a_path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
7495c51f124SMoriah Waterland if (fd < 0) {
7505c51f124SMoriah Waterland return (-1);
7515c51f124SMoriah Waterland }
7525c51f124SMoriah Waterland
7535c51f124SMoriah Waterland /* determine number of bytes to write */
7545c51f124SMoriah Waterland
7555c51f124SMoriah Waterland len = vfpGetModifiedLen(a_vfp);
7565c51f124SMoriah Waterland
7575c51f124SMoriah Waterland /*
7585c51f124SMoriah Waterland * if there is data associated with the file, write it out;
7595c51f124SMoriah Waterland * if an error occurs, close the file and return failure.
7605c51f124SMoriah Waterland */
7615c51f124SMoriah Waterland
7625c51f124SMoriah Waterland if (len > 0) {
7635c51f124SMoriah Waterland result = vfpSafeWrite(fd, a_vfp->_vfpStart, len);
7645c51f124SMoriah Waterland if (result != len) {
7655c51f124SMoriah Waterland /* error comitting data - return failure */
7665c51f124SMoriah Waterland lerrno = errno;
7675c51f124SMoriah Waterland (void) close(fd);
7685c51f124SMoriah Waterland errno = lerrno;
7695c51f124SMoriah Waterland return (-1);
7705c51f124SMoriah Waterland }
7715c51f124SMoriah Waterland }
7725c51f124SMoriah Waterland
7735c51f124SMoriah Waterland /* close the file */
7745c51f124SMoriah Waterland
7755c51f124SMoriah Waterland (void) close(fd);
7765c51f124SMoriah Waterland
7775c51f124SMoriah Waterland /* data committed to backing store - clear the modified flag */
7785c51f124SMoriah Waterland
7795c51f124SMoriah Waterland (void) vfpClearModified(a_vfp);
7805c51f124SMoriah Waterland
7815c51f124SMoriah Waterland /* return success */
7825c51f124SMoriah Waterland
7835c51f124SMoriah Waterland return (0);
7845c51f124SMoriah Waterland }
7855c51f124SMoriah Waterland
7865c51f124SMoriah Waterland /*
7875c51f124SMoriah Waterland * Name: vfpCheckpointFile
7885c51f124SMoriah Waterland * Description: Create new VFP that checkpoints existing VFP, can be used by
7895c51f124SMoriah Waterland * subsequent call to vfpCheckpointOpen to open a file using the
7905c51f124SMoriah Waterland * existing in-memory cache of the contents of the file
7915c51f124SMoriah Waterland * Arguments: VFP_T **r_cpVfp - pointer to pointer to VFP_T to be filled in
7925c51f124SMoriah Waterland * with "checkpointed file" VFP (backing store)
7935c51f124SMoriah Waterland * VFP_T **a_vfp - pointer to pointer to VFP_T returned by vfpOpen
7945c51f124SMoriah Waterland * representing the VFP to checkpoint
7955c51f124SMoriah Waterland * char *a_path - path to file that is the backing store for the
7965c51f124SMoriah Waterland * in-memory data represented by a_vfp - used to verify
7975c51f124SMoriah Waterland * that the data in memory is not out of date with respect
7985c51f124SMoriah Waterland * to the backing store when vfpCheckpointOpen is called
7995c51f124SMoriah Waterland * == (char *)NULL - use path associated with a_vfp
8005c51f124SMoriah Waterland * that is, the backing store file in use
8015c51f124SMoriah Waterland * Returns: int == 0 - operation was successful
8025c51f124SMoriah Waterland * - r_destVfp contains a pointer to a new VFP that
8035c51f124SMoriah Waterland * may be used in a subsequent call to
8045c51f124SMoriah Waterland * vfpCheckpointOpen
8055c51f124SMoriah Waterland * - the VFP referenced by *a_vfp is free()ed and
8065c51f124SMoriah Waterland * must no longer be referenced
8075c51f124SMoriah Waterland * != 0 - operation failed, errno contains reason
8085c51f124SMoriah Waterland * - the VFP referenced by *a_vfp is not affected;
8095c51f124SMoriah Waterland * the caller may continue to use it
8105c51f124SMoriah Waterland * Notes: If the data of a VFP to checkpoint is mmap()ed then this method
8115c51f124SMoriah Waterland * returns failure - only malloc()ed data VFPs can be
8125c51f124SMoriah Waterland * checkpointed.
8135c51f124SMoriah Waterland */
8145c51f124SMoriah Waterland
8155c51f124SMoriah Waterland int
vfpCheckpointFile(VFP_T ** r_cpVfp,VFP_T ** a_vfp,char * a_path)8165c51f124SMoriah Waterland vfpCheckpointFile(VFP_T **r_cpVfp, VFP_T **a_vfp, char *a_path)
8175c51f124SMoriah Waterland {
8185c51f124SMoriah Waterland VFP_T *vfp; /* newly allocated checkpointed VFP */
8195c51f124SMoriah Waterland VFP_T *avfp; /* local -> to a_vfp */
8205c51f124SMoriah Waterland struct stat statbuf; /* stat(2) info for backing store */
8215c51f124SMoriah Waterland
8225c51f124SMoriah Waterland /* return error if NULL VFP_T** to checkpoint provided */
8235c51f124SMoriah Waterland
8245c51f124SMoriah Waterland if (r_cpVfp == (VFP_T **)NULL) {
8255c51f124SMoriah Waterland errno = EFAULT;
8265c51f124SMoriah Waterland return (-1);
8275c51f124SMoriah Waterland }
8285c51f124SMoriah Waterland
8295c51f124SMoriah Waterland /* reset return checkpoint VFP pointer */
8305c51f124SMoriah Waterland
8315c51f124SMoriah Waterland (*r_cpVfp) = (VFP_T *)NULL;
8325c51f124SMoriah Waterland
8335c51f124SMoriah Waterland /* return error if no VFP to checkpoint specified */
8345c51f124SMoriah Waterland
8355c51f124SMoriah Waterland if (a_vfp == (VFP_T **)NULL) {
8365c51f124SMoriah Waterland errno = EFAULT;
8375c51f124SMoriah Waterland return (-1);
8385c51f124SMoriah Waterland }
8395c51f124SMoriah Waterland
8405c51f124SMoriah Waterland /* localize reference to a_vfp */
8415c51f124SMoriah Waterland
8425c51f124SMoriah Waterland avfp = *a_vfp;
8435c51f124SMoriah Waterland
8445c51f124SMoriah Waterland /* return error if no VFP to checkpoint specified */
8455c51f124SMoriah Waterland
8465c51f124SMoriah Waterland if (avfp == (VFP_T *)NULL) {
8475c51f124SMoriah Waterland errno = EFAULT;
8485c51f124SMoriah Waterland return (-1);
8495c51f124SMoriah Waterland }
8505c51f124SMoriah Waterland
8515c51f124SMoriah Waterland /* on buffer overflow generate error */
8525c51f124SMoriah Waterland
8535c51f124SMoriah Waterland if ((avfp->_vfpOverflow != 0) || (vfpGetBytesAvailable(avfp) < 1)) {
8545c51f124SMoriah Waterland errno = EFBIG;
8555c51f124SMoriah Waterland return (-1);
8565c51f124SMoriah Waterland }
8575c51f124SMoriah Waterland
8585c51f124SMoriah Waterland /* no checkpointing is possible if the existing VFP is mmap()ed */
8595c51f124SMoriah Waterland
8605c51f124SMoriah Waterland if (avfp->_vfpFlags & _VFP_MMAP) {
8615c51f124SMoriah Waterland errno = EIO;
8625c51f124SMoriah Waterland return (-1);
8635c51f124SMoriah Waterland }
8645c51f124SMoriah Waterland
8655c51f124SMoriah Waterland /* if no path specified, grab it from the VFP to checkpoint */
8665c51f124SMoriah Waterland
8675c51f124SMoriah Waterland if ((a_path == (char *)NULL) || (*a_path == '\0')) {
8685c51f124SMoriah Waterland a_path = avfp->_vfpPath;
8695c51f124SMoriah Waterland }
8705c51f124SMoriah Waterland
8715c51f124SMoriah Waterland /* backing store required: if VFP is "string" then this is an error */
8725c51f124SMoriah Waterland
8735c51f124SMoriah Waterland if ((a_path == (char *)NULL) ||
8745c51f124SMoriah Waterland strcmp(a_path, VFP_ANONYMOUS_PATH) == 0) {
8755c51f124SMoriah Waterland errno = EINVAL;
8765c51f124SMoriah Waterland return (-1);
8775c51f124SMoriah Waterland }
8785c51f124SMoriah Waterland
8795c51f124SMoriah Waterland /* Get the VFP to checkpoint (backing store) file size */
8805c51f124SMoriah Waterland
8815c51f124SMoriah Waterland if (stat(a_path, &statbuf) != 0) {
8825c51f124SMoriah Waterland return (-1);
8835c51f124SMoriah Waterland }
8845c51f124SMoriah Waterland
8855c51f124SMoriah Waterland /* allocate storage for checkpointed VFP (to return) */
8865c51f124SMoriah Waterland
8875c51f124SMoriah Waterland vfp = (VFP_T *)malloc(sizeof (VFP_T));
8885c51f124SMoriah Waterland if (vfp == (VFP_T *)NULL) {
8895c51f124SMoriah Waterland return (-1);
8905c51f124SMoriah Waterland }
8915c51f124SMoriah Waterland
8925c51f124SMoriah Waterland /*
8935c51f124SMoriah Waterland * close any file that is on the VFP to checkpoint (backing store);
8945c51f124SMoriah Waterland * subsequent processes can modify the backing store data, and
8955c51f124SMoriah Waterland * then when vfpCheckpointOpen is called, either the in-memory
8965c51f124SMoriah Waterland * cached data will be used (if backing store unmodified) or else
8975c51f124SMoriah Waterland * the in-memory data is released and the backing store is used.
8985c51f124SMoriah Waterland */
8995c51f124SMoriah Waterland
9005c51f124SMoriah Waterland if (avfp->_vfpFile != (FILE *)NULL) {
9015c51f124SMoriah Waterland (void) fclose(avfp->_vfpFile);
9025c51f124SMoriah Waterland avfp->_vfpFile = (FILE *)NULL;
9035c51f124SMoriah Waterland }
9045c51f124SMoriah Waterland
9055c51f124SMoriah Waterland /* free any path associated with VFP to checkpoint (backing store) */
9065c51f124SMoriah Waterland
9075c51f124SMoriah Waterland if (avfp->_vfpPath != (char *)NULL) {
9085c51f124SMoriah Waterland (void) free(avfp->_vfpPath);
9095c51f124SMoriah Waterland avfp->_vfpPath = (char *)NULL;
9105c51f124SMoriah Waterland }
9115c51f124SMoriah Waterland
9125c51f124SMoriah Waterland /* copy contents of VFP to checkpoint to checkpointed VFP */
9135c51f124SMoriah Waterland
914*4656d474SGarrett D'Amore (void) memcpy(vfp, avfp, sizeof (VFP_T));
9155c51f124SMoriah Waterland
9165c51f124SMoriah Waterland /* free contents of VFP to checkpoint */
9175c51f124SMoriah Waterland
9185c51f124SMoriah Waterland (void) free(avfp);
9195c51f124SMoriah Waterland
9205c51f124SMoriah Waterland /* reset pointer to VFP that has been free'd */
9215c51f124SMoriah Waterland
9225c51f124SMoriah Waterland *a_vfp = (VFP_T *)NULL;
9235c51f124SMoriah Waterland
9245c51f124SMoriah Waterland /* remember path associated with the checkpointed VFP (backing store) */
9255c51f124SMoriah Waterland
9265c51f124SMoriah Waterland vfp->_vfpPath = strdup(a_path);
9275c51f124SMoriah Waterland
9285c51f124SMoriah Waterland /* save tokens that identify the backing store for the in-memory data */
9295c51f124SMoriah Waterland
9305c51f124SMoriah Waterland vfp->_vfpCkDev = statbuf.st_dev; /* devid holding st_ino inode */
9315c51f124SMoriah Waterland vfp->_vfpCkIno = statbuf.st_ino; /* backing store inode */
9325c51f124SMoriah Waterland vfp->_vfpCkMtime = statbuf.st_mtime; /* last data modification */
9335c51f124SMoriah Waterland vfp->_vfpCkSize = statbuf.st_size; /* backing store size (bytes) */
9345c51f124SMoriah Waterland vfp->_vfpCkStBlocks = statbuf.st_blocks; /* blocks allocated to file */
9355c51f124SMoriah Waterland
9365c51f124SMoriah Waterland /* pass checkpointed VFP to caller */
9375c51f124SMoriah Waterland
9385c51f124SMoriah Waterland (*r_cpVfp) = vfp;
9395c51f124SMoriah Waterland
9405c51f124SMoriah Waterland /* success! */
9415c51f124SMoriah Waterland
9425c51f124SMoriah Waterland return (0);
9435c51f124SMoriah Waterland }
9445c51f124SMoriah Waterland
9455c51f124SMoriah Waterland /*
9465c51f124SMoriah Waterland * Name: vfpCheckpointOpen
9475c51f124SMoriah Waterland * Description: Open file on vfp, allocate storage, return pointer to VFP_T
9485c51f124SMoriah Waterland * that can be used to access/modify file contents. If a VFP_T to
9495c51f124SMoriah Waterland * a checkpointed VFP is passed in, and the in memory contents of
9505c51f124SMoriah Waterland * the VFP are not out of date with respect to the backing store
9515c51f124SMoriah Waterland * file, use the existing in-memory contents - otherwise, discard
9525c51f124SMoriah Waterland * the in-memory contents and reopen and reread the file.
9535c51f124SMoriah Waterland * Arguments: VFP_T **a_cpVfp - pointer to pointer to VFP_T that represents
9545c51f124SMoriah Waterland * checkpointed VFP to use to open the file IF the contents
9555c51f124SMoriah Waterland * of the backing store are identical to the in-memory data
9565c51f124SMoriah Waterland * VFP_T **r_vfp - pointer to pointer to VFP_T to open file on
9575c51f124SMoriah Waterland * char *a_path - path of file to open and associate with this VFP.
9585c51f124SMoriah Waterland * - if the path is (char *)NULL then no file is associated
9595c51f124SMoriah Waterland * with this VFP - this is a way to create a fixed length
9605c51f124SMoriah Waterland * string that can be manipulated with the VFP operators.
9615c51f124SMoriah Waterland * Before the VFP can be used "vfpSetSize" must be called
9625c51f124SMoriah Waterland * to set the size of the string buffer.
9635c51f124SMoriah Waterland * char *a_mode - fopen mode to open the file with
9645c51f124SMoriah Waterland * VFPFLAGS_T a_flags - one or more flags to control the operation:
9655c51f124SMoriah Waterland * - VFP_NONE - no special flags
9665c51f124SMoriah Waterland * - VFP_NEEDNOW - file data needed in memory now
9675c51f124SMoriah Waterland * - VFP_SEQUENTIAL - memory will be sequentially accessed
9685c51f124SMoriah Waterland * - VFP_RANDOM - memory will be randomly accessed
9695c51f124SMoriah Waterland * - VFP_NOMMAP - do not use mmap to access file
9705c51f124SMoriah Waterland * - VFP_NOMALLOC - do not use malloc to buffer file
9715c51f124SMoriah Waterland * Returns: int == 0 - operation was successful
9725c51f124SMoriah Waterland * != 0 - operation failed, errno contains reason
9735c51f124SMoriah Waterland * Side Effects: r_vfp -- filled in with a pointer to a newly allocated vfp
9745c51f124SMoriah Waterland * which can be used with the various VFP functions.
9755c51f124SMoriah Waterland * a_cpVfp -- contents reset to zero if used to open the file
9765c51f124SMoriah Waterland * errno -- contains system error number if return is != 0
9775c51f124SMoriah Waterland */
9785c51f124SMoriah Waterland
9795c51f124SMoriah Waterland int
vfpCheckpointOpen(VFP_T ** a_cpVfp,VFP_T ** r_vfp,char * a_path,char * a_mode,VFPFLAGS_T a_flags)9805c51f124SMoriah Waterland vfpCheckpointOpen(VFP_T **a_cpVfp, VFP_T **r_vfp, char *a_path,
9815c51f124SMoriah Waterland char *a_mode, VFPFLAGS_T a_flags)
9825c51f124SMoriah Waterland {
9835c51f124SMoriah Waterland FILE *fp; /* backing store */
9845c51f124SMoriah Waterland VFP_T *cpVfp; /* local -> to a_cpVfp checkpointed VFP */
9855c51f124SMoriah Waterland VFP_T *vfp; /* new VFP open on checkpointed backing store */
9865c51f124SMoriah Waterland struct stat statbuf; /* stat(2) info on backing store */
9875c51f124SMoriah Waterland
9885c51f124SMoriah Waterland /*
9895c51f124SMoriah Waterland * if no source VFP, or source VFP empty,
9905c51f124SMoriah Waterland * or no backing store, just open file
9915c51f124SMoriah Waterland */
9925c51f124SMoriah Waterland
9935c51f124SMoriah Waterland if ((a_cpVfp == (VFP_T **)NULL) || (*a_cpVfp == (VFP_T *)NULL) ||
9945c51f124SMoriah Waterland ((*a_cpVfp)->_vfpStart == (char *)NULL)) {
9955c51f124SMoriah Waterland (void) vfpClose(a_cpVfp);
9965c51f124SMoriah Waterland return (vfpOpen(r_vfp, a_path, a_mode, a_flags));
9975c51f124SMoriah Waterland }
9985c51f124SMoriah Waterland
9995c51f124SMoriah Waterland /* localize access to checkpointed VFP_T (*a_cpVfp) */
10005c51f124SMoriah Waterland
10015c51f124SMoriah Waterland cpVfp = *a_cpVfp;
10025c51f124SMoriah Waterland
10035c51f124SMoriah Waterland /* if no path specified, grab it from the checkpointed VFP */
10045c51f124SMoriah Waterland
10055c51f124SMoriah Waterland if ((a_path == (char *)NULL) || (*a_path == '\0')) {
10065c51f124SMoriah Waterland a_path = cpVfp->_vfpPath;
10075c51f124SMoriah Waterland }
10085c51f124SMoriah Waterland
10095c51f124SMoriah Waterland /* return error if no path specified and no path in checkpointed VFP */
10105c51f124SMoriah Waterland
10115c51f124SMoriah Waterland if ((a_path == (char *)NULL) && (*a_path == '\0')) {
10125c51f124SMoriah Waterland errno = EINVAL;
10135c51f124SMoriah Waterland return (-1);
10145c51f124SMoriah Waterland }
10155c51f124SMoriah Waterland
10165c51f124SMoriah Waterland /* if no backing store path, then just open file */
10175c51f124SMoriah Waterland
10185c51f124SMoriah Waterland if (stat(a_path, &statbuf) != 0) {
10195c51f124SMoriah Waterland (void) vfpClose(a_cpVfp);
10205c51f124SMoriah Waterland return (vfpOpen(r_vfp, a_path, a_mode, a_flags));
10215c51f124SMoriah Waterland }
10225c51f124SMoriah Waterland
10235c51f124SMoriah Waterland /*
10245c51f124SMoriah Waterland * if backing store tokens do not match checkpointed VFP,
10255c51f124SMoriah Waterland * the backing store has been updated since the VFP was checkpointed;
10265c51f124SMoriah Waterland * release the in-memory data, and open and read the backing store
10275c51f124SMoriah Waterland */
10285c51f124SMoriah Waterland
10295c51f124SMoriah Waterland if ((statbuf.st_size != cpVfp->_vfpCkSize) ||
10305c51f124SMoriah Waterland (statbuf.st_mtime != cpVfp->_vfpCkMtime) ||
10315c51f124SMoriah Waterland (statbuf.st_blocks != cpVfp->_vfpCkStBlocks) ||
10325c51f124SMoriah Waterland (statbuf.st_ino != cpVfp->_vfpCkIno) ||
10335c51f124SMoriah Waterland (statbuf.st_dev != cpVfp->_vfpCkDev)) {
10345c51f124SMoriah Waterland (void) vfpClose(a_cpVfp);
10355c51f124SMoriah Waterland return (vfpOpen(r_vfp, a_path, a_mode, a_flags));
10365c51f124SMoriah Waterland }
10375c51f124SMoriah Waterland
10385c51f124SMoriah Waterland /*
10395c51f124SMoriah Waterland * backing store has not been updated since the VFP was checkpointed;
10405c51f124SMoriah Waterland * use the in-memory data without re-reading the backing store; open the
10415c51f124SMoriah Waterland * backing store file (if no file already open on the checkpointed VFP)
10425c51f124SMoriah Waterland * so there is an open file associated with the in-memory data
10435c51f124SMoriah Waterland */
10445c51f124SMoriah Waterland
10455c51f124SMoriah Waterland fp = cpVfp->_vfpFile;
10465c51f124SMoriah Waterland if (fp == (FILE *)NULL) {
10475c51f124SMoriah Waterland fp = fopen(a_path, a_mode);
10485c51f124SMoriah Waterland if (fp == (FILE *)NULL) {
10495c51f124SMoriah Waterland int lerrno;
10505c51f124SMoriah Waterland
10515c51f124SMoriah Waterland lerrno = errno;
10525c51f124SMoriah Waterland (void) vfpClose(a_cpVfp);
10535c51f124SMoriah Waterland errno = lerrno;
10545c51f124SMoriah Waterland return (-1);
10555c51f124SMoriah Waterland }
10565c51f124SMoriah Waterland }
10575c51f124SMoriah Waterland
10585c51f124SMoriah Waterland /* allocate new VFP object to return as open VFP */
10595c51f124SMoriah Waterland
10605c51f124SMoriah Waterland vfp = (VFP_T *)malloc(sizeof (VFP_T));
10615c51f124SMoriah Waterland if (vfp == (VFP_T *)NULL) {
10625c51f124SMoriah Waterland (void) vfpClose(a_cpVfp);
10635c51f124SMoriah Waterland return (vfpOpen(r_vfp, a_path, a_mode, a_flags));
10645c51f124SMoriah Waterland }
10655c51f124SMoriah Waterland
10665c51f124SMoriah Waterland /* copy cached checkpointed VFP to new VFP to return */
10675c51f124SMoriah Waterland
10685c51f124SMoriah Waterland (void) memcpy(vfp, cpVfp, sizeof (VFP_T));
10695c51f124SMoriah Waterland
10705c51f124SMoriah Waterland /*
10715c51f124SMoriah Waterland * initialize VFP to return contents
10725c51f124SMoriah Waterland */
10735c51f124SMoriah Waterland
10745c51f124SMoriah Waterland /* FILE -> file opened on the VFPs backing store */
10755c51f124SMoriah Waterland
10765c51f124SMoriah Waterland vfp->_vfpFile = fp;
10775c51f124SMoriah Waterland
10785c51f124SMoriah Waterland /* release any existing path associated with the VFP */
10795c51f124SMoriah Waterland
10805c51f124SMoriah Waterland if (vfp->_vfpPath != (char *)NULL) {
10815c51f124SMoriah Waterland (void) free(vfp->_vfpPath);
10825c51f124SMoriah Waterland }
10835c51f124SMoriah Waterland
10845c51f124SMoriah Waterland /* path associated with the backing store for this VFP */
10855c51f124SMoriah Waterland
10865c51f124SMoriah Waterland vfp->_vfpPath = strdup(a_path);
10875c51f124SMoriah Waterland
10885c51f124SMoriah Waterland /*
10895c51f124SMoriah Waterland * data pointers associated with in memory copy of backing store
10905c51f124SMoriah Waterland * (such as _vfpHighWater, _vfpEnd, _vfpStart, etc.)
10915c51f124SMoriah Waterland * do not need to be modified because we are using the same backing
10925c51f124SMoriah Waterland * store as was checkpointed in cpVfp that is pointed to by vfp.
10935c51f124SMoriah Waterland */
10945c51f124SMoriah Waterland
10955c51f124SMoriah Waterland /* _vfpCurr -> next byte to read */
10965c51f124SMoriah Waterland vfp->_vfpCurr = (char *)vfp->_vfpStart;
10975c51f124SMoriah Waterland
10985c51f124SMoriah Waterland /* free checkpointed VFP as it is now open on "vfp" */
10995c51f124SMoriah Waterland
11005c51f124SMoriah Waterland (void) free(cpVfp);
11015c51f124SMoriah Waterland
11025c51f124SMoriah Waterland /* reset callers -> checkpointed VFP */
11035c51f124SMoriah Waterland
11045c51f124SMoriah Waterland (*a_cpVfp) = (VFP_T *)NULL;
11055c51f124SMoriah Waterland
11065c51f124SMoriah Waterland /* set return VFP pointer */
11075c51f124SMoriah Waterland
11085c51f124SMoriah Waterland (*r_vfp) = vfp;
11095c51f124SMoriah Waterland
11105c51f124SMoriah Waterland /* success! */
11115c51f124SMoriah Waterland
11125c51f124SMoriah Waterland return (0);
11135c51f124SMoriah Waterland }
11145c51f124SMoriah Waterland
11155c51f124SMoriah Waterland /*
11165c51f124SMoriah Waterland * Name: vfpClearModified
11175c51f124SMoriah Waterland * Description: Clear the "data is modified" indication from the VFP
11185c51f124SMoriah Waterland * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to clear
11195c51f124SMoriah Waterland * the "data is modified" indication
11205c51f124SMoriah Waterland * Returns: int - previous setting of "data is modified" indication
11215c51f124SMoriah Waterland * == 0 - "data is modified" was NOT previously set
11225c51f124SMoriah Waterland * != 0 - "data is modified" WAS previously set
11235c51f124SMoriah Waterland */
11245c51f124SMoriah Waterland
11255c51f124SMoriah Waterland int
vfpClearModified(VFP_T * a_vfp)11265c51f124SMoriah Waterland vfpClearModified(VFP_T *a_vfp)
11275c51f124SMoriah Waterland {
11285c51f124SMoriah Waterland VFPFLAGS_T flags;
11295c51f124SMoriah Waterland
11305c51f124SMoriah Waterland /* save current flags settings */
11315c51f124SMoriah Waterland
11325c51f124SMoriah Waterland flags = a_vfp->_vfpFlags;
11335c51f124SMoriah Waterland
11345c51f124SMoriah Waterland /* clear "data is modified" flag */
11355c51f124SMoriah Waterland
11365c51f124SMoriah Waterland a_vfp->_vfpFlags &= (~_VFP_MODIFIED);
11375c51f124SMoriah Waterland
11385c51f124SMoriah Waterland /* return previous "data is modified" flag setting */
11395c51f124SMoriah Waterland
11405c51f124SMoriah Waterland return ((flags & _VFP_MODIFIED) != 0);
11415c51f124SMoriah Waterland }
11425c51f124SMoriah Waterland
11435c51f124SMoriah Waterland /*
11445c51f124SMoriah Waterland * Name: vfpSetModified
11455c51f124SMoriah Waterland * Description: Set the "data is modified" indication from the VFP
11465c51f124SMoriah Waterland * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to set
11475c51f124SMoriah Waterland * the "data is modified" indication
11485c51f124SMoriah Waterland * Returns: int - previous setting of "data is modified" indication
11495c51f124SMoriah Waterland * == 0 - "data is modified" was NOT previously set
11505c51f124SMoriah Waterland * != 0 - "data is modified" WAS previously set
11515c51f124SMoriah Waterland */
11525c51f124SMoriah Waterland
11535c51f124SMoriah Waterland int
vfpSetModified(VFP_T * a_vfp)11545c51f124SMoriah Waterland vfpSetModified(VFP_T *a_vfp)
11555c51f124SMoriah Waterland {
11565c51f124SMoriah Waterland VFPFLAGS_T flags;
11575c51f124SMoriah Waterland
11585c51f124SMoriah Waterland /* save current flags settings */
11595c51f124SMoriah Waterland
11605c51f124SMoriah Waterland flags = a_vfp->_vfpFlags;
11615c51f124SMoriah Waterland
11625c51f124SMoriah Waterland /* set "data is modified" flag */
11635c51f124SMoriah Waterland
11645c51f124SMoriah Waterland a_vfp->_vfpFlags |= _VFP_MODIFIED;
11655c51f124SMoriah Waterland
11665c51f124SMoriah Waterland /* return previous "data is modified" flag setting */
11675c51f124SMoriah Waterland
11685c51f124SMoriah Waterland return ((flags & _VFP_MODIFIED) != 0);
11695c51f124SMoriah Waterland }
11705c51f124SMoriah Waterland
11715c51f124SMoriah Waterland /*
11725c51f124SMoriah Waterland * Name: vfpGetModified
11735c51f124SMoriah Waterland * Description: Get the "data is modified" indication from the VFP
11745c51f124SMoriah Waterland * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to get
11755c51f124SMoriah Waterland * the "data is modified" indication
11765c51f124SMoriah Waterland * Returns: int - current setting of "data is modified" indication
11775c51f124SMoriah Waterland * == 0 - "data is modified" is NOT set
11785c51f124SMoriah Waterland * != 0 - "data is modified" IS set
11795c51f124SMoriah Waterland */
11805c51f124SMoriah Waterland
11815c51f124SMoriah Waterland int
vfpGetModified(VFP_T * a_vfp)11825c51f124SMoriah Waterland vfpGetModified(VFP_T *a_vfp)
11835c51f124SMoriah Waterland {
11845c51f124SMoriah Waterland /* return current "data is modified" flag setting */
11855c51f124SMoriah Waterland
11865c51f124SMoriah Waterland return ((a_vfp->_vfpFlags & _VFP_MODIFIED) != 0);
11875c51f124SMoriah Waterland }
11885c51f124SMoriah Waterland
11895c51f124SMoriah Waterland /*
11905c51f124SMoriah Waterland * Name: vfpSafeWrite
11915c51f124SMoriah Waterland * Description: write data to open file safely
11925c51f124SMoriah Waterland * Arguments: a_fildes - file descriptor to write data to
11935c51f124SMoriah Waterland * a_buf - pointer to buffer containing data to write
11945c51f124SMoriah Waterland * a_nbyte - number of bytes to write to open file
11955c51f124SMoriah Waterland * Returns: int
11965c51f124SMoriah Waterland * < 0 - error, errno set
11975c51f124SMoriah Waterland * >= 0 - success
11985c51f124SMoriah Waterland * NOTE: unlike write(2), vfpSafeWrite() handles partial writes, and will
11995c51f124SMoriah Waterland * ----- restart the write() until all bytes are written, or an error occurs.
12005c51f124SMoriah Waterland */
12015c51f124SMoriah Waterland
12025c51f124SMoriah Waterland ssize_t
vfpSafeWrite(int a_fildes,void * a_buf,size_t a_nbyte)12035c51f124SMoriah Waterland vfpSafeWrite(int a_fildes, void *a_buf, size_t a_nbyte)
12045c51f124SMoriah Waterland {
12055c51f124SMoriah Waterland ssize_t r;
12065c51f124SMoriah Waterland size_t bytes = a_nbyte;
12075c51f124SMoriah Waterland
12085c51f124SMoriah Waterland for (;;) {
12095c51f124SMoriah Waterland /* write bytes to file */
12105c51f124SMoriah Waterland r = write(a_fildes, a_buf, a_nbyte);
12115c51f124SMoriah Waterland
12125c51f124SMoriah Waterland /* return error on failure of write() */
12135c51f124SMoriah Waterland if (r < 0) {
12145c51f124SMoriah Waterland /* EAGAIN: try again */
12155c51f124SMoriah Waterland if (errno == EAGAIN) {
12165c51f124SMoriah Waterland continue;
12175c51f124SMoriah Waterland }
12185c51f124SMoriah Waterland /* EINTR: interrupted - try again */
12195c51f124SMoriah Waterland if (errno == EINTR) {
12205c51f124SMoriah Waterland continue;
12215c51f124SMoriah Waterland }
12225c51f124SMoriah Waterland return (r);
12235c51f124SMoriah Waterland }
12245c51f124SMoriah Waterland
12255c51f124SMoriah Waterland /* return total bytes written on success */
12265c51f124SMoriah Waterland if (r >= a_nbyte) {
12275c51f124SMoriah Waterland return (bytes);
12285c51f124SMoriah Waterland }
12295c51f124SMoriah Waterland
12305c51f124SMoriah Waterland /* partial write, adjust pointers, call write again */
12315c51f124SMoriah Waterland a_buf = (void *)((ptrdiff_t)a_buf + (ptrdiff_t)r);
12325c51f124SMoriah Waterland a_nbyte -= (size_t)r;
12335c51f124SMoriah Waterland }
12345c51f124SMoriah Waterland }
12355c51f124SMoriah Waterland
12365c51f124SMoriah Waterland /*
12375c51f124SMoriah Waterland * Name: vfpSafePwrite
12385c51f124SMoriah Waterland * Description: write data to open file safely
12395c51f124SMoriah Waterland * Arguments: a_fildes - file descriptor to write data to
12405c51f124SMoriah Waterland * a_buf - pointer to buffer containing data to write
12415c51f124SMoriah Waterland * a_nbyte - number of bytes to write to open file
12425c51f124SMoriah Waterland * a_offset - offset into open file to write the first byte to
12435c51f124SMoriah Waterland * Returns: int
12445c51f124SMoriah Waterland * < 0 - error, errno set
12455c51f124SMoriah Waterland * >= 0 - success
12465c51f124SMoriah Waterland * NOTE: unlike pwrite(2), vfpSafePwrite() handles partial writes, and will
12475c51f124SMoriah Waterland * ----- restart the pwrite() until all bytes are written, or an error occurs.
12485c51f124SMoriah Waterland */
12495c51f124SMoriah Waterland
12505c51f124SMoriah Waterland ssize_t
vfpSafePwrite(int a_fildes,void * a_buf,size_t a_nbyte,off_t a_offset)12515c51f124SMoriah Waterland vfpSafePwrite(int a_fildes, void *a_buf, size_t a_nbyte, off_t a_offset)
12525c51f124SMoriah Waterland {
12535c51f124SMoriah Waterland ssize_t r;
12545c51f124SMoriah Waterland size_t bytes = a_nbyte;
12555c51f124SMoriah Waterland
12565c51f124SMoriah Waterland for (;;) {
12575c51f124SMoriah Waterland /* write bytes to file */
12585c51f124SMoriah Waterland r = pwrite(a_fildes, a_buf, a_nbyte, a_offset);
12595c51f124SMoriah Waterland
12605c51f124SMoriah Waterland /* return error on failure of write() */
12615c51f124SMoriah Waterland if (r < 0) {
12625c51f124SMoriah Waterland /* EAGAIN: try again */
12635c51f124SMoriah Waterland if (errno == EAGAIN) {
12645c51f124SMoriah Waterland continue;
12655c51f124SMoriah Waterland }
12665c51f124SMoriah Waterland /* EINTR: interrupted - try again */
12675c51f124SMoriah Waterland if (errno == EINTR) {
12685c51f124SMoriah Waterland continue;
12695c51f124SMoriah Waterland }
12705c51f124SMoriah Waterland return (r);
12715c51f124SMoriah Waterland }
12725c51f124SMoriah Waterland
12735c51f124SMoriah Waterland /* return total bytes written on success */
12745c51f124SMoriah Waterland if (r >= a_nbyte) {
12755c51f124SMoriah Waterland return (bytes);
12765c51f124SMoriah Waterland }
12775c51f124SMoriah Waterland
12785c51f124SMoriah Waterland /* partial write, adjust pointers, call write again */
12795c51f124SMoriah Waterland a_buf = (void *)((ptrdiff_t)a_buf + (ptrdiff_t)r);
12805c51f124SMoriah Waterland a_nbyte -= (size_t)r;
12815c51f124SMoriah Waterland a_offset += (off_t)r;
12825c51f124SMoriah Waterland }
12835c51f124SMoriah Waterland }
1284