11556Srgrimes/*- 21556Srgrimes * Copyright (c) 1992 Keith Muller. 31556Srgrimes * Copyright (c) 1992, 1993 41556Srgrimes * The Regents of the University of California. All rights reserved. 51556Srgrimes * 61556Srgrimes * This code is derived from software contributed to Berkeley by 71556Srgrimes * Keith Muller of the University of California, San Diego. 81556Srgrimes * 91556Srgrimes * Redistribution and use in source and binary forms, with or without 101556Srgrimes * modification, are permitted provided that the following conditions 111556Srgrimes * are met: 121556Srgrimes * 1. Redistributions of source code must retain the above copyright 131556Srgrimes * notice, this list of conditions and the following disclaimer. 141556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 151556Srgrimes * notice, this list of conditions and the following disclaimer in the 161556Srgrimes * documentation and/or other materials provided with the distribution. 171556Srgrimes * 4. Neither the name of the University nor the names of its contributors 181556Srgrimes * may be used to endorse or promote products derived from this software 191556Srgrimes * without specific prior written permission. 201556Srgrimes * 211556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311556Srgrimes * SUCH DAMAGE. 321556Srgrimes */ 331556Srgrimes 341556Srgrimes#ifndef lint 3536049Scharnier#if 0 3636049Scharnierstatic char sccsid[] = "@(#)cpio.c 8.1 (Berkeley) 5/31/93"; 3736049Scharnier#endif 381556Srgrimes#endif /* not lint */ 3999110Sobrien#include <sys/cdefs.h> 4099110Sobrien__FBSDID("$FreeBSD$"); 411556Srgrimes 421556Srgrimes#include <sys/types.h> 431556Srgrimes#include <sys/time.h> 441556Srgrimes#include <sys/stat.h> 451556Srgrimes#include <string.h> 46104548Stjr#include <stdint.h> 471556Srgrimes#include <stdio.h> 481556Srgrimes#include "pax.h" 491556Srgrimes#include "cpio.h" 501556Srgrimes#include "extern.h" 511556Srgrimes 5290113Simpstatic int rd_nm(ARCHD *, int); 5390113Simpstatic int rd_ln_nm(ARCHD *); 5490113Simpstatic int com_rd(ARCHD *); 551556Srgrimes 561556Srgrimes/* 571556Srgrimes * Routines which support the different cpio versions 581556Srgrimes */ 591556Srgrimes 601556Srgrimesstatic int swp_head; /* binary cpio header byte swap */ 611556Srgrimes 621556Srgrimes/* 631556Srgrimes * Routines common to all versions of cpio 641556Srgrimes */ 651556Srgrimes 661556Srgrimes/* 671556Srgrimes * cpio_strd() 681556Srgrimes * Fire up the hard link detection code 691556Srgrimes * Return: 701556Srgrimes * 0 if ok -1 otherwise (the return values of lnk_start()) 711556Srgrimes */ 721556Srgrimes 731556Srgrimesint 741556Srgrimescpio_strd(void) 751556Srgrimes{ 761556Srgrimes return(lnk_start()); 771556Srgrimes} 781556Srgrimes 791556Srgrimes/* 801556Srgrimes * cpio_trail() 811556Srgrimes * Called to determine if a header block is a valid trailer. We are 821556Srgrimes * passed the block, the in_sync flag (which tells us we are in resync 831556Srgrimes * mode; looking for a valid header), and cnt (which starts at zero) 841556Srgrimes * which is used to count the number of empty blocks we have seen so far. 851556Srgrimes * Return: 868855Srgrimes * 0 if a valid trailer, -1 if not a valid trailer, 871556Srgrimes */ 881556Srgrimes 891556Srgrimesint 9090113Simpcpio_trail(ARCHD *arcn) 911556Srgrimes{ 921556Srgrimes /* 931556Srgrimes * look for trailer id in file we are about to process 941556Srgrimes */ 951556Srgrimes if ((strcmp(arcn->name, TRAILER) == 0) && (arcn->sb.st_size == 0)) 961556Srgrimes return(0); 971556Srgrimes return(-1); 981556Srgrimes} 991556Srgrimes 1001556Srgrimes/* 1011556Srgrimes * com_rd() 1021556Srgrimes * operations common to all cpio read functions. 1031556Srgrimes * Return: 1041556Srgrimes * 0 1051556Srgrimes */ 1061556Srgrimes 1071556Srgrimesstatic int 10890113Simpcom_rd(ARCHD *arcn) 1091556Srgrimes{ 1101556Srgrimes arcn->skip = 0; 1111556Srgrimes arcn->pat = NULL; 1121556Srgrimes arcn->org_name = arcn->name; 1131556Srgrimes switch(arcn->sb.st_mode & C_IFMT) { 1141556Srgrimes case C_ISFIFO: 1151556Srgrimes arcn->type = PAX_FIF; 1161556Srgrimes break; 1171556Srgrimes case C_ISDIR: 1181556Srgrimes arcn->type = PAX_DIR; 1191556Srgrimes break; 1201556Srgrimes case C_ISBLK: 1211556Srgrimes arcn->type = PAX_BLK; 1221556Srgrimes break; 1231556Srgrimes case C_ISCHR: 1241556Srgrimes arcn->type = PAX_CHR; 1251556Srgrimes break; 1261556Srgrimes case C_ISLNK: 1271556Srgrimes arcn->type = PAX_SLK; 1281556Srgrimes break; 1291556Srgrimes case C_ISOCK: 1301556Srgrimes arcn->type = PAX_SCK; 1311556Srgrimes break; 1321556Srgrimes case C_ISCTG: 1331556Srgrimes case C_ISREG: 1341556Srgrimes default: 1351556Srgrimes /* 1361556Srgrimes * we have file data, set up skip (pad is set in the format 1371556Srgrimes * specific sections) 1381556Srgrimes */ 1391556Srgrimes arcn->sb.st_mode = (arcn->sb.st_mode & 0xfff) | C_ISREG; 1401556Srgrimes arcn->type = PAX_REG; 1411556Srgrimes arcn->skip = arcn->sb.st_size; 1421556Srgrimes break; 1431556Srgrimes } 1441556Srgrimes if (chk_lnk(arcn) < 0) 1451556Srgrimes return(-1); 1461556Srgrimes return(0); 1471556Srgrimes} 1481556Srgrimes 1491556Srgrimes/* 1501556Srgrimes * cpio_end_wr() 1511556Srgrimes * write the special file with the name trailer in the proper format 1521556Srgrimes * Return: 1531556Srgrimes * result of the write of the trailer from the cpio specific write func 1541556Srgrimes */ 1551556Srgrimes 1561556Srgrimesint 1571556Srgrimescpio_endwr(void) 1581556Srgrimes{ 1591556Srgrimes ARCHD last; 1601556Srgrimes 1611556Srgrimes /* 1621556Srgrimes * create a trailer request and call the proper format write function 1631556Srgrimes */ 16476017Skris memset(&last, 0, sizeof(last)); 1651556Srgrimes last.nlen = sizeof(TRAILER) - 1; 1661556Srgrimes last.type = PAX_REG; 1671556Srgrimes last.sb.st_nlink = 1; 1681556Srgrimes (void)strcpy(last.name, TRAILER); 1691556Srgrimes return((*frmt->wr)(&last)); 1701556Srgrimes} 1711556Srgrimes 1721556Srgrimes/* 1731556Srgrimes * rd_nam() 1741556Srgrimes * read in the file name which follows the cpio header 1751556Srgrimes * Return: 1761556Srgrimes * 0 if ok, -1 otherwise 1771556Srgrimes */ 1781556Srgrimes 1791556Srgrimesstatic int 18090113Simprd_nm(ARCHD *arcn, int nsz) 1811556Srgrimes{ 1821556Srgrimes /* 1831556Srgrimes * do not even try bogus values 1841556Srgrimes */ 185114469Sobrien if ((nsz == 0) || (nsz > (int)sizeof(arcn->name))) { 18676017Skris paxwarn(1, "Cpio file name length %d is out of range", nsz); 1871556Srgrimes return(-1); 1881556Srgrimes } 1891556Srgrimes 1901556Srgrimes /* 1911556Srgrimes * read the name and make sure it is not empty and is \0 terminated 1921556Srgrimes */ 1931556Srgrimes if ((rd_wrbuf(arcn->name,nsz) != nsz) || (arcn->name[nsz-1] != '\0') || 1941556Srgrimes (arcn->name[0] == '\0')) { 19576017Skris paxwarn(1, "Cpio file name in header is corrupted"); 1961556Srgrimes return(-1); 1971556Srgrimes } 1981556Srgrimes return(0); 1991556Srgrimes} 2001556Srgrimes 2011556Srgrimes/* 2021556Srgrimes * rd_ln_nm() 2031556Srgrimes * read in the link name for a file with links. The link name is stored 2041556Srgrimes * like file data (and is NOT \0 terminated!) 2051556Srgrimes * Return: 2061556Srgrimes * 0 if ok, -1 otherwise 2071556Srgrimes */ 2081556Srgrimes 2091556Srgrimesstatic int 21090113Simprd_ln_nm(ARCHD *arcn) 2111556Srgrimes{ 2121556Srgrimes /* 2131556Srgrimes * check the length specified for bogus values 2141556Srgrimes */ 2151556Srgrimes if ((arcn->sb.st_size == 0) || 216114583Smarkm ((size_t)arcn->sb.st_size >= sizeof(arcn->ln_name))) { 2171556Srgrimes# ifdef NET2_STAT 21876017Skris paxwarn(1, "Cpio link name length is invalid: %lu", 2191556Srgrimes arcn->sb.st_size); 2201556Srgrimes# else 221104548Stjr paxwarn(1, "Cpio link name length is invalid: %ju", 222104548Stjr (uintmax_t)arcn->sb.st_size); 2231556Srgrimes# endif 2241556Srgrimes return(-1); 2251556Srgrimes } 2261556Srgrimes 2271556Srgrimes /* 2281556Srgrimes * read in the link name and \0 terminate it 2291556Srgrimes */ 2301556Srgrimes if (rd_wrbuf(arcn->ln_name, (int)arcn->sb.st_size) != 2311556Srgrimes (int)arcn->sb.st_size) { 23276017Skris paxwarn(1, "Cpio link name read error"); 2331556Srgrimes return(-1); 2341556Srgrimes } 2351556Srgrimes arcn->ln_nlen = arcn->sb.st_size; 2361556Srgrimes arcn->ln_name[arcn->ln_nlen] = '\0'; 2371556Srgrimes 2381556Srgrimes /* 2391556Srgrimes * watch out for those empty link names 2401556Srgrimes */ 2411556Srgrimes if (arcn->ln_name[0] == '\0') { 24276017Skris paxwarn(1, "Cpio link name is corrupt"); 2431556Srgrimes return(-1); 2441556Srgrimes } 2451556Srgrimes return(0); 2461556Srgrimes} 2471556Srgrimes 2481556Srgrimes/* 2491556Srgrimes * Routines common to the extended byte oriented cpio format 2501556Srgrimes */ 2511556Srgrimes 2521556Srgrimes/* 2531556Srgrimes * cpio_id() 2541556Srgrimes * determine if a block given to us is a valid extended byte oriented 2551556Srgrimes * cpio header 2561556Srgrimes * Return: 2571556Srgrimes * 0 if a valid header, -1 otherwise 2581556Srgrimes */ 2591556Srgrimes 2601556Srgrimesint 2611556Srgrimescpio_id(char *blk, int size) 2621556Srgrimes{ 263114469Sobrien if ((size < (int)sizeof(HD_CPIO)) || 2641556Srgrimes (strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0)) 2651556Srgrimes return(-1); 2661556Srgrimes return(0); 2671556Srgrimes} 2681556Srgrimes 2691556Srgrimes/* 2701556Srgrimes * cpio_rd() 2711556Srgrimes * determine if a buffer is a byte oriented extended cpio archive entry. 2721556Srgrimes * convert and store the values in the ARCHD parameter. 2731556Srgrimes * Return: 2741556Srgrimes * 0 if a valid header, -1 otherwise. 2751556Srgrimes */ 2761556Srgrimes 2771556Srgrimesint 27890113Simpcpio_rd(ARCHD *arcn, char *buf) 2791556Srgrimes{ 28090113Simp int nsz; 28190113Simp HD_CPIO *hd; 2821556Srgrimes 2831556Srgrimes /* 2841556Srgrimes * check that this is a valid header, if not return -1 2851556Srgrimes */ 2861556Srgrimes if (cpio_id(buf, sizeof(HD_CPIO)) < 0) 2871556Srgrimes return(-1); 2881556Srgrimes hd = (HD_CPIO *)buf; 2891556Srgrimes 2901556Srgrimes /* 2911556Srgrimes * byte oriented cpio (posix) does not have padding! extract the octal 2921556Srgrimes * ascii fields from the header 2931556Srgrimes */ 2941556Srgrimes arcn->pad = 0L; 2951556Srgrimes arcn->sb.st_dev = (dev_t)asc_ul(hd->c_dev, sizeof(hd->c_dev), OCT); 2961556Srgrimes arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), OCT); 2971556Srgrimes arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), OCT); 2981556Srgrimes arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), OCT); 2991556Srgrimes arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), OCT); 3001556Srgrimes arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink), 3011556Srgrimes OCT); 3021556Srgrimes arcn->sb.st_rdev = (dev_t)asc_ul(hd->c_rdev, sizeof(hd->c_rdev), OCT); 30385617Sdillon#ifdef NET2_STAT 3041556Srgrimes arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime), 3051556Srgrimes OCT); 30685617Sdillon#else 30785617Sdillon arcn->sb.st_mtime = (time_t)asc_uqd(hd->c_mtime, sizeof(hd->c_mtime), 30885617Sdillon OCT); 30985617Sdillon#endif 3101556Srgrimes arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 31185617Sdillon#ifdef NET2_STAT 3121556Srgrimes arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,sizeof(hd->c_filesize), 3131556Srgrimes OCT); 31485617Sdillon#else 3151556Srgrimes arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,sizeof(hd->c_filesize), 3161556Srgrimes OCT); 31785617Sdillon#endif 3181556Srgrimes 3191556Srgrimes /* 3201556Srgrimes * check name size and if valid, read in the name of this entry (name 3211556Srgrimes * follows header in the archive) 3221556Srgrimes */ 3231556Srgrimes if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2) 3241556Srgrimes return(-1); 3251556Srgrimes arcn->nlen = nsz - 1; 3261556Srgrimes if (rd_nm(arcn, nsz) < 0) 3271556Srgrimes return(-1); 3281556Srgrimes 3291556Srgrimes if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) { 3301556Srgrimes /* 3311556Srgrimes * no link name to read for this file 3321556Srgrimes */ 3331556Srgrimes arcn->ln_nlen = 0; 3341556Srgrimes arcn->ln_name[0] = '\0'; 3351556Srgrimes return(com_rd(arcn)); 3361556Srgrimes } 3371556Srgrimes 3381556Srgrimes /* 3391556Srgrimes * check link name size and read in the link name. Link names are 3401556Srgrimes * stored like file data. 3411556Srgrimes */ 3421556Srgrimes if (rd_ln_nm(arcn) < 0) 3431556Srgrimes return(-1); 3441556Srgrimes 3451556Srgrimes /* 3461556Srgrimes * we have a valid header (with a link) 3471556Srgrimes */ 3481556Srgrimes return(com_rd(arcn)); 3491556Srgrimes} 3501556Srgrimes 3511556Srgrimes/* 3521556Srgrimes * cpio_endrd() 3531556Srgrimes * no cleanup needed here, just return size of the trailer (for append) 3541556Srgrimes * Return: 3551556Srgrimes * size of trailer header in this format 3561556Srgrimes */ 3571556Srgrimes 3581556Srgrimesoff_t 3591556Srgrimescpio_endrd(void) 3601556Srgrimes{ 3611556Srgrimes return((off_t)(sizeof(HD_CPIO) + sizeof(TRAILER))); 3621556Srgrimes} 3631556Srgrimes 3641556Srgrimes/* 3651556Srgrimes * cpio_stwr() 3661556Srgrimes * start up the device mapping table 3671556Srgrimes * Return: 3681556Srgrimes * 0 if ok, -1 otherwise (what dev_start() returns) 3691556Srgrimes */ 3701556Srgrimes 3711556Srgrimesint 3721556Srgrimescpio_stwr(void) 3731556Srgrimes{ 3741556Srgrimes return(dev_start()); 3751556Srgrimes} 3761556Srgrimes 3771556Srgrimes/* 3781556Srgrimes * cpio_wr() 3791556Srgrimes * copy the data in the ARCHD to buffer in extended byte oriented cpio 3801556Srgrimes * format. 3811556Srgrimes * Return 3821556Srgrimes * 0 if file has data to be written after the header, 1 if file has NO 3831556Srgrimes * data to write after the header, -1 if archive write failed 3841556Srgrimes */ 3851556Srgrimes 3861556Srgrimesint 38790113Simpcpio_wr(ARCHD *arcn) 3881556Srgrimes{ 38990113Simp HD_CPIO *hd; 39090113Simp int nsz; 391164699Sru HD_CPIO hdblk; 3921556Srgrimes 3931556Srgrimes /* 3941556Srgrimes * check and repair truncated device and inode fields in the header 3951556Srgrimes */ 3961556Srgrimes if (map_dev(arcn, (u_long)CPIO_MASK, (u_long)CPIO_MASK) < 0) 3971556Srgrimes return(-1); 3981556Srgrimes 3991556Srgrimes arcn->pad = 0L; 4001556Srgrimes nsz = arcn->nlen + 1; 401164699Sru hd = &hdblk; 4021556Srgrimes if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR)) 4031556Srgrimes arcn->sb.st_rdev = 0; 4041556Srgrimes 4051556Srgrimes switch(arcn->type) { 4061556Srgrimes case PAX_CTG: 4071556Srgrimes case PAX_REG: 4081556Srgrimes case PAX_HRG: 4091556Srgrimes /* 4101556Srgrimes * set data size for file data 4111556Srgrimes */ 4121556Srgrimes# ifdef NET2_STAT 4131556Srgrimes if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize, 4141556Srgrimes sizeof(hd->c_filesize), OCT)) { 4151556Srgrimes# else 4161556Srgrimes if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize, 4171556Srgrimes sizeof(hd->c_filesize), OCT)) { 4181556Srgrimes# endif 41976017Skris paxwarn(1,"File is too large for cpio format %s", 4201556Srgrimes arcn->org_name); 4211556Srgrimes return(1); 4221556Srgrimes } 4231556Srgrimes break; 4241556Srgrimes case PAX_SLK: 4251556Srgrimes /* 4261556Srgrimes * set data size to hold link name 4271556Srgrimes */ 4281556Srgrimes if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize, 4291556Srgrimes sizeof(hd->c_filesize), OCT)) 4301556Srgrimes goto out; 4311556Srgrimes break; 4321556Srgrimes default: 4331556Srgrimes /* 4341556Srgrimes * all other file types have no file data 4351556Srgrimes */ 4361556Srgrimes if (ul_asc((u_long)0, hd->c_filesize, sizeof(hd->c_filesize), 4371556Srgrimes OCT)) 4381556Srgrimes goto out; 4391556Srgrimes break; 4401556Srgrimes } 4411556Srgrimes 4421556Srgrimes /* 4431556Srgrimes * copy the values to the header using octal ascii 4441556Srgrimes */ 4451556Srgrimes if (ul_asc((u_long)MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) || 4461556Srgrimes ul_asc((u_long)arcn->sb.st_dev, hd->c_dev, sizeof(hd->c_dev), 44776019Skris OCT) || 4481556Srgrimes ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino), 4491556Srgrimes OCT) || 4501556Srgrimes ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode), 4511556Srgrimes OCT) || 4521556Srgrimes ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid), 4531556Srgrimes OCT) || 4541556Srgrimes ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid), 4551556Srgrimes OCT) || 4561556Srgrimes ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink), 4571556Srgrimes OCT) || 4581556Srgrimes ul_asc((u_long)arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev), 4591556Srgrimes OCT) || 4601556Srgrimes ul_asc((u_long)arcn->sb.st_mtime,hd->c_mtime,sizeof(hd->c_mtime), 4611556Srgrimes OCT) || 4621556Srgrimes ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT)) 4631556Srgrimes goto out; 4641556Srgrimes 4651556Srgrimes /* 4661556Srgrimes * write the file name to the archive 4671556Srgrimes */ 468164699Sru if ((wr_rdbuf((char *)&hdblk, (int)sizeof(HD_CPIO)) < 0) || 4691556Srgrimes (wr_rdbuf(arcn->name, nsz) < 0)) { 47076017Skris paxwarn(1, "Unable to write cpio header for %s", arcn->org_name); 4711556Srgrimes return(-1); 4721556Srgrimes } 4731556Srgrimes 4741556Srgrimes /* 4751556Srgrimes * if this file has data, we are done. The caller will write the file 4761556Srgrimes * data, if we are link tell caller we are done, go to next file 4771556Srgrimes */ 4781556Srgrimes if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) || 4791556Srgrimes (arcn->type == PAX_HRG)) 4801556Srgrimes return(0); 4811556Srgrimes if (arcn->type != PAX_SLK) 4821556Srgrimes return(1); 4831556Srgrimes 4841556Srgrimes /* 4851556Srgrimes * write the link name to the archive, tell the caller to go to the 4861556Srgrimes * next file as we are done. 4871556Srgrimes */ 4881556Srgrimes if (wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) { 48976017Skris paxwarn(1,"Unable to write cpio link name for %s",arcn->org_name); 4901556Srgrimes return(-1); 4911556Srgrimes } 4921556Srgrimes return(1); 4931556Srgrimes 4941556Srgrimes out: 4951556Srgrimes /* 4961556Srgrimes * header field is out of range 4971556Srgrimes */ 49876017Skris paxwarn(1, "Cpio header field is too small to store file %s", 4991556Srgrimes arcn->org_name); 5001556Srgrimes return(1); 5011556Srgrimes} 5021556Srgrimes 5031556Srgrimes/* 5041556Srgrimes * Routines common to the system VR4 version of cpio (with/without file CRC) 5051556Srgrimes */ 5061556Srgrimes 5071556Srgrimes/* 5081556Srgrimes * vcpio_id() 5091556Srgrimes * determine if a block given to us is a valid system VR4 cpio header 5108855Srgrimes * WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header 5111556Srgrimes * uses HEX 5121556Srgrimes * Return: 5131556Srgrimes * 0 if a valid header, -1 otherwise 5141556Srgrimes */ 5151556Srgrimes 5161556Srgrimesint 5171556Srgrimesvcpio_id(char *blk, int size) 5181556Srgrimes{ 519114469Sobrien if ((size < (int)sizeof(HD_VCPIO)) || 5201556Srgrimes (strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0)) 5211556Srgrimes return(-1); 5221556Srgrimes return(0); 5231556Srgrimes} 5241556Srgrimes 5251556Srgrimes/* 5261556Srgrimes * crc_id() 5271556Srgrimes * determine if a block given to us is a valid system VR4 cpio header 5281556Srgrimes * WITH crc. WATCH it the magic cookies are in OCTAL the header uses HEX 5291556Srgrimes * Return: 5301556Srgrimes * 0 if a valid header, -1 otherwise 5311556Srgrimes */ 5321556Srgrimes 5331556Srgrimesint 5341556Srgrimescrc_id(char *blk, int size) 5351556Srgrimes{ 536114469Sobrien if ((size < (int)sizeof(HD_VCPIO)) || 537114469Sobrien (strncmp(blk, AVCMAGIC, (int)sizeof(AVCMAGIC) - 1) != 0)) 5381556Srgrimes return(-1); 5391556Srgrimes return(0); 5401556Srgrimes} 5411556Srgrimes 5421556Srgrimes/* 5431556Srgrimes * crc_strd() 5441556Srgrimes w set file data CRC calculations. Fire up the hard link detection code 5451556Srgrimes * Return: 5461556Srgrimes * 0 if ok -1 otherwise (the return values of lnk_start()) 5471556Srgrimes */ 5481556Srgrimes 5491556Srgrimesint 5501556Srgrimescrc_strd(void) 5511556Srgrimes{ 5521556Srgrimes docrc = 1; 5531556Srgrimes return(lnk_start()); 5541556Srgrimes} 5551556Srgrimes 5561556Srgrimes/* 5571556Srgrimes * vcpio_rd() 5581556Srgrimes * determine if a buffer is a system VR4 archive entry. (with/without CRC) 5591556Srgrimes * convert and store the values in the ARCHD parameter. 5601556Srgrimes * Return: 5611556Srgrimes * 0 if a valid header, -1 otherwise. 5621556Srgrimes */ 5631556Srgrimes 5641556Srgrimesint 56590113Simpvcpio_rd(ARCHD *arcn, char *buf) 5661556Srgrimes{ 56790113Simp HD_VCPIO *hd; 5681556Srgrimes dev_t devminor; 5691556Srgrimes dev_t devmajor; 57090113Simp int nsz; 5711556Srgrimes 5721556Srgrimes /* 5731556Srgrimes * during the id phase it was determined if we were using CRC, use the 5741556Srgrimes * proper id routine. 5751556Srgrimes */ 5761556Srgrimes if (docrc) { 5771556Srgrimes if (crc_id(buf, sizeof(HD_VCPIO)) < 0) 5781556Srgrimes return(-1); 5791556Srgrimes } else { 5801556Srgrimes if (vcpio_id(buf, sizeof(HD_VCPIO)) < 0) 5811556Srgrimes return(-1); 5821556Srgrimes } 5831556Srgrimes 5841556Srgrimes hd = (HD_VCPIO *)buf; 5851556Srgrimes arcn->pad = 0L; 5861556Srgrimes 5871556Srgrimes /* 5881556Srgrimes * extract the hex ascii fields from the header 5891556Srgrimes */ 5901556Srgrimes arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), HEX); 5911556Srgrimes arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), HEX); 5921556Srgrimes arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), HEX); 5931556Srgrimes arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX); 59485617Sdillon#ifdef NET2_STAT 5951556Srgrimes arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX); 59685617Sdillon#else 59785617Sdillon arcn->sb.st_mtime = (time_t)asc_uqd(hd->c_mtime,sizeof(hd->c_mtime),HEX); 59885617Sdillon#endif 5991556Srgrimes arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 60085617Sdillon#ifdef NET2_STAT 6011556Srgrimes arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize, 6021556Srgrimes sizeof(hd->c_filesize), HEX); 60385617Sdillon#else 6041556Srgrimes arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize, 6051556Srgrimes sizeof(hd->c_filesize), HEX); 60685617Sdillon#endif 6071556Srgrimes arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink), 6081556Srgrimes HEX); 6091556Srgrimes devmajor = (dev_t)asc_ul(hd->c_maj, sizeof(hd->c_maj), HEX); 6101556Srgrimes devminor = (dev_t)asc_ul(hd->c_min, sizeof(hd->c_min), HEX); 6111556Srgrimes arcn->sb.st_dev = TODEV(devmajor, devminor); 6121556Srgrimes devmajor = (dev_t)asc_ul(hd->c_rmaj, sizeof(hd->c_maj), HEX); 6131556Srgrimes devminor = (dev_t)asc_ul(hd->c_rmin, sizeof(hd->c_min), HEX); 6141556Srgrimes arcn->sb.st_rdev = TODEV(devmajor, devminor); 6151556Srgrimes arcn->crc = asc_ul(hd->c_chksum, sizeof(hd->c_chksum), HEX); 6161556Srgrimes 6171556Srgrimes /* 6181556Srgrimes * check the length of the file name, if ok read it in, return -1 if 6191556Srgrimes * bogus 6201556Srgrimes */ 6211556Srgrimes if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2) 6221556Srgrimes return(-1); 6231556Srgrimes arcn->nlen = nsz - 1; 6241556Srgrimes if (rd_nm(arcn, nsz) < 0) 6251556Srgrimes return(-1); 6261556Srgrimes 6271556Srgrimes /* 628222177Suqs * skip padding. header + filename is aligned to 4 byte boundaries 6291556Srgrimes */ 6301556Srgrimes if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0) 6311556Srgrimes return(-1); 6321556Srgrimes 6331556Srgrimes /* 6341556Srgrimes * if not a link (or a file with no data), calculate pad size (for 6351556Srgrimes * padding which follows the file data), clear the link name and return 6361556Srgrimes */ 6371556Srgrimes if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) { 6381556Srgrimes /* 6391556Srgrimes * we have a valid header (not a link) 6401556Srgrimes */ 6411556Srgrimes arcn->ln_nlen = 0; 6421556Srgrimes arcn->ln_name[0] = '\0'; 6431556Srgrimes arcn->pad = VCPIO_PAD(arcn->sb.st_size); 6441556Srgrimes return(com_rd(arcn)); 6451556Srgrimes } 6461556Srgrimes 6471556Srgrimes /* 6481556Srgrimes * read in the link name and skip over the padding 6491556Srgrimes */ 6501556Srgrimes if ((rd_ln_nm(arcn) < 0) || 6511556Srgrimes (rd_skip((off_t)(VCPIO_PAD(arcn->sb.st_size))) < 0)) 6521556Srgrimes return(-1); 6531556Srgrimes 6541556Srgrimes /* 6551556Srgrimes * we have a valid header (with a link) 6561556Srgrimes */ 6571556Srgrimes return(com_rd(arcn)); 6581556Srgrimes} 6591556Srgrimes 6601556Srgrimes/* 6611556Srgrimes * vcpio_endrd() 6621556Srgrimes * no cleanup needed here, just return size of the trailer (for append) 6631556Srgrimes * Return: 6641556Srgrimes * size of trailer header in this format 6651556Srgrimes */ 6661556Srgrimes 6671556Srgrimesoff_t 6681556Srgrimesvcpio_endrd(void) 6691556Srgrimes{ 6701556Srgrimes return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) + 6711556Srgrimes (VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER))))); 6721556Srgrimes} 6731556Srgrimes 6741556Srgrimes/* 6751556Srgrimes * crc_stwr() 6761556Srgrimes * start up the device mapping table, enable crc file calculation 6771556Srgrimes * Return: 6781556Srgrimes * 0 if ok, -1 otherwise (what dev_start() returns) 6791556Srgrimes */ 6801556Srgrimes 6811556Srgrimesint 6821556Srgrimescrc_stwr(void) 6831556Srgrimes{ 6841556Srgrimes docrc = 1; 6851556Srgrimes return(dev_start()); 6861556Srgrimes} 6871556Srgrimes 6881556Srgrimes/* 6891556Srgrimes * vcpio_wr() 6901556Srgrimes * copy the data in the ARCHD to buffer in system VR4 cpio 6911556Srgrimes * (with/without crc) format. 6921556Srgrimes * Return 6931556Srgrimes * 0 if file has data to be written after the header, 1 if file has 6941556Srgrimes * NO data to write after the header, -1 if archive write failed 6951556Srgrimes */ 6961556Srgrimes 6971556Srgrimesint 69890113Simpvcpio_wr(ARCHD *arcn) 6991556Srgrimes{ 70090113Simp HD_VCPIO *hd; 7011556Srgrimes unsigned int nsz; 702164699Sru HD_VCPIO hdblk; 7031556Srgrimes 7041556Srgrimes /* 7051556Srgrimes * check and repair truncated device and inode fields in the cpio 7061556Srgrimes * header 7071556Srgrimes */ 7081556Srgrimes if (map_dev(arcn, (u_long)VCPIO_MASK, (u_long)VCPIO_MASK) < 0) 7091556Srgrimes return(-1); 7101556Srgrimes nsz = arcn->nlen + 1; 711164699Sru hd = &hdblk; 7121556Srgrimes if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR)) 7131556Srgrimes arcn->sb.st_rdev = 0; 7141556Srgrimes 7151556Srgrimes /* 7161556Srgrimes * add the proper magic value depending whether we were asked for 7171556Srgrimes * file data crc's, and the crc if needed. 7181556Srgrimes */ 7191556Srgrimes if (docrc) { 7201556Srgrimes if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic), 7211556Srgrimes OCT) || 7221556Srgrimes ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum), 7231556Srgrimes HEX)) 7241556Srgrimes goto out; 7251556Srgrimes } else { 7261556Srgrimes if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic), 7271556Srgrimes OCT) || 7281556Srgrimes ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX)) 7291556Srgrimes goto out; 7301556Srgrimes } 7311556Srgrimes 7321556Srgrimes switch(arcn->type) { 7331556Srgrimes case PAX_CTG: 7341556Srgrimes case PAX_REG: 7351556Srgrimes case PAX_HRG: 7361556Srgrimes /* 7371556Srgrimes * caller will copy file data to the archive. tell him how 7381556Srgrimes * much to pad. 7391556Srgrimes */ 7401556Srgrimes arcn->pad = VCPIO_PAD(arcn->sb.st_size); 7411556Srgrimes# ifdef NET2_STAT 7421556Srgrimes if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize, 7431556Srgrimes sizeof(hd->c_filesize), HEX)) { 7441556Srgrimes# else 7451556Srgrimes if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize, 7461556Srgrimes sizeof(hd->c_filesize), HEX)) { 7471556Srgrimes# endif 74876017Skris paxwarn(1,"File is too large for sv4cpio format %s", 7491556Srgrimes arcn->org_name); 7501556Srgrimes return(1); 7511556Srgrimes } 7521556Srgrimes break; 7531556Srgrimes case PAX_SLK: 7541556Srgrimes /* 7551556Srgrimes * no file data for the caller to process, the file data has 7561556Srgrimes * the size of the link 7571556Srgrimes */ 7581556Srgrimes arcn->pad = 0L; 7591556Srgrimes if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize, 7601556Srgrimes sizeof(hd->c_filesize), HEX)) 7611556Srgrimes goto out; 7621556Srgrimes break; 7631556Srgrimes default: 7641556Srgrimes /* 7651556Srgrimes * no file data for the caller to process 7661556Srgrimes */ 7671556Srgrimes arcn->pad = 0L; 7681556Srgrimes if (ul_asc((u_long)0L, hd->c_filesize, sizeof(hd->c_filesize), 7691556Srgrimes HEX)) 7701556Srgrimes goto out; 7711556Srgrimes break; 7721556Srgrimes } 7731556Srgrimes 7741556Srgrimes /* 7751556Srgrimes * set the other fields in the header 7761556Srgrimes */ 7771556Srgrimes if (ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino), 7781556Srgrimes HEX) || 7791556Srgrimes ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode), 7801556Srgrimes HEX) || 7811556Srgrimes ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid), 7821556Srgrimes HEX) || 7831556Srgrimes ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid), 7841556Srgrimes HEX) || 7851556Srgrimes ul_asc((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime), 7861556Srgrimes HEX) || 7871556Srgrimes ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink), 7881556Srgrimes HEX) || 7891556Srgrimes ul_asc((u_long)MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj), 7901556Srgrimes HEX) || 7911556Srgrimes ul_asc((u_long)MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min), 7921556Srgrimes HEX) || 7931556Srgrimes ul_asc((u_long)MAJOR(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj), 7941556Srgrimes HEX) || 7951556Srgrimes ul_asc((u_long)MINOR(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min), 7961556Srgrimes HEX) || 7971556Srgrimes ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX)) 7981556Srgrimes goto out; 7991556Srgrimes 8001556Srgrimes /* 8011556Srgrimes * write the header, the file name and padding as required. 8021556Srgrimes */ 803164699Sru if ((wr_rdbuf((char *)&hdblk, (int)sizeof(HD_VCPIO)) < 0) || 8041556Srgrimes (wr_rdbuf(arcn->name, (int)nsz) < 0) || 8051556Srgrimes (wr_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)) { 80676017Skris paxwarn(1,"Could not write sv4cpio header for %s",arcn->org_name); 8071556Srgrimes return(-1); 8081556Srgrimes } 8091556Srgrimes 8101556Srgrimes /* 8111556Srgrimes * if we have file data, tell the caller we are done, copy the file 8121556Srgrimes */ 8131556Srgrimes if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) || 8141556Srgrimes (arcn->type == PAX_HRG)) 8151556Srgrimes return(0); 8161556Srgrimes 8171556Srgrimes /* 8181556Srgrimes * if we are not a link, tell the caller we are done, go to next file 8191556Srgrimes */ 8201556Srgrimes if (arcn->type != PAX_SLK) 8211556Srgrimes return(1); 8221556Srgrimes 8231556Srgrimes /* 8241556Srgrimes * write the link name, tell the caller we are done. 8251556Srgrimes */ 8261556Srgrimes if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) || 8271556Srgrimes (wr_skip((off_t)(VCPIO_PAD(arcn->ln_nlen))) < 0)) { 82876017Skris paxwarn(1,"Could not write sv4cpio link name for %s", 8291556Srgrimes arcn->org_name); 8301556Srgrimes return(-1); 8311556Srgrimes } 8321556Srgrimes return(1); 8331556Srgrimes 8341556Srgrimes out: 8351556Srgrimes /* 8361556Srgrimes * header field is out of range 8371556Srgrimes */ 83876017Skris paxwarn(1,"Sv4cpio header field is too small for file %s",arcn->org_name); 8391556Srgrimes return(1); 8401556Srgrimes} 8411556Srgrimes 8421556Srgrimes/* 8431556Srgrimes * Routines common to the old binary header cpio 8441556Srgrimes */ 8451556Srgrimes 8461556Srgrimes/* 8471556Srgrimes * bcpio_id() 848108533Sschweikh * determine if a block given to us is an old binary cpio header 8491556Srgrimes * (with/without header byte swapping) 8501556Srgrimes * Return: 8511556Srgrimes * 0 if a valid header, -1 otherwise 8521556Srgrimes */ 8531556Srgrimes 8541556Srgrimesint 8551556Srgrimesbcpio_id(char *blk, int size) 8561556Srgrimes{ 857114469Sobrien if (size < (int)sizeof(HD_BCPIO)) 8581556Srgrimes return(-1); 8591556Srgrimes 8601556Srgrimes /* 8611556Srgrimes * check both normal and byte swapped magic cookies 8621556Srgrimes */ 8631556Srgrimes if (((u_short)SHRT_EXT(blk)) == MAGIC) 8641556Srgrimes return(0); 8651556Srgrimes if (((u_short)RSHRT_EXT(blk)) == MAGIC) { 8661556Srgrimes if (!swp_head) 8671556Srgrimes ++swp_head; 8681556Srgrimes return(0); 8691556Srgrimes } 8701556Srgrimes return(-1); 8711556Srgrimes} 8721556Srgrimes 8731556Srgrimes/* 8741556Srgrimes * bcpio_rd() 875108533Sschweikh * determine if a buffer is an old binary archive entry. (It may have byte 8761556Srgrimes * swapped header) convert and store the values in the ARCHD parameter. 8771556Srgrimes * This is a very old header format and should not really be used. 8781556Srgrimes * Return: 8791556Srgrimes * 0 if a valid header, -1 otherwise. 8801556Srgrimes */ 8811556Srgrimes 8821556Srgrimesint 88390113Simpbcpio_rd(ARCHD *arcn, char *buf) 8841556Srgrimes{ 88590113Simp HD_BCPIO *hd; 88690113Simp int nsz; 8871556Srgrimes 8881556Srgrimes /* 8891556Srgrimes * check the header 8901556Srgrimes */ 8911556Srgrimes if (bcpio_id(buf, sizeof(HD_BCPIO)) < 0) 8921556Srgrimes return(-1); 8931556Srgrimes 8941556Srgrimes arcn->pad = 0L; 8951556Srgrimes hd = (HD_BCPIO *)buf; 8961556Srgrimes if (swp_head) { 8971556Srgrimes /* 89846684Skris * header has swapped bytes on 16 bit boundaries 8991556Srgrimes */ 9001556Srgrimes arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev)); 9011556Srgrimes arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino)); 9021556Srgrimes arcn->sb.st_mode = (mode_t)(RSHRT_EXT(hd->h_mode)); 9031556Srgrimes arcn->sb.st_uid = (uid_t)(RSHRT_EXT(hd->h_uid)); 9041556Srgrimes arcn->sb.st_gid = (gid_t)(RSHRT_EXT(hd->h_gid)); 9051556Srgrimes arcn->sb.st_nlink = (nlink_t)(RSHRT_EXT(hd->h_nlink)); 9061556Srgrimes arcn->sb.st_rdev = (dev_t)(RSHRT_EXT(hd->h_rdev)); 9071556Srgrimes arcn->sb.st_mtime = (time_t)(RSHRT_EXT(hd->h_mtime_1)); 9081556Srgrimes arcn->sb.st_mtime = (arcn->sb.st_mtime << 16) | 9091556Srgrimes ((time_t)(RSHRT_EXT(hd->h_mtime_2))); 9101556Srgrimes arcn->sb.st_size = (off_t)(RSHRT_EXT(hd->h_filesize_1)); 9111556Srgrimes arcn->sb.st_size = (arcn->sb.st_size << 16) | 9121556Srgrimes ((off_t)(RSHRT_EXT(hd->h_filesize_2))); 9131556Srgrimes nsz = (int)(RSHRT_EXT(hd->h_namesize)); 9141556Srgrimes } else { 9151556Srgrimes arcn->sb.st_dev = (dev_t)(SHRT_EXT(hd->h_dev)); 9161556Srgrimes arcn->sb.st_ino = (ino_t)(SHRT_EXT(hd->h_ino)); 9171556Srgrimes arcn->sb.st_mode = (mode_t)(SHRT_EXT(hd->h_mode)); 9181556Srgrimes arcn->sb.st_uid = (uid_t)(SHRT_EXT(hd->h_uid)); 9191556Srgrimes arcn->sb.st_gid = (gid_t)(SHRT_EXT(hd->h_gid)); 9201556Srgrimes arcn->sb.st_nlink = (nlink_t)(SHRT_EXT(hd->h_nlink)); 9211556Srgrimes arcn->sb.st_rdev = (dev_t)(SHRT_EXT(hd->h_rdev)); 9221556Srgrimes arcn->sb.st_mtime = (time_t)(SHRT_EXT(hd->h_mtime_1)); 9231556Srgrimes arcn->sb.st_mtime = (arcn->sb.st_mtime << 16) | 9241556Srgrimes ((time_t)(SHRT_EXT(hd->h_mtime_2))); 9251556Srgrimes arcn->sb.st_size = (off_t)(SHRT_EXT(hd->h_filesize_1)); 9261556Srgrimes arcn->sb.st_size = (arcn->sb.st_size << 16) | 9271556Srgrimes ((off_t)(SHRT_EXT(hd->h_filesize_2))); 9281556Srgrimes nsz = (int)(SHRT_EXT(hd->h_namesize)); 9291556Srgrimes } 9301556Srgrimes arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 9311556Srgrimes 9321556Srgrimes /* 9331556Srgrimes * check the file name size, if bogus give up. otherwise read the file 9341556Srgrimes * name 9351556Srgrimes */ 9361556Srgrimes if (nsz < 2) 9371556Srgrimes return(-1); 9381556Srgrimes arcn->nlen = nsz - 1; 9391556Srgrimes if (rd_nm(arcn, nsz) < 0) 9401556Srgrimes return(-1); 9411556Srgrimes 9421556Srgrimes /* 943222177Suqs * header + file name are aligned to 2 byte boundaries, skip if needed 9441556Srgrimes */ 9451556Srgrimes if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0) 9461556Srgrimes return(-1); 9471556Srgrimes 9481556Srgrimes /* 9491556Srgrimes * if not a link (or a file with no data), calculate pad size (for 9501556Srgrimes * padding which follows the file data), clear the link name and return 9511556Srgrimes */ 9521556Srgrimes if (((arcn->sb.st_mode & C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)){ 9531556Srgrimes /* 9541556Srgrimes * we have a valid header (not a link) 9551556Srgrimes */ 9561556Srgrimes arcn->ln_nlen = 0; 9571556Srgrimes arcn->ln_name[0] = '\0'; 9581556Srgrimes arcn->pad = BCPIO_PAD(arcn->sb.st_size); 9591556Srgrimes return(com_rd(arcn)); 9601556Srgrimes } 9611556Srgrimes 9621556Srgrimes if ((rd_ln_nm(arcn) < 0) || 9631556Srgrimes (rd_skip((off_t)(BCPIO_PAD(arcn->sb.st_size))) < 0)) 9641556Srgrimes return(-1); 9651556Srgrimes 9661556Srgrimes /* 9671556Srgrimes * we have a valid header (with a link) 9681556Srgrimes */ 9691556Srgrimes return(com_rd(arcn)); 9701556Srgrimes} 9711556Srgrimes 9721556Srgrimes/* 9731556Srgrimes * bcpio_endrd() 9741556Srgrimes * no cleanup needed here, just return size of the trailer (for append) 9751556Srgrimes * Return: 9761556Srgrimes * size of trailer header in this format 9771556Srgrimes */ 9781556Srgrimes 9791556Srgrimesoff_t 9801556Srgrimesbcpio_endrd(void) 9811556Srgrimes{ 9821556Srgrimes return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) + 9831556Srgrimes (BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER))))); 9841556Srgrimes} 9851556Srgrimes 9861556Srgrimes/* 9871556Srgrimes * bcpio_wr() 9881556Srgrimes * copy the data in the ARCHD to buffer in old binary cpio format 9891556Srgrimes * There is a real chance of field overflow with this critter. So we 990222177Suqs * always check that the conversion is ok. nobody in their right mind 991222177Suqs * should write an archive in this format... 9921556Srgrimes * Return 9931556Srgrimes * 0 if file has data to be written after the header, 1 if file has NO 9941556Srgrimes * data to write after the header, -1 if archive write failed 9951556Srgrimes */ 9961556Srgrimes 9971556Srgrimesint 99890113Simpbcpio_wr(ARCHD *arcn) 9991556Srgrimes{ 100090113Simp HD_BCPIO *hd; 100190113Simp int nsz; 1002164699Sru HD_BCPIO hdblk; 10031556Srgrimes off_t t_offt; 10041556Srgrimes int t_int; 10051556Srgrimes time_t t_timet; 10061556Srgrimes 10071556Srgrimes /* 10081556Srgrimes * check and repair truncated device and inode fields in the cpio 10091556Srgrimes * header 10101556Srgrimes */ 10111556Srgrimes if (map_dev(arcn, (u_long)BCPIO_MASK, (u_long)BCPIO_MASK) < 0) 10121556Srgrimes return(-1); 10131556Srgrimes 10141556Srgrimes if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR)) 10151556Srgrimes arcn->sb.st_rdev = 0; 1016164699Sru hd = &hdblk; 10171556Srgrimes 10181556Srgrimes switch(arcn->type) { 10191556Srgrimes case PAX_CTG: 10201556Srgrimes case PAX_REG: 10211556Srgrimes case PAX_HRG: 10221556Srgrimes /* 10231556Srgrimes * caller will copy file data to the archive. tell him how 10241556Srgrimes * much to pad. 10251556Srgrimes */ 10261556Srgrimes arcn->pad = BCPIO_PAD(arcn->sb.st_size); 10271556Srgrimes hd->h_filesize_1[0] = CHR_WR_0(arcn->sb.st_size); 10281556Srgrimes hd->h_filesize_1[1] = CHR_WR_1(arcn->sb.st_size); 10291556Srgrimes hd->h_filesize_2[0] = CHR_WR_2(arcn->sb.st_size); 10301556Srgrimes hd->h_filesize_2[1] = CHR_WR_3(arcn->sb.st_size); 10311556Srgrimes t_offt = (off_t)(SHRT_EXT(hd->h_filesize_1)); 10321556Srgrimes t_offt = (t_offt<<16) | ((off_t)(SHRT_EXT(hd->h_filesize_2))); 10331556Srgrimes if (arcn->sb.st_size != t_offt) { 103476017Skris paxwarn(1,"File is too large for bcpio format %s", 10351556Srgrimes arcn->org_name); 10361556Srgrimes return(1); 10371556Srgrimes } 10381556Srgrimes break; 10391556Srgrimes case PAX_SLK: 10401556Srgrimes /* 10411556Srgrimes * no file data for the caller to process, the file data has 10421556Srgrimes * the size of the link 10431556Srgrimes */ 10441556Srgrimes arcn->pad = 0L; 10451556Srgrimes hd->h_filesize_1[0] = CHR_WR_0(arcn->ln_nlen); 10461556Srgrimes hd->h_filesize_1[1] = CHR_WR_1(arcn->ln_nlen); 10471556Srgrimes hd->h_filesize_2[0] = CHR_WR_2(arcn->ln_nlen); 10481556Srgrimes hd->h_filesize_2[1] = CHR_WR_3(arcn->ln_nlen); 10491556Srgrimes t_int = (int)(SHRT_EXT(hd->h_filesize_1)); 10501556Srgrimes t_int = (t_int << 16) | ((int)(SHRT_EXT(hd->h_filesize_2))); 10511556Srgrimes if (arcn->ln_nlen != t_int) 10521556Srgrimes goto out; 10531556Srgrimes break; 10541556Srgrimes default: 10551556Srgrimes /* 10561556Srgrimes * no file data for the caller to process 10571556Srgrimes */ 10581556Srgrimes arcn->pad = 0L; 10591556Srgrimes hd->h_filesize_1[0] = (char)0; 10601556Srgrimes hd->h_filesize_1[1] = (char)0; 10611556Srgrimes hd->h_filesize_2[0] = (char)0; 10621556Srgrimes hd->h_filesize_2[1] = (char)0; 10631556Srgrimes break; 10641556Srgrimes } 10651556Srgrimes 10661556Srgrimes /* 10671556Srgrimes * build up the rest of the fields 10681556Srgrimes */ 10691556Srgrimes hd->h_magic[0] = CHR_WR_2(MAGIC); 10701556Srgrimes hd->h_magic[1] = CHR_WR_3(MAGIC); 10711556Srgrimes hd->h_dev[0] = CHR_WR_2(arcn->sb.st_dev); 10721556Srgrimes hd->h_dev[1] = CHR_WR_3(arcn->sb.st_dev); 10731556Srgrimes if (arcn->sb.st_dev != (dev_t)(SHRT_EXT(hd->h_dev))) 10741556Srgrimes goto out; 10751556Srgrimes hd->h_ino[0] = CHR_WR_2(arcn->sb.st_ino); 10761556Srgrimes hd->h_ino[1] = CHR_WR_3(arcn->sb.st_ino); 10771556Srgrimes if (arcn->sb.st_ino != (ino_t)(SHRT_EXT(hd->h_ino))) 10781556Srgrimes goto out; 10791556Srgrimes hd->h_mode[0] = CHR_WR_2(arcn->sb.st_mode); 10801556Srgrimes hd->h_mode[1] = CHR_WR_3(arcn->sb.st_mode); 10811556Srgrimes if (arcn->sb.st_mode != (mode_t)(SHRT_EXT(hd->h_mode))) 10821556Srgrimes goto out; 10831556Srgrimes hd->h_uid[0] = CHR_WR_2(arcn->sb.st_uid); 10841556Srgrimes hd->h_uid[1] = CHR_WR_3(arcn->sb.st_uid); 10851556Srgrimes if (arcn->sb.st_uid != (uid_t)(SHRT_EXT(hd->h_uid))) 10861556Srgrimes goto out; 10871556Srgrimes hd->h_gid[0] = CHR_WR_2(arcn->sb.st_gid); 10881556Srgrimes hd->h_gid[1] = CHR_WR_3(arcn->sb.st_gid); 10891556Srgrimes if (arcn->sb.st_gid != (gid_t)(SHRT_EXT(hd->h_gid))) 10901556Srgrimes goto out; 10911556Srgrimes hd->h_nlink[0] = CHR_WR_2(arcn->sb.st_nlink); 10921556Srgrimes hd->h_nlink[1] = CHR_WR_3(arcn->sb.st_nlink); 10931556Srgrimes if (arcn->sb.st_nlink != (nlink_t)(SHRT_EXT(hd->h_nlink))) 10941556Srgrimes goto out; 10951556Srgrimes hd->h_rdev[0] = CHR_WR_2(arcn->sb.st_rdev); 10961556Srgrimes hd->h_rdev[1] = CHR_WR_3(arcn->sb.st_rdev); 10971556Srgrimes if (arcn->sb.st_rdev != (dev_t)(SHRT_EXT(hd->h_rdev))) 10981556Srgrimes goto out; 10991556Srgrimes hd->h_mtime_1[0] = CHR_WR_0(arcn->sb.st_mtime); 11001556Srgrimes hd->h_mtime_1[1] = CHR_WR_1(arcn->sb.st_mtime); 11011556Srgrimes hd->h_mtime_2[0] = CHR_WR_2(arcn->sb.st_mtime); 11021556Srgrimes hd->h_mtime_2[1] = CHR_WR_3(arcn->sb.st_mtime); 11031556Srgrimes t_timet = (time_t)(SHRT_EXT(hd->h_mtime_1)); 11041556Srgrimes t_timet = (t_timet << 16) | ((time_t)(SHRT_EXT(hd->h_mtime_2))); 11051556Srgrimes if (arcn->sb.st_mtime != t_timet) 11061556Srgrimes goto out; 11071556Srgrimes nsz = arcn->nlen + 1; 11081556Srgrimes hd->h_namesize[0] = CHR_WR_2(nsz); 11091556Srgrimes hd->h_namesize[1] = CHR_WR_3(nsz); 11101556Srgrimes if (nsz != (int)(SHRT_EXT(hd->h_namesize))) 11111556Srgrimes goto out; 11121556Srgrimes 11131556Srgrimes /* 11141556Srgrimes * write the header, the file name and padding as required. 11151556Srgrimes */ 1116164699Sru if ((wr_rdbuf((char *)&hdblk, (int)sizeof(HD_BCPIO)) < 0) || 11171556Srgrimes (wr_rdbuf(arcn->name, nsz) < 0) || 11181556Srgrimes (wr_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)) { 111976017Skris paxwarn(1, "Could not write bcpio header for %s", arcn->org_name); 11201556Srgrimes return(-1); 11211556Srgrimes } 11221556Srgrimes 11231556Srgrimes /* 11241556Srgrimes * if we have file data, tell the caller we are done 11251556Srgrimes */ 11261556Srgrimes if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) || 11271556Srgrimes (arcn->type == PAX_HRG)) 11281556Srgrimes return(0); 11291556Srgrimes 11301556Srgrimes /* 11311556Srgrimes * if we are not a link, tell the caller we are done, go to next file 11321556Srgrimes */ 11331556Srgrimes if (arcn->type != PAX_SLK) 11341556Srgrimes return(1); 11351556Srgrimes 11361556Srgrimes /* 11371556Srgrimes * write the link name, tell the caller we are done. 11381556Srgrimes */ 11391556Srgrimes if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) || 11401556Srgrimes (wr_skip((off_t)(BCPIO_PAD(arcn->ln_nlen))) < 0)) { 114176017Skris paxwarn(1,"Could not write bcpio link name for %s",arcn->org_name); 11421556Srgrimes return(-1); 11431556Srgrimes } 11441556Srgrimes return(1); 11451556Srgrimes 11461556Srgrimes out: 11471556Srgrimes /* 11481556Srgrimes * header field is out of range 11491556Srgrimes */ 115076017Skris paxwarn(1,"Bcpio header field is too small for file %s", arcn->org_name); 11511556Srgrimes return(1); 11521556Srgrimes} 1153