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