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 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 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 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 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 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 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 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 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 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 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 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 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 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 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