cpio.c revision 1557
1/*-
2 * Copyright (c) 1992 Keith Muller.
3 * Copyright (c) 1992, 1993
4 *	The Regents of the University of California.  All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Keith Muller of the University of California, San Diego.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *	This product includes software developed by the University of
20 *	California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37
38#ifndef lint
39static char sccsid[] = "@(#)cpio.c	8.1 (Berkeley) 5/31/93";
40#endif /* not lint */
41
42#include <sys/types.h>
43#include <sys/time.h>
44#include <sys/stat.h>
45#include <sys/param.h>
46#include <string.h>
47#include <ctype.h>
48#include <stdio.h>
49#include <unistd.h>
50#include <stdlib.h>
51#include "pax.h"
52#include "cpio.h"
53#include "extern.h"
54
55static int rd_nm __P((register ARCHD *, int));
56static int rd_ln_nm __P((register ARCHD *));
57static int com_rd __P((register ARCHD *));
58
59/*
60 * Routines which support the different cpio versions
61 */
62
63static int swp_head;		/* binary cpio header byte swap */
64
65/*
66 * Routines common to all versions of cpio
67 */
68
69/*
70 * cpio_strd()
71 *	Fire up the hard link detection code
72 * Return:
73 *      0 if ok -1 otherwise (the return values of lnk_start())
74 */
75
76#if __STDC__
77int
78cpio_strd(void)
79#else
80int
81cpio_strd()
82#endif
83{
84	return(lnk_start());
85}
86
87/*
88 * cpio_trail()
89 *	Called to determine if a header block is a valid trailer. We are
90 *	passed the block, the in_sync flag (which tells us we are in resync
91 *	mode; looking for a valid header), and cnt (which starts at zero)
92 *	which is used to count the number of empty blocks we have seen so far.
93 * Return:
94 *	0 if a valid trailer, -1 if not a valid trailer,
95 */
96
97#if __STDC__
98int
99cpio_trail(register ARCHD *arcn)
100#else
101int
102cpio_trail(arcn)
103	register ARCHD *arcn;
104#endif
105{
106	/*
107	 * look for trailer id in file we are about to process
108	 */
109	if ((strcmp(arcn->name, TRAILER) == 0) && (arcn->sb.st_size == 0))
110		return(0);
111	return(-1);
112}
113
114/*
115 * com_rd()
116 *	operations common to all cpio read functions.
117 * Return:
118 *	0
119 */
120
121#if __STDC__
122static int
123com_rd(register ARCHD *arcn)
124#else
125static int
126com_rd(arcn)
127	register ARCHD *arcn;
128#endif
129{
130	arcn->skip = 0;
131	arcn->pat = NULL;
132	arcn->org_name = arcn->name;
133	switch(arcn->sb.st_mode & C_IFMT) {
134	case C_ISFIFO:
135		arcn->type = PAX_FIF;
136		break;
137	case C_ISDIR:
138		arcn->type = PAX_DIR;
139		break;
140	case C_ISBLK:
141		arcn->type = PAX_BLK;
142		break;
143	case C_ISCHR:
144		arcn->type = PAX_CHR;
145		break;
146	case C_ISLNK:
147		arcn->type = PAX_SLK;
148		break;
149	case C_ISOCK:
150		arcn->type = PAX_SCK;
151		break;
152	case C_ISCTG:
153	case C_ISREG:
154	default:
155		/*
156		 * we have file data, set up skip (pad is set in the format
157		 * specific sections)
158		 */
159		arcn->sb.st_mode = (arcn->sb.st_mode & 0xfff) | C_ISREG;
160		arcn->type = PAX_REG;
161		arcn->skip = arcn->sb.st_size;
162		break;
163	}
164	if (chk_lnk(arcn) < 0)
165		return(-1);
166	return(0);
167}
168
169/*
170 * cpio_end_wr()
171 *	write the special file with the name trailer in the proper format
172 * Return:
173 *	result of the write of the trailer from the cpio specific write func
174 */
175
176#if __STDC__
177int
178cpio_endwr(void)
179#else
180int
181cpio_endwr()
182#endif
183{
184	ARCHD last;
185
186	/*
187	 * create a trailer request and call the proper format write function
188	 */
189	bzero((char *)&last, sizeof(last));
190	last.nlen = sizeof(TRAILER) - 1;
191	last.type = PAX_REG;
192	last.sb.st_nlink = 1;
193	(void)strcpy(last.name, TRAILER);
194	return((*frmt->wr)(&last));
195}
196
197/*
198 * rd_nam()
199 *	read in the file name which follows the cpio header
200 * Return:
201 *	0 if ok, -1 otherwise
202 */
203
204#if __STDC__
205static int
206rd_nm(register ARCHD *arcn, int nsz)
207#else
208static int
209rd_nm(arcn, nsz)
210	register ARCHD *arcn;
211	int nsz;
212#endif
213{
214	/*
215	 * do not even try bogus values
216	 */
217	if ((nsz == 0) || (nsz > sizeof(arcn->name))) {
218		warn(1, "Cpio file name length %d is out of range", nsz);
219		return(-1);
220	}
221
222	/*
223	 * read the name and make sure it is not empty and is \0 terminated
224	 */
225	if ((rd_wrbuf(arcn->name,nsz) != nsz) || (arcn->name[nsz-1] != '\0') ||
226	    (arcn->name[0] == '\0')) {
227		warn(1, "Cpio file name in header is corrupted");
228		return(-1);
229	}
230	return(0);
231}
232
233/*
234 * rd_ln_nm()
235 *	read in the link name for a file with links. The link name is stored
236 *	like file data (and is NOT \0 terminated!)
237 * Return:
238 *	0 if ok, -1 otherwise
239 */
240
241#if __STDC__
242static int
243rd_ln_nm(register ARCHD *arcn)
244#else
245static int
246rd_ln_nm(arcn)
247	register ARCHD *arcn;
248#endif
249{
250	/*
251	 * check the length specified for bogus values
252	 */
253	if ((arcn->sb.st_size == 0) ||
254	    (arcn->sb.st_size >= sizeof(arcn->ln_name))) {
255#		ifdef NET2_STAT
256		warn(1, "Cpio link name length is invalid: %lu",
257		    arcn->sb.st_size);
258#		else
259		warn(1, "Cpio link name length is invalid: %qu",
260		    arcn->sb.st_size);
261#		endif
262		return(-1);
263	}
264
265	/*
266	 * read in the link name and \0 terminate it
267	 */
268	if (rd_wrbuf(arcn->ln_name, (int)arcn->sb.st_size) !=
269	    (int)arcn->sb.st_size) {
270		warn(1, "Cpio link name read error");
271		return(-1);
272	}
273	arcn->ln_nlen = arcn->sb.st_size;
274	arcn->ln_name[arcn->ln_nlen] = '\0';
275
276	/*
277	 * watch out for those empty link names
278	 */
279	if (arcn->ln_name[0] == '\0') {
280		warn(1, "Cpio link name is corrupt");
281		return(-1);
282	}
283	return(0);
284}
285
286/*
287 * Routines common to the extended byte oriented cpio format
288 */
289
290/*
291 * cpio_id()
292 *      determine if a block given to us is a valid extended byte oriented
293 *	cpio header
294 * Return:
295 *      0 if a valid header, -1 otherwise
296 */
297
298#if __STDC__
299int
300cpio_id(char *blk, int size)
301#else
302int
303cpio_id(blk, size)
304	char *blk;
305	int size;
306#endif
307{
308	if ((size < sizeof(HD_CPIO)) ||
309	    (strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0))
310		return(-1);
311	return(0);
312}
313
314/*
315 * cpio_rd()
316 *	determine if a buffer is a byte oriented extended cpio archive entry.
317 *	convert and store the values in the ARCHD parameter.
318 * Return:
319 *	0 if a valid header, -1 otherwise.
320 */
321
322#if __STDC__
323int
324cpio_rd(register ARCHD *arcn, register char *buf)
325#else
326int
327cpio_rd(arcn, buf)
328	register ARCHD *arcn;
329	register char *buf;
330#endif
331{
332	register int nsz;
333	register HD_CPIO *hd;
334
335	/*
336	 * check that this is a valid header, if not return -1
337	 */
338	if (cpio_id(buf, sizeof(HD_CPIO)) < 0)
339		return(-1);
340	hd = (HD_CPIO *)buf;
341
342	/*
343	 * byte oriented cpio (posix) does not have padding! extract the octal
344	 * ascii fields from the header
345	 */
346	arcn->pad = 0L;
347	arcn->sb.st_dev = (dev_t)asc_ul(hd->c_dev, sizeof(hd->c_dev), OCT);
348	arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), OCT);
349	arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), OCT);
350	arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), OCT);
351	arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), OCT);
352	arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
353	    OCT);
354	arcn->sb.st_rdev = (dev_t)asc_ul(hd->c_rdev, sizeof(hd->c_rdev), OCT);
355	arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime),
356	    OCT);
357	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
358#	ifdef NET2_STAT
359	arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,sizeof(hd->c_filesize),
360	    OCT);
361#	else
362	arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,sizeof(hd->c_filesize),
363	    OCT);
364#	endif
365
366	/*
367	 * check name size and if valid, read in the name of this entry (name
368	 * follows header in the archive)
369	 */
370	if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2)
371		return(-1);
372	arcn->nlen = nsz - 1;
373	if (rd_nm(arcn, nsz) < 0)
374		return(-1);
375
376	if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
377		/*
378	 	 * no link name to read for this file
379	 	 */
380		arcn->ln_nlen = 0;
381		arcn->ln_name[0] = '\0';
382		return(com_rd(arcn));
383	}
384
385	/*
386	 * check link name size and read in the link name. Link names are
387	 * stored like file data.
388	 */
389	if (rd_ln_nm(arcn) < 0)
390		return(-1);
391
392	/*
393	 * we have a valid header (with a link)
394	 */
395	return(com_rd(arcn));
396}
397
398/*
399 * cpio_endrd()
400 *      no cleanup needed here, just return size of the trailer (for append)
401 * Return:
402 *      size of trailer header in this format
403 */
404
405#if __STDC__
406off_t
407cpio_endrd(void)
408#else
409off_t
410cpio_endrd()
411#endif
412{
413	return((off_t)(sizeof(HD_CPIO) + sizeof(TRAILER)));
414}
415
416/*
417 * cpio_stwr()
418 *	start up the device mapping table
419 * Return:
420 *	0 if ok, -1 otherwise (what dev_start() returns)
421 */
422
423#if __STDC__
424int
425cpio_stwr(void)
426#else
427int
428cpio_stwr()
429#endif
430{
431	return(dev_start());
432}
433
434/*
435 * cpio_wr()
436 *	copy the data in the ARCHD to buffer in extended byte oriented cpio
437 *	format.
438 * Return
439 *      0 if file has data to be written after the header, 1 if file has NO
440 *	data to write after the header, -1 if archive write failed
441 */
442
443#if __STDC__
444int
445cpio_wr(register ARCHD *arcn)
446#else
447int
448cpio_wr(arcn)
449	register ARCHD *arcn;
450#endif
451{
452	register HD_CPIO *hd;
453	register int nsz;
454	char hdblk[sizeof(HD_CPIO)];
455
456	/*
457	 * check and repair truncated device and inode fields in the header
458	 */
459	if (map_dev(arcn, (u_long)CPIO_MASK, (u_long)CPIO_MASK) < 0)
460		return(-1);
461
462	arcn->pad = 0L;
463	nsz = arcn->nlen + 1;
464	hd = (HD_CPIO *)hdblk;
465	if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
466		arcn->sb.st_rdev = 0;
467
468	switch(arcn->type) {
469	case PAX_CTG:
470	case PAX_REG:
471	case PAX_HRG:
472		/*
473		 * set data size for file data
474		 */
475#		ifdef NET2_STAT
476		if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
477		    sizeof(hd->c_filesize), OCT)) {
478#		else
479		if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize,
480		    sizeof(hd->c_filesize), OCT)) {
481#		endif
482			warn(1,"File is too large for cpio format %s",
483			    arcn->org_name);
484			return(1);
485		}
486		break;
487	case PAX_SLK:
488		/*
489		 * set data size to hold link name
490		 */
491		if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize,
492		    sizeof(hd->c_filesize), OCT))
493			goto out;
494		break;
495	default:
496		/*
497		 * all other file types have no file data
498		 */
499		if (ul_asc((u_long)0, hd->c_filesize, sizeof(hd->c_filesize),
500		     OCT))
501			goto out;
502		break;
503	}
504
505	/*
506	 * copy the values to the header using octal ascii
507	 */
508	if (ul_asc((u_long)MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) ||
509	    ul_asc((u_long)arcn->sb.st_dev, hd->c_dev, sizeof(hd->c_dev),
510	        OCT) ||
511	    ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
512		OCT) ||
513	    ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
514		OCT) ||
515	    ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
516		OCT) ||
517	    ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
518		OCT) ||
519	    ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
520		 OCT) ||
521	    ul_asc((u_long)arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev),
522		OCT) ||
523	    ul_asc((u_long)arcn->sb.st_mtime,hd->c_mtime,sizeof(hd->c_mtime),
524		OCT) ||
525	    ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT))
526		goto out;
527
528	/*
529	 * write the file name to the archive
530	 */
531	if ((wr_rdbuf(hdblk, (int)sizeof(HD_CPIO)) < 0) ||
532	    (wr_rdbuf(arcn->name, nsz) < 0)) {
533		warn(1, "Unable to write cpio header for %s", arcn->org_name);
534		return(-1);
535	}
536
537	/*
538	 * if this file has data, we are done. The caller will write the file
539	 * data, if we are link tell caller we are done, go to next file
540	 */
541	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
542	    (arcn->type == PAX_HRG))
543		return(0);
544	if (arcn->type != PAX_SLK)
545		return(1);
546
547	/*
548	 * write the link name to the archive, tell the caller to go to the
549	 * next file as we are done.
550	 */
551	if (wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) {
552		warn(1,"Unable to write cpio link name for %s",arcn->org_name);
553		return(-1);
554	}
555	return(1);
556
557    out:
558	/*
559	 * header field is out of range
560	 */
561	warn(1, "Cpio header field is too small to store file %s",
562	    arcn->org_name);
563	return(1);
564}
565
566/*
567 * Routines common to the system VR4 version of cpio (with/without file CRC)
568 */
569
570/*
571 * vcpio_id()
572 *      determine if a block given to us is a valid system VR4 cpio header
573 *	WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header
574 *	uses HEX
575 * Return:
576 *      0 if a valid header, -1 otherwise
577 */
578
579#if __STDC__
580int
581vcpio_id(char *blk, int size)
582#else
583int
584vcpio_id(blk, size)
585	char *blk;
586	int size;
587#endif
588{
589	if ((size < sizeof(HD_VCPIO)) ||
590	    (strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0))
591		return(-1);
592	return(0);
593}
594
595/*
596 * crc_id()
597 *      determine if a block given to us is a valid system VR4 cpio header
598 *	WITH crc. WATCH it the magic cookies are in OCTAL the header uses HEX
599 * Return:
600 *      0 if a valid header, -1 otherwise
601 */
602
603#if __STDC__
604int
605crc_id(char *blk, int size)
606#else
607int
608crc_id(blk, size)
609	char *blk;
610	int size;
611#endif
612{
613	if ((size < sizeof(HD_VCPIO)) ||
614	    (strncmp(blk, AVCMAGIC, sizeof(AVCMAGIC) - 1) != 0))
615		return(-1);
616	return(0);
617}
618
619/*
620 * crc_strd()
621 w	set file data CRC calculations. Fire up the hard link detection code
622 * Return:
623 *      0 if ok -1 otherwise (the return values of lnk_start())
624 */
625
626#if __STDC__
627int
628crc_strd(void)
629#else
630int
631crc_strd()
632#endif
633{
634	docrc = 1;
635	return(lnk_start());
636}
637
638/*
639 * vcpio_rd()
640 *	determine if a buffer is a system VR4 archive entry. (with/without CRC)
641 *	convert and store the values in the ARCHD parameter.
642 * Return:
643 *	0 if a valid header, -1 otherwise.
644 */
645
646#if __STDC__
647int
648vcpio_rd(register ARCHD *arcn, register char *buf)
649#else
650int
651vcpio_rd(arcn, buf)
652	register ARCHD *arcn;
653	register char *buf;
654#endif
655{
656	register HD_VCPIO *hd;
657	dev_t devminor;
658	dev_t devmajor;
659	register int nsz;
660
661	/*
662	 * during the id phase it was determined if we were using CRC, use the
663	 * proper id routine.
664	 */
665	if (docrc) {
666		if (crc_id(buf, sizeof(HD_VCPIO)) < 0)
667			return(-1);
668	} else {
669		if (vcpio_id(buf, sizeof(HD_VCPIO)) < 0)
670			return(-1);
671	}
672
673	hd = (HD_VCPIO *)buf;
674	arcn->pad = 0L;
675
676	/*
677	 * extract the hex ascii fields from the header
678	 */
679	arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), HEX);
680	arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), HEX);
681	arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), HEX);
682	arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX);
683	arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX);
684	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
685#	ifdef NET2_STAT
686	arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,
687	    sizeof(hd->c_filesize), HEX);
688#	else
689	arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,
690	    sizeof(hd->c_filesize), HEX);
691#	endif
692	arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
693	    HEX);
694	devmajor = (dev_t)asc_ul(hd->c_maj, sizeof(hd->c_maj), HEX);
695	devminor = (dev_t)asc_ul(hd->c_min, sizeof(hd->c_min), HEX);
696	arcn->sb.st_dev = TODEV(devmajor, devminor);
697	devmajor = (dev_t)asc_ul(hd->c_rmaj, sizeof(hd->c_maj), HEX);
698	devminor = (dev_t)asc_ul(hd->c_rmin, sizeof(hd->c_min), HEX);
699	arcn->sb.st_rdev = TODEV(devmajor, devminor);
700	arcn->crc = asc_ul(hd->c_chksum, sizeof(hd->c_chksum), HEX);
701
702	/*
703	 * check the length of the file name, if ok read it in, return -1 if
704	 * bogus
705	 */
706	if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2)
707		return(-1);
708	arcn->nlen = nsz - 1;
709	if (rd_nm(arcn, nsz) < 0)
710		return(-1);
711
712	/*
713	 * skip padding. header + filename is aligned to 4 byte boundries
714	 */
715	if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)
716		return(-1);
717
718	/*
719	 * if not a link (or a file with no data), calculate pad size (for
720	 * padding which follows the file data), clear the link name and return
721	 */
722	if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
723		/*
724		 * we have a valid header (not a link)
725		 */
726		arcn->ln_nlen = 0;
727		arcn->ln_name[0] = '\0';
728		arcn->pad = VCPIO_PAD(arcn->sb.st_size);
729		return(com_rd(arcn));
730	}
731
732	/*
733	 * read in the link name and skip over the padding
734	 */
735	if ((rd_ln_nm(arcn) < 0) ||
736	    (rd_skip((off_t)(VCPIO_PAD(arcn->sb.st_size))) < 0))
737		return(-1);
738
739	/*
740	 * we have a valid header (with a link)
741	 */
742	return(com_rd(arcn));
743}
744
745/*
746 * vcpio_endrd()
747 *      no cleanup needed here, just return size of the trailer (for append)
748 * Return:
749 *      size of trailer header in this format
750 */
751
752#if __STDC__
753off_t
754vcpio_endrd(void)
755#else
756off_t
757vcpio_endrd()
758#endif
759{
760	return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) +
761		(VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER)))));
762}
763
764/*
765 * crc_stwr()
766 *	start up the device mapping table, enable crc file calculation
767 * Return:
768 *	0 if ok, -1 otherwise (what dev_start() returns)
769 */
770
771#if __STDC__
772int
773crc_stwr(void)
774#else
775int
776crc_stwr()
777#endif
778{
779	docrc = 1;
780	return(dev_start());
781}
782
783/*
784 * vcpio_wr()
785 *	copy the data in the ARCHD to buffer in system VR4 cpio
786 *	(with/without crc) format.
787 * Return
788 *	0 if file has data to be written after the header, 1 if file has
789 *	NO data to write after the header, -1 if archive write failed
790 */
791
792#if __STDC__
793int
794vcpio_wr(register ARCHD *arcn)
795#else
796int
797vcpio_wr(arcn)
798	register ARCHD *arcn;
799#endif
800{
801	register HD_VCPIO *hd;
802	unsigned int nsz;
803	char hdblk[sizeof(HD_VCPIO)];
804
805	/*
806	 * check and repair truncated device and inode fields in the cpio
807	 * header
808	 */
809	if (map_dev(arcn, (u_long)VCPIO_MASK, (u_long)VCPIO_MASK) < 0)
810		return(-1);
811	nsz = arcn->nlen + 1;
812	hd = (HD_VCPIO *)hdblk;
813	if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
814		arcn->sb.st_rdev = 0;
815
816	/*
817	 * add the proper magic value depending whether we were asked for
818	 * file data crc's, and the crc if needed.
819	 */
820	if (docrc) {
821		if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic),
822	    		OCT) ||
823		    ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum),
824	    		HEX))
825			goto out;
826	} else {
827		if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic),
828	    		OCT) ||
829		    ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX))
830			goto out;
831	}
832
833	switch(arcn->type) {
834	case PAX_CTG:
835	case PAX_REG:
836	case PAX_HRG:
837		/*
838		 * caller will copy file data to the archive. tell him how
839		 * much to pad.
840		 */
841		arcn->pad = VCPIO_PAD(arcn->sb.st_size);
842#		ifdef NET2_STAT
843		if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
844		    sizeof(hd->c_filesize), HEX)) {
845#		else
846		if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize,
847		    sizeof(hd->c_filesize), HEX)) {
848#		endif
849			warn(1,"File is too large for sv4cpio format %s",
850			    arcn->org_name);
851			return(1);
852		}
853		break;
854	case PAX_SLK:
855		/*
856		 * no file data for the caller to process, the file data has
857		 * the size of the link
858		 */
859		arcn->pad = 0L;
860		if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize,
861		    sizeof(hd->c_filesize), HEX))
862			goto out;
863		break;
864	default:
865		/*
866		 * no file data for the caller to process
867		 */
868		arcn->pad = 0L;
869		if (ul_asc((u_long)0L, hd->c_filesize, sizeof(hd->c_filesize),
870		    HEX))
871			goto out;
872		break;
873	}
874
875	/*
876	 * set the other fields in the header
877	 */
878	if (ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
879		HEX) ||
880	    ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
881		HEX) ||
882	    ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
883		HEX) ||
884	    ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
885    		HEX) ||
886	    ul_asc((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime),
887    		HEX) ||
888	    ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
889    		HEX) ||
890	    ul_asc((u_long)MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj),
891		HEX) ||
892	    ul_asc((u_long)MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min),
893		HEX) ||
894	    ul_asc((u_long)MAJOR(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj),
895		HEX) ||
896	    ul_asc((u_long)MINOR(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min),
897		HEX) ||
898	    ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX))
899		goto out;
900
901	/*
902	 * write the header, the file name and padding as required.
903	 */
904	if ((wr_rdbuf(hdblk, (int)sizeof(HD_VCPIO)) < 0) ||
905	    (wr_rdbuf(arcn->name, (int)nsz) < 0)  ||
906	    (wr_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)) {
907		warn(1,"Could not write sv4cpio header for %s",arcn->org_name);
908		return(-1);
909	}
910
911	/*
912	 * if we have file data, tell the caller we are done, copy the file
913	 */
914	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
915	    (arcn->type == PAX_HRG))
916		return(0);
917
918	/*
919	 * if we are not a link, tell the caller we are done, go to next file
920	 */
921	if (arcn->type != PAX_SLK)
922		return(1);
923
924	/*
925	 * write the link name, tell the caller we are done.
926	 */
927	if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
928	    (wr_skip((off_t)(VCPIO_PAD(arcn->ln_nlen))) < 0)) {
929		warn(1,"Could not write sv4cpio link name for %s",
930		    arcn->org_name);
931		return(-1);
932	}
933	return(1);
934
935    out:
936	/*
937	 * header field is out of range
938	 */
939	warn(1,"Sv4cpio header field is too small for file %s",arcn->org_name);
940	return(1);
941}
942
943/*
944 * Routines common to the old binary header cpio
945 */
946
947/*
948 * bcpio_id()
949 *      determine if a block given to us is a old binary cpio header
950 *	(with/without header byte swapping)
951 * Return:
952 *      0 if a valid header, -1 otherwise
953 */
954
955#if __STDC__
956int
957bcpio_id(char *blk, int size)
958#else
959int
960bcpio_id(blk, size)
961	char *blk;
962	int size;
963#endif
964{
965	if (size < sizeof(HD_BCPIO))
966		return(-1);
967
968	/*
969	 * check both normal and byte swapped magic cookies
970	 */
971	if (((u_short)SHRT_EXT(blk)) == MAGIC)
972		return(0);
973	if (((u_short)RSHRT_EXT(blk)) == MAGIC) {
974		if (!swp_head)
975			++swp_head;
976		return(0);
977	}
978	return(-1);
979}
980
981/*
982 * bcpio_rd()
983 *	determine if a buffer is a old binary archive entry. (it may have byte
984 *	swapped header) convert and store the values in the ARCHD parameter.
985 *	This is a very old header format and should not really be used.
986 * Return:
987 *	0 if a valid header, -1 otherwise.
988 */
989
990#if __STDC__
991int
992bcpio_rd(register ARCHD *arcn, register char *buf)
993#else
994int
995bcpio_rd(arcn, buf)
996	register ARCHD *arcn;
997	register char *buf;
998#endif
999{
1000	register HD_BCPIO *hd;
1001	register int nsz;
1002
1003	/*
1004	 * check the header
1005	 */
1006	if (bcpio_id(buf, sizeof(HD_BCPIO)) < 0)
1007		return(-1);
1008
1009	arcn->pad = 0L;
1010	hd = (HD_BCPIO *)buf;
1011	if (swp_head) {
1012		/*
1013		 * header has swapped bytes on 16 bit boundries
1014		 */
1015		arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev));
1016		arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino));
1017		arcn->sb.st_mode = (mode_t)(RSHRT_EXT(hd->h_mode));
1018		arcn->sb.st_uid = (uid_t)(RSHRT_EXT(hd->h_uid));
1019		arcn->sb.st_gid = (gid_t)(RSHRT_EXT(hd->h_gid));
1020		arcn->sb.st_nlink = (nlink_t)(RSHRT_EXT(hd->h_nlink));
1021		arcn->sb.st_rdev = (dev_t)(RSHRT_EXT(hd->h_rdev));
1022		arcn->sb.st_mtime = (time_t)(RSHRT_EXT(hd->h_mtime_1));
1023		arcn->sb.st_mtime =  (arcn->sb.st_mtime << 16) |
1024			((time_t)(RSHRT_EXT(hd->h_mtime_2)));
1025		arcn->sb.st_size = (off_t)(RSHRT_EXT(hd->h_filesize_1));
1026		arcn->sb.st_size = (arcn->sb.st_size << 16) |
1027			((off_t)(RSHRT_EXT(hd->h_filesize_2)));
1028		nsz = (int)(RSHRT_EXT(hd->h_namesize));
1029	} else {
1030		arcn->sb.st_dev = (dev_t)(SHRT_EXT(hd->h_dev));
1031		arcn->sb.st_ino = (ino_t)(SHRT_EXT(hd->h_ino));
1032		arcn->sb.st_mode = (mode_t)(SHRT_EXT(hd->h_mode));
1033		arcn->sb.st_uid = (uid_t)(SHRT_EXT(hd->h_uid));
1034		arcn->sb.st_gid = (gid_t)(SHRT_EXT(hd->h_gid));
1035		arcn->sb.st_nlink = (nlink_t)(SHRT_EXT(hd->h_nlink));
1036		arcn->sb.st_rdev = (dev_t)(SHRT_EXT(hd->h_rdev));
1037		arcn->sb.st_mtime = (time_t)(SHRT_EXT(hd->h_mtime_1));
1038		arcn->sb.st_mtime =  (arcn->sb.st_mtime << 16) |
1039			((time_t)(SHRT_EXT(hd->h_mtime_2)));
1040		arcn->sb.st_size = (off_t)(SHRT_EXT(hd->h_filesize_1));
1041		arcn->sb.st_size = (arcn->sb.st_size << 16) |
1042			((off_t)(SHRT_EXT(hd->h_filesize_2)));
1043		nsz = (int)(SHRT_EXT(hd->h_namesize));
1044	}
1045	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
1046
1047	/*
1048	 * check the file name size, if bogus give up. otherwise read the file
1049	 * name
1050	 */
1051	if (nsz < 2)
1052		return(-1);
1053	arcn->nlen = nsz - 1;
1054	if (rd_nm(arcn, nsz) < 0)
1055		return(-1);
1056
1057	/*
1058	 * header + file name are aligned to 2 byte boundries, skip if needed
1059	 */
1060	if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)
1061		return(-1);
1062
1063	/*
1064	 * if not a link (or a file with no data), calculate pad size (for
1065	 * padding which follows the file data), clear the link name and return
1066	 */
1067	if (((arcn->sb.st_mode & C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)){
1068		/*
1069		 * we have a valid header (not a link)
1070		 */
1071		arcn->ln_nlen = 0;
1072		arcn->ln_name[0] = '\0';
1073		arcn->pad = BCPIO_PAD(arcn->sb.st_size);
1074		return(com_rd(arcn));
1075	}
1076
1077	if ((rd_ln_nm(arcn) < 0) ||
1078	    (rd_skip((off_t)(BCPIO_PAD(arcn->sb.st_size))) < 0))
1079		return(-1);
1080
1081	/*
1082	 * we have a valid header (with a link)
1083	 */
1084	return(com_rd(arcn));
1085}
1086
1087/*
1088 * bcpio_endrd()
1089 *      no cleanup needed here, just return size of the trailer (for append)
1090 * Return:
1091 *      size of trailer header in this format
1092 */
1093
1094#if __STDC__
1095off_t
1096bcpio_endrd(void)
1097#else
1098off_t
1099bcpio_endrd()
1100#endif
1101{
1102	return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) +
1103		(BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER)))));
1104}
1105
1106/*
1107 * bcpio_wr()
1108 *	copy the data in the ARCHD to buffer in old binary cpio format
1109 *	There is a real chance of field overflow with this critter. So we
1110 *	always check the conversion is ok. nobody in his their right mind
1111 *	should write an achive in this format...
1112 * Return
1113 *      0 if file has data to be written after the header, 1 if file has NO
1114 *	data to write after the header, -1 if archive write failed
1115 */
1116
1117#if __STDC__
1118int
1119bcpio_wr(register ARCHD *arcn)
1120#else
1121int
1122bcpio_wr(arcn)
1123	register ARCHD *arcn;
1124#endif
1125{
1126	register HD_BCPIO *hd;
1127	register int nsz;
1128	char hdblk[sizeof(HD_BCPIO)];
1129	off_t t_offt;
1130	int t_int;
1131	time_t t_timet;
1132
1133	/*
1134	 * check and repair truncated device and inode fields in the cpio
1135	 * header
1136	 */
1137	if (map_dev(arcn, (u_long)BCPIO_MASK, (u_long)BCPIO_MASK) < 0)
1138		return(-1);
1139
1140	if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
1141		arcn->sb.st_rdev = 0;
1142	hd = (HD_BCPIO *)hdblk;
1143
1144	switch(arcn->type) {
1145	case PAX_CTG:
1146	case PAX_REG:
1147	case PAX_HRG:
1148		/*
1149		 * caller will copy file data to the archive. tell him how
1150		 * much to pad.
1151		 */
1152		arcn->pad = BCPIO_PAD(arcn->sb.st_size);
1153		hd->h_filesize_1[0] = CHR_WR_0(arcn->sb.st_size);
1154		hd->h_filesize_1[1] = CHR_WR_1(arcn->sb.st_size);
1155		hd->h_filesize_2[0] = CHR_WR_2(arcn->sb.st_size);
1156		hd->h_filesize_2[1] = CHR_WR_3(arcn->sb.st_size);
1157		t_offt = (off_t)(SHRT_EXT(hd->h_filesize_1));
1158		t_offt = (t_offt<<16) | ((off_t)(SHRT_EXT(hd->h_filesize_2)));
1159		if (arcn->sb.st_size != t_offt) {
1160			warn(1,"File is too large for bcpio format %s",
1161			    arcn->org_name);
1162			return(1);
1163		}
1164		break;
1165	case PAX_SLK:
1166		/*
1167		 * no file data for the caller to process, the file data has
1168		 * the size of the link
1169		 */
1170		arcn->pad = 0L;
1171		hd->h_filesize_1[0] = CHR_WR_0(arcn->ln_nlen);
1172		hd->h_filesize_1[1] = CHR_WR_1(arcn->ln_nlen);
1173		hd->h_filesize_2[0] = CHR_WR_2(arcn->ln_nlen);
1174		hd->h_filesize_2[1] = CHR_WR_3(arcn->ln_nlen);
1175		t_int = (int)(SHRT_EXT(hd->h_filesize_1));
1176		t_int = (t_int << 16) | ((int)(SHRT_EXT(hd->h_filesize_2)));
1177		if (arcn->ln_nlen != t_int)
1178			goto out;
1179		break;
1180	default:
1181		/*
1182		 * no file data for the caller to process
1183		 */
1184		arcn->pad = 0L;
1185		hd->h_filesize_1[0] = (char)0;
1186		hd->h_filesize_1[1] = (char)0;
1187		hd->h_filesize_2[0] = (char)0;
1188		hd->h_filesize_2[1] = (char)0;
1189		break;
1190	}
1191
1192	/*
1193	 * build up the rest of the fields
1194	 */
1195	hd->h_magic[0] = CHR_WR_2(MAGIC);
1196	hd->h_magic[1] = CHR_WR_3(MAGIC);
1197	hd->h_dev[0] = CHR_WR_2(arcn->sb.st_dev);
1198	hd->h_dev[1] = CHR_WR_3(arcn->sb.st_dev);
1199	if (arcn->sb.st_dev != (dev_t)(SHRT_EXT(hd->h_dev)))
1200		goto out;
1201	hd->h_ino[0] = CHR_WR_2(arcn->sb.st_ino);
1202	hd->h_ino[1] = CHR_WR_3(arcn->sb.st_ino);
1203	if (arcn->sb.st_ino != (ino_t)(SHRT_EXT(hd->h_ino)))
1204		goto out;
1205	hd->h_mode[0] = CHR_WR_2(arcn->sb.st_mode);
1206	hd->h_mode[1] = CHR_WR_3(arcn->sb.st_mode);
1207	if (arcn->sb.st_mode != (mode_t)(SHRT_EXT(hd->h_mode)))
1208		goto out;
1209	hd->h_uid[0] = CHR_WR_2(arcn->sb.st_uid);
1210	hd->h_uid[1] = CHR_WR_3(arcn->sb.st_uid);
1211	if (arcn->sb.st_uid != (uid_t)(SHRT_EXT(hd->h_uid)))
1212		goto out;
1213	hd->h_gid[0] = CHR_WR_2(arcn->sb.st_gid);
1214	hd->h_gid[1] = CHR_WR_3(arcn->sb.st_gid);
1215	if (arcn->sb.st_gid != (gid_t)(SHRT_EXT(hd->h_gid)))
1216		goto out;
1217	hd->h_nlink[0] = CHR_WR_2(arcn->sb.st_nlink);
1218	hd->h_nlink[1] = CHR_WR_3(arcn->sb.st_nlink);
1219	if (arcn->sb.st_nlink != (nlink_t)(SHRT_EXT(hd->h_nlink)))
1220		goto out;
1221	hd->h_rdev[0] = CHR_WR_2(arcn->sb.st_rdev);
1222	hd->h_rdev[1] = CHR_WR_3(arcn->sb.st_rdev);
1223	if (arcn->sb.st_rdev != (dev_t)(SHRT_EXT(hd->h_rdev)))
1224		goto out;
1225	hd->h_mtime_1[0] = CHR_WR_0(arcn->sb.st_mtime);
1226	hd->h_mtime_1[1] = CHR_WR_1(arcn->sb.st_mtime);
1227	hd->h_mtime_2[0] = CHR_WR_2(arcn->sb.st_mtime);
1228	hd->h_mtime_2[1] = CHR_WR_3(arcn->sb.st_mtime);
1229	t_timet = (time_t)(SHRT_EXT(hd->h_mtime_1));
1230	t_timet =  (t_timet << 16) | ((time_t)(SHRT_EXT(hd->h_mtime_2)));
1231	if (arcn->sb.st_mtime != t_timet)
1232		goto out;
1233	nsz = arcn->nlen + 1;
1234	hd->h_namesize[0] = CHR_WR_2(nsz);
1235	hd->h_namesize[1] = CHR_WR_3(nsz);
1236	if (nsz != (int)(SHRT_EXT(hd->h_namesize)))
1237		goto out;
1238
1239	/*
1240	 * write the header, the file name and padding as required.
1241	 */
1242	if ((wr_rdbuf(hdblk, (int)sizeof(HD_BCPIO)) < 0) ||
1243	    (wr_rdbuf(arcn->name, nsz) < 0) ||
1244	    (wr_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)) {
1245		warn(1, "Could not write bcpio header for %s", arcn->org_name);
1246		return(-1);
1247	}
1248
1249	/*
1250	 * if we have file data, tell the caller we are done
1251	 */
1252	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
1253	    (arcn->type == PAX_HRG))
1254		return(0);
1255
1256	/*
1257	 * if we are not a link, tell the caller we are done, go to next file
1258	 */
1259	if (arcn->type != PAX_SLK)
1260		return(1);
1261
1262	/*
1263	 * write the link name, tell the caller we are done.
1264	 */
1265	if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
1266	    (wr_skip((off_t)(BCPIO_PAD(arcn->ln_nlen))) < 0)) {
1267		warn(1,"Could not write bcpio link name for %s",arcn->org_name);
1268		return(-1);
1269	}
1270	return(1);
1271
1272    out:
1273	/*
1274	 * header field is out of range
1275	 */
1276	warn(1,"Bcpio header field is too small for file %s", arcn->org_name);
1277	return(1);
1278}
1279