xref: /plan9/sys/src/ape/cmd/pax/buffer.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1*9a747e4fSDavid du Colombier /* $Source: /u/mark/src/pax/RCS/buffer.c,v $
2*9a747e4fSDavid du Colombier  *
3*9a747e4fSDavid du Colombier  * $Revision: 1.2 $
4*9a747e4fSDavid du Colombier  *
5*9a747e4fSDavid du Colombier  * buffer.c - Buffer management functions
6*9a747e4fSDavid du Colombier  *
7*9a747e4fSDavid du Colombier  * DESCRIPTION
8*9a747e4fSDavid du Colombier  *
9*9a747e4fSDavid du Colombier  *	These functions handle buffer manipulations for the archiving
10*9a747e4fSDavid du Colombier  *	formats.  Functions are provided to get memory for buffers,
11*9a747e4fSDavid du Colombier  *	flush buffers, read and write buffers and de-allocate buffers.
12*9a747e4fSDavid du Colombier  *	Several housekeeping functions are provided as well to get some
13*9a747e4fSDavid du Colombier  *	information about how full buffers are, etc.
14*9a747e4fSDavid du Colombier  *
15*9a747e4fSDavid du Colombier  * AUTHOR
16*9a747e4fSDavid du Colombier  *
17*9a747e4fSDavid du Colombier  *	Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
18*9a747e4fSDavid du Colombier  *
19*9a747e4fSDavid du Colombier  * Sponsored by The USENIX Association for public distribution.
20*9a747e4fSDavid du Colombier  *
21*9a747e4fSDavid du Colombier  * Copyright (c) 1989 Mark H. Colburn.
22*9a747e4fSDavid du Colombier  * All rights reserved.
23*9a747e4fSDavid du Colombier  *
24*9a747e4fSDavid du Colombier  * Redistribution and use in source and binary forms are permitted
25*9a747e4fSDavid du Colombier  * provided that the above copyright notice is duplicated in all such
26*9a747e4fSDavid du Colombier  * forms and that any documentation, advertising materials, and other
27*9a747e4fSDavid du Colombier  * materials related to such distribution and use acknowledge that the
28*9a747e4fSDavid du Colombier  * software was developed * by Mark H. Colburn and sponsored by The
29*9a747e4fSDavid du Colombier  * USENIX Association.
30*9a747e4fSDavid du Colombier  *
31*9a747e4fSDavid du Colombier  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
32*9a747e4fSDavid du Colombier  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
33*9a747e4fSDavid du Colombier  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
34*9a747e4fSDavid du Colombier  *
35*9a747e4fSDavid du Colombier  * $Log:	buffer.c,v $
36*9a747e4fSDavid du Colombier  * Revision 1.2  89/02/12  10:04:02  mark
37*9a747e4fSDavid du Colombier  * 1.2 release fixes
38*9a747e4fSDavid du Colombier  *
39*9a747e4fSDavid du Colombier  * Revision 1.1  88/12/23  18:02:01  mark
40*9a747e4fSDavid du Colombier  * Initial revision
41*9a747e4fSDavid du Colombier  *
42*9a747e4fSDavid du Colombier  */
43*9a747e4fSDavid du Colombier 
44*9a747e4fSDavid du Colombier #ifndef lint
45*9a747e4fSDavid du Colombier static char *ident = "$Id: buffer.c,v 1.2 89/02/12 10:04:02 mark Exp $";
46*9a747e4fSDavid du Colombier static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
47*9a747e4fSDavid du Colombier #endif /* ! lint */
48*9a747e4fSDavid du Colombier 
49*9a747e4fSDavid du Colombier 
50*9a747e4fSDavid du Colombier /* Headers */
51*9a747e4fSDavid du Colombier 
52*9a747e4fSDavid du Colombier #include "pax.h"
53*9a747e4fSDavid du Colombier 
54*9a747e4fSDavid du Colombier 
55*9a747e4fSDavid du Colombier /* Function Prototypes */
56*9a747e4fSDavid du Colombier 
57*9a747e4fSDavid du Colombier #ifdef __STDC__
58*9a747e4fSDavid du Colombier 
59*9a747e4fSDavid du Colombier static int ar_write(int, char *, uint);
60*9a747e4fSDavid du Colombier static void buf_pad(OFFSET);
61*9a747e4fSDavid du Colombier static int indata(int, OFFSET, char *);
62*9a747e4fSDavid du Colombier static void outflush(void);
63*9a747e4fSDavid du Colombier static void buf_use(uint);
64*9a747e4fSDavid du Colombier static int buf_in_avail(char **, uint *);
65*9a747e4fSDavid du Colombier static uint buf_out_avail(char **);
66*9a747e4fSDavid du Colombier 
67*9a747e4fSDavid du Colombier #else /* !__STDC__ */
68*9a747e4fSDavid du Colombier 
69*9a747e4fSDavid du Colombier static int ar_write();
70*9a747e4fSDavid du Colombier static void buf_pad();
71*9a747e4fSDavid du Colombier static int indata();
72*9a747e4fSDavid du Colombier static void outflush();
73*9a747e4fSDavid du Colombier static void buf_use();
74*9a747e4fSDavid du Colombier static int buf_in_avail();
75*9a747e4fSDavid du Colombier static uint buf_out_avail();
76*9a747e4fSDavid du Colombier 
77*9a747e4fSDavid du Colombier #endif /* __STDC__ */
78*9a747e4fSDavid du Colombier 
79*9a747e4fSDavid du Colombier 
80*9a747e4fSDavid du Colombier /* inentry - install a single archive entry
81*9a747e4fSDavid du Colombier  *
82*9a747e4fSDavid du Colombier  * DESCRIPTION
83*9a747e4fSDavid du Colombier  *
84*9a747e4fSDavid du Colombier  *	Inentry reads an archive entry from the archive file and writes it
85*9a747e4fSDavid du Colombier  *	out the the named file.  If we are in PASS mode during archive
86*9a747e4fSDavid du Colombier  *	processing, the pass() function is called, otherwise we will
87*9a747e4fSDavid du Colombier  *	extract from the archive file.
88*9a747e4fSDavid du Colombier  *
89*9a747e4fSDavid du Colombier  *	Inentry actaully calls indata to process the actual data to the
90*9a747e4fSDavid du Colombier  *	file.
91*9a747e4fSDavid du Colombier  *
92*9a747e4fSDavid du Colombier  * PARAMETERS
93*9a747e4fSDavid du Colombier  *
94*9a747e4fSDavid du Colombier  *	char	*name	- name of the file to extract from the archive
95*9a747e4fSDavid du Colombier  *	Stat	*asb	- stat block of the file to be extracted from the
96*9a747e4fSDavid du Colombier  *			  archive.
97*9a747e4fSDavid du Colombier  *
98*9a747e4fSDavid du Colombier  * RETURNS
99*9a747e4fSDavid du Colombier  *
100*9a747e4fSDavid du Colombier  * 	Returns zero if successful, -1 otherwise.
101*9a747e4fSDavid du Colombier  */
102*9a747e4fSDavid du Colombier 
103*9a747e4fSDavid du Colombier #ifdef __STDC__
104*9a747e4fSDavid du Colombier 
inentry(char * name,Stat * asb)105*9a747e4fSDavid du Colombier int inentry(char *name, Stat *asb)
106*9a747e4fSDavid du Colombier 
107*9a747e4fSDavid du Colombier #else
108*9a747e4fSDavid du Colombier 
109*9a747e4fSDavid du Colombier int inentry(name, asb)
110*9a747e4fSDavid du Colombier char           *name;
111*9a747e4fSDavid du Colombier Stat           *asb;
112*9a747e4fSDavid du Colombier 
113*9a747e4fSDavid du Colombier #endif
114*9a747e4fSDavid du Colombier {
115*9a747e4fSDavid du Colombier     Link           *linkp;
116*9a747e4fSDavid du Colombier     int             ifd;
117*9a747e4fSDavid du Colombier     int             ofd;
118*9a747e4fSDavid du Colombier     time_t          tstamp[2];
119*9a747e4fSDavid du Colombier 
120*9a747e4fSDavid du Colombier     if ((ofd = openout(name, asb, linkp = linkfrom(name, asb), 0)) > 0) {
121*9a747e4fSDavid du Colombier 	if (asb->sb_size || linkp == (Link *)NULL || linkp->l_size == 0) {
122*9a747e4fSDavid du Colombier 	    close(indata(ofd, asb->sb_size, name));
123*9a747e4fSDavid du Colombier 	} else if ((ifd = open(linkp->l_path->p_name, O_RDONLY)) < 0) {
124*9a747e4fSDavid du Colombier 	    warn(linkp->l_path->p_name, strerror());
125*9a747e4fSDavid du Colombier 	} else {
126*9a747e4fSDavid du Colombier 	    passdata(linkp->l_path->p_name, ifd, name, ofd);
127*9a747e4fSDavid du Colombier 	    close(ifd);
128*9a747e4fSDavid du Colombier 	    close(ofd);
129*9a747e4fSDavid du Colombier 	}
130*9a747e4fSDavid du Colombier     } else {
131*9a747e4fSDavid du Colombier 	return(buf_skip((OFFSET) asb->sb_size) >= 0);
132*9a747e4fSDavid du Colombier     }
133*9a747e4fSDavid du Colombier     tstamp[0] = (!f_pass && f_access_time) ? asb->sb_atime : time((time_t *) 0);
134*9a747e4fSDavid du Colombier     tstamp[1] = f_mtime ? asb->sb_mtime : time((time_t *) 0);
135*9a747e4fSDavid du Colombier     utime(name, tstamp);
136*9a747e4fSDavid du Colombier     return (0);
137*9a747e4fSDavid du Colombier }
138*9a747e4fSDavid du Colombier 
139*9a747e4fSDavid du Colombier 
140*9a747e4fSDavid du Colombier /* outdata - write archive data
141*9a747e4fSDavid du Colombier  *
142*9a747e4fSDavid du Colombier  * DESCRIPTION
143*9a747e4fSDavid du Colombier  *
144*9a747e4fSDavid du Colombier  *	Outdata transfers data from the named file to the archive buffer.
145*9a747e4fSDavid du Colombier  *	It knows about the file padding which is required by tar, but no
146*9a747e4fSDavid du Colombier  *	by cpio.  Outdata continues after file read errors, padding with
147*9a747e4fSDavid du Colombier  *	null characters if neccessary.   Closes the input file descriptor
148*9a747e4fSDavid du Colombier  *	when finished.
149*9a747e4fSDavid du Colombier  *
150*9a747e4fSDavid du Colombier  * PARAMETERS
151*9a747e4fSDavid du Colombier  *
152*9a747e4fSDavid du Colombier  *	int	fd	- file descriptor of file to read data from
153*9a747e4fSDavid du Colombier  *	char   *name	- name of file
154*9a747e4fSDavid du Colombier  *	OFFSET	size	- size of the file
155*9a747e4fSDavid du Colombier  *
156*9a747e4fSDavid du Colombier  */
157*9a747e4fSDavid du Colombier 
158*9a747e4fSDavid du Colombier #ifdef __STDC__
159*9a747e4fSDavid du Colombier 
outdata(int fd,char * name,OFFSET size)160*9a747e4fSDavid du Colombier void outdata(int fd, char *name, OFFSET size)
161*9a747e4fSDavid du Colombier 
162*9a747e4fSDavid du Colombier #else
163*9a747e4fSDavid du Colombier 
164*9a747e4fSDavid du Colombier void outdata(fd, name, size)
165*9a747e4fSDavid du Colombier int             fd;
166*9a747e4fSDavid du Colombier char           *name;
167*9a747e4fSDavid du Colombier OFFSET          size;
168*9a747e4fSDavid du Colombier 
169*9a747e4fSDavid du Colombier #endif
170*9a747e4fSDavid du Colombier {
171*9a747e4fSDavid du Colombier     uint            chunk;
172*9a747e4fSDavid du Colombier     int             got;
173*9a747e4fSDavid du Colombier     int             oops;
174*9a747e4fSDavid du Colombier     uint            avail;
175*9a747e4fSDavid du Colombier     int		    pad;
176*9a747e4fSDavid du Colombier     char           *buf;
177*9a747e4fSDavid du Colombier 
178*9a747e4fSDavid du Colombier     oops = got = 0;
179*9a747e4fSDavid du Colombier     if (pad = (size % BLOCKSIZE)) {
180*9a747e4fSDavid du Colombier 	pad = (BLOCKSIZE - pad);
181*9a747e4fSDavid du Colombier     }
182*9a747e4fSDavid du Colombier     while (size) {
183*9a747e4fSDavid du Colombier 	avail = buf_out_avail(&buf);
184*9a747e4fSDavid du Colombier 	size -= (chunk = size < avail ? (uint) size : avail);
185*9a747e4fSDavid du Colombier 	if (oops == 0 && (got = read(fd, buf, (unsigned int) chunk)) < 0) {
186*9a747e4fSDavid du Colombier 	    oops = -1;
187*9a747e4fSDavid du Colombier 	    warn(name, strerror());
188*9a747e4fSDavid du Colombier 	    got = 0;
189*9a747e4fSDavid du Colombier 	}
190*9a747e4fSDavid du Colombier 	if (got < chunk) {
191*9a747e4fSDavid du Colombier 	    if (oops == 0) {
192*9a747e4fSDavid du Colombier 		oops = -1;
193*9a747e4fSDavid du Colombier 	    }
194*9a747e4fSDavid du Colombier 	    warn(name, "Early EOF");
195*9a747e4fSDavid du Colombier 	    while (got < chunk) {
196*9a747e4fSDavid du Colombier 		buf[got++] = '\0';
197*9a747e4fSDavid du Colombier 	    }
198*9a747e4fSDavid du Colombier 	}
199*9a747e4fSDavid du Colombier 	buf_use(chunk);
200*9a747e4fSDavid du Colombier     }
201*9a747e4fSDavid du Colombier     close(fd);
202*9a747e4fSDavid du Colombier     if (ar_format == TAR) {
203*9a747e4fSDavid du Colombier 	buf_pad((OFFSET) pad);
204*9a747e4fSDavid du Colombier     }
205*9a747e4fSDavid du Colombier }
206*9a747e4fSDavid du Colombier 
207*9a747e4fSDavid du Colombier 
208*9a747e4fSDavid du Colombier /* write_eot -  write the end of archive record(s)
209*9a747e4fSDavid du Colombier  *
210*9a747e4fSDavid du Colombier  * DESCRIPTION
211*9a747e4fSDavid du Colombier  *
212*9a747e4fSDavid du Colombier  *	Write out an End-Of-Tape record.  We actually zero at least one
213*9a747e4fSDavid du Colombier  *	record, through the end of the block.  Old tar writes garbage after
214*9a747e4fSDavid du Colombier  *	two zeroed records -- and PDtar used to.
215*9a747e4fSDavid du Colombier  */
216*9a747e4fSDavid du Colombier 
217*9a747e4fSDavid du Colombier #ifdef __STDC__
218*9a747e4fSDavid du Colombier 
write_eot(void)219*9a747e4fSDavid du Colombier void write_eot(void)
220*9a747e4fSDavid du Colombier 
221*9a747e4fSDavid du Colombier #else
222*9a747e4fSDavid du Colombier 
223*9a747e4fSDavid du Colombier void write_eot()
224*9a747e4fSDavid du Colombier 
225*9a747e4fSDavid du Colombier #endif
226*9a747e4fSDavid du Colombier {
227*9a747e4fSDavid du Colombier     OFFSET           pad;
228*9a747e4fSDavid du Colombier     char            header[M_STRLEN + H_STRLEN + 1];
229*9a747e4fSDavid du Colombier 
230*9a747e4fSDavid du Colombier     if (ar_format == TAR) {
231*9a747e4fSDavid du Colombier 	/* write out two zero blocks for trailer */
232*9a747e4fSDavid du Colombier 	pad = 2 * BLOCKSIZE;
233*9a747e4fSDavid du Colombier     } else {
234*9a747e4fSDavid du Colombier 	if (pad = (total + M_STRLEN + H_STRLEN + TRAILZ) % BLOCKSIZE) {
235*9a747e4fSDavid du Colombier 	    pad = BLOCKSIZE - pad;
236*9a747e4fSDavid du Colombier 	}
237*9a747e4fSDavid du Colombier 	strcpy(header, M_ASCII);
238*9a747e4fSDavid du Colombier 	sprintf(header + M_STRLEN, H_PRINT, 0, 0,
239*9a747e4fSDavid du Colombier 		       0, 0, 0, 1, 0, (time_t) 0, TRAILZ, pad);
240*9a747e4fSDavid du Colombier 	outwrite(header, M_STRLEN + H_STRLEN);
241*9a747e4fSDavid du Colombier 	outwrite(TRAILER, TRAILZ);
242*9a747e4fSDavid du Colombier     }
243*9a747e4fSDavid du Colombier     buf_pad((OFFSET) pad);
244*9a747e4fSDavid du Colombier     outflush();
245*9a747e4fSDavid du Colombier }
246*9a747e4fSDavid du Colombier 
247*9a747e4fSDavid du Colombier 
248*9a747e4fSDavid du Colombier /* outwrite -  write archive data
249*9a747e4fSDavid du Colombier  *
250*9a747e4fSDavid du Colombier  * DESCRIPTION
251*9a747e4fSDavid du Colombier  *
252*9a747e4fSDavid du Colombier  *	Writes out data in the archive buffer to the archive file.  The
253*9a747e4fSDavid du Colombier  *	buffer index and the total byte count are incremented by the number
254*9a747e4fSDavid du Colombier  *	of data bytes written.
255*9a747e4fSDavid du Colombier  *
256*9a747e4fSDavid du Colombier  * PARAMETERS
257*9a747e4fSDavid du Colombier  *
258*9a747e4fSDavid du Colombier  *	char   *idx	- pointer to data to write
259*9a747e4fSDavid du Colombier  *	uint	len	- length of the data to write
260*9a747e4fSDavid du Colombier  */
261*9a747e4fSDavid du Colombier 
262*9a747e4fSDavid du Colombier #ifdef __STDC__
263*9a747e4fSDavid du Colombier 
outwrite(char * idx,uint len)264*9a747e4fSDavid du Colombier void outwrite(char *idx, uint len)
265*9a747e4fSDavid du Colombier 
266*9a747e4fSDavid du Colombier #else
267*9a747e4fSDavid du Colombier 
268*9a747e4fSDavid du Colombier void outwrite(idx, len)
269*9a747e4fSDavid du Colombier char           *idx;	/* pointer to data to write */
270*9a747e4fSDavid du Colombier uint            len;	/* length of data to write */
271*9a747e4fSDavid du Colombier 
272*9a747e4fSDavid du Colombier #endif
273*9a747e4fSDavid du Colombier {
274*9a747e4fSDavid du Colombier     uint            have;
275*9a747e4fSDavid du Colombier     uint            want;
276*9a747e4fSDavid du Colombier     char           *endx;
277*9a747e4fSDavid du Colombier 
278*9a747e4fSDavid du Colombier     endx = idx + len;
279*9a747e4fSDavid du Colombier     while (want = endx - idx) {
280*9a747e4fSDavid du Colombier 	if (bufend - bufidx < 0) {
281*9a747e4fSDavid du Colombier 	    fatal("Buffer overlow in out_write\n");
282*9a747e4fSDavid du Colombier 	}
283*9a747e4fSDavid du Colombier 	if ((have = bufend - bufidx) == 0) {
284*9a747e4fSDavid du Colombier 	    outflush();
285*9a747e4fSDavid du Colombier 	}
286*9a747e4fSDavid du Colombier 	if (have > want) {
287*9a747e4fSDavid du Colombier 	    have = want;
288*9a747e4fSDavid du Colombier 	}
289*9a747e4fSDavid du Colombier 	memcpy(bufidx, idx, (int) have);
290*9a747e4fSDavid du Colombier 	bufidx += have;
291*9a747e4fSDavid du Colombier 	idx += have;
292*9a747e4fSDavid du Colombier 	total += have;
293*9a747e4fSDavid du Colombier     }
294*9a747e4fSDavid du Colombier }
295*9a747e4fSDavid du Colombier 
296*9a747e4fSDavid du Colombier 
297*9a747e4fSDavid du Colombier /* passdata - copy data to one file
298*9a747e4fSDavid du Colombier  *
299*9a747e4fSDavid du Colombier  * DESCRIPTION
300*9a747e4fSDavid du Colombier  *
301*9a747e4fSDavid du Colombier  *	Copies a file from one place to another.  Doesn't believe in input
302*9a747e4fSDavid du Colombier  *	file descriptor zero (see description of kludge in openin() comments).
303*9a747e4fSDavid du Colombier  *	Closes the provided output file descriptor.
304*9a747e4fSDavid du Colombier  *
305*9a747e4fSDavid du Colombier  * PARAMETERS
306*9a747e4fSDavid du Colombier  *
307*9a747e4fSDavid du Colombier  *	char	*from	- input file name (old file)
308*9a747e4fSDavid du Colombier  *	int	ifd	- input file descriptor
309*9a747e4fSDavid du Colombier  *	char	*to	- output file name (new file)
310*9a747e4fSDavid du Colombier  *	int	ofd	- output file descriptor
311*9a747e4fSDavid du Colombier  */
312*9a747e4fSDavid du Colombier 
313*9a747e4fSDavid du Colombier #ifdef __STDC__
314*9a747e4fSDavid du Colombier 
passdata(char * from,int ifd,char * to,int ofd)315*9a747e4fSDavid du Colombier void passdata(char *from, int ifd, char *to, int ofd)
316*9a747e4fSDavid du Colombier 
317*9a747e4fSDavid du Colombier #else
318*9a747e4fSDavid du Colombier 
319*9a747e4fSDavid du Colombier void passdata(from, ifd, to, ofd)
320*9a747e4fSDavid du Colombier char           *from;
321*9a747e4fSDavid du Colombier int             ifd;
322*9a747e4fSDavid du Colombier char           *to;
323*9a747e4fSDavid du Colombier int             ofd;
324*9a747e4fSDavid du Colombier 
325*9a747e4fSDavid du Colombier #endif
326*9a747e4fSDavid du Colombier {
327*9a747e4fSDavid du Colombier     int             got;
328*9a747e4fSDavid du Colombier     int             sparse;
329*9a747e4fSDavid du Colombier     char            block[BUFSIZ];
330*9a747e4fSDavid du Colombier 
331*9a747e4fSDavid du Colombier     if (ifd) {
332*9a747e4fSDavid du Colombier 	lseek(ifd, (OFFSET) 0, 0);
333*9a747e4fSDavid du Colombier 	sparse = 0;
334*9a747e4fSDavid du Colombier 	while ((got = read(ifd, block, sizeof(block))) > 0
335*9a747e4fSDavid du Colombier 	       && (sparse = ar_write(ofd, block, (uint) got)) >= 0) {
336*9a747e4fSDavid du Colombier 	    total += got;
337*9a747e4fSDavid du Colombier 	}
338*9a747e4fSDavid du Colombier 	if (got) {
339*9a747e4fSDavid du Colombier 	    warn(got < 0 ? from : to, strerror());
340*9a747e4fSDavid du Colombier 	} else if (sparse > 0
341*9a747e4fSDavid du Colombier 		 && (lseek(ofd, (OFFSET)(-sparse), 1) < 0
342*9a747e4fSDavid du Colombier 		     || write(ofd, block, (uint) sparse) != sparse)) {
343*9a747e4fSDavid du Colombier 	    warn(to, strerror());
344*9a747e4fSDavid du Colombier 	}
345*9a747e4fSDavid du Colombier     }
346*9a747e4fSDavid du Colombier     close(ofd);
347*9a747e4fSDavid du Colombier }
348*9a747e4fSDavid du Colombier 
349*9a747e4fSDavid du Colombier 
350*9a747e4fSDavid du Colombier /* buf_allocate - get space for the I/O buffer
351*9a747e4fSDavid du Colombier  *
352*9a747e4fSDavid du Colombier  * DESCRIPTION
353*9a747e4fSDavid du Colombier  *
354*9a747e4fSDavid du Colombier  *	buf_allocate allocates an I/O buffer using malloc.  The resulting
355*9a747e4fSDavid du Colombier  *	buffer is used for all data buffering throughout the program.
356*9a747e4fSDavid du Colombier  *	Buf_allocate must be called prior to any use of the buffer or any
357*9a747e4fSDavid du Colombier  *	of the buffering calls.
358*9a747e4fSDavid du Colombier  *
359*9a747e4fSDavid du Colombier  * PARAMETERS
360*9a747e4fSDavid du Colombier  *
361*9a747e4fSDavid du Colombier  *	int	size	- size of the I/O buffer to request
362*9a747e4fSDavid du Colombier  *
363*9a747e4fSDavid du Colombier  * ERRORS
364*9a747e4fSDavid du Colombier  *
365*9a747e4fSDavid du Colombier  *	If an invalid size is given for a buffer or if a buffer of the
366*9a747e4fSDavid du Colombier  *	required size cannot be allocated, then the function prints out an
367*9a747e4fSDavid du Colombier  *	error message and returns a non-zero exit status to the calling
368*9a747e4fSDavid du Colombier  *	process, terminating the program.
369*9a747e4fSDavid du Colombier  *
370*9a747e4fSDavid du Colombier  */
371*9a747e4fSDavid du Colombier 
372*9a747e4fSDavid du Colombier #ifdef __STDC__
373*9a747e4fSDavid du Colombier 
buf_allocate(OFFSET size)374*9a747e4fSDavid du Colombier void buf_allocate(OFFSET size)
375*9a747e4fSDavid du Colombier 
376*9a747e4fSDavid du Colombier #else
377*9a747e4fSDavid du Colombier 
378*9a747e4fSDavid du Colombier void buf_allocate(size)
379*9a747e4fSDavid du Colombier OFFSET            size;
380*9a747e4fSDavid du Colombier 
381*9a747e4fSDavid du Colombier #endif
382*9a747e4fSDavid du Colombier {
383*9a747e4fSDavid du Colombier     if (size <= 0) {
384*9a747e4fSDavid du Colombier 	fatal("invalid value for blocksize");
385*9a747e4fSDavid du Colombier     }
386*9a747e4fSDavid du Colombier     if ((bufstart = malloc((unsigned) size)) == (char *)NULL) {
387*9a747e4fSDavid du Colombier 	fatal("Cannot allocate I/O buffer");
388*9a747e4fSDavid du Colombier     }
389*9a747e4fSDavid du Colombier     bufend = bufidx = bufstart;
390*9a747e4fSDavid du Colombier     bufend += size;
391*9a747e4fSDavid du Colombier }
392*9a747e4fSDavid du Colombier 
393*9a747e4fSDavid du Colombier 
394*9a747e4fSDavid du Colombier /* buf_skip - skip input archive data
395*9a747e4fSDavid du Colombier  *
396*9a747e4fSDavid du Colombier  * DESCRIPTION
397*9a747e4fSDavid du Colombier  *
398*9a747e4fSDavid du Colombier  *	Buf_skip skips past archive data.  It is used when the length of
399*9a747e4fSDavid du Colombier  *	the archive data is known, and we do not wish to process the data.
400*9a747e4fSDavid du Colombier  *
401*9a747e4fSDavid du Colombier  * PARAMETERS
402*9a747e4fSDavid du Colombier  *
403*9a747e4fSDavid du Colombier  *	OFFSET	len	- number of bytes to skip
404*9a747e4fSDavid du Colombier  *
405*9a747e4fSDavid du Colombier  * RETURNS
406*9a747e4fSDavid du Colombier  *
407*9a747e4fSDavid du Colombier  * 	Returns zero under normal circumstances, -1 if unreadable data is
408*9a747e4fSDavid du Colombier  * 	encountered.
409*9a747e4fSDavid du Colombier  */
410*9a747e4fSDavid du Colombier 
411*9a747e4fSDavid du Colombier #ifdef __STDC__
412*9a747e4fSDavid du Colombier 
buf_skip(OFFSET len)413*9a747e4fSDavid du Colombier int buf_skip(OFFSET len)
414*9a747e4fSDavid du Colombier 
415*9a747e4fSDavid du Colombier #else
416*9a747e4fSDavid du Colombier 
417*9a747e4fSDavid du Colombier int buf_skip(len)
418*9a747e4fSDavid du Colombier OFFSET           len;
419*9a747e4fSDavid du Colombier 
420*9a747e4fSDavid du Colombier #endif
421*9a747e4fSDavid du Colombier {
422*9a747e4fSDavid du Colombier     uint            chunk;
423*9a747e4fSDavid du Colombier     int             corrupt = 0;
424*9a747e4fSDavid du Colombier 
425*9a747e4fSDavid du Colombier     while (len) {
426*9a747e4fSDavid du Colombier 	if (bufend - bufidx < 0) {
427*9a747e4fSDavid du Colombier 	    fatal("Buffer overlow in buf_skip\n");
428*9a747e4fSDavid du Colombier 	}
429*9a747e4fSDavid du Colombier 	while ((chunk = bufend - bufidx) == 0) {
430*9a747e4fSDavid du Colombier 	    corrupt |= ar_read();
431*9a747e4fSDavid du Colombier 	}
432*9a747e4fSDavid du Colombier 	if (chunk > len) {
433*9a747e4fSDavid du Colombier 	    chunk = len;
434*9a747e4fSDavid du Colombier 	}
435*9a747e4fSDavid du Colombier 	bufidx += chunk;
436*9a747e4fSDavid du Colombier 	len -= chunk;
437*9a747e4fSDavid du Colombier 	total += chunk;
438*9a747e4fSDavid du Colombier     }
439*9a747e4fSDavid du Colombier     return (corrupt);
440*9a747e4fSDavid du Colombier }
441*9a747e4fSDavid du Colombier 
442*9a747e4fSDavid du Colombier 
443*9a747e4fSDavid du Colombier /* buf_read - read a given number of characters from the input archive
444*9a747e4fSDavid du Colombier  *
445*9a747e4fSDavid du Colombier  * DESCRIPTION
446*9a747e4fSDavid du Colombier  *
447*9a747e4fSDavid du Colombier  *	Reads len number of characters from the input archive and
448*9a747e4fSDavid du Colombier  *	stores them in the buffer pointed at by dst.
449*9a747e4fSDavid du Colombier  *
450*9a747e4fSDavid du Colombier  * PARAMETERS
451*9a747e4fSDavid du Colombier  *
452*9a747e4fSDavid du Colombier  *	char   *dst	- pointer to buffer to store data into
453*9a747e4fSDavid du Colombier  *	uint	len	- length of data to read
454*9a747e4fSDavid du Colombier  *
455*9a747e4fSDavid du Colombier  * RETURNS
456*9a747e4fSDavid du Colombier  *
457*9a747e4fSDavid du Colombier  * 	Returns zero with valid data, -1 if unreadable portions were
458*9a747e4fSDavid du Colombier  *	replaced by null characters.
459*9a747e4fSDavid du Colombier  */
460*9a747e4fSDavid du Colombier 
461*9a747e4fSDavid du Colombier #ifdef __STDC__
462*9a747e4fSDavid du Colombier 
buf_read(char * dst,uint len)463*9a747e4fSDavid du Colombier int buf_read(char *dst, uint len)
464*9a747e4fSDavid du Colombier 
465*9a747e4fSDavid du Colombier #else
466*9a747e4fSDavid du Colombier 
467*9a747e4fSDavid du Colombier int buf_read(dst, len)
468*9a747e4fSDavid du Colombier char           *dst;
469*9a747e4fSDavid du Colombier uint            len;
470*9a747e4fSDavid du Colombier 
471*9a747e4fSDavid du Colombier #endif
472*9a747e4fSDavid du Colombier {
473*9a747e4fSDavid du Colombier     int             have;
474*9a747e4fSDavid du Colombier     int             want;
475*9a747e4fSDavid du Colombier     int             corrupt = 0;
476*9a747e4fSDavid du Colombier     char           *endx = dst + len;
477*9a747e4fSDavid du Colombier 
478*9a747e4fSDavid du Colombier     while (want = endx - dst) {
479*9a747e4fSDavid du Colombier 	if (bufend - bufidx < 0) {
480*9a747e4fSDavid du Colombier 	    fatal("Buffer overlow in buf_read\n");
481*9a747e4fSDavid du Colombier 	}
482*9a747e4fSDavid du Colombier 	while ((have = bufend - bufidx) == 0) {
483*9a747e4fSDavid du Colombier 	    have = 0;
484*9a747e4fSDavid du Colombier 	    corrupt |= ar_read();
485*9a747e4fSDavid du Colombier 	}
486*9a747e4fSDavid du Colombier 	if (have > want) {
487*9a747e4fSDavid du Colombier 	    have = want;
488*9a747e4fSDavid du Colombier 	}
489*9a747e4fSDavid du Colombier 	memcpy(dst, bufidx, have);
490*9a747e4fSDavid du Colombier 	bufidx += have;
491*9a747e4fSDavid du Colombier 	dst += have;
492*9a747e4fSDavid du Colombier 	total += have;
493*9a747e4fSDavid du Colombier     }
494*9a747e4fSDavid du Colombier     return (corrupt);
495*9a747e4fSDavid du Colombier }
496*9a747e4fSDavid du Colombier 
497*9a747e4fSDavid du Colombier 
498*9a747e4fSDavid du Colombier /* indata - install data from an archive
499*9a747e4fSDavid du Colombier  *
500*9a747e4fSDavid du Colombier  * DESCRIPTION
501*9a747e4fSDavid du Colombier  *
502*9a747e4fSDavid du Colombier  *	Indata writes size bytes of data from the archive buffer to the output
503*9a747e4fSDavid du Colombier  *	file specified by fd.  The filename which is being written, pointed
504*9a747e4fSDavid du Colombier  *	to by name is provided only for diagnostics.
505*9a747e4fSDavid du Colombier  *
506*9a747e4fSDavid du Colombier  * PARAMETERS
507*9a747e4fSDavid du Colombier  *
508*9a747e4fSDavid du Colombier  *	int	fd	- output file descriptor
509*9a747e4fSDavid du Colombier  *	OFFSET	size	- number of bytes to write to output file
510*9a747e4fSDavid du Colombier  *	char	*name	- name of file which corresponds to fd
511*9a747e4fSDavid du Colombier  *
512*9a747e4fSDavid du Colombier  * RETURNS
513*9a747e4fSDavid du Colombier  *
514*9a747e4fSDavid du Colombier  * 	Returns given file descriptor.
515*9a747e4fSDavid du Colombier  */
516*9a747e4fSDavid du Colombier 
517*9a747e4fSDavid du Colombier #ifdef __STDC__
518*9a747e4fSDavid du Colombier 
indata(int fd,OFFSET size,char * name)519*9a747e4fSDavid du Colombier static int indata(int fd, OFFSET size, char *name)
520*9a747e4fSDavid du Colombier 
521*9a747e4fSDavid du Colombier #else
522*9a747e4fSDavid du Colombier 
523*9a747e4fSDavid du Colombier static int indata(fd, size, name)
524*9a747e4fSDavid du Colombier int             fd;
525*9a747e4fSDavid du Colombier OFFSET          size;
526*9a747e4fSDavid du Colombier char           *name;
527*9a747e4fSDavid du Colombier 
528*9a747e4fSDavid du Colombier #endif
529*9a747e4fSDavid du Colombier {
530*9a747e4fSDavid du Colombier     uint            chunk;
531*9a747e4fSDavid du Colombier     char           *oops;
532*9a747e4fSDavid du Colombier     int             sparse;
533*9a747e4fSDavid du Colombier     int             corrupt;
534*9a747e4fSDavid du Colombier     char           *buf;
535*9a747e4fSDavid du Colombier     uint            avail;
536*9a747e4fSDavid du Colombier 
537*9a747e4fSDavid du Colombier     corrupt = sparse = 0;
538*9a747e4fSDavid du Colombier     oops = (char *)NULL;
539*9a747e4fSDavid du Colombier     while (size) {
540*9a747e4fSDavid du Colombier 	corrupt |= buf_in_avail(&buf, &avail);
541*9a747e4fSDavid du Colombier 	size -= (chunk = size < avail ? (uint) size : avail);
542*9a747e4fSDavid du Colombier 	if (oops == (char *)NULL && (sparse = ar_write(fd, buf, chunk)) < 0) {
543*9a747e4fSDavid du Colombier 	    oops = strerror();
544*9a747e4fSDavid du Colombier 	}
545*9a747e4fSDavid du Colombier 	buf_use(chunk);
546*9a747e4fSDavid du Colombier     }
547*9a747e4fSDavid du Colombier     if (corrupt) {
548*9a747e4fSDavid du Colombier 	warn(name, "Corrupt archive data");
549*9a747e4fSDavid du Colombier     }
550*9a747e4fSDavid du Colombier     if (oops) {
551*9a747e4fSDavid du Colombier 	warn(name, oops);
552*9a747e4fSDavid du Colombier     } else if (sparse > 0 && (lseek(fd, (OFFSET) - 1, 1) < 0
553*9a747e4fSDavid du Colombier 			      || write(fd, "", 1) != 1)) {
554*9a747e4fSDavid du Colombier 	warn(name, strerror());
555*9a747e4fSDavid du Colombier     }
556*9a747e4fSDavid du Colombier     return (fd);
557*9a747e4fSDavid du Colombier }
558*9a747e4fSDavid du Colombier 
559*9a747e4fSDavid du Colombier 
560*9a747e4fSDavid du Colombier /* outflush - flush the output buffer
561*9a747e4fSDavid du Colombier  *
562*9a747e4fSDavid du Colombier  * DESCRIPTION
563*9a747e4fSDavid du Colombier  *
564*9a747e4fSDavid du Colombier  *	The output buffer is written, if there is anything in it, to the
565*9a747e4fSDavid du Colombier  *	archive file.
566*9a747e4fSDavid du Colombier  */
567*9a747e4fSDavid du Colombier 
568*9a747e4fSDavid du Colombier #ifdef __STDC__
569*9a747e4fSDavid du Colombier 
outflush(void)570*9a747e4fSDavid du Colombier static void outflush(void)
571*9a747e4fSDavid du Colombier 
572*9a747e4fSDavid du Colombier #else
573*9a747e4fSDavid du Colombier 
574*9a747e4fSDavid du Colombier static void outflush()
575*9a747e4fSDavid du Colombier 
576*9a747e4fSDavid du Colombier #endif
577*9a747e4fSDavid du Colombier {
578*9a747e4fSDavid du Colombier     char           *buf;
579*9a747e4fSDavid du Colombier     int             got;
580*9a747e4fSDavid du Colombier     uint            len;
581*9a747e4fSDavid du Colombier 
582*9a747e4fSDavid du Colombier     /* if (bufidx - buf > 0) */
583*9a747e4fSDavid du Colombier 	for (buf = bufstart; len = bufidx - buf;) {
584*9a747e4fSDavid du Colombier 	    if ((got = write(archivefd, buf, MIN(len, blocksize))) > 0) {
585*9a747e4fSDavid du Colombier 		buf += got;
586*9a747e4fSDavid du Colombier 	    } else if (got < 0) {
587*9a747e4fSDavid du Colombier 		next(AR_WRITE);
588*9a747e4fSDavid du Colombier 	    }
589*9a747e4fSDavid du Colombier 	}
590*9a747e4fSDavid du Colombier     bufend = (bufidx = bufstart) + blocksize;
591*9a747e4fSDavid du Colombier }
592*9a747e4fSDavid du Colombier 
593*9a747e4fSDavid du Colombier 
594*9a747e4fSDavid du Colombier /* ar_read - fill the archive buffer
595*9a747e4fSDavid du Colombier  *
596*9a747e4fSDavid du Colombier  * DESCRIPTION
597*9a747e4fSDavid du Colombier  *
598*9a747e4fSDavid du Colombier  * 	Remembers mid-buffer read failures and reports them the next time
599*9a747e4fSDavid du Colombier  *	through.  Replaces unreadable data with null characters.   Resets
600*9a747e4fSDavid du Colombier  *	the buffer pointers as appropriate.
601*9a747e4fSDavid du Colombier  *
602*9a747e4fSDavid du Colombier  * RETURNS
603*9a747e4fSDavid du Colombier  *
604*9a747e4fSDavid du Colombier  *	Returns zero with valid data, -1 otherwise.
605*9a747e4fSDavid du Colombier  */
606*9a747e4fSDavid du Colombier 
607*9a747e4fSDavid du Colombier #ifdef __STDC__
608*9a747e4fSDavid du Colombier 
ar_read(void)609*9a747e4fSDavid du Colombier int ar_read(void)
610*9a747e4fSDavid du Colombier 
611*9a747e4fSDavid du Colombier #else
612*9a747e4fSDavid du Colombier 
613*9a747e4fSDavid du Colombier int ar_read()
614*9a747e4fSDavid du Colombier 
615*9a747e4fSDavid du Colombier #endif
616*9a747e4fSDavid du Colombier {
617*9a747e4fSDavid du Colombier     int             got;
618*9a747e4fSDavid du Colombier     static int      failed;
619*9a747e4fSDavid du Colombier 
620*9a747e4fSDavid du Colombier     bufend = bufidx = bufstart;
621*9a747e4fSDavid du Colombier     if (!failed) {
622*9a747e4fSDavid du Colombier 	if (areof) {
623*9a747e4fSDavid du Colombier 	    if (total == 0) {
624*9a747e4fSDavid du Colombier 		fatal("No input");
625*9a747e4fSDavid du Colombier 	    } else {
626*9a747e4fSDavid du Colombier 		next(AR_READ);
627*9a747e4fSDavid du Colombier 	    }
628*9a747e4fSDavid du Colombier 	}
629*9a747e4fSDavid du Colombier 	while (!failed && !areof && bufstart + blocksize - bufend >= blocksize) {
630*9a747e4fSDavid du Colombier 	    if ((got = read(archivefd, bufend, (unsigned int) blocksize)) > 0) {
631*9a747e4fSDavid du Colombier 		bufend += got;
632*9a747e4fSDavid du Colombier 	    } else if (got < 0) {
633*9a747e4fSDavid du Colombier 		failed = -1;
634*9a747e4fSDavid du Colombier 		warnarch(strerror(), (OFFSET) 0 - (bufend - bufidx));
635*9a747e4fSDavid du Colombier 	    } else {
636*9a747e4fSDavid du Colombier 		++areof;
637*9a747e4fSDavid du Colombier 	    }
638*9a747e4fSDavid du Colombier 	}
639*9a747e4fSDavid du Colombier     }
640*9a747e4fSDavid du Colombier     if (failed && bufend == bufstart) {
641*9a747e4fSDavid du Colombier 	failed = 0;
642*9a747e4fSDavid du Colombier 	for (got = 0; got < blocksize; ++got) {
643*9a747e4fSDavid du Colombier 	    *bufend++ = '\0';
644*9a747e4fSDavid du Colombier 	}
645*9a747e4fSDavid du Colombier 	return (-1);
646*9a747e4fSDavid du Colombier     }
647*9a747e4fSDavid du Colombier     return (0);
648*9a747e4fSDavid du Colombier }
649*9a747e4fSDavid du Colombier 
650*9a747e4fSDavid du Colombier 
651*9a747e4fSDavid du Colombier /* ar_write - write a filesystem block
652*9a747e4fSDavid du Colombier  *
653*9a747e4fSDavid du Colombier  * DESCRIPTION
654*9a747e4fSDavid du Colombier  *
655*9a747e4fSDavid du Colombier  * 	Writes len bytes of data data from the specified buffer to the
656*9a747e4fSDavid du Colombier  *	specified file.   Seeks past sparse blocks.
657*9a747e4fSDavid du Colombier  *
658*9a747e4fSDavid du Colombier  * PARAMETERS
659*9a747e4fSDavid du Colombier  *
660*9a747e4fSDavid du Colombier  *	int     fd	- file to write to
661*9a747e4fSDavid du Colombier  *	char   *buf	- buffer to get data from
662*9a747e4fSDavid du Colombier  *	uint	len	- number of bytes to transfer
663*9a747e4fSDavid du Colombier  *
664*9a747e4fSDavid du Colombier  * RETURNS
665*9a747e4fSDavid du Colombier  *
666*9a747e4fSDavid du Colombier  *	Returns 0 if the block was written, the given length for a sparse
667*9a747e4fSDavid du Colombier  *	block or -1 if unsuccessful.
668*9a747e4fSDavid du Colombier  */
669*9a747e4fSDavid du Colombier 
670*9a747e4fSDavid du Colombier #ifdef __STDC__
671*9a747e4fSDavid du Colombier 
ar_write(int fd,char * buf,uint len)672*9a747e4fSDavid du Colombier static int ar_write(int fd, char *buf, uint len)
673*9a747e4fSDavid du Colombier 
674*9a747e4fSDavid du Colombier #else
675*9a747e4fSDavid du Colombier 
676*9a747e4fSDavid du Colombier static int ar_write(fd, buf, len)
677*9a747e4fSDavid du Colombier int             fd;
678*9a747e4fSDavid du Colombier char           *buf;
679*9a747e4fSDavid du Colombier uint            len;
680*9a747e4fSDavid du Colombier 
681*9a747e4fSDavid du Colombier #endif
682*9a747e4fSDavid du Colombier {
683*9a747e4fSDavid du Colombier     char           *bidx;
684*9a747e4fSDavid du Colombier     char           *bend;
685*9a747e4fSDavid du Colombier 
686*9a747e4fSDavid du Colombier     bend = (bidx = buf) + len;
687*9a747e4fSDavid du Colombier     while (bidx < bend) {
688*9a747e4fSDavid du Colombier 	if (*bidx++) {
689*9a747e4fSDavid du Colombier 	    return (write(fd, buf, len) == len ? 0 : -1);
690*9a747e4fSDavid du Colombier 	}
691*9a747e4fSDavid du Colombier     }
692*9a747e4fSDavid du Colombier     return (lseek(fd, (OFFSET) len, 1) < 0 ? -1 : len);
693*9a747e4fSDavid du Colombier }
694*9a747e4fSDavid du Colombier 
695*9a747e4fSDavid du Colombier 
696*9a747e4fSDavid du Colombier /* buf_pad - pad the archive buffer
697*9a747e4fSDavid du Colombier  *
698*9a747e4fSDavid du Colombier  * DESCRIPTION
699*9a747e4fSDavid du Colombier  *
700*9a747e4fSDavid du Colombier  *	Buf_pad writes len zero bytes to the archive buffer in order to
701*9a747e4fSDavid du Colombier  *	pad it.
702*9a747e4fSDavid du Colombier  *
703*9a747e4fSDavid du Colombier  * PARAMETERS
704*9a747e4fSDavid du Colombier  *
705*9a747e4fSDavid du Colombier  *	OFFSET	pad	- number of zero bytes to pad
706*9a747e4fSDavid du Colombier  *
707*9a747e4fSDavid du Colombier  */
708*9a747e4fSDavid du Colombier 
709*9a747e4fSDavid du Colombier #ifdef __STDC__
710*9a747e4fSDavid du Colombier 
buf_pad(OFFSET pad)711*9a747e4fSDavid du Colombier static void buf_pad(OFFSET pad)
712*9a747e4fSDavid du Colombier 
713*9a747e4fSDavid du Colombier #else
714*9a747e4fSDavid du Colombier 
715*9a747e4fSDavid du Colombier static void buf_pad(pad)
716*9a747e4fSDavid du Colombier OFFSET           pad;
717*9a747e4fSDavid du Colombier 
718*9a747e4fSDavid du Colombier #endif
719*9a747e4fSDavid du Colombier {
720*9a747e4fSDavid du Colombier     int             idx;
721*9a747e4fSDavid du Colombier     int             have;
722*9a747e4fSDavid du Colombier 
723*9a747e4fSDavid du Colombier     while (pad) {
724*9a747e4fSDavid du Colombier 	if ((have = bufend - bufidx) > pad) {
725*9a747e4fSDavid du Colombier 	    have = pad;
726*9a747e4fSDavid du Colombier 	}
727*9a747e4fSDavid du Colombier 	for (idx = 0; idx < have; ++idx) {
728*9a747e4fSDavid du Colombier 	    *bufidx++ = '\0';
729*9a747e4fSDavid du Colombier 	}
730*9a747e4fSDavid du Colombier 	total += have;
731*9a747e4fSDavid du Colombier 	pad -= have;
732*9a747e4fSDavid du Colombier 	if (bufend - bufidx == 0) {
733*9a747e4fSDavid du Colombier 	    outflush();
734*9a747e4fSDavid du Colombier 	}
735*9a747e4fSDavid du Colombier     }
736*9a747e4fSDavid du Colombier }
737*9a747e4fSDavid du Colombier 
738*9a747e4fSDavid du Colombier 
739*9a747e4fSDavid du Colombier /* buf_use - allocate buffer space
740*9a747e4fSDavid du Colombier  *
741*9a747e4fSDavid du Colombier  * DESCRIPTION
742*9a747e4fSDavid du Colombier  *
743*9a747e4fSDavid du Colombier  *	Buf_use marks space in the buffer as being used; advancing both the
744*9a747e4fSDavid du Colombier  *	buffer index (bufidx) and the total byte count (total).
745*9a747e4fSDavid du Colombier  *
746*9a747e4fSDavid du Colombier  * PARAMETERS
747*9a747e4fSDavid du Colombier  *
748*9a747e4fSDavid du Colombier  *	uint	len	- Amount of space to allocate in the buffer
749*9a747e4fSDavid du Colombier  */
750*9a747e4fSDavid du Colombier 
751*9a747e4fSDavid du Colombier #ifdef __STDC__
752*9a747e4fSDavid du Colombier 
buf_use(uint len)753*9a747e4fSDavid du Colombier static void buf_use(uint len)
754*9a747e4fSDavid du Colombier 
755*9a747e4fSDavid du Colombier #else
756*9a747e4fSDavid du Colombier 
757*9a747e4fSDavid du Colombier static void buf_use(len)
758*9a747e4fSDavid du Colombier uint            len;
759*9a747e4fSDavid du Colombier 
760*9a747e4fSDavid du Colombier #endif
761*9a747e4fSDavid du Colombier {
762*9a747e4fSDavid du Colombier     bufidx += len;
763*9a747e4fSDavid du Colombier     total += len;
764*9a747e4fSDavid du Colombier }
765*9a747e4fSDavid du Colombier 
766*9a747e4fSDavid du Colombier 
767*9a747e4fSDavid du Colombier /* buf_in_avail - index available input data within the buffer
768*9a747e4fSDavid du Colombier  *
769*9a747e4fSDavid du Colombier  * DESCRIPTION
770*9a747e4fSDavid du Colombier  *
771*9a747e4fSDavid du Colombier  *	Buf_in_avail fills the archive buffer, and points the bufp
772*9a747e4fSDavid du Colombier  *	parameter at the start of the data.  The lenp parameter is
773*9a747e4fSDavid du Colombier  *	modified to contain the number of bytes which were read.
774*9a747e4fSDavid du Colombier  *
775*9a747e4fSDavid du Colombier  * PARAMETERS
776*9a747e4fSDavid du Colombier  *
777*9a747e4fSDavid du Colombier  *	char   **bufp	- pointer to the buffer to read data into
778*9a747e4fSDavid du Colombier  *	uint	*lenp	- pointer to the number of bytes which were read
779*9a747e4fSDavid du Colombier  *			  (returned to the caller)
780*9a747e4fSDavid du Colombier  *
781*9a747e4fSDavid du Colombier  * RETURNS
782*9a747e4fSDavid du Colombier  *
783*9a747e4fSDavid du Colombier  * 	Stores a pointer to the data and its length in given locations.
784*9a747e4fSDavid du Colombier  *	Returns zero with valid data, -1 if unreadable portions were
785*9a747e4fSDavid du Colombier  *	replaced with nulls.
786*9a747e4fSDavid du Colombier  *
787*9a747e4fSDavid du Colombier  * ERRORS
788*9a747e4fSDavid du Colombier  *
789*9a747e4fSDavid du Colombier  *	If an error occurs in ar_read, the error code is returned to the
790*9a747e4fSDavid du Colombier  *	calling function.
791*9a747e4fSDavid du Colombier  *
792*9a747e4fSDavid du Colombier  */
793*9a747e4fSDavid du Colombier 
794*9a747e4fSDavid du Colombier #ifdef __STDC__
795*9a747e4fSDavid du Colombier 
buf_in_avail(char ** bufp,uint * lenp)796*9a747e4fSDavid du Colombier static int buf_in_avail(char **bufp, uint *lenp)
797*9a747e4fSDavid du Colombier 
798*9a747e4fSDavid du Colombier #else
799*9a747e4fSDavid du Colombier 
800*9a747e4fSDavid du Colombier static int buf_in_avail(bufp, lenp)
801*9a747e4fSDavid du Colombier char          **bufp;
802*9a747e4fSDavid du Colombier uint           *lenp;
803*9a747e4fSDavid du Colombier 
804*9a747e4fSDavid du Colombier #endif
805*9a747e4fSDavid du Colombier {
806*9a747e4fSDavid du Colombier     uint            have;
807*9a747e4fSDavid du Colombier     int             corrupt = 0;
808*9a747e4fSDavid du Colombier 
809*9a747e4fSDavid du Colombier     while ((have = bufend - bufidx) == 0) {
810*9a747e4fSDavid du Colombier 	corrupt |= ar_read();
811*9a747e4fSDavid du Colombier     }
812*9a747e4fSDavid du Colombier     *bufp = bufidx;
813*9a747e4fSDavid du Colombier     *lenp = have;
814*9a747e4fSDavid du Colombier     return (corrupt);
815*9a747e4fSDavid du Colombier }
816*9a747e4fSDavid du Colombier 
817*9a747e4fSDavid du Colombier 
818*9a747e4fSDavid du Colombier /* buf_out_avail  - index buffer space for archive output
819*9a747e4fSDavid du Colombier  *
820*9a747e4fSDavid du Colombier  * DESCRIPTION
821*9a747e4fSDavid du Colombier  *
822*9a747e4fSDavid du Colombier  * 	Stores a buffer pointer at a given location. Returns the number
823*9a747e4fSDavid du Colombier  *	of bytes available.
824*9a747e4fSDavid du Colombier  *
825*9a747e4fSDavid du Colombier  * PARAMETERS
826*9a747e4fSDavid du Colombier  *
827*9a747e4fSDavid du Colombier  *	char	**bufp	- pointer to the buffer which is to be stored
828*9a747e4fSDavid du Colombier  *
829*9a747e4fSDavid du Colombier  * RETURNS
830*9a747e4fSDavid du Colombier  *
831*9a747e4fSDavid du Colombier  * 	The number of bytes which are available in the buffer.
832*9a747e4fSDavid du Colombier  *
833*9a747e4fSDavid du Colombier  */
834*9a747e4fSDavid du Colombier 
835*9a747e4fSDavid du Colombier #ifdef __STDC__
836*9a747e4fSDavid du Colombier 
buf_out_avail(char ** bufp)837*9a747e4fSDavid du Colombier static uint buf_out_avail(char **bufp)
838*9a747e4fSDavid du Colombier 
839*9a747e4fSDavid du Colombier #else
840*9a747e4fSDavid du Colombier 
841*9a747e4fSDavid du Colombier static uint buf_out_avail(bufp)
842*9a747e4fSDavid du Colombier char          **bufp;
843*9a747e4fSDavid du Colombier 
844*9a747e4fSDavid du Colombier #endif
845*9a747e4fSDavid du Colombier {
846*9a747e4fSDavid du Colombier     int             have;
847*9a747e4fSDavid du Colombier 
848*9a747e4fSDavid du Colombier     if (bufend - bufidx < 0) {
849*9a747e4fSDavid du Colombier 	fatal("Buffer overlow in buf_out_avail\n");
850*9a747e4fSDavid du Colombier     }
851*9a747e4fSDavid du Colombier     if ((have = bufend - bufidx) == 0) {
852*9a747e4fSDavid du Colombier 	outflush();
853*9a747e4fSDavid du Colombier     }
854*9a747e4fSDavid du Colombier     *bufp = bufidx;
855*9a747e4fSDavid du Colombier     return (have);
856*9a747e4fSDavid du Colombier }
857