1*2f186deaSmillert /* $OpenBSD: cpio.c,v 1.34 2023/06/26 18:00:59 millert Exp $ */
2df930be7Sderaadt /* $NetBSD: cpio.c,v 1.5 1995/03/21 09:07:13 cgd Exp $ */
3df930be7Sderaadt
4df930be7Sderaadt /*-
5df930be7Sderaadt * Copyright (c) 1992 Keith Muller.
6df930be7Sderaadt * Copyright (c) 1992, 1993
7df930be7Sderaadt * The Regents of the University of California. All rights reserved.
8df930be7Sderaadt *
9df930be7Sderaadt * This code is derived from software contributed to Berkeley by
10df930be7Sderaadt * Keith Muller of the University of California, San Diego.
11df930be7Sderaadt *
12df930be7Sderaadt * Redistribution and use in source and binary forms, with or without
13df930be7Sderaadt * modification, are permitted provided that the following conditions
14df930be7Sderaadt * are met:
15df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright
16df930be7Sderaadt * notice, this list of conditions and the following disclaimer.
17df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
18df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the
19df930be7Sderaadt * documentation and/or other materials provided with the distribution.
2029295d1cSmillert * 3. Neither the name of the University nor the names of its contributors
21df930be7Sderaadt * may be used to endorse or promote products derived from this software
22df930be7Sderaadt * without specific prior written permission.
23df930be7Sderaadt *
24df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34df930be7Sderaadt * SUCH DAMAGE.
35df930be7Sderaadt */
36df930be7Sderaadt
37df930be7Sderaadt #include <sys/types.h>
38df930be7Sderaadt #include <sys/stat.h>
39bdaaddddSguenther #include <limits.h>
40df930be7Sderaadt #include <string.h>
41df930be7Sderaadt #include <stdio.h>
42df930be7Sderaadt #include <unistd.h>
43df930be7Sderaadt #include <stdlib.h>
44df930be7Sderaadt #include "pax.h"
45df930be7Sderaadt #include "cpio.h"
46df930be7Sderaadt #include "extern.h"
47df930be7Sderaadt
48be87792eSmillert static int rd_nm(ARCHD *, int);
49be87792eSmillert static int rd_ln_nm(ARCHD *);
50be87792eSmillert static int com_rd(ARCHD *);
51df930be7Sderaadt
52df930be7Sderaadt /*
53df930be7Sderaadt * Routines which support the different cpio versions
54df930be7Sderaadt */
55df930be7Sderaadt
56df930be7Sderaadt static int swp_head; /* binary cpio header byte swap */
57df930be7Sderaadt
58df930be7Sderaadt /*
59df930be7Sderaadt * Routines common to all versions of cpio
60df930be7Sderaadt */
61df930be7Sderaadt
62df930be7Sderaadt /*
63df930be7Sderaadt * cpio_strd()
64df930be7Sderaadt * Fire up the hard link detection code
65df930be7Sderaadt * Return:
66df930be7Sderaadt * 0 if ok -1 otherwise (the return values of lnk_start())
67df930be7Sderaadt */
68df930be7Sderaadt
69df930be7Sderaadt int
cpio_strd(void)70df930be7Sderaadt cpio_strd(void)
71df930be7Sderaadt {
72df930be7Sderaadt return(lnk_start());
73df930be7Sderaadt }
74df930be7Sderaadt
75df930be7Sderaadt /*
76df930be7Sderaadt * cpio_trail()
77df930be7Sderaadt * Called to determine if a header block is a valid trailer. We are
78df930be7Sderaadt * passed the block, the in_sync flag (which tells us we are in resync
79df930be7Sderaadt * mode; looking for a valid header), and cnt (which starts at zero)
80df930be7Sderaadt * which is used to count the number of empty blocks we have seen so far.
81df930be7Sderaadt * Return:
82df930be7Sderaadt * 0 if a valid trailer, -1 if not a valid trailer,
83df930be7Sderaadt */
84df930be7Sderaadt
85df930be7Sderaadt int
cpio_trail(ARCHD * arcn,char * notused,int notused2,int * notused3)86cd90c754Sderaadt cpio_trail(ARCHD *arcn, char *notused, int notused2, int *notused3)
87df930be7Sderaadt {
88df930be7Sderaadt /*
89df930be7Sderaadt * look for trailer id in file we are about to process
90df930be7Sderaadt */
91df930be7Sderaadt if ((strcmp(arcn->name, TRAILER) == 0) && (arcn->sb.st_size == 0))
92df930be7Sderaadt return(0);
93df930be7Sderaadt return(-1);
94df930be7Sderaadt }
95df930be7Sderaadt
96df930be7Sderaadt /*
97df930be7Sderaadt * com_rd()
98df930be7Sderaadt * operations common to all cpio read functions.
99df930be7Sderaadt * Return:
100df930be7Sderaadt * 0
101df930be7Sderaadt */
102df930be7Sderaadt
103df930be7Sderaadt static int
com_rd(ARCHD * arcn)104be87792eSmillert com_rd(ARCHD *arcn)
105df930be7Sderaadt {
106df930be7Sderaadt arcn->skip = 0;
107df930be7Sderaadt arcn->pat = NULL;
108df930be7Sderaadt arcn->org_name = arcn->name;
109df930be7Sderaadt switch (arcn->sb.st_mode & C_IFMT) {
110df930be7Sderaadt case C_ISFIFO:
111df930be7Sderaadt arcn->type = PAX_FIF;
112df930be7Sderaadt break;
113df930be7Sderaadt case C_ISDIR:
114df930be7Sderaadt arcn->type = PAX_DIR;
115df930be7Sderaadt break;
116df930be7Sderaadt case C_ISBLK:
117df930be7Sderaadt arcn->type = PAX_BLK;
118df930be7Sderaadt break;
119df930be7Sderaadt case C_ISCHR:
120df930be7Sderaadt arcn->type = PAX_CHR;
121df930be7Sderaadt break;
122df930be7Sderaadt case C_ISLNK:
123df930be7Sderaadt arcn->type = PAX_SLK;
124df930be7Sderaadt break;
125df930be7Sderaadt case C_ISOCK:
126df930be7Sderaadt arcn->type = PAX_SCK;
127df930be7Sderaadt break;
128df930be7Sderaadt case C_ISCTG:
129df930be7Sderaadt case C_ISREG:
130df930be7Sderaadt default:
131df930be7Sderaadt /*
132df930be7Sderaadt * we have file data, set up skip (pad is set in the format
133df930be7Sderaadt * specific sections)
134df930be7Sderaadt */
135df930be7Sderaadt arcn->sb.st_mode = (arcn->sb.st_mode & 0xfff) | C_ISREG;
136df930be7Sderaadt arcn->type = PAX_REG;
137df930be7Sderaadt arcn->skip = arcn->sb.st_size;
138df930be7Sderaadt break;
139df930be7Sderaadt }
140df930be7Sderaadt if (chk_lnk(arcn) < 0)
141df930be7Sderaadt return(-1);
142df930be7Sderaadt return(0);
143df930be7Sderaadt }
144df930be7Sderaadt
145df930be7Sderaadt /*
1463f3cfa71Stobias * cpio_endwr()
147df930be7Sderaadt * write the special file with the name trailer in the proper format
148df930be7Sderaadt * Return:
149df930be7Sderaadt * result of the write of the trailer from the cpio specific write func
150df930be7Sderaadt */
151df930be7Sderaadt
152df930be7Sderaadt int
cpio_endwr(void)153df930be7Sderaadt cpio_endwr(void)
154df930be7Sderaadt {
155df930be7Sderaadt ARCHD last;
156df930be7Sderaadt
157df930be7Sderaadt /*
158df930be7Sderaadt * create a trailer request and call the proper format write function
159df930be7Sderaadt */
160df930be7Sderaadt memset(&last, 0, sizeof(last));
161df930be7Sderaadt last.nlen = sizeof(TRAILER) - 1;
162df930be7Sderaadt last.type = PAX_REG;
163df930be7Sderaadt last.sb.st_nlink = 1;
1644efeba66Sitojun (void)strlcpy(last.name, TRAILER, sizeof(last.name));
165df930be7Sderaadt return((*frmt->wr)(&last));
166df930be7Sderaadt }
167df930be7Sderaadt
168df930be7Sderaadt /*
1694346e15aSlum * rd_nm()
170df930be7Sderaadt * read in the file name which follows the cpio header
171df930be7Sderaadt * Return:
172df930be7Sderaadt * 0 if ok, -1 otherwise
173df930be7Sderaadt */
174df930be7Sderaadt
175df930be7Sderaadt static int
rd_nm(ARCHD * arcn,int nsz)176be87792eSmillert rd_nm(ARCHD *arcn, int nsz)
177df930be7Sderaadt {
178df930be7Sderaadt /*
179df930be7Sderaadt * do not even try bogus values
180df930be7Sderaadt */
181a38f4902Sotto if ((nsz == 0) || ((size_t)nsz > sizeof(arcn->name))) {
18242cf9836Stholo paxwarn(1, "Cpio file name length %d is out of range", nsz);
183df930be7Sderaadt return(-1);
184df930be7Sderaadt }
185df930be7Sderaadt
186df930be7Sderaadt /*
187df930be7Sderaadt * read the name and make sure it is not empty and is \0 terminated
188df930be7Sderaadt */
189df930be7Sderaadt if ((rd_wrbuf(arcn->name,nsz) != nsz) || (arcn->name[nsz-1] != '\0') ||
190df930be7Sderaadt (arcn->name[0] == '\0')) {
19142cf9836Stholo paxwarn(1, "Cpio file name in header is corrupted");
192df930be7Sderaadt return(-1);
193df930be7Sderaadt }
194df930be7Sderaadt return(0);
195df930be7Sderaadt }
196df930be7Sderaadt
197df930be7Sderaadt /*
198df930be7Sderaadt * rd_ln_nm()
199df930be7Sderaadt * read in the link name for a file with links. The link name is stored
200df930be7Sderaadt * like file data (and is NOT \0 terminated!)
201df930be7Sderaadt * Return:
202df930be7Sderaadt * 0 if ok, -1 otherwise
203df930be7Sderaadt */
204df930be7Sderaadt
205df930be7Sderaadt static int
rd_ln_nm(ARCHD * arcn)206be87792eSmillert rd_ln_nm(ARCHD *arcn)
207df930be7Sderaadt {
208df930be7Sderaadt /*
209df930be7Sderaadt * check the length specified for bogus values
210df930be7Sderaadt */
211a38f4902Sotto if ((arcn->sb.st_size <= 0) ||
212a38f4902Sotto (arcn->sb.st_size >= (off_t)sizeof(arcn->ln_name))) {
213a38f4902Sotto paxwarn(1, "Cpio link name length is invalid: %lld",
214df930be7Sderaadt arcn->sb.st_size);
215df930be7Sderaadt return(-1);
216df930be7Sderaadt }
217df930be7Sderaadt
218df930be7Sderaadt /*
219df930be7Sderaadt * read in the link name and \0 terminate it
220df930be7Sderaadt */
221df930be7Sderaadt if (rd_wrbuf(arcn->ln_name, (int)arcn->sb.st_size) !=
222df930be7Sderaadt (int)arcn->sb.st_size) {
22342cf9836Stholo paxwarn(1, "Cpio link name read error");
224df930be7Sderaadt return(-1);
225df930be7Sderaadt }
226df930be7Sderaadt arcn->ln_nlen = arcn->sb.st_size;
227df930be7Sderaadt arcn->ln_name[arcn->ln_nlen] = '\0';
228df930be7Sderaadt
229df930be7Sderaadt /*
230df930be7Sderaadt * watch out for those empty link names
231df930be7Sderaadt */
232df930be7Sderaadt if (arcn->ln_name[0] == '\0') {
23342cf9836Stholo paxwarn(1, "Cpio link name is corrupt");
234df930be7Sderaadt return(-1);
235df930be7Sderaadt }
236df930be7Sderaadt return(0);
237df930be7Sderaadt }
238df930be7Sderaadt
239df930be7Sderaadt /*
240df930be7Sderaadt * Routines common to the extended byte oriented cpio format
241df930be7Sderaadt */
242df930be7Sderaadt
243df930be7Sderaadt /*
244df930be7Sderaadt * cpio_id()
245df930be7Sderaadt * determine if a block given to us is a valid extended byte oriented
246df930be7Sderaadt * cpio header
247df930be7Sderaadt * Return:
248df930be7Sderaadt * 0 if a valid header, -1 otherwise
249df930be7Sderaadt */
250df930be7Sderaadt
251df930be7Sderaadt int
cpio_id(char * blk,int size)252df930be7Sderaadt cpio_id(char *blk, int size)
253df930be7Sderaadt {
254b95ac8d3Sotto if ((size < (int)sizeof(HD_CPIO)) ||
255df930be7Sderaadt (strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0))
256df930be7Sderaadt return(-1);
257df930be7Sderaadt return(0);
258df930be7Sderaadt }
259df930be7Sderaadt
260df930be7Sderaadt /*
261df930be7Sderaadt * cpio_rd()
262df930be7Sderaadt * determine if a buffer is a byte oriented extended cpio archive entry.
263df930be7Sderaadt * convert and store the values in the ARCHD parameter.
264df930be7Sderaadt * Return:
265df930be7Sderaadt * 0 if a valid header, -1 otherwise.
266df930be7Sderaadt */
267df930be7Sderaadt
268df930be7Sderaadt int
cpio_rd(ARCHD * arcn,char * buf)269be87792eSmillert cpio_rd(ARCHD *arcn, char *buf)
270df930be7Sderaadt {
271be87792eSmillert int nsz;
272f37d86feSguenther unsigned long long val;
273be87792eSmillert HD_CPIO *hd;
274df930be7Sderaadt
275df930be7Sderaadt /*
276df930be7Sderaadt * check that this is a valid header, if not return -1
277df930be7Sderaadt */
278df930be7Sderaadt if (cpio_id(buf, sizeof(HD_CPIO)) < 0)
279df930be7Sderaadt return(-1);
280df930be7Sderaadt hd = (HD_CPIO *)buf;
281df930be7Sderaadt
282df930be7Sderaadt /*
283df930be7Sderaadt * byte oriented cpio (posix) does not have padding! extract the octal
284df930be7Sderaadt * ascii fields from the header
285df930be7Sderaadt */
2869a58b8c6Sguenther arcn->pad = 0;
287df930be7Sderaadt arcn->sb.st_dev = (dev_t)asc_ul(hd->c_dev, sizeof(hd->c_dev), OCT);
288df930be7Sderaadt arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), OCT);
289df930be7Sderaadt arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), OCT);
290df930be7Sderaadt arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), OCT);
291df930be7Sderaadt arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), OCT);
292df930be7Sderaadt arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
293df930be7Sderaadt OCT);
294df930be7Sderaadt arcn->sb.st_rdev = (dev_t)asc_ul(hd->c_rdev, sizeof(hd->c_rdev), OCT);
295f37d86feSguenther val = asc_ull(hd->c_mtime, sizeof(hd->c_mtime), OCT);
29676c0e1cfSotto if (val > MAX_TIME_T)
297*2f186deaSmillert arcn->sb.st_mtime = MAX_TIME_T;
298bdaaddddSguenther else
299bdaaddddSguenther arcn->sb.st_mtime = val;
3008b72bc25Sguenther arcn->sb.st_mtim.tv_nsec = 0;
3018b72bc25Sguenther arcn->sb.st_ctim = arcn->sb.st_atim = arcn->sb.st_mtim;
302f37d86feSguenther arcn->sb.st_size = (off_t)asc_ull(hd->c_filesize,sizeof(hd->c_filesize),
303df930be7Sderaadt OCT);
304df930be7Sderaadt
305df930be7Sderaadt /*
306df930be7Sderaadt * check name size and if valid, read in the name of this entry (name
307df930be7Sderaadt * follows header in the archive)
308df930be7Sderaadt */
309df930be7Sderaadt if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2)
310df930be7Sderaadt return(-1);
311df930be7Sderaadt arcn->nlen = nsz - 1;
312df930be7Sderaadt if (rd_nm(arcn, nsz) < 0)
313df930be7Sderaadt return(-1);
314df930be7Sderaadt
315df930be7Sderaadt if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
316df930be7Sderaadt /*
317df930be7Sderaadt * no link name to read for this file
318df930be7Sderaadt */
319df930be7Sderaadt arcn->ln_nlen = 0;
320df930be7Sderaadt arcn->ln_name[0] = '\0';
321df930be7Sderaadt return(com_rd(arcn));
322df930be7Sderaadt }
323df930be7Sderaadt
324df930be7Sderaadt /*
325df930be7Sderaadt * check link name size and read in the link name. Link names are
326df930be7Sderaadt * stored like file data.
327df930be7Sderaadt */
328df930be7Sderaadt if (rd_ln_nm(arcn) < 0)
329df930be7Sderaadt return(-1);
330df930be7Sderaadt
331df930be7Sderaadt /*
332df930be7Sderaadt * we have a valid header (with a link)
333df930be7Sderaadt */
334df930be7Sderaadt return(com_rd(arcn));
335df930be7Sderaadt }
336df930be7Sderaadt
337df930be7Sderaadt /*
338df930be7Sderaadt * cpio_endrd()
339df930be7Sderaadt * no cleanup needed here, just return size of the trailer (for append)
340df930be7Sderaadt * Return:
341df930be7Sderaadt * size of trailer header in this format
342df930be7Sderaadt */
343df930be7Sderaadt
344df930be7Sderaadt off_t
cpio_endrd(void)345df930be7Sderaadt cpio_endrd(void)
346df930be7Sderaadt {
3479a58b8c6Sguenther return sizeof(HD_CPIO) + sizeof(TRAILER);
348df930be7Sderaadt }
349df930be7Sderaadt
350df930be7Sderaadt /*
351df930be7Sderaadt * cpio_stwr()
352df930be7Sderaadt * start up the device mapping table
353df930be7Sderaadt * Return:
354df930be7Sderaadt * 0 if ok, -1 otherwise (what dev_start() returns)
355df930be7Sderaadt */
356df930be7Sderaadt
357df930be7Sderaadt int
cpio_stwr(void)358df930be7Sderaadt cpio_stwr(void)
359df930be7Sderaadt {
360df930be7Sderaadt return(dev_start());
361df930be7Sderaadt }
362df930be7Sderaadt
363df930be7Sderaadt /*
364df930be7Sderaadt * cpio_wr()
365df930be7Sderaadt * copy the data in the ARCHD to buffer in extended byte oriented cpio
366df930be7Sderaadt * format.
367df930be7Sderaadt * Return
368df930be7Sderaadt * 0 if file has data to be written after the header, 1 if file has NO
369df930be7Sderaadt * data to write after the header, -1 if archive write failed
370df930be7Sderaadt */
371df930be7Sderaadt
372df930be7Sderaadt int
cpio_wr(ARCHD * arcn)373be87792eSmillert cpio_wr(ARCHD *arcn)
374df930be7Sderaadt {
375be87792eSmillert HD_CPIO *hd;
376be87792eSmillert int nsz;
377df930be7Sderaadt char hdblk[sizeof(HD_CPIO)];
378df930be7Sderaadt
379df930be7Sderaadt /*
380df930be7Sderaadt * check and repair truncated device and inode fields in the header
381df930be7Sderaadt */
3829a58b8c6Sguenther if (map_dev(arcn, CPIO_MASK, CPIO_MASK) < 0)
383df930be7Sderaadt return(-1);
384df930be7Sderaadt
3859a58b8c6Sguenther arcn->pad = 0;
386df930be7Sderaadt nsz = arcn->nlen + 1;
387df930be7Sderaadt hd = (HD_CPIO *)hdblk;
388df930be7Sderaadt if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
389df930be7Sderaadt arcn->sb.st_rdev = 0;
390df930be7Sderaadt
391df930be7Sderaadt switch (arcn->type) {
392df930be7Sderaadt case PAX_CTG:
393df930be7Sderaadt case PAX_REG:
394df930be7Sderaadt case PAX_HRG:
395df930be7Sderaadt /*
396df930be7Sderaadt * set data size for file data
397df930be7Sderaadt */
398f37d86feSguenther if (ull_asc(arcn->sb.st_size, hd->c_filesize,
399df930be7Sderaadt sizeof(hd->c_filesize), OCT)) {
40042cf9836Stholo paxwarn(1,"File is too large for cpio format %s",
401df930be7Sderaadt arcn->org_name);
402df930be7Sderaadt return(1);
403df930be7Sderaadt }
404df930be7Sderaadt break;
405df930be7Sderaadt case PAX_SLK:
406df930be7Sderaadt /*
407df930be7Sderaadt * set data size to hold link name
408df930be7Sderaadt */
4099a58b8c6Sguenther if (ul_asc(arcn->ln_nlen, hd->c_filesize,
410df930be7Sderaadt sizeof(hd->c_filesize), OCT))
411df930be7Sderaadt goto out;
412df930be7Sderaadt break;
413df930be7Sderaadt default:
414df930be7Sderaadt /*
415df930be7Sderaadt * all other file types have no file data
416df930be7Sderaadt */
4179a58b8c6Sguenther if (ul_asc(0, hd->c_filesize, sizeof(hd->c_filesize), OCT))
418df930be7Sderaadt goto out;
419df930be7Sderaadt break;
420df930be7Sderaadt }
421df930be7Sderaadt
422df930be7Sderaadt /*
423df930be7Sderaadt * copy the values to the header using octal ascii
424df930be7Sderaadt */
4259a58b8c6Sguenther if (ul_asc(MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) ||
4269a58b8c6Sguenther ul_asc(arcn->sb.st_dev, hd->c_dev, sizeof(hd->c_dev), OCT) ||
4279a58b8c6Sguenther ul_asc(arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino), OCT) ||
4289a58b8c6Sguenther ul_asc(arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode), OCT) ||
4299a58b8c6Sguenther ul_asc(arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid), OCT) ||
4309a58b8c6Sguenther ul_asc(arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid), OCT) ||
4319a58b8c6Sguenther ul_asc(arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink), OCT) ||
4329a58b8c6Sguenther ul_asc(arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev), OCT) ||
433f37d86feSguenther ull_asc(arcn->sb.st_mtime < 0 ? 0 : arcn->sb.st_mtime, hd->c_mtime,
434b5f8b155Sguenther sizeof(hd->c_mtime), OCT) ||
4359a58b8c6Sguenther ul_asc(nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT))
436df930be7Sderaadt goto out;
437df930be7Sderaadt
438df930be7Sderaadt /*
439df930be7Sderaadt * write the file name to the archive
440df930be7Sderaadt */
441df930be7Sderaadt if ((wr_rdbuf(hdblk, (int)sizeof(HD_CPIO)) < 0) ||
442df930be7Sderaadt (wr_rdbuf(arcn->name, nsz) < 0)) {
44342cf9836Stholo paxwarn(1, "Unable to write cpio header for %s", arcn->org_name);
444df930be7Sderaadt return(-1);
445df930be7Sderaadt }
446df930be7Sderaadt
447df930be7Sderaadt /*
448df930be7Sderaadt * if this file has data, we are done. The caller will write the file
449df930be7Sderaadt * data, if we are link tell caller we are done, go to next file
450df930be7Sderaadt */
4515316f7a4Sguenther if (PAX_IS_REG(arcn->type) || (arcn->type == PAX_HRG))
452df930be7Sderaadt return(0);
453df930be7Sderaadt if (arcn->type != PAX_SLK)
454df930be7Sderaadt return(1);
455df930be7Sderaadt
456df930be7Sderaadt /*
457df930be7Sderaadt * write the link name to the archive, tell the caller to go to the
458df930be7Sderaadt * next file as we are done.
459df930be7Sderaadt */
460df930be7Sderaadt if (wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) {
46142cf9836Stholo paxwarn(1,"Unable to write cpio link name for %s",arcn->org_name);
462df930be7Sderaadt return(-1);
463df930be7Sderaadt }
464df930be7Sderaadt return(1);
465df930be7Sderaadt
466df930be7Sderaadt out:
467df930be7Sderaadt /*
468df930be7Sderaadt * header field is out of range
469df930be7Sderaadt */
47042cf9836Stholo paxwarn(1, "Cpio header field is too small to store file %s",
471df930be7Sderaadt arcn->org_name);
472df930be7Sderaadt return(1);
473df930be7Sderaadt }
474df930be7Sderaadt
475df930be7Sderaadt /*
476df930be7Sderaadt * Routines common to the system VR4 version of cpio (with/without file CRC)
477df930be7Sderaadt */
478df930be7Sderaadt
479df930be7Sderaadt /*
480df930be7Sderaadt * vcpio_id()
481df930be7Sderaadt * determine if a block given to us is a valid system VR4 cpio header
482df930be7Sderaadt * WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header
483df930be7Sderaadt * uses HEX
484df930be7Sderaadt * Return:
485df930be7Sderaadt * 0 if a valid header, -1 otherwise
486df930be7Sderaadt */
487df930be7Sderaadt
488df930be7Sderaadt int
vcpio_id(char * blk,int size)489df930be7Sderaadt vcpio_id(char *blk, int size)
490df930be7Sderaadt {
491b95ac8d3Sotto if ((size < (int)sizeof(HD_VCPIO)) ||
492df930be7Sderaadt (strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0))
493df930be7Sderaadt return(-1);
494df930be7Sderaadt return(0);
495df930be7Sderaadt }
496df930be7Sderaadt
497df930be7Sderaadt /*
498df930be7Sderaadt * crc_id()
499df930be7Sderaadt * determine if a block given to us is a valid system VR4 cpio header
500df930be7Sderaadt * WITH crc. WATCH it the magic cookies are in OCTAL the header uses HEX
501df930be7Sderaadt * Return:
502df930be7Sderaadt * 0 if a valid header, -1 otherwise
503df930be7Sderaadt */
504df930be7Sderaadt
505df930be7Sderaadt int
crc_id(char * blk,int size)506df930be7Sderaadt crc_id(char *blk, int size)
507df930be7Sderaadt {
508b95ac8d3Sotto if ((size < (int)sizeof(HD_VCPIO)) ||
509df930be7Sderaadt (strncmp(blk, AVCMAGIC, sizeof(AVCMAGIC) - 1) != 0))
510df930be7Sderaadt return(-1);
511df930be7Sderaadt return(0);
512df930be7Sderaadt }
513df930be7Sderaadt
514df930be7Sderaadt /*
515df930be7Sderaadt * crc_strd()
516df930be7Sderaadt w set file data CRC calculations. Fire up the hard link detection code
517df930be7Sderaadt * Return:
518df930be7Sderaadt * 0 if ok -1 otherwise (the return values of lnk_start())
519df930be7Sderaadt */
520df930be7Sderaadt
521df930be7Sderaadt int
crc_strd(void)522df930be7Sderaadt crc_strd(void)
523df930be7Sderaadt {
524df930be7Sderaadt docrc = 1;
525df930be7Sderaadt return(lnk_start());
526df930be7Sderaadt }
527df930be7Sderaadt
528df930be7Sderaadt /*
529df930be7Sderaadt * vcpio_rd()
530df930be7Sderaadt * determine if a buffer is a system VR4 archive entry. (with/without CRC)
531df930be7Sderaadt * convert and store the values in the ARCHD parameter.
532df930be7Sderaadt * Return:
533df930be7Sderaadt * 0 if a valid header, -1 otherwise.
534df930be7Sderaadt */
535df930be7Sderaadt
536df930be7Sderaadt int
vcpio_rd(ARCHD * arcn,char * buf)537be87792eSmillert vcpio_rd(ARCHD *arcn, char *buf)
538df930be7Sderaadt {
539be87792eSmillert HD_VCPIO *hd;
540df930be7Sderaadt dev_t devminor;
541df930be7Sderaadt dev_t devmajor;
542be87792eSmillert int nsz;
543df930be7Sderaadt
544df930be7Sderaadt /*
545df930be7Sderaadt * during the id phase it was determined if we were using CRC, use the
546df930be7Sderaadt * proper id routine.
547df930be7Sderaadt */
548df930be7Sderaadt if (docrc) {
549df930be7Sderaadt if (crc_id(buf, sizeof(HD_VCPIO)) < 0)
550df930be7Sderaadt return(-1);
551df930be7Sderaadt } else {
552df930be7Sderaadt if (vcpio_id(buf, sizeof(HD_VCPIO)) < 0)
553df930be7Sderaadt return(-1);
554df930be7Sderaadt }
555df930be7Sderaadt
556df930be7Sderaadt hd = (HD_VCPIO *)buf;
5579a58b8c6Sguenther arcn->pad = 0;
558df930be7Sderaadt
559df930be7Sderaadt /*
560df930be7Sderaadt * extract the hex ascii fields from the header
561df930be7Sderaadt */
562df930be7Sderaadt arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), HEX);
563df930be7Sderaadt arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), HEX);
564df930be7Sderaadt arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), HEX);
565df930be7Sderaadt arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX);
566df930be7Sderaadt arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX);
5678b72bc25Sguenther arcn->sb.st_mtim.tv_nsec = 0;
5688b72bc25Sguenther arcn->sb.st_ctim = arcn->sb.st_atim = arcn->sb.st_mtim;
569f37d86feSguenther arcn->sb.st_size = (off_t)asc_ull(hd->c_filesize,
570df930be7Sderaadt sizeof(hd->c_filesize), HEX);
571df930be7Sderaadt arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
572df930be7Sderaadt HEX);
573df930be7Sderaadt devmajor = (dev_t)asc_ul(hd->c_maj, sizeof(hd->c_maj), HEX);
574df930be7Sderaadt devminor = (dev_t)asc_ul(hd->c_min, sizeof(hd->c_min), HEX);
575df930be7Sderaadt arcn->sb.st_dev = TODEV(devmajor, devminor);
576df930be7Sderaadt devmajor = (dev_t)asc_ul(hd->c_rmaj, sizeof(hd->c_maj), HEX);
577df930be7Sderaadt devminor = (dev_t)asc_ul(hd->c_rmin, sizeof(hd->c_min), HEX);
578df930be7Sderaadt arcn->sb.st_rdev = TODEV(devmajor, devminor);
579df930be7Sderaadt arcn->crc = asc_ul(hd->c_chksum, sizeof(hd->c_chksum), HEX);
580df930be7Sderaadt
581df930be7Sderaadt /*
582df930be7Sderaadt * check the length of the file name, if ok read it in, return -1 if
583df930be7Sderaadt * bogus
584df930be7Sderaadt */
585df930be7Sderaadt if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2)
586df930be7Sderaadt return(-1);
587df930be7Sderaadt arcn->nlen = nsz - 1;
588df930be7Sderaadt if (rd_nm(arcn, nsz) < 0)
589df930be7Sderaadt return(-1);
590df930be7Sderaadt
591df930be7Sderaadt /*
5924eb0b000Smillert * skip padding. header + filename is aligned to 4 byte boundaries
593df930be7Sderaadt */
5949a58b8c6Sguenther if (rd_skip(VCPIO_PAD(sizeof(HD_VCPIO) + nsz)) < 0)
595df930be7Sderaadt return(-1);
596df930be7Sderaadt
597df930be7Sderaadt /*
598df930be7Sderaadt * if not a link (or a file with no data), calculate pad size (for
599df930be7Sderaadt * padding which follows the file data), clear the link name and return
600df930be7Sderaadt */
601df930be7Sderaadt if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
602df930be7Sderaadt /*
603df930be7Sderaadt * we have a valid header (not a link)
604df930be7Sderaadt */
605df930be7Sderaadt arcn->ln_nlen = 0;
606df930be7Sderaadt arcn->ln_name[0] = '\0';
607df930be7Sderaadt arcn->pad = VCPIO_PAD(arcn->sb.st_size);
608df930be7Sderaadt return(com_rd(arcn));
609df930be7Sderaadt }
610df930be7Sderaadt
611df930be7Sderaadt /*
612df930be7Sderaadt * read in the link name and skip over the padding
613df930be7Sderaadt */
614df930be7Sderaadt if ((rd_ln_nm(arcn) < 0) ||
6159a58b8c6Sguenther (rd_skip(VCPIO_PAD(arcn->sb.st_size)) < 0))
616df930be7Sderaadt return(-1);
617df930be7Sderaadt
618df930be7Sderaadt /*
619df930be7Sderaadt * we have a valid header (with a link)
620df930be7Sderaadt */
621df930be7Sderaadt return(com_rd(arcn));
622df930be7Sderaadt }
623df930be7Sderaadt
624df930be7Sderaadt /*
625df930be7Sderaadt * vcpio_endrd()
626df930be7Sderaadt * no cleanup needed here, just return size of the trailer (for append)
627df930be7Sderaadt * Return:
628df930be7Sderaadt * size of trailer header in this format
629df930be7Sderaadt */
630df930be7Sderaadt
631df930be7Sderaadt off_t
vcpio_endrd(void)632df930be7Sderaadt vcpio_endrd(void)
633df930be7Sderaadt {
6349a58b8c6Sguenther return sizeof(HD_VCPIO) + sizeof(TRAILER) +
6359a58b8c6Sguenther (VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER)));
636df930be7Sderaadt }
637df930be7Sderaadt
638df930be7Sderaadt /*
639df930be7Sderaadt * crc_stwr()
640df930be7Sderaadt * start up the device mapping table, enable crc file calculation
641df930be7Sderaadt * Return:
642df930be7Sderaadt * 0 if ok, -1 otherwise (what dev_start() returns)
643df930be7Sderaadt */
644df930be7Sderaadt
645df930be7Sderaadt int
crc_stwr(void)646df930be7Sderaadt crc_stwr(void)
647df930be7Sderaadt {
648df930be7Sderaadt docrc = 1;
649df930be7Sderaadt return(dev_start());
650df930be7Sderaadt }
651df930be7Sderaadt
652df930be7Sderaadt /*
653df930be7Sderaadt * vcpio_wr()
654df930be7Sderaadt * copy the data in the ARCHD to buffer in system VR4 cpio
655df930be7Sderaadt * (with/without crc) format.
656df930be7Sderaadt * Return
657df930be7Sderaadt * 0 if file has data to be written after the header, 1 if file has
658df930be7Sderaadt * NO data to write after the header, -1 if archive write failed
659df930be7Sderaadt */
660df930be7Sderaadt
661df930be7Sderaadt int
vcpio_wr(ARCHD * arcn)662be87792eSmillert vcpio_wr(ARCHD *arcn)
663df930be7Sderaadt {
664be87792eSmillert HD_VCPIO *hd;
665df930be7Sderaadt unsigned int nsz;
666df930be7Sderaadt char hdblk[sizeof(HD_VCPIO)];
667df930be7Sderaadt
668df930be7Sderaadt /*
669df930be7Sderaadt * check and repair truncated device and inode fields in the cpio
670df930be7Sderaadt * header
671df930be7Sderaadt */
6729a58b8c6Sguenther if (map_dev(arcn, VCPIO_MASK, VCPIO_MASK) < 0)
673df930be7Sderaadt return(-1);
674df930be7Sderaadt nsz = arcn->nlen + 1;
675df930be7Sderaadt hd = (HD_VCPIO *)hdblk;
676df930be7Sderaadt if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
677df930be7Sderaadt arcn->sb.st_rdev = 0;
678df930be7Sderaadt
679df930be7Sderaadt /*
680df930be7Sderaadt * add the proper magic value depending whether we were asked for
681df930be7Sderaadt * file data crc's, and the crc if needed.
682df930be7Sderaadt */
683df930be7Sderaadt if (docrc) {
6849a58b8c6Sguenther if (ul_asc(VCMAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) ||
6859a58b8c6Sguenther ul_asc(arcn->crc,hd->c_chksum,sizeof(hd->c_chksum), HEX))
686df930be7Sderaadt goto out;
687df930be7Sderaadt } else {
6889a58b8c6Sguenther if (ul_asc(VMAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) ||
6899a58b8c6Sguenther ul_asc(0, hd->c_chksum, sizeof(hd->c_chksum),HEX))
690df930be7Sderaadt goto out;
691df930be7Sderaadt }
692df930be7Sderaadt
693df930be7Sderaadt switch (arcn->type) {
694df930be7Sderaadt case PAX_CTG:
695df930be7Sderaadt case PAX_REG:
696df930be7Sderaadt case PAX_HRG:
697df930be7Sderaadt /*
698df930be7Sderaadt * caller will copy file data to the archive. tell him how
699df930be7Sderaadt * much to pad.
700df930be7Sderaadt */
701df930be7Sderaadt arcn->pad = VCPIO_PAD(arcn->sb.st_size);
702f37d86feSguenther if (ull_asc(arcn->sb.st_size, hd->c_filesize,
703df930be7Sderaadt sizeof(hd->c_filesize), HEX)) {
70442cf9836Stholo paxwarn(1,"File is too large for sv4cpio format %s",
705df930be7Sderaadt arcn->org_name);
706df930be7Sderaadt return(1);
707df930be7Sderaadt }
708df930be7Sderaadt break;
709df930be7Sderaadt case PAX_SLK:
710df930be7Sderaadt /*
711df930be7Sderaadt * no file data for the caller to process, the file data has
712df930be7Sderaadt * the size of the link
713df930be7Sderaadt */
7149a58b8c6Sguenther arcn->pad = 0;
7159a58b8c6Sguenther if (ul_asc(arcn->ln_nlen, hd->c_filesize,
716df930be7Sderaadt sizeof(hd->c_filesize), HEX))
717df930be7Sderaadt goto out;
718df930be7Sderaadt break;
719df930be7Sderaadt default:
720df930be7Sderaadt /*
721df930be7Sderaadt * no file data for the caller to process
722df930be7Sderaadt */
7239a58b8c6Sguenther arcn->pad = 0;
7249a58b8c6Sguenther if (ul_asc(0, hd->c_filesize, sizeof(hd->c_filesize), HEX))
725df930be7Sderaadt goto out;
726df930be7Sderaadt break;
727df930be7Sderaadt }
728df930be7Sderaadt
729df930be7Sderaadt /*
730df930be7Sderaadt * set the other fields in the header
731df930be7Sderaadt */
7329a58b8c6Sguenther if (ul_asc(arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino), HEX) ||
7339a58b8c6Sguenther ul_asc(arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode), HEX) ||
7349a58b8c6Sguenther ul_asc(arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid), HEX) ||
7359a58b8c6Sguenther ul_asc(arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid), HEX) ||
736b5f8b155Sguenther ul_asc(arcn->sb.st_mtime < 0 ? 0 : arcn->sb.st_mtime, hd->c_mtime,
737b5f8b155Sguenther sizeof(hd->c_mtime), HEX) ||
7389a58b8c6Sguenther ul_asc(arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink), HEX) ||
7399a58b8c6Sguenther ul_asc(MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj), HEX) ||
7409a58b8c6Sguenther ul_asc(MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min), HEX) ||
7419a58b8c6Sguenther ul_asc(MAJOR(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj), HEX) ||
7429a58b8c6Sguenther ul_asc(MINOR(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min), HEX) ||
7439a58b8c6Sguenther ul_asc(nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX))
744df930be7Sderaadt goto out;
745df930be7Sderaadt
746df930be7Sderaadt /*
747df930be7Sderaadt * write the header, the file name and padding as required.
748df930be7Sderaadt */
749df930be7Sderaadt if ((wr_rdbuf(hdblk, (int)sizeof(HD_VCPIO)) < 0) ||
750df930be7Sderaadt (wr_rdbuf(arcn->name, (int)nsz) < 0) ||
7519a58b8c6Sguenther (wr_skip(VCPIO_PAD(sizeof(HD_VCPIO) + nsz)) < 0)) {
75242cf9836Stholo paxwarn(1,"Could not write sv4cpio header for %s",arcn->org_name);
753df930be7Sderaadt return(-1);
754df930be7Sderaadt }
755df930be7Sderaadt
756df930be7Sderaadt /*
757df930be7Sderaadt * if we have file data, tell the caller we are done, copy the file
758df930be7Sderaadt */
7595316f7a4Sguenther if (PAX_IS_REG(arcn->type) || (arcn->type == PAX_HRG))
760df930be7Sderaadt return(0);
761df930be7Sderaadt
762df930be7Sderaadt /*
763df930be7Sderaadt * if we are not a link, tell the caller we are done, go to next file
764df930be7Sderaadt */
765df930be7Sderaadt if (arcn->type != PAX_SLK)
766df930be7Sderaadt return(1);
767df930be7Sderaadt
768df930be7Sderaadt /*
769df930be7Sderaadt * write the link name, tell the caller we are done.
770df930be7Sderaadt */
771df930be7Sderaadt if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
7729a58b8c6Sguenther (wr_skip(VCPIO_PAD(arcn->ln_nlen)) < 0)) {
77342cf9836Stholo paxwarn(1,"Could not write sv4cpio link name for %s",
774df930be7Sderaadt arcn->org_name);
775df930be7Sderaadt return(-1);
776df930be7Sderaadt }
777df930be7Sderaadt return(1);
778df930be7Sderaadt
779df930be7Sderaadt out:
780df930be7Sderaadt /*
781df930be7Sderaadt * header field is out of range
782df930be7Sderaadt */
78342cf9836Stholo paxwarn(1,"Sv4cpio header field is too small for file %s",arcn->org_name);
784df930be7Sderaadt return(1);
785df930be7Sderaadt }
786df930be7Sderaadt
787df930be7Sderaadt /*
788df930be7Sderaadt * Routines common to the old binary header cpio
789df930be7Sderaadt */
790df930be7Sderaadt
791df930be7Sderaadt /*
792df930be7Sderaadt * bcpio_id()
793df930be7Sderaadt * determine if a block given to us is a old binary cpio header
794df930be7Sderaadt * (with/without header byte swapping)
795df930be7Sderaadt * Return:
796df930be7Sderaadt * 0 if a valid header, -1 otherwise
797df930be7Sderaadt */
798df930be7Sderaadt
799df930be7Sderaadt int
bcpio_id(char * blk,int size)800df930be7Sderaadt bcpio_id(char *blk, int size)
801df930be7Sderaadt {
802b95ac8d3Sotto if (size < (int)sizeof(HD_BCPIO))
803df930be7Sderaadt return(-1);
804df930be7Sderaadt
805df930be7Sderaadt /*
806df930be7Sderaadt * check both normal and byte swapped magic cookies
807df930be7Sderaadt */
808df930be7Sderaadt if (((u_short)SHRT_EXT(blk)) == MAGIC)
809df930be7Sderaadt return(0);
810df930be7Sderaadt if (((u_short)RSHRT_EXT(blk)) == MAGIC) {
811df930be7Sderaadt if (!swp_head)
812df930be7Sderaadt ++swp_head;
813df930be7Sderaadt return(0);
814df930be7Sderaadt }
815df930be7Sderaadt return(-1);
816df930be7Sderaadt }
817df930be7Sderaadt
818df930be7Sderaadt /*
819df930be7Sderaadt * bcpio_rd()
820df930be7Sderaadt * determine if a buffer is a old binary archive entry. (it may have byte
821df930be7Sderaadt * swapped header) convert and store the values in the ARCHD parameter.
822df930be7Sderaadt * This is a very old header format and should not really be used.
823df930be7Sderaadt * Return:
824df930be7Sderaadt * 0 if a valid header, -1 otherwise.
825df930be7Sderaadt */
826df930be7Sderaadt
827df930be7Sderaadt int
bcpio_rd(ARCHD * arcn,char * buf)828be87792eSmillert bcpio_rd(ARCHD *arcn, char *buf)
829df930be7Sderaadt {
830be87792eSmillert HD_BCPIO *hd;
831be87792eSmillert int nsz;
832df930be7Sderaadt
833df930be7Sderaadt /*
834df930be7Sderaadt * check the header
835df930be7Sderaadt */
836df930be7Sderaadt if (bcpio_id(buf, sizeof(HD_BCPIO)) < 0)
837df930be7Sderaadt return(-1);
838df930be7Sderaadt
8399a58b8c6Sguenther arcn->pad = 0;
840df930be7Sderaadt hd = (HD_BCPIO *)buf;
841df930be7Sderaadt if (swp_head) {
842df930be7Sderaadt /*
8434eb0b000Smillert * header has swapped bytes on 16 bit boundaries
844df930be7Sderaadt */
845df930be7Sderaadt arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev));
846df930be7Sderaadt arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino));
847df930be7Sderaadt arcn->sb.st_mode = (mode_t)(RSHRT_EXT(hd->h_mode));
848df930be7Sderaadt arcn->sb.st_uid = (uid_t)(RSHRT_EXT(hd->h_uid));
849df930be7Sderaadt arcn->sb.st_gid = (gid_t)(RSHRT_EXT(hd->h_gid));
850df930be7Sderaadt arcn->sb.st_nlink = (nlink_t)(RSHRT_EXT(hd->h_nlink));
851df930be7Sderaadt arcn->sb.st_rdev = (dev_t)(RSHRT_EXT(hd->h_rdev));
852df930be7Sderaadt arcn->sb.st_mtime = (time_t)(RSHRT_EXT(hd->h_mtime_1));
853df930be7Sderaadt arcn->sb.st_mtime = (arcn->sb.st_mtime << 16) |
854df930be7Sderaadt ((time_t)(RSHRT_EXT(hd->h_mtime_2)));
855df930be7Sderaadt arcn->sb.st_size = (off_t)(RSHRT_EXT(hd->h_filesize_1));
856df930be7Sderaadt arcn->sb.st_size = (arcn->sb.st_size << 16) |
857df930be7Sderaadt ((off_t)(RSHRT_EXT(hd->h_filesize_2)));
858df930be7Sderaadt nsz = (int)(RSHRT_EXT(hd->h_namesize));
859df930be7Sderaadt } else {
860df930be7Sderaadt arcn->sb.st_dev = (dev_t)(SHRT_EXT(hd->h_dev));
861df930be7Sderaadt arcn->sb.st_ino = (ino_t)(SHRT_EXT(hd->h_ino));
862df930be7Sderaadt arcn->sb.st_mode = (mode_t)(SHRT_EXT(hd->h_mode));
863df930be7Sderaadt arcn->sb.st_uid = (uid_t)(SHRT_EXT(hd->h_uid));
864df930be7Sderaadt arcn->sb.st_gid = (gid_t)(SHRT_EXT(hd->h_gid));
865df930be7Sderaadt arcn->sb.st_nlink = (nlink_t)(SHRT_EXT(hd->h_nlink));
866df930be7Sderaadt arcn->sb.st_rdev = (dev_t)(SHRT_EXT(hd->h_rdev));
867df930be7Sderaadt arcn->sb.st_mtime = (time_t)(SHRT_EXT(hd->h_mtime_1));
868df930be7Sderaadt arcn->sb.st_mtime = (arcn->sb.st_mtime << 16) |
869df930be7Sderaadt ((time_t)(SHRT_EXT(hd->h_mtime_2)));
870df930be7Sderaadt arcn->sb.st_size = (off_t)(SHRT_EXT(hd->h_filesize_1));
871df930be7Sderaadt arcn->sb.st_size = (arcn->sb.st_size << 16) |
872df930be7Sderaadt ((off_t)(SHRT_EXT(hd->h_filesize_2)));
873df930be7Sderaadt nsz = (int)(SHRT_EXT(hd->h_namesize));
874df930be7Sderaadt }
8758b72bc25Sguenther arcn->sb.st_mtim.tv_nsec = 0;
8768b72bc25Sguenther arcn->sb.st_ctim = arcn->sb.st_atim = arcn->sb.st_mtim;
877df930be7Sderaadt
878df930be7Sderaadt /*
879df930be7Sderaadt * check the file name size, if bogus give up. otherwise read the file
880df930be7Sderaadt * name
881df930be7Sderaadt */
882df930be7Sderaadt if (nsz < 2)
883df930be7Sderaadt return(-1);
884df930be7Sderaadt arcn->nlen = nsz - 1;
885df930be7Sderaadt if (rd_nm(arcn, nsz) < 0)
886df930be7Sderaadt return(-1);
887df930be7Sderaadt
888df930be7Sderaadt /*
8894eb0b000Smillert * header + file name are aligned to 2 byte boundaries, skip if needed
890df930be7Sderaadt */
8919a58b8c6Sguenther if (rd_skip(BCPIO_PAD(sizeof(HD_BCPIO) + nsz)) < 0)
892df930be7Sderaadt return(-1);
893df930be7Sderaadt
894df930be7Sderaadt /*
895df930be7Sderaadt * if not a link (or a file with no data), calculate pad size (for
896df930be7Sderaadt * padding which follows the file data), clear the link name and return
897df930be7Sderaadt */
898df930be7Sderaadt if (((arcn->sb.st_mode & C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)){
899df930be7Sderaadt /*
900df930be7Sderaadt * we have a valid header (not a link)
901df930be7Sderaadt */
902df930be7Sderaadt arcn->ln_nlen = 0;
903df930be7Sderaadt arcn->ln_name[0] = '\0';
904df930be7Sderaadt arcn->pad = BCPIO_PAD(arcn->sb.st_size);
905df930be7Sderaadt return(com_rd(arcn));
906df930be7Sderaadt }
907df930be7Sderaadt
908df930be7Sderaadt if ((rd_ln_nm(arcn) < 0) ||
9099a58b8c6Sguenther (rd_skip(BCPIO_PAD(arcn->sb.st_size)) < 0))
910df930be7Sderaadt return(-1);
911df930be7Sderaadt
912df930be7Sderaadt /*
913df930be7Sderaadt * we have a valid header (with a link)
914df930be7Sderaadt */
915df930be7Sderaadt return(com_rd(arcn));
916df930be7Sderaadt }
917df930be7Sderaadt
918df930be7Sderaadt /*
919df930be7Sderaadt * bcpio_endrd()
920df930be7Sderaadt * no cleanup needed here, just return size of the trailer (for append)
921df930be7Sderaadt * Return:
922df930be7Sderaadt * size of trailer header in this format
923df930be7Sderaadt */
924df930be7Sderaadt
925df930be7Sderaadt off_t
bcpio_endrd(void)926df930be7Sderaadt bcpio_endrd(void)
927df930be7Sderaadt {
9289a58b8c6Sguenther return sizeof(HD_BCPIO) + sizeof(TRAILER) +
9299a58b8c6Sguenther (BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER)));
930df930be7Sderaadt }
931df930be7Sderaadt
932df930be7Sderaadt /*
933df930be7Sderaadt * bcpio_wr()
934df930be7Sderaadt * copy the data in the ARCHD to buffer in old binary cpio format
935df930be7Sderaadt * There is a real chance of field overflow with this critter. So we
936f0f82a05Sjmc * always check the conversion is ok. nobody in their right mind
9374eb0b000Smillert * should write an archive in this format...
938df930be7Sderaadt * Return
939df930be7Sderaadt * 0 if file has data to be written after the header, 1 if file has NO
940df930be7Sderaadt * data to write after the header, -1 if archive write failed
941df930be7Sderaadt */
942df930be7Sderaadt
943df930be7Sderaadt int
bcpio_wr(ARCHD * arcn)944be87792eSmillert bcpio_wr(ARCHD *arcn)
945df930be7Sderaadt {
946be87792eSmillert HD_BCPIO *hd;
947be87792eSmillert int nsz;
948df930be7Sderaadt char hdblk[sizeof(HD_BCPIO)];
949df930be7Sderaadt off_t t_offt;
950df930be7Sderaadt int t_int;
951df930be7Sderaadt time_t t_timet;
952df930be7Sderaadt
953df930be7Sderaadt /*
954df930be7Sderaadt * check and repair truncated device and inode fields in the cpio
955df930be7Sderaadt * header
956df930be7Sderaadt */
9579a58b8c6Sguenther if (map_dev(arcn, BCPIO_MASK, BCPIO_MASK) < 0)
958df930be7Sderaadt return(-1);
959df930be7Sderaadt
960df930be7Sderaadt if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
961df930be7Sderaadt arcn->sb.st_rdev = 0;
962df930be7Sderaadt hd = (HD_BCPIO *)hdblk;
963df930be7Sderaadt
964df930be7Sderaadt switch (arcn->type) {
965df930be7Sderaadt case PAX_CTG:
966df930be7Sderaadt case PAX_REG:
967df930be7Sderaadt case PAX_HRG:
968df930be7Sderaadt /*
969df930be7Sderaadt * caller will copy file data to the archive. tell him how
970df930be7Sderaadt * much to pad.
971df930be7Sderaadt */
972df930be7Sderaadt arcn->pad = BCPIO_PAD(arcn->sb.st_size);
973df930be7Sderaadt hd->h_filesize_1[0] = CHR_WR_0(arcn->sb.st_size);
974df930be7Sderaadt hd->h_filesize_1[1] = CHR_WR_1(arcn->sb.st_size);
975df930be7Sderaadt hd->h_filesize_2[0] = CHR_WR_2(arcn->sb.st_size);
976df930be7Sderaadt hd->h_filesize_2[1] = CHR_WR_3(arcn->sb.st_size);
977df930be7Sderaadt t_offt = (off_t)(SHRT_EXT(hd->h_filesize_1));
978df930be7Sderaadt t_offt = (t_offt<<16) | ((off_t)(SHRT_EXT(hd->h_filesize_2)));
979df930be7Sderaadt if (arcn->sb.st_size != t_offt) {
98042cf9836Stholo paxwarn(1,"File is too large for bcpio format %s",
981df930be7Sderaadt arcn->org_name);
982df930be7Sderaadt return(1);
983df930be7Sderaadt }
984df930be7Sderaadt break;
985df930be7Sderaadt case PAX_SLK:
986df930be7Sderaadt /*
987df930be7Sderaadt * no file data for the caller to process, the file data has
988df930be7Sderaadt * the size of the link
989df930be7Sderaadt */
9909a58b8c6Sguenther arcn->pad = 0;
991df930be7Sderaadt hd->h_filesize_1[0] = CHR_WR_0(arcn->ln_nlen);
992df930be7Sderaadt hd->h_filesize_1[1] = CHR_WR_1(arcn->ln_nlen);
993df930be7Sderaadt hd->h_filesize_2[0] = CHR_WR_2(arcn->ln_nlen);
994df930be7Sderaadt hd->h_filesize_2[1] = CHR_WR_3(arcn->ln_nlen);
995df930be7Sderaadt t_int = (int)(SHRT_EXT(hd->h_filesize_1));
996df930be7Sderaadt t_int = (t_int << 16) | ((int)(SHRT_EXT(hd->h_filesize_2)));
997df930be7Sderaadt if (arcn->ln_nlen != t_int)
998df930be7Sderaadt goto out;
999df930be7Sderaadt break;
1000df930be7Sderaadt default:
1001df930be7Sderaadt /*
1002df930be7Sderaadt * no file data for the caller to process
1003df930be7Sderaadt */
10049a58b8c6Sguenther arcn->pad = 0;
1005df930be7Sderaadt hd->h_filesize_1[0] = (char)0;
1006df930be7Sderaadt hd->h_filesize_1[1] = (char)0;
1007df930be7Sderaadt hd->h_filesize_2[0] = (char)0;
1008df930be7Sderaadt hd->h_filesize_2[1] = (char)0;
1009df930be7Sderaadt break;
1010df930be7Sderaadt }
1011df930be7Sderaadt
1012df930be7Sderaadt /*
1013df930be7Sderaadt * build up the rest of the fields
1014df930be7Sderaadt */
1015df930be7Sderaadt hd->h_magic[0] = CHR_WR_2(MAGIC);
1016df930be7Sderaadt hd->h_magic[1] = CHR_WR_3(MAGIC);
1017df930be7Sderaadt hd->h_dev[0] = CHR_WR_2(arcn->sb.st_dev);
1018df930be7Sderaadt hd->h_dev[1] = CHR_WR_3(arcn->sb.st_dev);
1019df930be7Sderaadt if (arcn->sb.st_dev != (dev_t)(SHRT_EXT(hd->h_dev)))
1020df930be7Sderaadt goto out;
1021df930be7Sderaadt hd->h_ino[0] = CHR_WR_2(arcn->sb.st_ino);
1022df930be7Sderaadt hd->h_ino[1] = CHR_WR_3(arcn->sb.st_ino);
1023df930be7Sderaadt if (arcn->sb.st_ino != (ino_t)(SHRT_EXT(hd->h_ino)))
1024df930be7Sderaadt goto out;
1025df930be7Sderaadt hd->h_mode[0] = CHR_WR_2(arcn->sb.st_mode);
1026df930be7Sderaadt hd->h_mode[1] = CHR_WR_3(arcn->sb.st_mode);
1027df930be7Sderaadt if (arcn->sb.st_mode != (mode_t)(SHRT_EXT(hd->h_mode)))
1028df930be7Sderaadt goto out;
1029df930be7Sderaadt hd->h_uid[0] = CHR_WR_2(arcn->sb.st_uid);
1030df930be7Sderaadt hd->h_uid[1] = CHR_WR_3(arcn->sb.st_uid);
1031df930be7Sderaadt if (arcn->sb.st_uid != (uid_t)(SHRT_EXT(hd->h_uid)))
1032df930be7Sderaadt goto out;
1033df930be7Sderaadt hd->h_gid[0] = CHR_WR_2(arcn->sb.st_gid);
1034df930be7Sderaadt hd->h_gid[1] = CHR_WR_3(arcn->sb.st_gid);
1035df930be7Sderaadt if (arcn->sb.st_gid != (gid_t)(SHRT_EXT(hd->h_gid)))
1036df930be7Sderaadt goto out;
1037df930be7Sderaadt hd->h_nlink[0] = CHR_WR_2(arcn->sb.st_nlink);
1038df930be7Sderaadt hd->h_nlink[1] = CHR_WR_3(arcn->sb.st_nlink);
1039df930be7Sderaadt if (arcn->sb.st_nlink != (nlink_t)(SHRT_EXT(hd->h_nlink)))
1040df930be7Sderaadt goto out;
1041df930be7Sderaadt hd->h_rdev[0] = CHR_WR_2(arcn->sb.st_rdev);
1042df930be7Sderaadt hd->h_rdev[1] = CHR_WR_3(arcn->sb.st_rdev);
1043df930be7Sderaadt if (arcn->sb.st_rdev != (dev_t)(SHRT_EXT(hd->h_rdev)))
1044df930be7Sderaadt goto out;
1045b5f8b155Sguenther if (arcn->sb.st_mtime > 0) {
1046df930be7Sderaadt hd->h_mtime_1[0] = CHR_WR_0(arcn->sb.st_mtime);
1047df930be7Sderaadt hd->h_mtime_1[1] = CHR_WR_1(arcn->sb.st_mtime);
1048df930be7Sderaadt hd->h_mtime_2[0] = CHR_WR_2(arcn->sb.st_mtime);
1049df930be7Sderaadt hd->h_mtime_2[1] = CHR_WR_3(arcn->sb.st_mtime);
1050b5f8b155Sguenther t_timet = (time_t)SHRT_EXT(hd->h_mtime_1);
1051b5f8b155Sguenther t_timet = t_timet << 16 | (time_t)SHRT_EXT(hd->h_mtime_2);
1052df930be7Sderaadt if (arcn->sb.st_mtime != t_timet)
1053df930be7Sderaadt goto out;
1054b5f8b155Sguenther } else {
1055b5f8b155Sguenther hd->h_mtime_1[0] = hd->h_mtime_1[1] = 0;
1056b5f8b155Sguenther hd->h_mtime_2[0] = hd->h_mtime_2[1] = 0;
1057b5f8b155Sguenther }
1058df930be7Sderaadt nsz = arcn->nlen + 1;
1059df930be7Sderaadt hd->h_namesize[0] = CHR_WR_2(nsz);
1060df930be7Sderaadt hd->h_namesize[1] = CHR_WR_3(nsz);
1061df930be7Sderaadt if (nsz != (int)(SHRT_EXT(hd->h_namesize)))
1062df930be7Sderaadt goto out;
1063df930be7Sderaadt
1064df930be7Sderaadt /*
1065df930be7Sderaadt * write the header, the file name and padding as required.
1066df930be7Sderaadt */
1067df930be7Sderaadt if ((wr_rdbuf(hdblk, (int)sizeof(HD_BCPIO)) < 0) ||
1068df930be7Sderaadt (wr_rdbuf(arcn->name, nsz) < 0) ||
10699a58b8c6Sguenther (wr_skip(BCPIO_PAD(sizeof(HD_BCPIO) + nsz)) < 0)) {
107042cf9836Stholo paxwarn(1, "Could not write bcpio header for %s", arcn->org_name);
1071df930be7Sderaadt return(-1);
1072df930be7Sderaadt }
1073df930be7Sderaadt
1074df930be7Sderaadt /*
1075df930be7Sderaadt * if we have file data, tell the caller we are done
1076df930be7Sderaadt */
10775316f7a4Sguenther if (PAX_IS_REG(arcn->type) || (arcn->type == PAX_HRG))
1078df930be7Sderaadt return(0);
1079df930be7Sderaadt
1080df930be7Sderaadt /*
1081df930be7Sderaadt * if we are not a link, tell the caller we are done, go to next file
1082df930be7Sderaadt */
1083df930be7Sderaadt if (arcn->type != PAX_SLK)
1084df930be7Sderaadt return(1);
1085df930be7Sderaadt
1086df930be7Sderaadt /*
1087df930be7Sderaadt * write the link name, tell the caller we are done.
1088df930be7Sderaadt */
1089df930be7Sderaadt if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
10909a58b8c6Sguenther (wr_skip(BCPIO_PAD(arcn->ln_nlen)) < 0)) {
109142cf9836Stholo paxwarn(1,"Could not write bcpio link name for %s",arcn->org_name);
1092df930be7Sderaadt return(-1);
1093df930be7Sderaadt }
1094df930be7Sderaadt return(1);
1095df930be7Sderaadt
1096df930be7Sderaadt out:
1097df930be7Sderaadt /*
1098df930be7Sderaadt * header field is out of range
1099df930be7Sderaadt */
110042cf9836Stholo paxwarn(1,"Bcpio header field is too small for file %s", arcn->org_name);
1101df930be7Sderaadt return(1);
1102df930be7Sderaadt }
1103