1*9781SMoriah.Waterland@Sun.COM /*
2*9781SMoriah.Waterland@Sun.COM * CDDL HEADER START
3*9781SMoriah.Waterland@Sun.COM *
4*9781SMoriah.Waterland@Sun.COM * The contents of this file are subject to the terms of the
5*9781SMoriah.Waterland@Sun.COM * Common Development and Distribution License (the "License").
6*9781SMoriah.Waterland@Sun.COM * You may not use this file except in compliance with the License.
7*9781SMoriah.Waterland@Sun.COM *
8*9781SMoriah.Waterland@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*9781SMoriah.Waterland@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*9781SMoriah.Waterland@Sun.COM * See the License for the specific language governing permissions
11*9781SMoriah.Waterland@Sun.COM * and limitations under the License.
12*9781SMoriah.Waterland@Sun.COM *
13*9781SMoriah.Waterland@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*9781SMoriah.Waterland@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*9781SMoriah.Waterland@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*9781SMoriah.Waterland@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*9781SMoriah.Waterland@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*9781SMoriah.Waterland@Sun.COM *
19*9781SMoriah.Waterland@Sun.COM * CDDL HEADER END
20*9781SMoriah.Waterland@Sun.COM */
21*9781SMoriah.Waterland@Sun.COM
22*9781SMoriah.Waterland@Sun.COM /*
23*9781SMoriah.Waterland@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24*9781SMoriah.Waterland@Sun.COM * Use is subject to license terms.
25*9781SMoriah.Waterland@Sun.COM */
26*9781SMoriah.Waterland@Sun.COM
27*9781SMoriah.Waterland@Sun.COM
28*9781SMoriah.Waterland@Sun.COM
29*9781SMoriah.Waterland@Sun.COM /*
30*9781SMoriah.Waterland@Sun.COM * Module: vfpops.c
31*9781SMoriah.Waterland@Sun.COM * Synopsis: Implements virtual file protocol operations
32*9781SMoriah.Waterland@Sun.COM * Description:
33*9781SMoriah.Waterland@Sun.COM *
34*9781SMoriah.Waterland@Sun.COM * This module implements the "Virtual File protocol" operations. These
35*9781SMoriah.Waterland@Sun.COM * operations are intended to provide very fast access to file data,
36*9781SMoriah.Waterland@Sun.COM * allowing a file to be accessed in very efficient ways with extremely
37*9781SMoriah.Waterland@Sun.COM * low-cpu intensive operations. If possible file data is mapped directly
38*9781SMoriah.Waterland@Sun.COM * into memory allowing the data to be accessed directly. If the data
39*9781SMoriah.Waterland@Sun.COM * cannot be mapped directly into memory, memory will be allocated and
40*9781SMoriah.Waterland@Sun.COM * the file data read directly into memory. If that fails currently the
41*9781SMoriah.Waterland@Sun.COM * file data is not accessible. Other methods of making the file could
42*9781SMoriah.Waterland@Sun.COM * be implemented in the future (e.g. stdio if all else fails).
43*9781SMoriah.Waterland@Sun.COM *
44*9781SMoriah.Waterland@Sun.COM * In general any code that uses stdio to access a file can be changed
45*9781SMoriah.Waterland@Sun.COM * to use the various "vfp" operations to access a file, with a resulting
46*9781SMoriah.Waterland@Sun.COM * increase in performance and decrease in cpu time required to access
47*9781SMoriah.Waterland@Sun.COM * the file contents.
48*9781SMoriah.Waterland@Sun.COM *
49*9781SMoriah.Waterland@Sun.COM * Public Methods:
50*9781SMoriah.Waterland@Sun.COM *
51*9781SMoriah.Waterland@Sun.COM * vfpCheckpointFile - Create new VFP that checkpoints existing VFP
52*9781SMoriah.Waterland@Sun.COM * vfpCheckpointOpen - open file, allocate storage, return pointer to VFP_T
53*9781SMoriah.Waterland@Sun.COM * vfpClose - close file associated with vfp
54*9781SMoriah.Waterland@Sun.COM * vfpDecCurrPtr - decrement current character pointer
55*9781SMoriah.Waterland@Sun.COM * vfpGetBytesRemaining - get number of bytes remaining to read
56*9781SMoriah.Waterland@Sun.COM * vfpGetCurrCharPtr - get pointer to current character
57*9781SMoriah.Waterland@Sun.COM * vfpGetCurrPtrDelta - get number of bytes between current and specified char
58*9781SMoriah.Waterland@Sun.COM * vfpGetFirstCharPtr - get pointer to first character
59*9781SMoriah.Waterland@Sun.COM * vfpGetLastCharPtr - get pointer to last character
60*9781SMoriah.Waterland@Sun.COM * vfpGetModifiedLen - get highest modified byte (length) contained in vfp
61*9781SMoriah.Waterland@Sun.COM * vfpGetPath - get the path associated with the vfp
62*9781SMoriah.Waterland@Sun.COM * vfpGetc - get current character and increment to next
63*9781SMoriah.Waterland@Sun.COM * vfpGetcNoInc - get current character - do not increment
64*9781SMoriah.Waterland@Sun.COM * vfpGets - get a string from the vfp into a fixed size buffer
65*9781SMoriah.Waterland@Sun.COM * vfpIncCurrPtr - increment current character pointer
66*9781SMoriah.Waterland@Sun.COM * vfpIncCurrPtrBy - increment current pointer by specified delta
67*9781SMoriah.Waterland@Sun.COM * vfpOpen - open file on vfp
68*9781SMoriah.Waterland@Sun.COM * vfpPutBytes - put fixed number of bytes to current character and increment
69*9781SMoriah.Waterland@Sun.COM * vfpPutFormat - put format one arg to current character and increment
70*9781SMoriah.Waterland@Sun.COM * vfpPutInteger - put integer to current character and increment
71*9781SMoriah.Waterland@Sun.COM * vfpPutLong - put long to current character and increment
72*9781SMoriah.Waterland@Sun.COM * vfpPutc - put current character and increment to next
73*9781SMoriah.Waterland@Sun.COM * vfpPuts - put string to current character and increment
74*9781SMoriah.Waterland@Sun.COM * vfpRewind - rewind file to first byte
75*9781SMoriah.Waterland@Sun.COM * vfpSeekToEnd - seek to end of file
76*9781SMoriah.Waterland@Sun.COM * vfpSetCurrCharPtr - set pointer to current character
77*9781SMoriah.Waterland@Sun.COM * vfpSetFlags - set flags that affect file access
78*9781SMoriah.Waterland@Sun.COM * vfpSetSize - set size of file (for writing)
79*9781SMoriah.Waterland@Sun.COM * vfpTruncate - truncate file
80*9781SMoriah.Waterland@Sun.COM * vfpWriteToFile - write data contained in vfp to specified file
81*9781SMoriah.Waterland@Sun.COM */
82*9781SMoriah.Waterland@Sun.COM
83*9781SMoriah.Waterland@Sun.COM #include <stdio.h>
84*9781SMoriah.Waterland@Sun.COM #include <limits.h>
85*9781SMoriah.Waterland@Sun.COM #include <stdlib.h>
86*9781SMoriah.Waterland@Sun.COM #include <string.h>
87*9781SMoriah.Waterland@Sun.COM #include <strings.h>
88*9781SMoriah.Waterland@Sun.COM #include <unistd.h>
89*9781SMoriah.Waterland@Sun.COM #include <ctype.h>
90*9781SMoriah.Waterland@Sun.COM #include <fcntl.h>
91*9781SMoriah.Waterland@Sun.COM #include <sys/types.h>
92*9781SMoriah.Waterland@Sun.COM #include <sys/stat.h>
93*9781SMoriah.Waterland@Sun.COM #include <sys/mman.h>
94*9781SMoriah.Waterland@Sun.COM #include <errno.h>
95*9781SMoriah.Waterland@Sun.COM #include <libintl.h>
96*9781SMoriah.Waterland@Sun.COM #include "pkglib.h"
97*9781SMoriah.Waterland@Sun.COM #include "pkgstrct.h"
98*9781SMoriah.Waterland@Sun.COM #include "pkglocale.h"
99*9781SMoriah.Waterland@Sun.COM
100*9781SMoriah.Waterland@Sun.COM /*
101*9781SMoriah.Waterland@Sun.COM * These are internal flags that occupy the high order byte of the VFPFLAGS_T
102*9781SMoriah.Waterland@Sun.COM * flags element of the vfp. These flags may only occupy the high order order
103*9781SMoriah.Waterland@Sun.COM * 16 bits of the 32-bit unsigned vfp "flags" object.
104*9781SMoriah.Waterland@Sun.COM */
105*9781SMoriah.Waterland@Sun.COM
106*9781SMoriah.Waterland@Sun.COM #define _VFP_MMAP 0x00010000 /* mmap used */
107*9781SMoriah.Waterland@Sun.COM #define _VFP_MALLOC 0x00020000 /* malloc used */
108*9781SMoriah.Waterland@Sun.COM #define _VFP_WRITE 0x00040000 /* file opened for write */
109*9781SMoriah.Waterland@Sun.COM #define _VFP_READ 0x00080000 /* file opened for reading */
110*9781SMoriah.Waterland@Sun.COM #define _VFP_MODIFIED 0x00100000 /* contents are marked modified */
111*9781SMoriah.Waterland@Sun.COM
112*9781SMoriah.Waterland@Sun.COM /* path name given to "anonymous" (string) vfp */
113*9781SMoriah.Waterland@Sun.COM
114*9781SMoriah.Waterland@Sun.COM #define VFP_ANONYMOUS_PATH "<<string>>"
115*9781SMoriah.Waterland@Sun.COM
116*9781SMoriah.Waterland@Sun.COM /* minimum size file to mmap (64mb) */
117*9781SMoriah.Waterland@Sun.COM
118*9781SMoriah.Waterland@Sun.COM #define MIN_MMAP_SIZE (64*1024)
119*9781SMoriah.Waterland@Sun.COM
120*9781SMoriah.Waterland@Sun.COM /*
121*9781SMoriah.Waterland@Sun.COM * *****************************************************************************
122*9781SMoriah.Waterland@Sun.COM * global external (public) functions
123*9781SMoriah.Waterland@Sun.COM * *****************************************************************************
124*9781SMoriah.Waterland@Sun.COM */
125*9781SMoriah.Waterland@Sun.COM
126*9781SMoriah.Waterland@Sun.COM /*
127*9781SMoriah.Waterland@Sun.COM * Name: vfpOpen
128*9781SMoriah.Waterland@Sun.COM * Description: Open file on vfp, allocate storage, return pointer to VFP_T
129*9781SMoriah.Waterland@Sun.COM * that can be used to access/modify file contents.
130*9781SMoriah.Waterland@Sun.COM * Arguments: VFP_T **r_vfp - pointer to pointer to VFP_T
131*9781SMoriah.Waterland@Sun.COM * char *a_path - path of file to open and associate with this VFP.
132*9781SMoriah.Waterland@Sun.COM * - if the path is (char *)NULL then no file is associated
133*9781SMoriah.Waterland@Sun.COM * with this VFP - this is a way to create a fixed length
134*9781SMoriah.Waterland@Sun.COM * string that can be manipulated with the VFP operators.
135*9781SMoriah.Waterland@Sun.COM * Before the VFP can be used "vfpSetSize" must be called
136*9781SMoriah.Waterland@Sun.COM * to set the size of the string buffer.
137*9781SMoriah.Waterland@Sun.COM * char *a_mode - fopen mode to open the file with
138*9781SMoriah.Waterland@Sun.COM * VFPFLAGS_T a_flags - one or more flags to control the operation:
139*9781SMoriah.Waterland@Sun.COM * - VFP_NONE - no special flags
140*9781SMoriah.Waterland@Sun.COM * - VFP_NEEDNOW - file data needed in memory now
141*9781SMoriah.Waterland@Sun.COM * - VFP_SEQUENTIAL - memory will be sequentially accessed
142*9781SMoriah.Waterland@Sun.COM * - VFP_RANDOM - memory will be randomly accessed
143*9781SMoriah.Waterland@Sun.COM * - VFP_NOMMAP - do not use mmap to access file
144*9781SMoriah.Waterland@Sun.COM * - VFP_NOMALLOC - do not use malloc to buffer file
145*9781SMoriah.Waterland@Sun.COM * Returns: int == 0 - operation was successful
146*9781SMoriah.Waterland@Sun.COM * != 0 - operation failed, errno contains reason
147*9781SMoriah.Waterland@Sun.COM * Side Effects: r_vfp -- filled in with a pointer to a newly allocated vfp
148*9781SMoriah.Waterland@Sun.COM * which can be used with the various vfp functions.
149*9781SMoriah.Waterland@Sun.COM * errno -- contains system error number if return is != 0
150*9781SMoriah.Waterland@Sun.COM */
151*9781SMoriah.Waterland@Sun.COM
152*9781SMoriah.Waterland@Sun.COM int
vfpOpen(VFP_T ** r_vfp,char * a_path,char * a_mode,VFPFLAGS_T a_flags)153*9781SMoriah.Waterland@Sun.COM vfpOpen(VFP_T **r_vfp, char *a_path, char *a_mode, VFPFLAGS_T a_flags)
154*9781SMoriah.Waterland@Sun.COM {
155*9781SMoriah.Waterland@Sun.COM FILE *fp = (FILE *)NULL;
156*9781SMoriah.Waterland@Sun.COM VFP_T *vfp;
157*9781SMoriah.Waterland@Sun.COM int lerrno;
158*9781SMoriah.Waterland@Sun.COM struct stat statbuf;
159*9781SMoriah.Waterland@Sun.COM int pagesize = getpagesize();
160*9781SMoriah.Waterland@Sun.COM
161*9781SMoriah.Waterland@Sun.COM /* reset return VFP/FILE pointers */
162*9781SMoriah.Waterland@Sun.COM
163*9781SMoriah.Waterland@Sun.COM (*r_vfp) = (VFP_T *)NULL;
164*9781SMoriah.Waterland@Sun.COM
165*9781SMoriah.Waterland@Sun.COM /* allocate pre-zeroed vfp object */
166*9781SMoriah.Waterland@Sun.COM
167*9781SMoriah.Waterland@Sun.COM vfp = (VFP_T *)calloc(sizeof (VFP_T), 1);
168*9781SMoriah.Waterland@Sun.COM if (vfp == (VFP_T *)NULL) {
169*9781SMoriah.Waterland@Sun.COM return (-1);
170*9781SMoriah.Waterland@Sun.COM }
171*9781SMoriah.Waterland@Sun.COM
172*9781SMoriah.Waterland@Sun.COM /* create "string" vfp if no path specified */
173*9781SMoriah.Waterland@Sun.COM
174*9781SMoriah.Waterland@Sun.COM if (a_path == (char *)NULL) {
175*9781SMoriah.Waterland@Sun.COM /*
176*9781SMoriah.Waterland@Sun.COM * no path specified - no open file associated with vfp
177*9781SMoriah.Waterland@Sun.COM * The vfp is initialized to all zeros - initialize just those
178*9781SMoriah.Waterland@Sun.COM * values that need to be non-zero.
179*9781SMoriah.Waterland@Sun.COM */
180*9781SMoriah.Waterland@Sun.COM
181*9781SMoriah.Waterland@Sun.COM vfp->_vfpFlags = _VFP_MALLOC;
182*9781SMoriah.Waterland@Sun.COM vfp->_vfpPath = strdup(VFP_ANONYMOUS_PATH);
183*9781SMoriah.Waterland@Sun.COM (*r_vfp) = vfp;
184*9781SMoriah.Waterland@Sun.COM return (0);
185*9781SMoriah.Waterland@Sun.COM }
186*9781SMoriah.Waterland@Sun.COM
187*9781SMoriah.Waterland@Sun.COM /*
188*9781SMoriah.Waterland@Sun.COM * path specified - associate open file with vfp;
189*9781SMoriah.Waterland@Sun.COM * return an error if no path or mode specified
190*9781SMoriah.Waterland@Sun.COM */
191*9781SMoriah.Waterland@Sun.COM
192*9781SMoriah.Waterland@Sun.COM if (a_mode == (char *)NULL) {
193*9781SMoriah.Waterland@Sun.COM errno = EFAULT; /* Bad address */
194*9781SMoriah.Waterland@Sun.COM (void) free(vfp);
195*9781SMoriah.Waterland@Sun.COM return (-1);
196*9781SMoriah.Waterland@Sun.COM }
197*9781SMoriah.Waterland@Sun.COM
198*9781SMoriah.Waterland@Sun.COM /* return an error if an empty path or mode specified */
199*9781SMoriah.Waterland@Sun.COM
200*9781SMoriah.Waterland@Sun.COM if ((*a_path == '\0') || (*a_mode == '\0')) {
201*9781SMoriah.Waterland@Sun.COM errno = EINVAL; /* Invalid argument */
202*9781SMoriah.Waterland@Sun.COM (void) free(vfp);
203*9781SMoriah.Waterland@Sun.COM return (-1);
204*9781SMoriah.Waterland@Sun.COM }
205*9781SMoriah.Waterland@Sun.COM
206*9781SMoriah.Waterland@Sun.COM /* open the file */
207*9781SMoriah.Waterland@Sun.COM
208*9781SMoriah.Waterland@Sun.COM fp = fopen(a_path, a_mode);
209*9781SMoriah.Waterland@Sun.COM if (fp == (FILE *)NULL) {
210*9781SMoriah.Waterland@Sun.COM lerrno = errno;
211*9781SMoriah.Waterland@Sun.COM (void) free(vfp);
212*9781SMoriah.Waterland@Sun.COM errno = lerrno;
213*9781SMoriah.Waterland@Sun.COM return (-1);
214*9781SMoriah.Waterland@Sun.COM }
215*9781SMoriah.Waterland@Sun.COM
216*9781SMoriah.Waterland@Sun.COM /* Get the file size */
217*9781SMoriah.Waterland@Sun.COM
218*9781SMoriah.Waterland@Sun.COM if (fstat(fileno(fp), &statbuf) != 0) {
219*9781SMoriah.Waterland@Sun.COM lerrno = errno;
220*9781SMoriah.Waterland@Sun.COM (void) fclose(fp);
221*9781SMoriah.Waterland@Sun.COM (void) free(vfp);
222*9781SMoriah.Waterland@Sun.COM errno = lerrno;
223*9781SMoriah.Waterland@Sun.COM return (-1);
224*9781SMoriah.Waterland@Sun.COM }
225*9781SMoriah.Waterland@Sun.COM
226*9781SMoriah.Waterland@Sun.COM /*
227*9781SMoriah.Waterland@Sun.COM * Obtain access to existing file contents:
228*9781SMoriah.Waterland@Sun.COM * -> plan a: map contents file into memory
229*9781SMoriah.Waterland@Sun.COM * -> plan b: on failure just read into large buffer
230*9781SMoriah.Waterland@Sun.COM */
231*9781SMoriah.Waterland@Sun.COM
232*9781SMoriah.Waterland@Sun.COM /* attempt to mmap file if mmap is allowed */
233*9781SMoriah.Waterland@Sun.COM
234*9781SMoriah.Waterland@Sun.COM vfp->_vfpStart = MAP_FAILED; /* assume map failed if not allowed */
235*9781SMoriah.Waterland@Sun.COM
236*9781SMoriah.Waterland@Sun.COM /*
237*9781SMoriah.Waterland@Sun.COM * if file is a regular file, and if mmap allowed,
238*9781SMoriah.Waterland@Sun.COM * and (malloc not forbidden or size is > minumum size to mmap)
239*9781SMoriah.Waterland@Sun.COM */
240*9781SMoriah.Waterland@Sun.COM
241*9781SMoriah.Waterland@Sun.COM if ((S_ISREG(statbuf.st_mode)) && (!(a_flags & VFP_NOMMAP)) &&
242*9781SMoriah.Waterland@Sun.COM ((a_flags & VFP_NOMALLOC) || statbuf.st_size > MIN_MMAP_SIZE)) {
243*9781SMoriah.Waterland@Sun.COM char *p;
244*9781SMoriah.Waterland@Sun.COM /* set size to current size of file */
245*9781SMoriah.Waterland@Sun.COM
246*9781SMoriah.Waterland@Sun.COM vfp->_vfpMapSize = statbuf.st_size;
247*9781SMoriah.Waterland@Sun.COM
248*9781SMoriah.Waterland@Sun.COM /*
249*9781SMoriah.Waterland@Sun.COM * compute proper size for mapping for the file contents;
250*9781SMoriah.Waterland@Sun.COM * add in one extra page so falling off end when file size is
251*9781SMoriah.Waterland@Sun.COM * exactly modulo page size does not cause a page fault to
252*9781SMoriah.Waterland@Sun.COM * guarantee that the end of the file contents will always
253*9781SMoriah.Waterland@Sun.COM * contain a '\0' null character.
254*9781SMoriah.Waterland@Sun.COM */
255*9781SMoriah.Waterland@Sun.COM
256*9781SMoriah.Waterland@Sun.COM vfp->_vfpSize = (statbuf.st_size + pagesize +
257*9781SMoriah.Waterland@Sun.COM (pagesize-(statbuf.st_size % pagesize)));
258*9781SMoriah.Waterland@Sun.COM
259*9781SMoriah.Waterland@Sun.COM /*
260*9781SMoriah.Waterland@Sun.COM * mmap allowed: mmap file into memory
261*9781SMoriah.Waterland@Sun.COM * first allocate space on top of which the mapping can be done;
262*9781SMoriah.Waterland@Sun.COM * this way we can guarantee that if the mapping happens to be
263*9781SMoriah.Waterland@Sun.COM * an exact multiple of a page size, that there will be at least
264*9781SMoriah.Waterland@Sun.COM * one byte past the end of the mapping that can be accessed and
265*9781SMoriah.Waterland@Sun.COM * that is guaranteed to be zero.
266*9781SMoriah.Waterland@Sun.COM */
267*9781SMoriah.Waterland@Sun.COM
268*9781SMoriah.Waterland@Sun.COM /* allocate backing space */
269*9781SMoriah.Waterland@Sun.COM
270*9781SMoriah.Waterland@Sun.COM p = (char *)memalign(pagesize, vfp->_vfpSize);
271*9781SMoriah.Waterland@Sun.COM if (p == (char *)NULL) {
272*9781SMoriah.Waterland@Sun.COM vfp->_vfpStart = MAP_FAILED;
273*9781SMoriah.Waterland@Sun.COM } else {
274*9781SMoriah.Waterland@Sun.COM /* guarantee first byte after end of data is zero */
275*9781SMoriah.Waterland@Sun.COM
276*9781SMoriah.Waterland@Sun.COM p[vfp->_vfpMapSize] = '\0';
277*9781SMoriah.Waterland@Sun.COM
278*9781SMoriah.Waterland@Sun.COM /* map file on top of the backing space */
279*9781SMoriah.Waterland@Sun.COM
280*9781SMoriah.Waterland@Sun.COM vfp->_vfpStart = mmap(p, vfp->_vfpMapSize, PROT_READ,
281*9781SMoriah.Waterland@Sun.COM MAP_PRIVATE|MAP_FIXED, fileno(fp), (off_t)0);
282*9781SMoriah.Waterland@Sun.COM
283*9781SMoriah.Waterland@Sun.COM /* if mmap succeeded set mmap used flag in vfp */
284*9781SMoriah.Waterland@Sun.COM
285*9781SMoriah.Waterland@Sun.COM if (vfp->_vfpStart != MAP_FAILED) {
286*9781SMoriah.Waterland@Sun.COM vfp->_vfpFlags |= _VFP_MMAP;
287*9781SMoriah.Waterland@Sun.COM }
288*9781SMoriah.Waterland@Sun.COM }
289*9781SMoriah.Waterland@Sun.COM }
290*9781SMoriah.Waterland@Sun.COM
291*9781SMoriah.Waterland@Sun.COM /* if map failed (or not allowed) attempt malloc (if allowed) */
292*9781SMoriah.Waterland@Sun.COM
293*9781SMoriah.Waterland@Sun.COM if ((vfp->_vfpStart == MAP_FAILED) && (!(a_flags & VFP_NOMALLOC))) {
294*9781SMoriah.Waterland@Sun.COM /* mmap failed - plan b: read directly into memory */
295*9781SMoriah.Waterland@Sun.COM ssize_t rlen;
296*9781SMoriah.Waterland@Sun.COM
297*9781SMoriah.Waterland@Sun.COM /*
298*9781SMoriah.Waterland@Sun.COM * compute proper size for allocating storage for file contents;
299*9781SMoriah.Waterland@Sun.COM * add in one extra page so falling off end when file size is
300*9781SMoriah.Waterland@Sun.COM * exactly modulo page size does not cause a page fault to
301*9781SMoriah.Waterland@Sun.COM * guarantee that the end of the file contents will always
302*9781SMoriah.Waterland@Sun.COM * contain a '\0' null character.
303*9781SMoriah.Waterland@Sun.COM */
304*9781SMoriah.Waterland@Sun.COM
305*9781SMoriah.Waterland@Sun.COM vfp->_vfpSize = statbuf.st_size+pagesize;
306*9781SMoriah.Waterland@Sun.COM
307*9781SMoriah.Waterland@Sun.COM /* allocate buffer to hold file data */
308*9781SMoriah.Waterland@Sun.COM
309*9781SMoriah.Waterland@Sun.COM vfp->_vfpStart = memalign((size_t)pagesize, vfp->_vfpSize);
310*9781SMoriah.Waterland@Sun.COM if (vfp->_vfpStart == (char *)NULL) {
311*9781SMoriah.Waterland@Sun.COM lerrno = errno;
312*9781SMoriah.Waterland@Sun.COM (void) fclose(fp);
313*9781SMoriah.Waterland@Sun.COM (void) free(vfp);
314*9781SMoriah.Waterland@Sun.COM errno = lerrno;
315*9781SMoriah.Waterland@Sun.COM return (-1);
316*9781SMoriah.Waterland@Sun.COM }
317*9781SMoriah.Waterland@Sun.COM
318*9781SMoriah.Waterland@Sun.COM /* read the file into the buffer */
319*9781SMoriah.Waterland@Sun.COM
320*9781SMoriah.Waterland@Sun.COM if (statbuf.st_size != 0) {
321*9781SMoriah.Waterland@Sun.COM rlen = read(fileno(fp), vfp->_vfpStart,
322*9781SMoriah.Waterland@Sun.COM statbuf.st_size);
323*9781SMoriah.Waterland@Sun.COM if (rlen != statbuf.st_size) {
324*9781SMoriah.Waterland@Sun.COM lerrno = errno;
325*9781SMoriah.Waterland@Sun.COM if (lerrno == 0) {
326*9781SMoriah.Waterland@Sun.COM lerrno = EIO;
327*9781SMoriah.Waterland@Sun.COM }
328*9781SMoriah.Waterland@Sun.COM (void) free(vfp->_vfpStart);
329*9781SMoriah.Waterland@Sun.COM (void) fclose(fp);
330*9781SMoriah.Waterland@Sun.COM (void) free(vfp);
331*9781SMoriah.Waterland@Sun.COM errno = lerrno;
332*9781SMoriah.Waterland@Sun.COM return (-1);
333*9781SMoriah.Waterland@Sun.COM }
334*9781SMoriah.Waterland@Sun.COM
335*9781SMoriah.Waterland@Sun.COM /* assure last byte+1 is null character */
336*9781SMoriah.Waterland@Sun.COM
337*9781SMoriah.Waterland@Sun.COM ((char *)vfp->_vfpStart)[statbuf.st_size] = '\0';
338*9781SMoriah.Waterland@Sun.COM }
339*9781SMoriah.Waterland@Sun.COM
340*9781SMoriah.Waterland@Sun.COM /* set malloc used flag in vfp */
341*9781SMoriah.Waterland@Sun.COM
342*9781SMoriah.Waterland@Sun.COM vfp->_vfpFlags |= _VFP_MALLOC;
343*9781SMoriah.Waterland@Sun.COM }
344*9781SMoriah.Waterland@Sun.COM
345*9781SMoriah.Waterland@Sun.COM /* if no starting address all read methods failed */
346*9781SMoriah.Waterland@Sun.COM
347*9781SMoriah.Waterland@Sun.COM if (vfp->_vfpStart == MAP_FAILED) {
348*9781SMoriah.Waterland@Sun.COM /* no mmap() - no read() - cannot allocate memory */
349*9781SMoriah.Waterland@Sun.COM (void) fclose(fp);
350*9781SMoriah.Waterland@Sun.COM (void) free(vfp);
351*9781SMoriah.Waterland@Sun.COM errno = ENOMEM;
352*9781SMoriah.Waterland@Sun.COM return (-1);
353*9781SMoriah.Waterland@Sun.COM }
354*9781SMoriah.Waterland@Sun.COM
355*9781SMoriah.Waterland@Sun.COM /*
356*9781SMoriah.Waterland@Sun.COM * initialize vfp contents
357*9781SMoriah.Waterland@Sun.COM */
358*9781SMoriah.Waterland@Sun.COM
359*9781SMoriah.Waterland@Sun.COM /* _vfpCurr -> next byte to read */
360*9781SMoriah.Waterland@Sun.COM vfp->_vfpCurr = (char *)vfp->_vfpStart;
361*9781SMoriah.Waterland@Sun.COM
362*9781SMoriah.Waterland@Sun.COM /* _vfpEnd -> last data byte */
363*9781SMoriah.Waterland@Sun.COM vfp->_vfpEnd = (((char *)vfp->_vfpStart) + statbuf.st_size)-1;
364*9781SMoriah.Waterland@Sun.COM
365*9781SMoriah.Waterland@Sun.COM /* _vfpHighWater -> last byte written */
366*9781SMoriah.Waterland@Sun.COM vfp->_vfpHighWater = (char *)vfp->_vfpEnd;
367*9781SMoriah.Waterland@Sun.COM
368*9781SMoriah.Waterland@Sun.COM /* _vfpFile -> associated FILE* object */
369*9781SMoriah.Waterland@Sun.COM vfp->_vfpFile = fp;
370*9781SMoriah.Waterland@Sun.COM
371*9781SMoriah.Waterland@Sun.COM /* set flags as appropriate */
372*9781SMoriah.Waterland@Sun.COM
373*9781SMoriah.Waterland@Sun.COM (void) vfpSetFlags(vfp, a_flags);
374*9781SMoriah.Waterland@Sun.COM
375*9781SMoriah.Waterland@Sun.COM /* retain path name */
376*9781SMoriah.Waterland@Sun.COM
377*9781SMoriah.Waterland@Sun.COM vfp->_vfpPath = strdup(a_path ? a_path : "");
378*9781SMoriah.Waterland@Sun.COM
379*9781SMoriah.Waterland@Sun.COM /* set read/write flags */
380*9781SMoriah.Waterland@Sun.COM
381*9781SMoriah.Waterland@Sun.COM if (*a_mode == 'w') {
382*9781SMoriah.Waterland@Sun.COM vfp->_vfpFlags |= _VFP_WRITE;
383*9781SMoriah.Waterland@Sun.COM }
384*9781SMoriah.Waterland@Sun.COM
385*9781SMoriah.Waterland@Sun.COM if (*a_mode == 'r') {
386*9781SMoriah.Waterland@Sun.COM vfp->_vfpFlags |= _VFP_READ;
387*9781SMoriah.Waterland@Sun.COM }
388*9781SMoriah.Waterland@Sun.COM
389*9781SMoriah.Waterland@Sun.COM /* set return vfp pointer */
390*9781SMoriah.Waterland@Sun.COM
391*9781SMoriah.Waterland@Sun.COM (*r_vfp) = vfp;
392*9781SMoriah.Waterland@Sun.COM
393*9781SMoriah.Waterland@Sun.COM /* All OK */
394*9781SMoriah.Waterland@Sun.COM
395*9781SMoriah.Waterland@Sun.COM return (0);
396*9781SMoriah.Waterland@Sun.COM }
397*9781SMoriah.Waterland@Sun.COM
398*9781SMoriah.Waterland@Sun.COM /*
399*9781SMoriah.Waterland@Sun.COM * Name: vfpClose
400*9781SMoriah.Waterland@Sun.COM * Description: Close an open vfp, causing any modified data to be written out
401*9781SMoriah.Waterland@Sun.COM * to the file associated with the vfp.
402*9781SMoriah.Waterland@Sun.COM * Arguments: VFP_T **r_vfp - pointer to pointer to VFP_T returned by vfpOpen
403*9781SMoriah.Waterland@Sun.COM * Returns: int == 0 - operation was successful
404*9781SMoriah.Waterland@Sun.COM * != 0 - operation failed, errno contains reason
405*9781SMoriah.Waterland@Sun.COM * Side Effects: r_vfp is set to (VFP_T)NULL
406*9781SMoriah.Waterland@Sun.COM */
407*9781SMoriah.Waterland@Sun.COM
408*9781SMoriah.Waterland@Sun.COM int
vfpClose(VFP_T ** r_vfp)409*9781SMoriah.Waterland@Sun.COM vfpClose(VFP_T **r_vfp)
410*9781SMoriah.Waterland@Sun.COM {
411*9781SMoriah.Waterland@Sun.COM int ret;
412*9781SMoriah.Waterland@Sun.COM int lerrno;
413*9781SMoriah.Waterland@Sun.COM VFP_T *vfp;
414*9781SMoriah.Waterland@Sun.COM
415*9781SMoriah.Waterland@Sun.COM /* return error if NULL VFP_T** provided */
416*9781SMoriah.Waterland@Sun.COM
417*9781SMoriah.Waterland@Sun.COM if (r_vfp == (VFP_T **)NULL) {
418*9781SMoriah.Waterland@Sun.COM errno = EFAULT;
419*9781SMoriah.Waterland@Sun.COM return (-1);
420*9781SMoriah.Waterland@Sun.COM }
421*9781SMoriah.Waterland@Sun.COM
422*9781SMoriah.Waterland@Sun.COM /* localize access to VFP_T */
423*9781SMoriah.Waterland@Sun.COM
424*9781SMoriah.Waterland@Sun.COM vfp = *r_vfp;
425*9781SMoriah.Waterland@Sun.COM
426*9781SMoriah.Waterland@Sun.COM /* return successful if NULL VFP_T* provided */
427*9781SMoriah.Waterland@Sun.COM
428*9781SMoriah.Waterland@Sun.COM if (vfp == (VFP_T *)NULL) {
429*9781SMoriah.Waterland@Sun.COM return (0);
430*9781SMoriah.Waterland@Sun.COM }
431*9781SMoriah.Waterland@Sun.COM
432*9781SMoriah.Waterland@Sun.COM /* reset return VFP_T* handle */
433*9781SMoriah.Waterland@Sun.COM
434*9781SMoriah.Waterland@Sun.COM *r_vfp = (VFP_T *)NULL;
435*9781SMoriah.Waterland@Sun.COM
436*9781SMoriah.Waterland@Sun.COM /*
437*9781SMoriah.Waterland@Sun.COM * if closing a file that is open for writing, commit all data if the
438*9781SMoriah.Waterland@Sun.COM * backing memory is volatile and if there is a file open to write
439*9781SMoriah.Waterland@Sun.COM * the data to.
440*9781SMoriah.Waterland@Sun.COM */
441*9781SMoriah.Waterland@Sun.COM
442*9781SMoriah.Waterland@Sun.COM if (vfp->_vfpFlags & _VFP_WRITE) {
443*9781SMoriah.Waterland@Sun.COM if ((vfp->_vfpFlags & _VFP_MALLOC) &&
444*9781SMoriah.Waterland@Sun.COM (vfp->_vfpFile != (FILE *)NULL)) {
445*9781SMoriah.Waterland@Sun.COM size_t len;
446*9781SMoriah.Waterland@Sun.COM
447*9781SMoriah.Waterland@Sun.COM /* determine number of bytes to write */
448*9781SMoriah.Waterland@Sun.COM len = vfpGetModifiedLen(vfp);
449*9781SMoriah.Waterland@Sun.COM
450*9781SMoriah.Waterland@Sun.COM /* if modified bytes present commit data to the file */
451*9781SMoriah.Waterland@Sun.COM if (len > 0) {
452*9781SMoriah.Waterland@Sun.COM (void) vfpSafePwrite(fileno(vfp->_vfpFile),
453*9781SMoriah.Waterland@Sun.COM vfp->_vfpStart, len, (off_t)0);
454*9781SMoriah.Waterland@Sun.COM }
455*9781SMoriah.Waterland@Sun.COM }
456*9781SMoriah.Waterland@Sun.COM }
457*9781SMoriah.Waterland@Sun.COM
458*9781SMoriah.Waterland@Sun.COM /* deallocate any allocated storage/mappings/etc */
459*9781SMoriah.Waterland@Sun.COM
460*9781SMoriah.Waterland@Sun.COM if (vfp->_vfpFlags & _VFP_MALLOC) {
461*9781SMoriah.Waterland@Sun.COM (void) free(vfp->_vfpStart);
462*9781SMoriah.Waterland@Sun.COM } else if (vfp->_vfpFlags & _VFP_MMAP) {
463*9781SMoriah.Waterland@Sun.COM /* unmap the file mapping */
464*9781SMoriah.Waterland@Sun.COM
465*9781SMoriah.Waterland@Sun.COM (void) munmap(vfp->_vfpStart, vfp->_vfpMapSize);
466*9781SMoriah.Waterland@Sun.COM
467*9781SMoriah.Waterland@Sun.COM /* free the backing allocation */
468*9781SMoriah.Waterland@Sun.COM
469*9781SMoriah.Waterland@Sun.COM (void) free(vfp->_vfpStart);
470*9781SMoriah.Waterland@Sun.COM }
471*9781SMoriah.Waterland@Sun.COM
472*9781SMoriah.Waterland@Sun.COM /* free up path */
473*9781SMoriah.Waterland@Sun.COM
474*9781SMoriah.Waterland@Sun.COM (void) free(vfp->_vfpPath);
475*9781SMoriah.Waterland@Sun.COM
476*9781SMoriah.Waterland@Sun.COM /* close the file */
477*9781SMoriah.Waterland@Sun.COM
478*9781SMoriah.Waterland@Sun.COM ret = 0;
479*9781SMoriah.Waterland@Sun.COM if (vfp->_vfpFile != (FILE *)NULL) {
480*9781SMoriah.Waterland@Sun.COM ret = fclose(vfp->_vfpFile);
481*9781SMoriah.Waterland@Sun.COM lerrno = errno;
482*9781SMoriah.Waterland@Sun.COM }
483*9781SMoriah.Waterland@Sun.COM
484*9781SMoriah.Waterland@Sun.COM /* deallocate the vfp itself */
485*9781SMoriah.Waterland@Sun.COM
486*9781SMoriah.Waterland@Sun.COM (void) free(vfp);
487*9781SMoriah.Waterland@Sun.COM
488*9781SMoriah.Waterland@Sun.COM /* if the fclose() failed, return error and errno */
489*9781SMoriah.Waterland@Sun.COM
490*9781SMoriah.Waterland@Sun.COM if (ret != 0) {
491*9781SMoriah.Waterland@Sun.COM errno = lerrno;
492*9781SMoriah.Waterland@Sun.COM return (-1);
493*9781SMoriah.Waterland@Sun.COM }
494*9781SMoriah.Waterland@Sun.COM
495*9781SMoriah.Waterland@Sun.COM return (0);
496*9781SMoriah.Waterland@Sun.COM }
497*9781SMoriah.Waterland@Sun.COM
498*9781SMoriah.Waterland@Sun.COM /*
499*9781SMoriah.Waterland@Sun.COM * Name: vfpSetFlags
500*9781SMoriah.Waterland@Sun.COM * Description: Modify operation of VFP according to flags specified
501*9781SMoriah.Waterland@Sun.COM * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to set flags
502*9781SMoriah.Waterland@Sun.COM * VFPFLAGS_T a_flags - one or more flags to control the operation:
503*9781SMoriah.Waterland@Sun.COM * - VFP_NEEDNOW - file data needed in memory now
504*9781SMoriah.Waterland@Sun.COM * - VFP_SEQUENTIAL - file data sequentially accessed
505*9781SMoriah.Waterland@Sun.COM * - VFP_RANDOM - file data randomly accessed
506*9781SMoriah.Waterland@Sun.COM * Any other flags specified are silently ignored.
507*9781SMoriah.Waterland@Sun.COM * Returns: int == 0 - operation was successful
508*9781SMoriah.Waterland@Sun.COM * != 0 - operation failed, errno contains reason
509*9781SMoriah.Waterland@Sun.COM */
510*9781SMoriah.Waterland@Sun.COM
511*9781SMoriah.Waterland@Sun.COM int
vfpSetFlags(VFP_T * a_vfp,VFPFLAGS_T a_flags)512*9781SMoriah.Waterland@Sun.COM vfpSetFlags(VFP_T *a_vfp, VFPFLAGS_T a_flags)
513*9781SMoriah.Waterland@Sun.COM {
514*9781SMoriah.Waterland@Sun.COM /* return if no vfp specified */
515*9781SMoriah.Waterland@Sun.COM
516*9781SMoriah.Waterland@Sun.COM if (a_vfp == (VFP_T *)NULL) {
517*9781SMoriah.Waterland@Sun.COM return (0);
518*9781SMoriah.Waterland@Sun.COM }
519*9781SMoriah.Waterland@Sun.COM
520*9781SMoriah.Waterland@Sun.COM /* if file data mapped into memory, apply vm flags */
521*9781SMoriah.Waterland@Sun.COM
522*9781SMoriah.Waterland@Sun.COM if ((a_vfp->_vfpSize != 0) && (a_vfp->_vfpFlags & _VFP_MMAP)) {
523*9781SMoriah.Waterland@Sun.COM /* mmap succeeded: properly advise vm system */
524*9781SMoriah.Waterland@Sun.COM
525*9781SMoriah.Waterland@Sun.COM if (a_flags & VFP_NEEDNOW) {
526*9781SMoriah.Waterland@Sun.COM /* advise vm system data is needed now */
527*9781SMoriah.Waterland@Sun.COM (void) madvise(a_vfp->_vfpStart, a_vfp->_vfpMapSize,
528*9781SMoriah.Waterland@Sun.COM MADV_WILLNEED);
529*9781SMoriah.Waterland@Sun.COM }
530*9781SMoriah.Waterland@Sun.COM if (a_flags & VFP_SEQUENTIAL) {
531*9781SMoriah.Waterland@Sun.COM /* advise vm system data access is sequential */
532*9781SMoriah.Waterland@Sun.COM (void) madvise(a_vfp->_vfpStart, a_vfp->_vfpSize,
533*9781SMoriah.Waterland@Sun.COM MADV_SEQUENTIAL);
534*9781SMoriah.Waterland@Sun.COM }
535*9781SMoriah.Waterland@Sun.COM if (a_flags & VFP_RANDOM) {
536*9781SMoriah.Waterland@Sun.COM /* advise vm system data access is random */
537*9781SMoriah.Waterland@Sun.COM (void) madvise(a_vfp->_vfpStart, a_vfp->_vfpSize,
538*9781SMoriah.Waterland@Sun.COM MADV_RANDOM);
539*9781SMoriah.Waterland@Sun.COM }
540*9781SMoriah.Waterland@Sun.COM }
541*9781SMoriah.Waterland@Sun.COM
542*9781SMoriah.Waterland@Sun.COM return (0);
543*9781SMoriah.Waterland@Sun.COM }
544*9781SMoriah.Waterland@Sun.COM
545*9781SMoriah.Waterland@Sun.COM /*
546*9781SMoriah.Waterland@Sun.COM * Name: vfpRewind
547*9781SMoriah.Waterland@Sun.COM * Description: Reset default pointer for next read/write to start of file data
548*9781SMoriah.Waterland@Sun.COM * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to rewind
549*9781SMoriah.Waterland@Sun.COM * Returns: void
550*9781SMoriah.Waterland@Sun.COM * Operation is always successful
551*9781SMoriah.Waterland@Sun.COM */
552*9781SMoriah.Waterland@Sun.COM
553*9781SMoriah.Waterland@Sun.COM void
vfpRewind(VFP_T * a_vfp)554*9781SMoriah.Waterland@Sun.COM vfpRewind(VFP_T *a_vfp)
555*9781SMoriah.Waterland@Sun.COM {
556*9781SMoriah.Waterland@Sun.COM /* return if no vfp specified */
557*9781SMoriah.Waterland@Sun.COM
558*9781SMoriah.Waterland@Sun.COM if (a_vfp == (VFP_T *)NULL) {
559*9781SMoriah.Waterland@Sun.COM return;
560*9781SMoriah.Waterland@Sun.COM }
561*9781SMoriah.Waterland@Sun.COM
562*9781SMoriah.Waterland@Sun.COM /* set high water mark of last modified data */
563*9781SMoriah.Waterland@Sun.COM
564*9781SMoriah.Waterland@Sun.COM if (a_vfp->_vfpCurr > a_vfp->_vfpHighWater) {
565*9781SMoriah.Waterland@Sun.COM a_vfp->_vfpHighWater = a_vfp->_vfpCurr;
566*9781SMoriah.Waterland@Sun.COM }
567*9781SMoriah.Waterland@Sun.COM
568*9781SMoriah.Waterland@Sun.COM /* reset next character pointer to start of file data */
569*9781SMoriah.Waterland@Sun.COM
570*9781SMoriah.Waterland@Sun.COM a_vfp->_vfpCurr = a_vfp->_vfpStart;
571*9781SMoriah.Waterland@Sun.COM }
572*9781SMoriah.Waterland@Sun.COM
573*9781SMoriah.Waterland@Sun.COM /*
574*9781SMoriah.Waterland@Sun.COM * Name: vfpSetSize
575*9781SMoriah.Waterland@Sun.COM * Description: Set size of in-memory image associated with VFP
576*9781SMoriah.Waterland@Sun.COM * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to set
577*9781SMoriah.Waterland@Sun.COM * size_t a_size - number of bytes to associatge with VFP
578*9781SMoriah.Waterland@Sun.COM * Returns: int == 0 - operation was successful
579*9781SMoriah.Waterland@Sun.COM * != 0 - operation failed, errno contains reason
580*9781SMoriah.Waterland@Sun.COM * Side Effects:
581*9781SMoriah.Waterland@Sun.COM * Currently only a file that is in malloc()ed memory can
582*9781SMoriah.Waterland@Sun.COM * have its in-memory size changed.
583*9781SMoriah.Waterland@Sun.COM * An error is returned If the file is mapped into memory.
584*9781SMoriah.Waterland@Sun.COM * A file cannot be decreased in size - if the specified
585*9781SMoriah.Waterland@Sun.COM * size is less than the current size, the operation is
586*9781SMoriah.Waterland@Sun.COM * successful but no change in file size occurs.
587*9781SMoriah.Waterland@Sun.COM * If no file is associated with the VFP (no "name" was
588*9781SMoriah.Waterland@Sun.COM * given to vfpOpen) the first call to vfpSetSize allocates
589*9781SMoriah.Waterland@Sun.COM * the initial size of the file data - effectively calling
590*9781SMoriah.Waterland@Sun.COM * "malloc" to allocate the initial memory for the file data.
591*9781SMoriah.Waterland@Sun.COM * Once an initial allocation has been made, subsequent calls
592*9781SMoriah.Waterland@Sun.COM * to vfpSetSize are effectively a "realloc" of the existing
593*9781SMoriah.Waterland@Sun.COM * file data.
594*9781SMoriah.Waterland@Sun.COM * All existing file data is preserved.
595*9781SMoriah.Waterland@Sun.COM */
596*9781SMoriah.Waterland@Sun.COM
597*9781SMoriah.Waterland@Sun.COM int
vfpSetSize(VFP_T * a_vfp,size_t a_size)598*9781SMoriah.Waterland@Sun.COM vfpSetSize(VFP_T *a_vfp, size_t a_size)
599*9781SMoriah.Waterland@Sun.COM {
600*9781SMoriah.Waterland@Sun.COM char *np;
601*9781SMoriah.Waterland@Sun.COM size_t curSize;
602*9781SMoriah.Waterland@Sun.COM
603*9781SMoriah.Waterland@Sun.COM /* return if no vfp specified */
604*9781SMoriah.Waterland@Sun.COM
605*9781SMoriah.Waterland@Sun.COM if (a_vfp == (VFP_T *)NULL) {
606*9781SMoriah.Waterland@Sun.COM return (0);
607*9781SMoriah.Waterland@Sun.COM }
608*9781SMoriah.Waterland@Sun.COM
609*9781SMoriah.Waterland@Sun.COM /* if malloc not used don't know how to set size right now */
610*9781SMoriah.Waterland@Sun.COM
611*9781SMoriah.Waterland@Sun.COM if (!(a_vfp->_vfpFlags & _VFP_MALLOC)) {
612*9781SMoriah.Waterland@Sun.COM return (-1);
613*9781SMoriah.Waterland@Sun.COM }
614*9781SMoriah.Waterland@Sun.COM
615*9781SMoriah.Waterland@Sun.COM /* adjust size to reflect extra page of data maintained */
616*9781SMoriah.Waterland@Sun.COM
617*9781SMoriah.Waterland@Sun.COM a_size += getpagesize();
618*9781SMoriah.Waterland@Sun.COM
619*9781SMoriah.Waterland@Sun.COM /* if size is not larger than current nothing to do */
620*9781SMoriah.Waterland@Sun.COM
621*9781SMoriah.Waterland@Sun.COM if (a_size <= a_vfp->_vfpSize) {
622*9781SMoriah.Waterland@Sun.COM return (0);
623*9781SMoriah.Waterland@Sun.COM }
624*9781SMoriah.Waterland@Sun.COM
625*9781SMoriah.Waterland@Sun.COM /* remember new size */
626*9781SMoriah.Waterland@Sun.COM
627*9781SMoriah.Waterland@Sun.COM curSize = a_vfp->_vfpSize;
628*9781SMoriah.Waterland@Sun.COM a_vfp->_vfpSize = a_size;
629*9781SMoriah.Waterland@Sun.COM
630*9781SMoriah.Waterland@Sun.COM /* allocate/reallocate memory as appropriate */
631*9781SMoriah.Waterland@Sun.COM
632*9781SMoriah.Waterland@Sun.COM if (a_vfp->_vfpStart != (char *)NULL) {
633*9781SMoriah.Waterland@Sun.COM np = (char *)realloc(a_vfp->_vfpStart, a_vfp->_vfpSize+1);
634*9781SMoriah.Waterland@Sun.COM if (np == (char *)NULL) {
635*9781SMoriah.Waterland@Sun.COM return (-1);
636*9781SMoriah.Waterland@Sun.COM }
637*9781SMoriah.Waterland@Sun.COM np[curSize-1] = '\0';
638*9781SMoriah.Waterland@Sun.COM } else {
639*9781SMoriah.Waterland@Sun.COM np = (char *)malloc(a_vfp->_vfpSize+1);
640*9781SMoriah.Waterland@Sun.COM if (np == (char *)NULL) {
641*9781SMoriah.Waterland@Sun.COM return (-1);
642*9781SMoriah.Waterland@Sun.COM }
643*9781SMoriah.Waterland@Sun.COM np[0] = '\0';
644*9781SMoriah.Waterland@Sun.COM }
645*9781SMoriah.Waterland@Sun.COM
646*9781SMoriah.Waterland@Sun.COM /* make sure last allocated byte is a null */
647*9781SMoriah.Waterland@Sun.COM
648*9781SMoriah.Waterland@Sun.COM np[a_vfp->_vfpSize] = '\0';
649*9781SMoriah.Waterland@Sun.COM
650*9781SMoriah.Waterland@Sun.COM /*
651*9781SMoriah.Waterland@Sun.COM * adjust all pointers to account for buffer address change
652*9781SMoriah.Waterland@Sun.COM */
653*9781SMoriah.Waterland@Sun.COM
654*9781SMoriah.Waterland@Sun.COM /* _vfpCurr -> next byte to read */
655*9781SMoriah.Waterland@Sun.COM a_vfp->_vfpCurr = (char *)(((ptrdiff_t)a_vfp->_vfpCurr -
656*9781SMoriah.Waterland@Sun.COM (ptrdiff_t)a_vfp->_vfpStart) + np);
657*9781SMoriah.Waterland@Sun.COM
658*9781SMoriah.Waterland@Sun.COM /* _vfpHighWater -> last byte written */
659*9781SMoriah.Waterland@Sun.COM a_vfp->_vfpHighWater = (char *)(((ptrdiff_t)a_vfp->_vfpHighWater -
660*9781SMoriah.Waterland@Sun.COM (ptrdiff_t)a_vfp->_vfpStart) + np);
661*9781SMoriah.Waterland@Sun.COM
662*9781SMoriah.Waterland@Sun.COM /* _vfpEnd -> last data byte */
663*9781SMoriah.Waterland@Sun.COM a_vfp->_vfpEnd = (np + a_vfp->_vfpSize)-1;
664*9781SMoriah.Waterland@Sun.COM
665*9781SMoriah.Waterland@Sun.COM /* _vfpStart -> first data byte */
666*9781SMoriah.Waterland@Sun.COM a_vfp->_vfpStart = np;
667*9781SMoriah.Waterland@Sun.COM
668*9781SMoriah.Waterland@Sun.COM return (0);
669*9781SMoriah.Waterland@Sun.COM }
670*9781SMoriah.Waterland@Sun.COM
671*9781SMoriah.Waterland@Sun.COM /*
672*9781SMoriah.Waterland@Sun.COM * Name: vfpTruncate
673*9781SMoriah.Waterland@Sun.COM * Description: Truncate data associated with VFP
674*9781SMoriah.Waterland@Sun.COM * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to truncate
675*9781SMoriah.Waterland@Sun.COM * Returns: void
676*9781SMoriah.Waterland@Sun.COM * Operation is always successful.
677*9781SMoriah.Waterland@Sun.COM * Side Effects:
678*9781SMoriah.Waterland@Sun.COM * In memory data associated with file is believed to be empty.
679*9781SMoriah.Waterland@Sun.COM * Actual memory associated with file is not affected.
680*9781SMoriah.Waterland@Sun.COM * If a file is associated with the VFP, it is truncated.
681*9781SMoriah.Waterland@Sun.COM */
682*9781SMoriah.Waterland@Sun.COM
683*9781SMoriah.Waterland@Sun.COM void
vfpTruncate(VFP_T * a_vfp)684*9781SMoriah.Waterland@Sun.COM vfpTruncate(VFP_T *a_vfp)
685*9781SMoriah.Waterland@Sun.COM {
686*9781SMoriah.Waterland@Sun.COM /* return if no vfp specified */
687*9781SMoriah.Waterland@Sun.COM
688*9781SMoriah.Waterland@Sun.COM if (a_vfp == (VFP_T *)NULL) {
689*9781SMoriah.Waterland@Sun.COM return;
690*9781SMoriah.Waterland@Sun.COM }
691*9781SMoriah.Waterland@Sun.COM
692*9781SMoriah.Waterland@Sun.COM /*
693*9781SMoriah.Waterland@Sun.COM * reset all pointers so that no data is associated with file
694*9781SMoriah.Waterland@Sun.COM */
695*9781SMoriah.Waterland@Sun.COM
696*9781SMoriah.Waterland@Sun.COM /* current byte is start of data area */
697*9781SMoriah.Waterland@Sun.COM
698*9781SMoriah.Waterland@Sun.COM a_vfp->_vfpCurr = a_vfp->_vfpStart;
699*9781SMoriah.Waterland@Sun.COM
700*9781SMoriah.Waterland@Sun.COM /* last byte written is start of data area */
701*9781SMoriah.Waterland@Sun.COM
702*9781SMoriah.Waterland@Sun.COM a_vfp->_vfpHighWater = a_vfp->_vfpStart;
703*9781SMoriah.Waterland@Sun.COM
704*9781SMoriah.Waterland@Sun.COM /* current character is NULL */
705*9781SMoriah.Waterland@Sun.COM
706*9781SMoriah.Waterland@Sun.COM *a_vfp->_vfpCurr = '\0';
707*9781SMoriah.Waterland@Sun.COM
708*9781SMoriah.Waterland@Sun.COM /* if file associated with VFP, truncate actual file */
709*9781SMoriah.Waterland@Sun.COM
710*9781SMoriah.Waterland@Sun.COM if (a_vfp->_vfpFile != (FILE *)NULL) {
711*9781SMoriah.Waterland@Sun.COM (void) ftruncate(fileno(a_vfp->_vfpFile), 0);
712*9781SMoriah.Waterland@Sun.COM }
713*9781SMoriah.Waterland@Sun.COM }
714*9781SMoriah.Waterland@Sun.COM
715*9781SMoriah.Waterland@Sun.COM /*
716*9781SMoriah.Waterland@Sun.COM * Name: vfpWriteToFile
717*9781SMoriah.Waterland@Sun.COM * Description: Write data associated with VFP to specified file
718*9781SMoriah.Waterland@Sun.COM * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to write
719*9781SMoriah.Waterland@Sun.COM * char *a_path - path of file to write file data to
720*9781SMoriah.Waterland@Sun.COM * Returns: int == 0 - operation was successful
721*9781SMoriah.Waterland@Sun.COM * != 0 - operation failed, errno contains reason
722*9781SMoriah.Waterland@Sun.COM */
723*9781SMoriah.Waterland@Sun.COM
724*9781SMoriah.Waterland@Sun.COM int
vfpWriteToFile(VFP_T * a_vfp,char * a_path)725*9781SMoriah.Waterland@Sun.COM vfpWriteToFile(VFP_T *a_vfp, char *a_path)
726*9781SMoriah.Waterland@Sun.COM {
727*9781SMoriah.Waterland@Sun.COM int fd;
728*9781SMoriah.Waterland@Sun.COM int lerrno = 0;
729*9781SMoriah.Waterland@Sun.COM size_t len;
730*9781SMoriah.Waterland@Sun.COM ssize_t result = 0;
731*9781SMoriah.Waterland@Sun.COM
732*9781SMoriah.Waterland@Sun.COM /* return if no vfp specified */
733*9781SMoriah.Waterland@Sun.COM
734*9781SMoriah.Waterland@Sun.COM if (a_vfp == (VFP_T *)NULL) {
735*9781SMoriah.Waterland@Sun.COM errno = EFAULT;
736*9781SMoriah.Waterland@Sun.COM return (-1);
737*9781SMoriah.Waterland@Sun.COM }
738*9781SMoriah.Waterland@Sun.COM
739*9781SMoriah.Waterland@Sun.COM /* on buffer overflow generate error */
740*9781SMoriah.Waterland@Sun.COM
741*9781SMoriah.Waterland@Sun.COM if ((a_vfp->_vfpOverflow != 0) || (vfpGetBytesAvailable(a_vfp) < 1)) {
742*9781SMoriah.Waterland@Sun.COM errno = EFBIG;
743*9781SMoriah.Waterland@Sun.COM return (-1);
744*9781SMoriah.Waterland@Sun.COM }
745*9781SMoriah.Waterland@Sun.COM
746*9781SMoriah.Waterland@Sun.COM /* open file to write data to */
747*9781SMoriah.Waterland@Sun.COM
748*9781SMoriah.Waterland@Sun.COM fd = open(a_path, O_WRONLY|O_CREAT|O_TRUNC, 0644);
749*9781SMoriah.Waterland@Sun.COM if (fd < 0) {
750*9781SMoriah.Waterland@Sun.COM return (-1);
751*9781SMoriah.Waterland@Sun.COM }
752*9781SMoriah.Waterland@Sun.COM
753*9781SMoriah.Waterland@Sun.COM /* determine number of bytes to write */
754*9781SMoriah.Waterland@Sun.COM
755*9781SMoriah.Waterland@Sun.COM len = vfpGetModifiedLen(a_vfp);
756*9781SMoriah.Waterland@Sun.COM
757*9781SMoriah.Waterland@Sun.COM /*
758*9781SMoriah.Waterland@Sun.COM * if there is data associated with the file, write it out;
759*9781SMoriah.Waterland@Sun.COM * if an error occurs, close the file and return failure.
760*9781SMoriah.Waterland@Sun.COM */
761*9781SMoriah.Waterland@Sun.COM
762*9781SMoriah.Waterland@Sun.COM if (len > 0) {
763*9781SMoriah.Waterland@Sun.COM result = vfpSafeWrite(fd, a_vfp->_vfpStart, len);
764*9781SMoriah.Waterland@Sun.COM if (result != len) {
765*9781SMoriah.Waterland@Sun.COM /* error comitting data - return failure */
766*9781SMoriah.Waterland@Sun.COM lerrno = errno;
767*9781SMoriah.Waterland@Sun.COM (void) close(fd);
768*9781SMoriah.Waterland@Sun.COM errno = lerrno;
769*9781SMoriah.Waterland@Sun.COM return (-1);
770*9781SMoriah.Waterland@Sun.COM }
771*9781SMoriah.Waterland@Sun.COM }
772*9781SMoriah.Waterland@Sun.COM
773*9781SMoriah.Waterland@Sun.COM /* close the file */
774*9781SMoriah.Waterland@Sun.COM
775*9781SMoriah.Waterland@Sun.COM (void) close(fd);
776*9781SMoriah.Waterland@Sun.COM
777*9781SMoriah.Waterland@Sun.COM /* data committed to backing store - clear the modified flag */
778*9781SMoriah.Waterland@Sun.COM
779*9781SMoriah.Waterland@Sun.COM (void) vfpClearModified(a_vfp);
780*9781SMoriah.Waterland@Sun.COM
781*9781SMoriah.Waterland@Sun.COM /* return success */
782*9781SMoriah.Waterland@Sun.COM
783*9781SMoriah.Waterland@Sun.COM return (0);
784*9781SMoriah.Waterland@Sun.COM }
785*9781SMoriah.Waterland@Sun.COM
786*9781SMoriah.Waterland@Sun.COM /*
787*9781SMoriah.Waterland@Sun.COM * Name: vfpCheckpointFile
788*9781SMoriah.Waterland@Sun.COM * Description: Create new VFP that checkpoints existing VFP, can be used by
789*9781SMoriah.Waterland@Sun.COM * subsequent call to vfpCheckpointOpen to open a file using the
790*9781SMoriah.Waterland@Sun.COM * existing in-memory cache of the contents of the file
791*9781SMoriah.Waterland@Sun.COM * Arguments: VFP_T **r_cpVfp - pointer to pointer to VFP_T to be filled in
792*9781SMoriah.Waterland@Sun.COM * with "checkpointed file" VFP (backing store)
793*9781SMoriah.Waterland@Sun.COM * VFP_T **a_vfp - pointer to pointer to VFP_T returned by vfpOpen
794*9781SMoriah.Waterland@Sun.COM * representing the VFP to checkpoint
795*9781SMoriah.Waterland@Sun.COM * char *a_path - path to file that is the backing store for the
796*9781SMoriah.Waterland@Sun.COM * in-memory data represented by a_vfp - used to verify
797*9781SMoriah.Waterland@Sun.COM * that the data in memory is not out of date with respect
798*9781SMoriah.Waterland@Sun.COM * to the backing store when vfpCheckpointOpen is called
799*9781SMoriah.Waterland@Sun.COM * == (char *)NULL - use path associated with a_vfp
800*9781SMoriah.Waterland@Sun.COM * that is, the backing store file in use
801*9781SMoriah.Waterland@Sun.COM * Returns: int == 0 - operation was successful
802*9781SMoriah.Waterland@Sun.COM * - r_destVfp contains a pointer to a new VFP that
803*9781SMoriah.Waterland@Sun.COM * may be used in a subsequent call to
804*9781SMoriah.Waterland@Sun.COM * vfpCheckpointOpen
805*9781SMoriah.Waterland@Sun.COM * - the VFP referenced by *a_vfp is free()ed and
806*9781SMoriah.Waterland@Sun.COM * must no longer be referenced
807*9781SMoriah.Waterland@Sun.COM * != 0 - operation failed, errno contains reason
808*9781SMoriah.Waterland@Sun.COM * - the VFP referenced by *a_vfp is not affected;
809*9781SMoriah.Waterland@Sun.COM * the caller may continue to use it
810*9781SMoriah.Waterland@Sun.COM * Notes: If the data of a VFP to checkpoint is mmap()ed then this method
811*9781SMoriah.Waterland@Sun.COM * returns failure - only malloc()ed data VFPs can be
812*9781SMoriah.Waterland@Sun.COM * checkpointed.
813*9781SMoriah.Waterland@Sun.COM */
814*9781SMoriah.Waterland@Sun.COM
815*9781SMoriah.Waterland@Sun.COM int
vfpCheckpointFile(VFP_T ** r_cpVfp,VFP_T ** a_vfp,char * a_path)816*9781SMoriah.Waterland@Sun.COM vfpCheckpointFile(VFP_T **r_cpVfp, VFP_T **a_vfp, char *a_path)
817*9781SMoriah.Waterland@Sun.COM {
818*9781SMoriah.Waterland@Sun.COM VFP_T *vfp; /* newly allocated checkpointed VFP */
819*9781SMoriah.Waterland@Sun.COM VFP_T *avfp; /* local -> to a_vfp */
820*9781SMoriah.Waterland@Sun.COM struct stat statbuf; /* stat(2) info for backing store */
821*9781SMoriah.Waterland@Sun.COM
822*9781SMoriah.Waterland@Sun.COM /* return error if NULL VFP_T** to checkpoint provided */
823*9781SMoriah.Waterland@Sun.COM
824*9781SMoriah.Waterland@Sun.COM if (r_cpVfp == (VFP_T **)NULL) {
825*9781SMoriah.Waterland@Sun.COM errno = EFAULT;
826*9781SMoriah.Waterland@Sun.COM return (-1);
827*9781SMoriah.Waterland@Sun.COM }
828*9781SMoriah.Waterland@Sun.COM
829*9781SMoriah.Waterland@Sun.COM /* reset return checkpoint VFP pointer */
830*9781SMoriah.Waterland@Sun.COM
831*9781SMoriah.Waterland@Sun.COM (*r_cpVfp) = (VFP_T *)NULL;
832*9781SMoriah.Waterland@Sun.COM
833*9781SMoriah.Waterland@Sun.COM /* return error if no VFP to checkpoint specified */
834*9781SMoriah.Waterland@Sun.COM
835*9781SMoriah.Waterland@Sun.COM if (a_vfp == (VFP_T **)NULL) {
836*9781SMoriah.Waterland@Sun.COM errno = EFAULT;
837*9781SMoriah.Waterland@Sun.COM return (-1);
838*9781SMoriah.Waterland@Sun.COM }
839*9781SMoriah.Waterland@Sun.COM
840*9781SMoriah.Waterland@Sun.COM /* localize reference to a_vfp */
841*9781SMoriah.Waterland@Sun.COM
842*9781SMoriah.Waterland@Sun.COM avfp = *a_vfp;
843*9781SMoriah.Waterland@Sun.COM
844*9781SMoriah.Waterland@Sun.COM /* return error if no VFP to checkpoint specified */
845*9781SMoriah.Waterland@Sun.COM
846*9781SMoriah.Waterland@Sun.COM if (avfp == (VFP_T *)NULL) {
847*9781SMoriah.Waterland@Sun.COM errno = EFAULT;
848*9781SMoriah.Waterland@Sun.COM return (-1);
849*9781SMoriah.Waterland@Sun.COM }
850*9781SMoriah.Waterland@Sun.COM
851*9781SMoriah.Waterland@Sun.COM /* on buffer overflow generate error */
852*9781SMoriah.Waterland@Sun.COM
853*9781SMoriah.Waterland@Sun.COM if ((avfp->_vfpOverflow != 0) || (vfpGetBytesAvailable(avfp) < 1)) {
854*9781SMoriah.Waterland@Sun.COM errno = EFBIG;
855*9781SMoriah.Waterland@Sun.COM return (-1);
856*9781SMoriah.Waterland@Sun.COM }
857*9781SMoriah.Waterland@Sun.COM
858*9781SMoriah.Waterland@Sun.COM /* no checkpointing is possible if the existing VFP is mmap()ed */
859*9781SMoriah.Waterland@Sun.COM
860*9781SMoriah.Waterland@Sun.COM if (avfp->_vfpFlags & _VFP_MMAP) {
861*9781SMoriah.Waterland@Sun.COM errno = EIO;
862*9781SMoriah.Waterland@Sun.COM return (-1);
863*9781SMoriah.Waterland@Sun.COM }
864*9781SMoriah.Waterland@Sun.COM
865*9781SMoriah.Waterland@Sun.COM /* if no path specified, grab it from the VFP to checkpoint */
866*9781SMoriah.Waterland@Sun.COM
867*9781SMoriah.Waterland@Sun.COM if ((a_path == (char *)NULL) || (*a_path == '\0')) {
868*9781SMoriah.Waterland@Sun.COM a_path = avfp->_vfpPath;
869*9781SMoriah.Waterland@Sun.COM }
870*9781SMoriah.Waterland@Sun.COM
871*9781SMoriah.Waterland@Sun.COM /* backing store required: if VFP is "string" then this is an error */
872*9781SMoriah.Waterland@Sun.COM
873*9781SMoriah.Waterland@Sun.COM if ((a_path == (char *)NULL) ||
874*9781SMoriah.Waterland@Sun.COM strcmp(a_path, VFP_ANONYMOUS_PATH) == 0) {
875*9781SMoriah.Waterland@Sun.COM errno = EINVAL;
876*9781SMoriah.Waterland@Sun.COM return (-1);
877*9781SMoriah.Waterland@Sun.COM }
878*9781SMoriah.Waterland@Sun.COM
879*9781SMoriah.Waterland@Sun.COM /* Get the VFP to checkpoint (backing store) file size */
880*9781SMoriah.Waterland@Sun.COM
881*9781SMoriah.Waterland@Sun.COM if (stat(a_path, &statbuf) != 0) {
882*9781SMoriah.Waterland@Sun.COM return (-1);
883*9781SMoriah.Waterland@Sun.COM }
884*9781SMoriah.Waterland@Sun.COM
885*9781SMoriah.Waterland@Sun.COM /* allocate storage for checkpointed VFP (to return) */
886*9781SMoriah.Waterland@Sun.COM
887*9781SMoriah.Waterland@Sun.COM vfp = (VFP_T *)malloc(sizeof (VFP_T));
888*9781SMoriah.Waterland@Sun.COM if (vfp == (VFP_T *)NULL) {
889*9781SMoriah.Waterland@Sun.COM return (-1);
890*9781SMoriah.Waterland@Sun.COM }
891*9781SMoriah.Waterland@Sun.COM
892*9781SMoriah.Waterland@Sun.COM /*
893*9781SMoriah.Waterland@Sun.COM * close any file that is on the VFP to checkpoint (backing store);
894*9781SMoriah.Waterland@Sun.COM * subsequent processes can modify the backing store data, and
895*9781SMoriah.Waterland@Sun.COM * then when vfpCheckpointOpen is called, either the in-memory
896*9781SMoriah.Waterland@Sun.COM * cached data will be used (if backing store unmodified) or else
897*9781SMoriah.Waterland@Sun.COM * the in-memory data is released and the backing store is used.
898*9781SMoriah.Waterland@Sun.COM */
899*9781SMoriah.Waterland@Sun.COM
900*9781SMoriah.Waterland@Sun.COM if (avfp->_vfpFile != (FILE *)NULL) {
901*9781SMoriah.Waterland@Sun.COM (void) fclose(avfp->_vfpFile);
902*9781SMoriah.Waterland@Sun.COM avfp->_vfpFile = (FILE *)NULL;
903*9781SMoriah.Waterland@Sun.COM }
904*9781SMoriah.Waterland@Sun.COM
905*9781SMoriah.Waterland@Sun.COM /* free any path associated with VFP to checkpoint (backing store) */
906*9781SMoriah.Waterland@Sun.COM
907*9781SMoriah.Waterland@Sun.COM if (avfp->_vfpPath != (char *)NULL) {
908*9781SMoriah.Waterland@Sun.COM (void) free(avfp->_vfpPath);
909*9781SMoriah.Waterland@Sun.COM avfp->_vfpPath = (char *)NULL;
910*9781SMoriah.Waterland@Sun.COM }
911*9781SMoriah.Waterland@Sun.COM
912*9781SMoriah.Waterland@Sun.COM /* copy contents of VFP to checkpoint to checkpointed VFP */
913*9781SMoriah.Waterland@Sun.COM
914*9781SMoriah.Waterland@Sun.COM memcpy(vfp, avfp, sizeof (VFP_T));
915*9781SMoriah.Waterland@Sun.COM
916*9781SMoriah.Waterland@Sun.COM /* free contents of VFP to checkpoint */
917*9781SMoriah.Waterland@Sun.COM
918*9781SMoriah.Waterland@Sun.COM (void) free(avfp);
919*9781SMoriah.Waterland@Sun.COM
920*9781SMoriah.Waterland@Sun.COM /* reset pointer to VFP that has been free'd */
921*9781SMoriah.Waterland@Sun.COM
922*9781SMoriah.Waterland@Sun.COM *a_vfp = (VFP_T *)NULL;
923*9781SMoriah.Waterland@Sun.COM
924*9781SMoriah.Waterland@Sun.COM /* remember path associated with the checkpointed VFP (backing store) */
925*9781SMoriah.Waterland@Sun.COM
926*9781SMoriah.Waterland@Sun.COM vfp->_vfpPath = strdup(a_path);
927*9781SMoriah.Waterland@Sun.COM
928*9781SMoriah.Waterland@Sun.COM /* save tokens that identify the backing store for the in-memory data */
929*9781SMoriah.Waterland@Sun.COM
930*9781SMoriah.Waterland@Sun.COM vfp->_vfpCkDev = statbuf.st_dev; /* devid holding st_ino inode */
931*9781SMoriah.Waterland@Sun.COM vfp->_vfpCkIno = statbuf.st_ino; /* backing store inode */
932*9781SMoriah.Waterland@Sun.COM vfp->_vfpCkMtime = statbuf.st_mtime; /* last data modification */
933*9781SMoriah.Waterland@Sun.COM vfp->_vfpCkSize = statbuf.st_size; /* backing store size (bytes) */
934*9781SMoriah.Waterland@Sun.COM vfp->_vfpCkStBlocks = statbuf.st_blocks; /* blocks allocated to file */
935*9781SMoriah.Waterland@Sun.COM
936*9781SMoriah.Waterland@Sun.COM /* pass checkpointed VFP to caller */
937*9781SMoriah.Waterland@Sun.COM
938*9781SMoriah.Waterland@Sun.COM (*r_cpVfp) = vfp;
939*9781SMoriah.Waterland@Sun.COM
940*9781SMoriah.Waterland@Sun.COM /* success! */
941*9781SMoriah.Waterland@Sun.COM
942*9781SMoriah.Waterland@Sun.COM return (0);
943*9781SMoriah.Waterland@Sun.COM }
944*9781SMoriah.Waterland@Sun.COM
945*9781SMoriah.Waterland@Sun.COM /*
946*9781SMoriah.Waterland@Sun.COM * Name: vfpCheckpointOpen
947*9781SMoriah.Waterland@Sun.COM * Description: Open file on vfp, allocate storage, return pointer to VFP_T
948*9781SMoriah.Waterland@Sun.COM * that can be used to access/modify file contents. If a VFP_T to
949*9781SMoriah.Waterland@Sun.COM * a checkpointed VFP is passed in, and the in memory contents of
950*9781SMoriah.Waterland@Sun.COM * the VFP are not out of date with respect to the backing store
951*9781SMoriah.Waterland@Sun.COM * file, use the existing in-memory contents - otherwise, discard
952*9781SMoriah.Waterland@Sun.COM * the in-memory contents and reopen and reread the file.
953*9781SMoriah.Waterland@Sun.COM * Arguments: VFP_T **a_cpVfp - pointer to pointer to VFP_T that represents
954*9781SMoriah.Waterland@Sun.COM * checkpointed VFP to use to open the file IF the contents
955*9781SMoriah.Waterland@Sun.COM * of the backing store are identical to the in-memory data
956*9781SMoriah.Waterland@Sun.COM * VFP_T **r_vfp - pointer to pointer to VFP_T to open file on
957*9781SMoriah.Waterland@Sun.COM * char *a_path - path of file to open and associate with this VFP.
958*9781SMoriah.Waterland@Sun.COM * - if the path is (char *)NULL then no file is associated
959*9781SMoriah.Waterland@Sun.COM * with this VFP - this is a way to create a fixed length
960*9781SMoriah.Waterland@Sun.COM * string that can be manipulated with the VFP operators.
961*9781SMoriah.Waterland@Sun.COM * Before the VFP can be used "vfpSetSize" must be called
962*9781SMoriah.Waterland@Sun.COM * to set the size of the string buffer.
963*9781SMoriah.Waterland@Sun.COM * char *a_mode - fopen mode to open the file with
964*9781SMoriah.Waterland@Sun.COM * VFPFLAGS_T a_flags - one or more flags to control the operation:
965*9781SMoriah.Waterland@Sun.COM * - VFP_NONE - no special flags
966*9781SMoriah.Waterland@Sun.COM * - VFP_NEEDNOW - file data needed in memory now
967*9781SMoriah.Waterland@Sun.COM * - VFP_SEQUENTIAL - memory will be sequentially accessed
968*9781SMoriah.Waterland@Sun.COM * - VFP_RANDOM - memory will be randomly accessed
969*9781SMoriah.Waterland@Sun.COM * - VFP_NOMMAP - do not use mmap to access file
970*9781SMoriah.Waterland@Sun.COM * - VFP_NOMALLOC - do not use malloc to buffer file
971*9781SMoriah.Waterland@Sun.COM * Returns: int == 0 - operation was successful
972*9781SMoriah.Waterland@Sun.COM * != 0 - operation failed, errno contains reason
973*9781SMoriah.Waterland@Sun.COM * Side Effects: r_vfp -- filled in with a pointer to a newly allocated vfp
974*9781SMoriah.Waterland@Sun.COM * which can be used with the various VFP functions.
975*9781SMoriah.Waterland@Sun.COM * a_cpVfp -- contents reset to zero if used to open the file
976*9781SMoriah.Waterland@Sun.COM * errno -- contains system error number if return is != 0
977*9781SMoriah.Waterland@Sun.COM */
978*9781SMoriah.Waterland@Sun.COM
979*9781SMoriah.Waterland@Sun.COM int
vfpCheckpointOpen(VFP_T ** a_cpVfp,VFP_T ** r_vfp,char * a_path,char * a_mode,VFPFLAGS_T a_flags)980*9781SMoriah.Waterland@Sun.COM vfpCheckpointOpen(VFP_T **a_cpVfp, VFP_T **r_vfp, char *a_path,
981*9781SMoriah.Waterland@Sun.COM char *a_mode, VFPFLAGS_T a_flags)
982*9781SMoriah.Waterland@Sun.COM {
983*9781SMoriah.Waterland@Sun.COM FILE *fp; /* backing store */
984*9781SMoriah.Waterland@Sun.COM VFP_T *cpVfp; /* local -> to a_cpVfp checkpointed VFP */
985*9781SMoriah.Waterland@Sun.COM VFP_T *vfp; /* new VFP open on checkpointed backing store */
986*9781SMoriah.Waterland@Sun.COM struct stat statbuf; /* stat(2) info on backing store */
987*9781SMoriah.Waterland@Sun.COM
988*9781SMoriah.Waterland@Sun.COM /*
989*9781SMoriah.Waterland@Sun.COM * if no source VFP, or source VFP empty,
990*9781SMoriah.Waterland@Sun.COM * or no backing store, just open file
991*9781SMoriah.Waterland@Sun.COM */
992*9781SMoriah.Waterland@Sun.COM
993*9781SMoriah.Waterland@Sun.COM if ((a_cpVfp == (VFP_T **)NULL) || (*a_cpVfp == (VFP_T *)NULL) ||
994*9781SMoriah.Waterland@Sun.COM ((*a_cpVfp)->_vfpStart == (char *)NULL)) {
995*9781SMoriah.Waterland@Sun.COM (void) vfpClose(a_cpVfp);
996*9781SMoriah.Waterland@Sun.COM return (vfpOpen(r_vfp, a_path, a_mode, a_flags));
997*9781SMoriah.Waterland@Sun.COM }
998*9781SMoriah.Waterland@Sun.COM
999*9781SMoriah.Waterland@Sun.COM /* localize access to checkpointed VFP_T (*a_cpVfp) */
1000*9781SMoriah.Waterland@Sun.COM
1001*9781SMoriah.Waterland@Sun.COM cpVfp = *a_cpVfp;
1002*9781SMoriah.Waterland@Sun.COM
1003*9781SMoriah.Waterland@Sun.COM /* if no path specified, grab it from the checkpointed VFP */
1004*9781SMoriah.Waterland@Sun.COM
1005*9781SMoriah.Waterland@Sun.COM if ((a_path == (char *)NULL) || (*a_path == '\0')) {
1006*9781SMoriah.Waterland@Sun.COM a_path = cpVfp->_vfpPath;
1007*9781SMoriah.Waterland@Sun.COM }
1008*9781SMoriah.Waterland@Sun.COM
1009*9781SMoriah.Waterland@Sun.COM /* return error if no path specified and no path in checkpointed VFP */
1010*9781SMoriah.Waterland@Sun.COM
1011*9781SMoriah.Waterland@Sun.COM if ((a_path == (char *)NULL) && (*a_path == '\0')) {
1012*9781SMoriah.Waterland@Sun.COM errno = EINVAL;
1013*9781SMoriah.Waterland@Sun.COM return (-1);
1014*9781SMoriah.Waterland@Sun.COM }
1015*9781SMoriah.Waterland@Sun.COM
1016*9781SMoriah.Waterland@Sun.COM /* if no backing store path, then just open file */
1017*9781SMoriah.Waterland@Sun.COM
1018*9781SMoriah.Waterland@Sun.COM if (stat(a_path, &statbuf) != 0) {
1019*9781SMoriah.Waterland@Sun.COM (void) vfpClose(a_cpVfp);
1020*9781SMoriah.Waterland@Sun.COM return (vfpOpen(r_vfp, a_path, a_mode, a_flags));
1021*9781SMoriah.Waterland@Sun.COM }
1022*9781SMoriah.Waterland@Sun.COM
1023*9781SMoriah.Waterland@Sun.COM /*
1024*9781SMoriah.Waterland@Sun.COM * if backing store tokens do not match checkpointed VFP,
1025*9781SMoriah.Waterland@Sun.COM * the backing store has been updated since the VFP was checkpointed;
1026*9781SMoriah.Waterland@Sun.COM * release the in-memory data, and open and read the backing store
1027*9781SMoriah.Waterland@Sun.COM */
1028*9781SMoriah.Waterland@Sun.COM
1029*9781SMoriah.Waterland@Sun.COM if ((statbuf.st_size != cpVfp->_vfpCkSize) ||
1030*9781SMoriah.Waterland@Sun.COM (statbuf.st_mtime != cpVfp->_vfpCkMtime) ||
1031*9781SMoriah.Waterland@Sun.COM (statbuf.st_blocks != cpVfp->_vfpCkStBlocks) ||
1032*9781SMoriah.Waterland@Sun.COM (statbuf.st_ino != cpVfp->_vfpCkIno) ||
1033*9781SMoriah.Waterland@Sun.COM (statbuf.st_dev != cpVfp->_vfpCkDev)) {
1034*9781SMoriah.Waterland@Sun.COM (void) vfpClose(a_cpVfp);
1035*9781SMoriah.Waterland@Sun.COM return (vfpOpen(r_vfp, a_path, a_mode, a_flags));
1036*9781SMoriah.Waterland@Sun.COM }
1037*9781SMoriah.Waterland@Sun.COM
1038*9781SMoriah.Waterland@Sun.COM /*
1039*9781SMoriah.Waterland@Sun.COM * backing store has not been updated since the VFP was checkpointed;
1040*9781SMoriah.Waterland@Sun.COM * use the in-memory data without re-reading the backing store; open the
1041*9781SMoriah.Waterland@Sun.COM * backing store file (if no file already open on the checkpointed VFP)
1042*9781SMoriah.Waterland@Sun.COM * so there is an open file associated with the in-memory data
1043*9781SMoriah.Waterland@Sun.COM */
1044*9781SMoriah.Waterland@Sun.COM
1045*9781SMoriah.Waterland@Sun.COM fp = cpVfp->_vfpFile;
1046*9781SMoriah.Waterland@Sun.COM if (fp == (FILE *)NULL) {
1047*9781SMoriah.Waterland@Sun.COM fp = fopen(a_path, a_mode);
1048*9781SMoriah.Waterland@Sun.COM if (fp == (FILE *)NULL) {
1049*9781SMoriah.Waterland@Sun.COM int lerrno;
1050*9781SMoriah.Waterland@Sun.COM
1051*9781SMoriah.Waterland@Sun.COM lerrno = errno;
1052*9781SMoriah.Waterland@Sun.COM (void) vfpClose(a_cpVfp);
1053*9781SMoriah.Waterland@Sun.COM errno = lerrno;
1054*9781SMoriah.Waterland@Sun.COM return (-1);
1055*9781SMoriah.Waterland@Sun.COM }
1056*9781SMoriah.Waterland@Sun.COM }
1057*9781SMoriah.Waterland@Sun.COM
1058*9781SMoriah.Waterland@Sun.COM /* allocate new VFP object to return as open VFP */
1059*9781SMoriah.Waterland@Sun.COM
1060*9781SMoriah.Waterland@Sun.COM vfp = (VFP_T *)malloc(sizeof (VFP_T));
1061*9781SMoriah.Waterland@Sun.COM if (vfp == (VFP_T *)NULL) {
1062*9781SMoriah.Waterland@Sun.COM (void) vfpClose(a_cpVfp);
1063*9781SMoriah.Waterland@Sun.COM return (vfpOpen(r_vfp, a_path, a_mode, a_flags));
1064*9781SMoriah.Waterland@Sun.COM }
1065*9781SMoriah.Waterland@Sun.COM
1066*9781SMoriah.Waterland@Sun.COM /* copy cached checkpointed VFP to new VFP to return */
1067*9781SMoriah.Waterland@Sun.COM
1068*9781SMoriah.Waterland@Sun.COM (void) memcpy(vfp, cpVfp, sizeof (VFP_T));
1069*9781SMoriah.Waterland@Sun.COM
1070*9781SMoriah.Waterland@Sun.COM /*
1071*9781SMoriah.Waterland@Sun.COM * initialize VFP to return contents
1072*9781SMoriah.Waterland@Sun.COM */
1073*9781SMoriah.Waterland@Sun.COM
1074*9781SMoriah.Waterland@Sun.COM /* FILE -> file opened on the VFPs backing store */
1075*9781SMoriah.Waterland@Sun.COM
1076*9781SMoriah.Waterland@Sun.COM vfp->_vfpFile = fp;
1077*9781SMoriah.Waterland@Sun.COM
1078*9781SMoriah.Waterland@Sun.COM /* release any existing path associated with the VFP */
1079*9781SMoriah.Waterland@Sun.COM
1080*9781SMoriah.Waterland@Sun.COM if (vfp->_vfpPath != (char *)NULL) {
1081*9781SMoriah.Waterland@Sun.COM (void) free(vfp->_vfpPath);
1082*9781SMoriah.Waterland@Sun.COM }
1083*9781SMoriah.Waterland@Sun.COM
1084*9781SMoriah.Waterland@Sun.COM /* path associated with the backing store for this VFP */
1085*9781SMoriah.Waterland@Sun.COM
1086*9781SMoriah.Waterland@Sun.COM vfp->_vfpPath = strdup(a_path);
1087*9781SMoriah.Waterland@Sun.COM
1088*9781SMoriah.Waterland@Sun.COM /*
1089*9781SMoriah.Waterland@Sun.COM * data pointers associated with in memory copy of backing store
1090*9781SMoriah.Waterland@Sun.COM * (such as _vfpHighWater, _vfpEnd, _vfpStart, etc.)
1091*9781SMoriah.Waterland@Sun.COM * do not need to be modified because we are using the same backing
1092*9781SMoriah.Waterland@Sun.COM * store as was checkpointed in cpVfp that is pointed to by vfp.
1093*9781SMoriah.Waterland@Sun.COM */
1094*9781SMoriah.Waterland@Sun.COM
1095*9781SMoriah.Waterland@Sun.COM /* _vfpCurr -> next byte to read */
1096*9781SMoriah.Waterland@Sun.COM vfp->_vfpCurr = (char *)vfp->_vfpStart;
1097*9781SMoriah.Waterland@Sun.COM
1098*9781SMoriah.Waterland@Sun.COM /* free checkpointed VFP as it is now open on "vfp" */
1099*9781SMoriah.Waterland@Sun.COM
1100*9781SMoriah.Waterland@Sun.COM (void) free(cpVfp);
1101*9781SMoriah.Waterland@Sun.COM
1102*9781SMoriah.Waterland@Sun.COM /* reset callers -> checkpointed VFP */
1103*9781SMoriah.Waterland@Sun.COM
1104*9781SMoriah.Waterland@Sun.COM (*a_cpVfp) = (VFP_T *)NULL;
1105*9781SMoriah.Waterland@Sun.COM
1106*9781SMoriah.Waterland@Sun.COM /* set return VFP pointer */
1107*9781SMoriah.Waterland@Sun.COM
1108*9781SMoriah.Waterland@Sun.COM (*r_vfp) = vfp;
1109*9781SMoriah.Waterland@Sun.COM
1110*9781SMoriah.Waterland@Sun.COM /* success! */
1111*9781SMoriah.Waterland@Sun.COM
1112*9781SMoriah.Waterland@Sun.COM return (0);
1113*9781SMoriah.Waterland@Sun.COM }
1114*9781SMoriah.Waterland@Sun.COM
1115*9781SMoriah.Waterland@Sun.COM /*
1116*9781SMoriah.Waterland@Sun.COM * Name: vfpClearModified
1117*9781SMoriah.Waterland@Sun.COM * Description: Clear the "data is modified" indication from the VFP
1118*9781SMoriah.Waterland@Sun.COM * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to clear
1119*9781SMoriah.Waterland@Sun.COM * the "data is modified" indication
1120*9781SMoriah.Waterland@Sun.COM * Returns: int - previous setting of "data is modified" indication
1121*9781SMoriah.Waterland@Sun.COM * == 0 - "data is modified" was NOT previously set
1122*9781SMoriah.Waterland@Sun.COM * != 0 - "data is modified" WAS previously set
1123*9781SMoriah.Waterland@Sun.COM */
1124*9781SMoriah.Waterland@Sun.COM
1125*9781SMoriah.Waterland@Sun.COM int
vfpClearModified(VFP_T * a_vfp)1126*9781SMoriah.Waterland@Sun.COM vfpClearModified(VFP_T *a_vfp)
1127*9781SMoriah.Waterland@Sun.COM {
1128*9781SMoriah.Waterland@Sun.COM VFPFLAGS_T flags;
1129*9781SMoriah.Waterland@Sun.COM
1130*9781SMoriah.Waterland@Sun.COM /* save current flags settings */
1131*9781SMoriah.Waterland@Sun.COM
1132*9781SMoriah.Waterland@Sun.COM flags = a_vfp->_vfpFlags;
1133*9781SMoriah.Waterland@Sun.COM
1134*9781SMoriah.Waterland@Sun.COM /* clear "data is modified" flag */
1135*9781SMoriah.Waterland@Sun.COM
1136*9781SMoriah.Waterland@Sun.COM a_vfp->_vfpFlags &= (~_VFP_MODIFIED);
1137*9781SMoriah.Waterland@Sun.COM
1138*9781SMoriah.Waterland@Sun.COM /* return previous "data is modified" flag setting */
1139*9781SMoriah.Waterland@Sun.COM
1140*9781SMoriah.Waterland@Sun.COM return ((flags & _VFP_MODIFIED) != 0);
1141*9781SMoriah.Waterland@Sun.COM }
1142*9781SMoriah.Waterland@Sun.COM
1143*9781SMoriah.Waterland@Sun.COM /*
1144*9781SMoriah.Waterland@Sun.COM * Name: vfpSetModified
1145*9781SMoriah.Waterland@Sun.COM * Description: Set the "data is modified" indication from the VFP
1146*9781SMoriah.Waterland@Sun.COM * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to set
1147*9781SMoriah.Waterland@Sun.COM * the "data is modified" indication
1148*9781SMoriah.Waterland@Sun.COM * Returns: int - previous setting of "data is modified" indication
1149*9781SMoriah.Waterland@Sun.COM * == 0 - "data is modified" was NOT previously set
1150*9781SMoriah.Waterland@Sun.COM * != 0 - "data is modified" WAS previously set
1151*9781SMoriah.Waterland@Sun.COM */
1152*9781SMoriah.Waterland@Sun.COM
1153*9781SMoriah.Waterland@Sun.COM int
vfpSetModified(VFP_T * a_vfp)1154*9781SMoriah.Waterland@Sun.COM vfpSetModified(VFP_T *a_vfp)
1155*9781SMoriah.Waterland@Sun.COM {
1156*9781SMoriah.Waterland@Sun.COM VFPFLAGS_T flags;
1157*9781SMoriah.Waterland@Sun.COM
1158*9781SMoriah.Waterland@Sun.COM /* save current flags settings */
1159*9781SMoriah.Waterland@Sun.COM
1160*9781SMoriah.Waterland@Sun.COM flags = a_vfp->_vfpFlags;
1161*9781SMoriah.Waterland@Sun.COM
1162*9781SMoriah.Waterland@Sun.COM /* set "data is modified" flag */
1163*9781SMoriah.Waterland@Sun.COM
1164*9781SMoriah.Waterland@Sun.COM a_vfp->_vfpFlags |= _VFP_MODIFIED;
1165*9781SMoriah.Waterland@Sun.COM
1166*9781SMoriah.Waterland@Sun.COM /* return previous "data is modified" flag setting */
1167*9781SMoriah.Waterland@Sun.COM
1168*9781SMoriah.Waterland@Sun.COM return ((flags & _VFP_MODIFIED) != 0);
1169*9781SMoriah.Waterland@Sun.COM }
1170*9781SMoriah.Waterland@Sun.COM
1171*9781SMoriah.Waterland@Sun.COM /*
1172*9781SMoriah.Waterland@Sun.COM * Name: vfpGetModified
1173*9781SMoriah.Waterland@Sun.COM * Description: Get the "data is modified" indication from the VFP
1174*9781SMoriah.Waterland@Sun.COM * Arguments: VFP_T *a_vfp - VFP_T pointer associated with file to get
1175*9781SMoriah.Waterland@Sun.COM * the "data is modified" indication
1176*9781SMoriah.Waterland@Sun.COM * Returns: int - current setting of "data is modified" indication
1177*9781SMoriah.Waterland@Sun.COM * == 0 - "data is modified" is NOT set
1178*9781SMoriah.Waterland@Sun.COM * != 0 - "data is modified" IS set
1179*9781SMoriah.Waterland@Sun.COM */
1180*9781SMoriah.Waterland@Sun.COM
1181*9781SMoriah.Waterland@Sun.COM int
vfpGetModified(VFP_T * a_vfp)1182*9781SMoriah.Waterland@Sun.COM vfpGetModified(VFP_T *a_vfp)
1183*9781SMoriah.Waterland@Sun.COM {
1184*9781SMoriah.Waterland@Sun.COM /* return current "data is modified" flag setting */
1185*9781SMoriah.Waterland@Sun.COM
1186*9781SMoriah.Waterland@Sun.COM return ((a_vfp->_vfpFlags & _VFP_MODIFIED) != 0);
1187*9781SMoriah.Waterland@Sun.COM }
1188*9781SMoriah.Waterland@Sun.COM
1189*9781SMoriah.Waterland@Sun.COM /*
1190*9781SMoriah.Waterland@Sun.COM * Name: vfpSafeWrite
1191*9781SMoriah.Waterland@Sun.COM * Description: write data to open file safely
1192*9781SMoriah.Waterland@Sun.COM * Arguments: a_fildes - file descriptor to write data to
1193*9781SMoriah.Waterland@Sun.COM * a_buf - pointer to buffer containing data to write
1194*9781SMoriah.Waterland@Sun.COM * a_nbyte - number of bytes to write to open file
1195*9781SMoriah.Waterland@Sun.COM * Returns: int
1196*9781SMoriah.Waterland@Sun.COM * < 0 - error, errno set
1197*9781SMoriah.Waterland@Sun.COM * >= 0 - success
1198*9781SMoriah.Waterland@Sun.COM * NOTE: unlike write(2), vfpSafeWrite() handles partial writes, and will
1199*9781SMoriah.Waterland@Sun.COM * ----- restart the write() until all bytes are written, or an error occurs.
1200*9781SMoriah.Waterland@Sun.COM */
1201*9781SMoriah.Waterland@Sun.COM
1202*9781SMoriah.Waterland@Sun.COM ssize_t
vfpSafeWrite(int a_fildes,void * a_buf,size_t a_nbyte)1203*9781SMoriah.Waterland@Sun.COM vfpSafeWrite(int a_fildes, void *a_buf, size_t a_nbyte)
1204*9781SMoriah.Waterland@Sun.COM {
1205*9781SMoriah.Waterland@Sun.COM ssize_t r;
1206*9781SMoriah.Waterland@Sun.COM size_t bytes = a_nbyte;
1207*9781SMoriah.Waterland@Sun.COM
1208*9781SMoriah.Waterland@Sun.COM for (;;) {
1209*9781SMoriah.Waterland@Sun.COM /* write bytes to file */
1210*9781SMoriah.Waterland@Sun.COM r = write(a_fildes, a_buf, a_nbyte);
1211*9781SMoriah.Waterland@Sun.COM
1212*9781SMoriah.Waterland@Sun.COM /* return error on failure of write() */
1213*9781SMoriah.Waterland@Sun.COM if (r < 0) {
1214*9781SMoriah.Waterland@Sun.COM /* EAGAIN: try again */
1215*9781SMoriah.Waterland@Sun.COM if (errno == EAGAIN) {
1216*9781SMoriah.Waterland@Sun.COM continue;
1217*9781SMoriah.Waterland@Sun.COM }
1218*9781SMoriah.Waterland@Sun.COM /* EINTR: interrupted - try again */
1219*9781SMoriah.Waterland@Sun.COM if (errno == EINTR) {
1220*9781SMoriah.Waterland@Sun.COM continue;
1221*9781SMoriah.Waterland@Sun.COM }
1222*9781SMoriah.Waterland@Sun.COM return (r);
1223*9781SMoriah.Waterland@Sun.COM }
1224*9781SMoriah.Waterland@Sun.COM
1225*9781SMoriah.Waterland@Sun.COM /* return total bytes written on success */
1226*9781SMoriah.Waterland@Sun.COM if (r >= a_nbyte) {
1227*9781SMoriah.Waterland@Sun.COM return (bytes);
1228*9781SMoriah.Waterland@Sun.COM }
1229*9781SMoriah.Waterland@Sun.COM
1230*9781SMoriah.Waterland@Sun.COM /* partial write, adjust pointers, call write again */
1231*9781SMoriah.Waterland@Sun.COM a_buf = (void *)((ptrdiff_t)a_buf + (ptrdiff_t)r);
1232*9781SMoriah.Waterland@Sun.COM a_nbyte -= (size_t)r;
1233*9781SMoriah.Waterland@Sun.COM }
1234*9781SMoriah.Waterland@Sun.COM }
1235*9781SMoriah.Waterland@Sun.COM
1236*9781SMoriah.Waterland@Sun.COM /*
1237*9781SMoriah.Waterland@Sun.COM * Name: vfpSafePwrite
1238*9781SMoriah.Waterland@Sun.COM * Description: write data to open file safely
1239*9781SMoriah.Waterland@Sun.COM * Arguments: a_fildes - file descriptor to write data to
1240*9781SMoriah.Waterland@Sun.COM * a_buf - pointer to buffer containing data to write
1241*9781SMoriah.Waterland@Sun.COM * a_nbyte - number of bytes to write to open file
1242*9781SMoriah.Waterland@Sun.COM * a_offset - offset into open file to write the first byte to
1243*9781SMoriah.Waterland@Sun.COM * Returns: int
1244*9781SMoriah.Waterland@Sun.COM * < 0 - error, errno set
1245*9781SMoriah.Waterland@Sun.COM * >= 0 - success
1246*9781SMoriah.Waterland@Sun.COM * NOTE: unlike pwrite(2), vfpSafePwrite() handles partial writes, and will
1247*9781SMoriah.Waterland@Sun.COM * ----- restart the pwrite() until all bytes are written, or an error occurs.
1248*9781SMoriah.Waterland@Sun.COM */
1249*9781SMoriah.Waterland@Sun.COM
1250*9781SMoriah.Waterland@Sun.COM ssize_t
vfpSafePwrite(int a_fildes,void * a_buf,size_t a_nbyte,off_t a_offset)1251*9781SMoriah.Waterland@Sun.COM vfpSafePwrite(int a_fildes, void *a_buf, size_t a_nbyte, off_t a_offset)
1252*9781SMoriah.Waterland@Sun.COM {
1253*9781SMoriah.Waterland@Sun.COM ssize_t r;
1254*9781SMoriah.Waterland@Sun.COM size_t bytes = a_nbyte;
1255*9781SMoriah.Waterland@Sun.COM
1256*9781SMoriah.Waterland@Sun.COM for (;;) {
1257*9781SMoriah.Waterland@Sun.COM /* write bytes to file */
1258*9781SMoriah.Waterland@Sun.COM r = pwrite(a_fildes, a_buf, a_nbyte, a_offset);
1259*9781SMoriah.Waterland@Sun.COM
1260*9781SMoriah.Waterland@Sun.COM /* return error on failure of write() */
1261*9781SMoriah.Waterland@Sun.COM if (r < 0) {
1262*9781SMoriah.Waterland@Sun.COM /* EAGAIN: try again */
1263*9781SMoriah.Waterland@Sun.COM if (errno == EAGAIN) {
1264*9781SMoriah.Waterland@Sun.COM continue;
1265*9781SMoriah.Waterland@Sun.COM }
1266*9781SMoriah.Waterland@Sun.COM /* EINTR: interrupted - try again */
1267*9781SMoriah.Waterland@Sun.COM if (errno == EINTR) {
1268*9781SMoriah.Waterland@Sun.COM continue;
1269*9781SMoriah.Waterland@Sun.COM }
1270*9781SMoriah.Waterland@Sun.COM return (r);
1271*9781SMoriah.Waterland@Sun.COM }
1272*9781SMoriah.Waterland@Sun.COM
1273*9781SMoriah.Waterland@Sun.COM /* return total bytes written on success */
1274*9781SMoriah.Waterland@Sun.COM if (r >= a_nbyte) {
1275*9781SMoriah.Waterland@Sun.COM return (bytes);
1276*9781SMoriah.Waterland@Sun.COM }
1277*9781SMoriah.Waterland@Sun.COM
1278*9781SMoriah.Waterland@Sun.COM /* partial write, adjust pointers, call write again */
1279*9781SMoriah.Waterland@Sun.COM a_buf = (void *)((ptrdiff_t)a_buf + (ptrdiff_t)r);
1280*9781SMoriah.Waterland@Sun.COM a_nbyte -= (size_t)r;
1281*9781SMoriah.Waterland@Sun.COM a_offset += (off_t)r;
1282*9781SMoriah.Waterland@Sun.COM }
1283*9781SMoriah.Waterland@Sun.COM }
1284