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 <unistd.h> 491556Srgrimes#include <stdlib.h> 501556Srgrimes#include "pax.h" 511556Srgrimes#include "cpio.h" 521556Srgrimes#include "extern.h" 531556Srgrimes 5490113Simpstatic int rd_nm(ARCHD *, int); 5590113Simpstatic int rd_ln_nm(ARCHD *); 5690113Simpstatic int com_rd(ARCHD *); 571556Srgrimes 581556Srgrimes/* 591556Srgrimes * Routines which support the different cpio versions 601556Srgrimes */ 611556Srgrimes 621556Srgrimesstatic int swp_head; /* binary cpio header byte swap */ 631556Srgrimes 641556Srgrimes/* 651556Srgrimes * Routines common to all versions of cpio 661556Srgrimes */ 671556Srgrimes 681556Srgrimes/* 691556Srgrimes * cpio_strd() 701556Srgrimes * Fire up the hard link detection code 711556Srgrimes * Return: 721556Srgrimes * 0 if ok -1 otherwise (the return values of lnk_start()) 731556Srgrimes */ 741556Srgrimes 751556Srgrimesint 761556Srgrimescpio_strd(void) 771556Srgrimes{ 781556Srgrimes return(lnk_start()); 791556Srgrimes} 801556Srgrimes 811556Srgrimes/* 821556Srgrimes * cpio_trail() 831556Srgrimes * Called to determine if a header block is a valid trailer. We are 841556Srgrimes * passed the block, the in_sync flag (which tells us we are in resync 851556Srgrimes * mode; looking for a valid header), and cnt (which starts at zero) 861556Srgrimes * which is used to count the number of empty blocks we have seen so far. 871556Srgrimes * Return: 888855Srgrimes * 0 if a valid trailer, -1 if not a valid trailer, 891556Srgrimes */ 901556Srgrimes 911556Srgrimesint 9290113Simpcpio_trail(ARCHD *arcn) 931556Srgrimes{ 941556Srgrimes /* 951556Srgrimes * look for trailer id in file we are about to process 961556Srgrimes */ 971556Srgrimes if ((strcmp(arcn->name, TRAILER) == 0) && (arcn->sb.st_size == 0)) 981556Srgrimes return(0); 991556Srgrimes return(-1); 1001556Srgrimes} 1011556Srgrimes 1021556Srgrimes/* 1031556Srgrimes * com_rd() 1041556Srgrimes * operations common to all cpio read functions. 1051556Srgrimes * Return: 1061556Srgrimes * 0 1071556Srgrimes */ 1081556Srgrimes 1091556Srgrimesstatic int 11090113Simpcom_rd(ARCHD *arcn) 1111556Srgrimes{ 1121556Srgrimes arcn->skip = 0; 1131556Srgrimes arcn->pat = NULL; 1141556Srgrimes arcn->org_name = arcn->name; 1151556Srgrimes switch(arcn->sb.st_mode & C_IFMT) { 1161556Srgrimes case C_ISFIFO: 1171556Srgrimes arcn->type = PAX_FIF; 1181556Srgrimes break; 1191556Srgrimes case C_ISDIR: 1201556Srgrimes arcn->type = PAX_DIR; 1211556Srgrimes break; 1221556Srgrimes case C_ISBLK: 1231556Srgrimes arcn->type = PAX_BLK; 1241556Srgrimes break; 1251556Srgrimes case C_ISCHR: 1261556Srgrimes arcn->type = PAX_CHR; 1271556Srgrimes break; 1281556Srgrimes case C_ISLNK: 1291556Srgrimes arcn->type = PAX_SLK; 1301556Srgrimes break; 1311556Srgrimes case C_ISOCK: 1321556Srgrimes arcn->type = PAX_SCK; 1331556Srgrimes break; 1341556Srgrimes case C_ISCTG: 1351556Srgrimes case C_ISREG: 1361556Srgrimes default: 1371556Srgrimes /* 1381556Srgrimes * we have file data, set up skip (pad is set in the format 1391556Srgrimes * specific sections) 1401556Srgrimes */ 1411556Srgrimes arcn->sb.st_mode = (arcn->sb.st_mode & 0xfff) | C_ISREG; 1421556Srgrimes arcn->type = PAX_REG; 1431556Srgrimes arcn->skip = arcn->sb.st_size; 1441556Srgrimes break; 1451556Srgrimes } 1461556Srgrimes if (chk_lnk(arcn) < 0) 1471556Srgrimes return(-1); 1481556Srgrimes return(0); 1491556Srgrimes} 1501556Srgrimes 1511556Srgrimes/* 1521556Srgrimes * cpio_end_wr() 1531556Srgrimes * write the special file with the name trailer in the proper format 1541556Srgrimes * Return: 1551556Srgrimes * result of the write of the trailer from the cpio specific write func 1561556Srgrimes */ 1571556Srgrimes 1581556Srgrimesint 1591556Srgrimescpio_endwr(void) 1601556Srgrimes{ 1611556Srgrimes ARCHD last; 1621556Srgrimes 1631556Srgrimes /* 1641556Srgrimes * create a trailer request and call the proper format write function 1651556Srgrimes */ 16676017Skris memset(&last, 0, sizeof(last)); 1671556Srgrimes last.nlen = sizeof(TRAILER) - 1; 1681556Srgrimes last.type = PAX_REG; 1691556Srgrimes last.sb.st_nlink = 1; 1701556Srgrimes (void)strcpy(last.name, TRAILER); 1711556Srgrimes return((*frmt->wr)(&last)); 1721556Srgrimes} 1731556Srgrimes 1741556Srgrimes/* 1751556Srgrimes * rd_nam() 1761556Srgrimes * read in the file name which follows the cpio header 1771556Srgrimes * Return: 1781556Srgrimes * 0 if ok, -1 otherwise 1791556Srgrimes */ 1801556Srgrimes 1811556Srgrimesstatic int 18290113Simprd_nm(ARCHD *arcn, int nsz) 1831556Srgrimes{ 1841556Srgrimes /* 1851556Srgrimes * do not even try bogus values 1861556Srgrimes */ 187114469Sobrien if ((nsz == 0) || (nsz > (int)sizeof(arcn->name))) { 18876017Skris paxwarn(1, "Cpio file name length %d is out of range", nsz); 1891556Srgrimes return(-1); 1901556Srgrimes } 1911556Srgrimes 1921556Srgrimes /* 1931556Srgrimes * read the name and make sure it is not empty and is \0 terminated 1941556Srgrimes */ 1951556Srgrimes if ((rd_wrbuf(arcn->name,nsz) != nsz) || (arcn->name[nsz-1] != '\0') || 1961556Srgrimes (arcn->name[0] == '\0')) { 19776017Skris paxwarn(1, "Cpio file name in header is corrupted"); 1981556Srgrimes return(-1); 1991556Srgrimes } 2001556Srgrimes return(0); 2011556Srgrimes} 2021556Srgrimes 2031556Srgrimes/* 2041556Srgrimes * rd_ln_nm() 2051556Srgrimes * read in the link name for a file with links. The link name is stored 2061556Srgrimes * like file data (and is NOT \0 terminated!) 2071556Srgrimes * Return: 2081556Srgrimes * 0 if ok, -1 otherwise 2091556Srgrimes */ 2101556Srgrimes 2111556Srgrimesstatic int 21290113Simprd_ln_nm(ARCHD *arcn) 2131556Srgrimes{ 2141556Srgrimes /* 2151556Srgrimes * check the length specified for bogus values 2161556Srgrimes */ 2171556Srgrimes if ((arcn->sb.st_size == 0) || 218114583Smarkm ((size_t)arcn->sb.st_size >= sizeof(arcn->ln_name))) { 2191556Srgrimes# ifdef NET2_STAT 22076017Skris paxwarn(1, "Cpio link name length is invalid: %lu", 2211556Srgrimes arcn->sb.st_size); 2221556Srgrimes# else 223104548Stjr paxwarn(1, "Cpio link name length is invalid: %ju", 224104548Stjr (uintmax_t)arcn->sb.st_size); 2251556Srgrimes# endif 2261556Srgrimes return(-1); 2271556Srgrimes } 2281556Srgrimes 2291556Srgrimes /* 2301556Srgrimes * read in the link name and \0 terminate it 2311556Srgrimes */ 2321556Srgrimes if (rd_wrbuf(arcn->ln_name, (int)arcn->sb.st_size) != 2331556Srgrimes (int)arcn->sb.st_size) { 23476017Skris paxwarn(1, "Cpio link name read error"); 2351556Srgrimes return(-1); 2361556Srgrimes } 2371556Srgrimes arcn->ln_nlen = arcn->sb.st_size; 2381556Srgrimes arcn->ln_name[arcn->ln_nlen] = '\0'; 2391556Srgrimes 2401556Srgrimes /* 2411556Srgrimes * watch out for those empty link names 2421556Srgrimes */ 2431556Srgrimes if (arcn->ln_name[0] == '\0') { 24476017Skris paxwarn(1, "Cpio link name is corrupt"); 2451556Srgrimes return(-1); 2461556Srgrimes } 2471556Srgrimes return(0); 2481556Srgrimes} 2491556Srgrimes 2501556Srgrimes/* 2511556Srgrimes * Routines common to the extended byte oriented cpio format 2521556Srgrimes */ 2531556Srgrimes 2541556Srgrimes/* 2551556Srgrimes * cpio_id() 2561556Srgrimes * determine if a block given to us is a valid extended byte oriented 2571556Srgrimes * cpio header 2581556Srgrimes * Return: 2591556Srgrimes * 0 if a valid header, -1 otherwise 2601556Srgrimes */ 2611556Srgrimes 2621556Srgrimesint 2631556Srgrimescpio_id(char *blk, int size) 2641556Srgrimes{ 265114469Sobrien if ((size < (int)sizeof(HD_CPIO)) || 2661556Srgrimes (strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0)) 2671556Srgrimes return(-1); 2681556Srgrimes return(0); 2691556Srgrimes} 2701556Srgrimes 2711556Srgrimes/* 2721556Srgrimes * cpio_rd() 2731556Srgrimes * determine if a buffer is a byte oriented extended cpio archive entry. 2741556Srgrimes * convert and store the values in the ARCHD parameter. 2751556Srgrimes * Return: 2761556Srgrimes * 0 if a valid header, -1 otherwise. 2771556Srgrimes */ 2781556Srgrimes 2791556Srgrimesint 28090113Simpcpio_rd(ARCHD *arcn, char *buf) 2811556Srgrimes{ 28290113Simp int nsz; 28390113Simp HD_CPIO *hd; 2841556Srgrimes 2851556Srgrimes /* 2861556Srgrimes * check that this is a valid header, if not return -1 2871556Srgrimes */ 2881556Srgrimes if (cpio_id(buf, sizeof(HD_CPIO)) < 0) 2891556Srgrimes return(-1); 2901556Srgrimes hd = (HD_CPIO *)buf; 2911556Srgrimes 2921556Srgrimes /* 2931556Srgrimes * byte oriented cpio (posix) does not have padding! extract the octal 2941556Srgrimes * ascii fields from the header 2951556Srgrimes */ 2961556Srgrimes arcn->pad = 0L; 2971556Srgrimes arcn->sb.st_dev = (dev_t)asc_ul(hd->c_dev, sizeof(hd->c_dev), OCT); 2981556Srgrimes arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), OCT); 2991556Srgrimes arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), OCT); 3001556Srgrimes arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), OCT); 3011556Srgrimes arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), OCT); 3021556Srgrimes arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink), 3031556Srgrimes OCT); 3041556Srgrimes arcn->sb.st_rdev = (dev_t)asc_ul(hd->c_rdev, sizeof(hd->c_rdev), OCT); 30585617Sdillon#ifdef NET2_STAT 3061556Srgrimes arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime), 3071556Srgrimes OCT); 30885617Sdillon#else 30985617Sdillon arcn->sb.st_mtime = (time_t)asc_uqd(hd->c_mtime, sizeof(hd->c_mtime), 31085617Sdillon OCT); 31185617Sdillon#endif 3121556Srgrimes arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 31385617Sdillon#ifdef NET2_STAT 3141556Srgrimes arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,sizeof(hd->c_filesize), 3151556Srgrimes OCT); 31685617Sdillon#else 3171556Srgrimes arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,sizeof(hd->c_filesize), 3181556Srgrimes OCT); 31985617Sdillon#endif 3201556Srgrimes 3211556Srgrimes /* 3221556Srgrimes * check name size and if valid, read in the name of this entry (name 3231556Srgrimes * follows header in the archive) 3241556Srgrimes */ 3251556Srgrimes if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2) 3261556Srgrimes return(-1); 3271556Srgrimes arcn->nlen = nsz - 1; 3281556Srgrimes if (rd_nm(arcn, nsz) < 0) 3291556Srgrimes return(-1); 3301556Srgrimes 3311556Srgrimes if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) { 3321556Srgrimes /* 3331556Srgrimes * no link name to read for this file 3341556Srgrimes */ 3351556Srgrimes arcn->ln_nlen = 0; 3361556Srgrimes arcn->ln_name[0] = '\0'; 3371556Srgrimes return(com_rd(arcn)); 3381556Srgrimes } 3391556Srgrimes 3401556Srgrimes /* 3411556Srgrimes * check link name size and read in the link name. Link names are 3421556Srgrimes * stored like file data. 3431556Srgrimes */ 3441556Srgrimes if (rd_ln_nm(arcn) < 0) 3451556Srgrimes return(-1); 3461556Srgrimes 3471556Srgrimes /* 3481556Srgrimes * we have a valid header (with a link) 3491556Srgrimes */ 3501556Srgrimes return(com_rd(arcn)); 3511556Srgrimes} 3521556Srgrimes 3531556Srgrimes/* 3541556Srgrimes * cpio_endrd() 3551556Srgrimes * no cleanup needed here, just return size of the trailer (for append) 3561556Srgrimes * Return: 3571556Srgrimes * size of trailer header in this format 3581556Srgrimes */ 3591556Srgrimes 3601556Srgrimesoff_t 3611556Srgrimescpio_endrd(void) 3621556Srgrimes{ 3631556Srgrimes return((off_t)(sizeof(HD_CPIO) + sizeof(TRAILER))); 3641556Srgrimes} 3651556Srgrimes 3661556Srgrimes/* 3671556Srgrimes * cpio_stwr() 3681556Srgrimes * start up the device mapping table 3691556Srgrimes * Return: 3701556Srgrimes * 0 if ok, -1 otherwise (what dev_start() returns) 3711556Srgrimes */ 3721556Srgrimes 3731556Srgrimesint 3741556Srgrimescpio_stwr(void) 3751556Srgrimes{ 3761556Srgrimes return(dev_start()); 3771556Srgrimes} 3781556Srgrimes 3791556Srgrimes/* 3801556Srgrimes * cpio_wr() 3811556Srgrimes * copy the data in the ARCHD to buffer in extended byte oriented cpio 3821556Srgrimes * format. 3831556Srgrimes * Return 3841556Srgrimes * 0 if file has data to be written after the header, 1 if file has NO 3851556Srgrimes * data to write after the header, -1 if archive write failed 3861556Srgrimes */ 3871556Srgrimes 3881556Srgrimesint 38990113Simpcpio_wr(ARCHD *arcn) 3901556Srgrimes{ 39190113Simp HD_CPIO *hd; 39290113Simp int nsz; 393164699Sru HD_CPIO hdblk; 3941556Srgrimes 3951556Srgrimes /* 3961556Srgrimes * check and repair truncated device and inode fields in the header 3971556Srgrimes */ 3981556Srgrimes if (map_dev(arcn, (u_long)CPIO_MASK, (u_long)CPIO_MASK) < 0) 3991556Srgrimes return(-1); 4001556Srgrimes 4011556Srgrimes arcn->pad = 0L; 4021556Srgrimes nsz = arcn->nlen + 1; 403164699Sru hd = &hdblk; 4041556Srgrimes if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR)) 4051556Srgrimes arcn->sb.st_rdev = 0; 4061556Srgrimes 4071556Srgrimes switch(arcn->type) { 4081556Srgrimes case PAX_CTG: 4091556Srgrimes case PAX_REG: 4101556Srgrimes case PAX_HRG: 4111556Srgrimes /* 4121556Srgrimes * set data size for file data 4131556Srgrimes */ 4141556Srgrimes# ifdef NET2_STAT 4151556Srgrimes if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize, 4161556Srgrimes sizeof(hd->c_filesize), OCT)) { 4171556Srgrimes# else 4181556Srgrimes if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize, 4191556Srgrimes sizeof(hd->c_filesize), OCT)) { 4201556Srgrimes# endif 42176017Skris paxwarn(1,"File is too large for cpio format %s", 4221556Srgrimes arcn->org_name); 4231556Srgrimes return(1); 4241556Srgrimes } 4251556Srgrimes break; 4261556Srgrimes case PAX_SLK: 4271556Srgrimes /* 4281556Srgrimes * set data size to hold link name 4291556Srgrimes */ 4301556Srgrimes if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize, 4311556Srgrimes sizeof(hd->c_filesize), OCT)) 4321556Srgrimes goto out; 4331556Srgrimes break; 4341556Srgrimes default: 4351556Srgrimes /* 4361556Srgrimes * all other file types have no file data 4371556Srgrimes */ 4381556Srgrimes if (ul_asc((u_long)0, hd->c_filesize, sizeof(hd->c_filesize), 4391556Srgrimes OCT)) 4401556Srgrimes goto out; 4411556Srgrimes break; 4421556Srgrimes } 4431556Srgrimes 4441556Srgrimes /* 4451556Srgrimes * copy the values to the header using octal ascii 4461556Srgrimes */ 4471556Srgrimes if (ul_asc((u_long)MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) || 4481556Srgrimes ul_asc((u_long)arcn->sb.st_dev, hd->c_dev, sizeof(hd->c_dev), 44976019Skris OCT) || 4501556Srgrimes ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino), 4511556Srgrimes OCT) || 4521556Srgrimes ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode), 4531556Srgrimes OCT) || 4541556Srgrimes ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid), 4551556Srgrimes OCT) || 4561556Srgrimes ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid), 4571556Srgrimes OCT) || 4581556Srgrimes ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink), 4591556Srgrimes OCT) || 4601556Srgrimes ul_asc((u_long)arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev), 4611556Srgrimes OCT) || 4621556Srgrimes ul_asc((u_long)arcn->sb.st_mtime,hd->c_mtime,sizeof(hd->c_mtime), 4631556Srgrimes OCT) || 4641556Srgrimes ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT)) 4651556Srgrimes goto out; 4661556Srgrimes 4671556Srgrimes /* 4681556Srgrimes * write the file name to the archive 4691556Srgrimes */ 470164699Sru if ((wr_rdbuf((char *)&hdblk, (int)sizeof(HD_CPIO)) < 0) || 4711556Srgrimes (wr_rdbuf(arcn->name, nsz) < 0)) { 47276017Skris paxwarn(1, "Unable to write cpio header for %s", arcn->org_name); 4731556Srgrimes return(-1); 4741556Srgrimes } 4751556Srgrimes 4761556Srgrimes /* 4771556Srgrimes * if this file has data, we are done. The caller will write the file 4781556Srgrimes * data, if we are link tell caller we are done, go to next file 4791556Srgrimes */ 4801556Srgrimes if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) || 4811556Srgrimes (arcn->type == PAX_HRG)) 4821556Srgrimes return(0); 4831556Srgrimes if (arcn->type != PAX_SLK) 4841556Srgrimes return(1); 4851556Srgrimes 4861556Srgrimes /* 4871556Srgrimes * write the link name to the archive, tell the caller to go to the 4881556Srgrimes * next file as we are done. 4891556Srgrimes */ 4901556Srgrimes if (wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) { 49176017Skris paxwarn(1,"Unable to write cpio link name for %s",arcn->org_name); 4921556Srgrimes return(-1); 4931556Srgrimes } 4941556Srgrimes return(1); 4951556Srgrimes 4961556Srgrimes out: 4971556Srgrimes /* 4981556Srgrimes * header field is out of range 4991556Srgrimes */ 50076017Skris paxwarn(1, "Cpio header field is too small to store file %s", 5011556Srgrimes arcn->org_name); 5021556Srgrimes return(1); 5031556Srgrimes} 5041556Srgrimes 5051556Srgrimes/* 5061556Srgrimes * Routines common to the system VR4 version of cpio (with/without file CRC) 5071556Srgrimes */ 5081556Srgrimes 5091556Srgrimes/* 5101556Srgrimes * vcpio_id() 5111556Srgrimes * determine if a block given to us is a valid system VR4 cpio header 5128855Srgrimes * WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header 5131556Srgrimes * uses HEX 5141556Srgrimes * Return: 5151556Srgrimes * 0 if a valid header, -1 otherwise 5161556Srgrimes */ 5171556Srgrimes 5181556Srgrimesint 5191556Srgrimesvcpio_id(char *blk, int size) 5201556Srgrimes{ 521114469Sobrien if ((size < (int)sizeof(HD_VCPIO)) || 5221556Srgrimes (strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0)) 5231556Srgrimes return(-1); 5241556Srgrimes return(0); 5251556Srgrimes} 5261556Srgrimes 5271556Srgrimes/* 5281556Srgrimes * crc_id() 5291556Srgrimes * determine if a block given to us is a valid system VR4 cpio header 5301556Srgrimes * WITH crc. WATCH it the magic cookies are in OCTAL the header uses HEX 5311556Srgrimes * Return: 5321556Srgrimes * 0 if a valid header, -1 otherwise 5331556Srgrimes */ 5341556Srgrimes 5351556Srgrimesint 5361556Srgrimescrc_id(char *blk, int size) 5371556Srgrimes{ 538114469Sobrien if ((size < (int)sizeof(HD_VCPIO)) || 539114469Sobrien (strncmp(blk, AVCMAGIC, (int)sizeof(AVCMAGIC) - 1) != 0)) 5401556Srgrimes return(-1); 5411556Srgrimes return(0); 5421556Srgrimes} 5431556Srgrimes 5441556Srgrimes/* 5451556Srgrimes * crc_strd() 5461556Srgrimes w set file data CRC calculations. Fire up the hard link detection code 5471556Srgrimes * Return: 5481556Srgrimes * 0 if ok -1 otherwise (the return values of lnk_start()) 5491556Srgrimes */ 5501556Srgrimes 5511556Srgrimesint 5521556Srgrimescrc_strd(void) 5531556Srgrimes{ 5541556Srgrimes docrc = 1; 5551556Srgrimes return(lnk_start()); 5561556Srgrimes} 5571556Srgrimes 5581556Srgrimes/* 5591556Srgrimes * vcpio_rd() 5601556Srgrimes * determine if a buffer is a system VR4 archive entry. (with/without CRC) 5611556Srgrimes * convert and store the values in the ARCHD parameter. 5621556Srgrimes * Return: 5631556Srgrimes * 0 if a valid header, -1 otherwise. 5641556Srgrimes */ 5651556Srgrimes 5661556Srgrimesint 56790113Simpvcpio_rd(ARCHD *arcn, char *buf) 5681556Srgrimes{ 56990113Simp HD_VCPIO *hd; 5701556Srgrimes dev_t devminor; 5711556Srgrimes dev_t devmajor; 57290113Simp int nsz; 5731556Srgrimes 5741556Srgrimes /* 5751556Srgrimes * during the id phase it was determined if we were using CRC, use the 5761556Srgrimes * proper id routine. 5771556Srgrimes */ 5781556Srgrimes if (docrc) { 5791556Srgrimes if (crc_id(buf, sizeof(HD_VCPIO)) < 0) 5801556Srgrimes return(-1); 5811556Srgrimes } else { 5821556Srgrimes if (vcpio_id(buf, sizeof(HD_VCPIO)) < 0) 5831556Srgrimes return(-1); 5841556Srgrimes } 5851556Srgrimes 5861556Srgrimes hd = (HD_VCPIO *)buf; 5871556Srgrimes arcn->pad = 0L; 5881556Srgrimes 5891556Srgrimes /* 5901556Srgrimes * extract the hex ascii fields from the header 5911556Srgrimes */ 5921556Srgrimes arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), HEX); 5931556Srgrimes arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), HEX); 5941556Srgrimes arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), HEX); 5951556Srgrimes arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX); 59685617Sdillon#ifdef NET2_STAT 5971556Srgrimes arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX); 59885617Sdillon#else 59985617Sdillon arcn->sb.st_mtime = (time_t)asc_uqd(hd->c_mtime,sizeof(hd->c_mtime),HEX); 60085617Sdillon#endif 6011556Srgrimes arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 60285617Sdillon#ifdef NET2_STAT 6031556Srgrimes arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize, 6041556Srgrimes sizeof(hd->c_filesize), HEX); 60585617Sdillon#else 6061556Srgrimes arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize, 6071556Srgrimes sizeof(hd->c_filesize), HEX); 60885617Sdillon#endif 6091556Srgrimes arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink), 6101556Srgrimes HEX); 6111556Srgrimes devmajor = (dev_t)asc_ul(hd->c_maj, sizeof(hd->c_maj), HEX); 6121556Srgrimes devminor = (dev_t)asc_ul(hd->c_min, sizeof(hd->c_min), HEX); 6131556Srgrimes arcn->sb.st_dev = TODEV(devmajor, devminor); 6141556Srgrimes devmajor = (dev_t)asc_ul(hd->c_rmaj, sizeof(hd->c_maj), HEX); 6151556Srgrimes devminor = (dev_t)asc_ul(hd->c_rmin, sizeof(hd->c_min), HEX); 6161556Srgrimes arcn->sb.st_rdev = TODEV(devmajor, devminor); 6171556Srgrimes arcn->crc = asc_ul(hd->c_chksum, sizeof(hd->c_chksum), HEX); 6181556Srgrimes 6191556Srgrimes /* 6201556Srgrimes * check the length of the file name, if ok read it in, return -1 if 6211556Srgrimes * bogus 6221556Srgrimes */ 6231556Srgrimes if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2) 6241556Srgrimes return(-1); 6251556Srgrimes arcn->nlen = nsz - 1; 6261556Srgrimes if (rd_nm(arcn, nsz) < 0) 6271556Srgrimes return(-1); 6281556Srgrimes 6291556Srgrimes /* 630222177Suqs * skip padding. header + filename is aligned to 4 byte boundaries 6311556Srgrimes */ 6321556Srgrimes if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0) 6331556Srgrimes return(-1); 6341556Srgrimes 6351556Srgrimes /* 6361556Srgrimes * if not a link (or a file with no data), calculate pad size (for 6371556Srgrimes * padding which follows the file data), clear the link name and return 6381556Srgrimes */ 6391556Srgrimes if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) { 6401556Srgrimes /* 6411556Srgrimes * we have a valid header (not a link) 6421556Srgrimes */ 6431556Srgrimes arcn->ln_nlen = 0; 6441556Srgrimes arcn->ln_name[0] = '\0'; 6451556Srgrimes arcn->pad = VCPIO_PAD(arcn->sb.st_size); 6461556Srgrimes return(com_rd(arcn)); 6471556Srgrimes } 6481556Srgrimes 6491556Srgrimes /* 6501556Srgrimes * read in the link name and skip over the padding 6511556Srgrimes */ 6521556Srgrimes if ((rd_ln_nm(arcn) < 0) || 6531556Srgrimes (rd_skip((off_t)(VCPIO_PAD(arcn->sb.st_size))) < 0)) 6541556Srgrimes return(-1); 6551556Srgrimes 6561556Srgrimes /* 6571556Srgrimes * we have a valid header (with a link) 6581556Srgrimes */ 6591556Srgrimes return(com_rd(arcn)); 6601556Srgrimes} 6611556Srgrimes 6621556Srgrimes/* 6631556Srgrimes * vcpio_endrd() 6641556Srgrimes * no cleanup needed here, just return size of the trailer (for append) 6651556Srgrimes * Return: 6661556Srgrimes * size of trailer header in this format 6671556Srgrimes */ 6681556Srgrimes 6691556Srgrimesoff_t 6701556Srgrimesvcpio_endrd(void) 6711556Srgrimes{ 6721556Srgrimes return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) + 6731556Srgrimes (VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER))))); 6741556Srgrimes} 6751556Srgrimes 6761556Srgrimes/* 6771556Srgrimes * crc_stwr() 6781556Srgrimes * start up the device mapping table, enable crc file calculation 6791556Srgrimes * Return: 6801556Srgrimes * 0 if ok, -1 otherwise (what dev_start() returns) 6811556Srgrimes */ 6821556Srgrimes 6831556Srgrimesint 6841556Srgrimescrc_stwr(void) 6851556Srgrimes{ 6861556Srgrimes docrc = 1; 6871556Srgrimes return(dev_start()); 6881556Srgrimes} 6891556Srgrimes 6901556Srgrimes/* 6911556Srgrimes * vcpio_wr() 6921556Srgrimes * copy the data in the ARCHD to buffer in system VR4 cpio 6931556Srgrimes * (with/without crc) format. 6941556Srgrimes * Return 6951556Srgrimes * 0 if file has data to be written after the header, 1 if file has 6961556Srgrimes * NO data to write after the header, -1 if archive write failed 6971556Srgrimes */ 6981556Srgrimes 6991556Srgrimesint 70090113Simpvcpio_wr(ARCHD *arcn) 7011556Srgrimes{ 70290113Simp HD_VCPIO *hd; 7031556Srgrimes unsigned int nsz; 704164699Sru HD_VCPIO hdblk; 7051556Srgrimes 7061556Srgrimes /* 7071556Srgrimes * check and repair truncated device and inode fields in the cpio 7081556Srgrimes * header 7091556Srgrimes */ 7101556Srgrimes if (map_dev(arcn, (u_long)VCPIO_MASK, (u_long)VCPIO_MASK) < 0) 7111556Srgrimes return(-1); 7121556Srgrimes nsz = arcn->nlen + 1; 713164699Sru hd = &hdblk; 7141556Srgrimes if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR)) 7151556Srgrimes arcn->sb.st_rdev = 0; 7161556Srgrimes 7171556Srgrimes /* 7181556Srgrimes * add the proper magic value depending whether we were asked for 7191556Srgrimes * file data crc's, and the crc if needed. 7201556Srgrimes */ 7211556Srgrimes if (docrc) { 7221556Srgrimes if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic), 7231556Srgrimes OCT) || 7241556Srgrimes ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum), 7251556Srgrimes HEX)) 7261556Srgrimes goto out; 7271556Srgrimes } else { 7281556Srgrimes if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic), 7291556Srgrimes OCT) || 7301556Srgrimes ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX)) 7311556Srgrimes goto out; 7321556Srgrimes } 7331556Srgrimes 7341556Srgrimes switch(arcn->type) { 7351556Srgrimes case PAX_CTG: 7361556Srgrimes case PAX_REG: 7371556Srgrimes case PAX_HRG: 7381556Srgrimes /* 7391556Srgrimes * caller will copy file data to the archive. tell him how 7401556Srgrimes * much to pad. 7411556Srgrimes */ 7421556Srgrimes arcn->pad = VCPIO_PAD(arcn->sb.st_size); 7431556Srgrimes# ifdef NET2_STAT 7441556Srgrimes if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize, 7451556Srgrimes sizeof(hd->c_filesize), HEX)) { 7461556Srgrimes# else 7471556Srgrimes if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize, 7481556Srgrimes sizeof(hd->c_filesize), HEX)) { 7491556Srgrimes# endif 75076017Skris paxwarn(1,"File is too large for sv4cpio format %s", 7511556Srgrimes arcn->org_name); 7521556Srgrimes return(1); 7531556Srgrimes } 7541556Srgrimes break; 7551556Srgrimes case PAX_SLK: 7561556Srgrimes /* 7571556Srgrimes * no file data for the caller to process, the file data has 7581556Srgrimes * the size of the link 7591556Srgrimes */ 7601556Srgrimes arcn->pad = 0L; 7611556Srgrimes if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize, 7621556Srgrimes sizeof(hd->c_filesize), HEX)) 7631556Srgrimes goto out; 7641556Srgrimes break; 7651556Srgrimes default: 7661556Srgrimes /* 7671556Srgrimes * no file data for the caller to process 7681556Srgrimes */ 7691556Srgrimes arcn->pad = 0L; 7701556Srgrimes if (ul_asc((u_long)0L, hd->c_filesize, sizeof(hd->c_filesize), 7711556Srgrimes HEX)) 7721556Srgrimes goto out; 7731556Srgrimes break; 7741556Srgrimes } 7751556Srgrimes 7761556Srgrimes /* 7771556Srgrimes * set the other fields in the header 7781556Srgrimes */ 7791556Srgrimes if (ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino), 7801556Srgrimes HEX) || 7811556Srgrimes ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode), 7821556Srgrimes HEX) || 7831556Srgrimes ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid), 7841556Srgrimes HEX) || 7851556Srgrimes ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid), 7861556Srgrimes HEX) || 7871556Srgrimes ul_asc((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime), 7881556Srgrimes HEX) || 7891556Srgrimes ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink), 7901556Srgrimes HEX) || 7911556Srgrimes ul_asc((u_long)MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj), 7921556Srgrimes HEX) || 7931556Srgrimes ul_asc((u_long)MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min), 7941556Srgrimes HEX) || 7951556Srgrimes ul_asc((u_long)MAJOR(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj), 7961556Srgrimes HEX) || 7971556Srgrimes ul_asc((u_long)MINOR(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min), 7981556Srgrimes HEX) || 7991556Srgrimes ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX)) 8001556Srgrimes goto out; 8011556Srgrimes 8021556Srgrimes /* 8031556Srgrimes * write the header, the file name and padding as required. 8041556Srgrimes */ 805164699Sru if ((wr_rdbuf((char *)&hdblk, (int)sizeof(HD_VCPIO)) < 0) || 8061556Srgrimes (wr_rdbuf(arcn->name, (int)nsz) < 0) || 8071556Srgrimes (wr_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)) { 80876017Skris paxwarn(1,"Could not write sv4cpio header for %s",arcn->org_name); 8091556Srgrimes return(-1); 8101556Srgrimes } 8111556Srgrimes 8121556Srgrimes /* 8131556Srgrimes * if we have file data, tell the caller we are done, copy the file 8141556Srgrimes */ 8151556Srgrimes if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) || 8161556Srgrimes (arcn->type == PAX_HRG)) 8171556Srgrimes return(0); 8181556Srgrimes 8191556Srgrimes /* 8201556Srgrimes * if we are not a link, tell the caller we are done, go to next file 8211556Srgrimes */ 8221556Srgrimes if (arcn->type != PAX_SLK) 8231556Srgrimes return(1); 8241556Srgrimes 8251556Srgrimes /* 8261556Srgrimes * write the link name, tell the caller we are done. 8271556Srgrimes */ 8281556Srgrimes if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) || 8291556Srgrimes (wr_skip((off_t)(VCPIO_PAD(arcn->ln_nlen))) < 0)) { 83076017Skris paxwarn(1,"Could not write sv4cpio link name for %s", 8311556Srgrimes arcn->org_name); 8321556Srgrimes return(-1); 8331556Srgrimes } 8341556Srgrimes return(1); 8351556Srgrimes 8361556Srgrimes out: 8371556Srgrimes /* 8381556Srgrimes * header field is out of range 8391556Srgrimes */ 84076017Skris paxwarn(1,"Sv4cpio header field is too small for file %s",arcn->org_name); 8411556Srgrimes return(1); 8421556Srgrimes} 8431556Srgrimes 8441556Srgrimes/* 8451556Srgrimes * Routines common to the old binary header cpio 8461556Srgrimes */ 8471556Srgrimes 8481556Srgrimes/* 8491556Srgrimes * bcpio_id() 850108533Sschweikh * determine if a block given to us is an old binary cpio header 8511556Srgrimes * (with/without header byte swapping) 8521556Srgrimes * Return: 8531556Srgrimes * 0 if a valid header, -1 otherwise 8541556Srgrimes */ 8551556Srgrimes 8561556Srgrimesint 8571556Srgrimesbcpio_id(char *blk, int size) 8581556Srgrimes{ 859114469Sobrien if (size < (int)sizeof(HD_BCPIO)) 8601556Srgrimes return(-1); 8611556Srgrimes 8621556Srgrimes /* 8631556Srgrimes * check both normal and byte swapped magic cookies 8641556Srgrimes */ 8651556Srgrimes if (((u_short)SHRT_EXT(blk)) == MAGIC) 8661556Srgrimes return(0); 8671556Srgrimes if (((u_short)RSHRT_EXT(blk)) == MAGIC) { 8681556Srgrimes if (!swp_head) 8691556Srgrimes ++swp_head; 8701556Srgrimes return(0); 8711556Srgrimes } 8721556Srgrimes return(-1); 8731556Srgrimes} 8741556Srgrimes 8751556Srgrimes/* 8761556Srgrimes * bcpio_rd() 877108533Sschweikh * determine if a buffer is an old binary archive entry. (It may have byte 8781556Srgrimes * swapped header) convert and store the values in the ARCHD parameter. 8791556Srgrimes * This is a very old header format and should not really be used. 8801556Srgrimes * Return: 8811556Srgrimes * 0 if a valid header, -1 otherwise. 8821556Srgrimes */ 8831556Srgrimes 8841556Srgrimesint 88590113Simpbcpio_rd(ARCHD *arcn, char *buf) 8861556Srgrimes{ 88790113Simp HD_BCPIO *hd; 88890113Simp int nsz; 8891556Srgrimes 8901556Srgrimes /* 8911556Srgrimes * check the header 8921556Srgrimes */ 8931556Srgrimes if (bcpio_id(buf, sizeof(HD_BCPIO)) < 0) 8941556Srgrimes return(-1); 8951556Srgrimes 8961556Srgrimes arcn->pad = 0L; 8971556Srgrimes hd = (HD_BCPIO *)buf; 8981556Srgrimes if (swp_head) { 8991556Srgrimes /* 90046684Skris * header has swapped bytes on 16 bit boundaries 9011556Srgrimes */ 9021556Srgrimes arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev)); 9031556Srgrimes arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino)); 9041556Srgrimes arcn->sb.st_mode = (mode_t)(RSHRT_EXT(hd->h_mode)); 9051556Srgrimes arcn->sb.st_uid = (uid_t)(RSHRT_EXT(hd->h_uid)); 9061556Srgrimes arcn->sb.st_gid = (gid_t)(RSHRT_EXT(hd->h_gid)); 9071556Srgrimes arcn->sb.st_nlink = (nlink_t)(RSHRT_EXT(hd->h_nlink)); 9081556Srgrimes arcn->sb.st_rdev = (dev_t)(RSHRT_EXT(hd->h_rdev)); 9091556Srgrimes arcn->sb.st_mtime = (time_t)(RSHRT_EXT(hd->h_mtime_1)); 9101556Srgrimes arcn->sb.st_mtime = (arcn->sb.st_mtime << 16) | 9111556Srgrimes ((time_t)(RSHRT_EXT(hd->h_mtime_2))); 9121556Srgrimes arcn->sb.st_size = (off_t)(RSHRT_EXT(hd->h_filesize_1)); 9131556Srgrimes arcn->sb.st_size = (arcn->sb.st_size << 16) | 9141556Srgrimes ((off_t)(RSHRT_EXT(hd->h_filesize_2))); 9151556Srgrimes nsz = (int)(RSHRT_EXT(hd->h_namesize)); 9161556Srgrimes } else { 9171556Srgrimes arcn->sb.st_dev = (dev_t)(SHRT_EXT(hd->h_dev)); 9181556Srgrimes arcn->sb.st_ino = (ino_t)(SHRT_EXT(hd->h_ino)); 9191556Srgrimes arcn->sb.st_mode = (mode_t)(SHRT_EXT(hd->h_mode)); 9201556Srgrimes arcn->sb.st_uid = (uid_t)(SHRT_EXT(hd->h_uid)); 9211556Srgrimes arcn->sb.st_gid = (gid_t)(SHRT_EXT(hd->h_gid)); 9221556Srgrimes arcn->sb.st_nlink = (nlink_t)(SHRT_EXT(hd->h_nlink)); 9231556Srgrimes arcn->sb.st_rdev = (dev_t)(SHRT_EXT(hd->h_rdev)); 9241556Srgrimes arcn->sb.st_mtime = (time_t)(SHRT_EXT(hd->h_mtime_1)); 9251556Srgrimes arcn->sb.st_mtime = (arcn->sb.st_mtime << 16) | 9261556Srgrimes ((time_t)(SHRT_EXT(hd->h_mtime_2))); 9271556Srgrimes arcn->sb.st_size = (off_t)(SHRT_EXT(hd->h_filesize_1)); 9281556Srgrimes arcn->sb.st_size = (arcn->sb.st_size << 16) | 9291556Srgrimes ((off_t)(SHRT_EXT(hd->h_filesize_2))); 9301556Srgrimes nsz = (int)(SHRT_EXT(hd->h_namesize)); 9311556Srgrimes } 9321556Srgrimes arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 9331556Srgrimes 9341556Srgrimes /* 9351556Srgrimes * check the file name size, if bogus give up. otherwise read the file 9361556Srgrimes * name 9371556Srgrimes */ 9381556Srgrimes if (nsz < 2) 9391556Srgrimes return(-1); 9401556Srgrimes arcn->nlen = nsz - 1; 9411556Srgrimes if (rd_nm(arcn, nsz) < 0) 9421556Srgrimes return(-1); 9431556Srgrimes 9441556Srgrimes /* 945222177Suqs * header + file name are aligned to 2 byte boundaries, skip if needed 9461556Srgrimes */ 9471556Srgrimes if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0) 9481556Srgrimes return(-1); 9491556Srgrimes 9501556Srgrimes /* 9511556Srgrimes * if not a link (or a file with no data), calculate pad size (for 9521556Srgrimes * padding which follows the file data), clear the link name and return 9531556Srgrimes */ 9541556Srgrimes if (((arcn->sb.st_mode & C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)){ 9551556Srgrimes /* 9561556Srgrimes * we have a valid header (not a link) 9571556Srgrimes */ 9581556Srgrimes arcn->ln_nlen = 0; 9591556Srgrimes arcn->ln_name[0] = '\0'; 9601556Srgrimes arcn->pad = BCPIO_PAD(arcn->sb.st_size); 9611556Srgrimes return(com_rd(arcn)); 9621556Srgrimes } 9631556Srgrimes 9641556Srgrimes if ((rd_ln_nm(arcn) < 0) || 9651556Srgrimes (rd_skip((off_t)(BCPIO_PAD(arcn->sb.st_size))) < 0)) 9661556Srgrimes return(-1); 9671556Srgrimes 9681556Srgrimes /* 9691556Srgrimes * we have a valid header (with a link) 9701556Srgrimes */ 9711556Srgrimes return(com_rd(arcn)); 9721556Srgrimes} 9731556Srgrimes 9741556Srgrimes/* 9751556Srgrimes * bcpio_endrd() 9761556Srgrimes * no cleanup needed here, just return size of the trailer (for append) 9771556Srgrimes * Return: 9781556Srgrimes * size of trailer header in this format 9791556Srgrimes */ 9801556Srgrimes 9811556Srgrimesoff_t 9821556Srgrimesbcpio_endrd(void) 9831556Srgrimes{ 9841556Srgrimes return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) + 9851556Srgrimes (BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER))))); 9861556Srgrimes} 9871556Srgrimes 9881556Srgrimes/* 9891556Srgrimes * bcpio_wr() 9901556Srgrimes * copy the data in the ARCHD to buffer in old binary cpio format 9911556Srgrimes * There is a real chance of field overflow with this critter. So we 992222177Suqs * always check that the conversion is ok. nobody in their right mind 993222177Suqs * should write an archive in this format... 9941556Srgrimes * Return 9951556Srgrimes * 0 if file has data to be written after the header, 1 if file has NO 9961556Srgrimes * data to write after the header, -1 if archive write failed 9971556Srgrimes */ 9981556Srgrimes 9991556Srgrimesint 100090113Simpbcpio_wr(ARCHD *arcn) 10011556Srgrimes{ 100290113Simp HD_BCPIO *hd; 100390113Simp int nsz; 1004164699Sru HD_BCPIO hdblk; 10051556Srgrimes off_t t_offt; 10061556Srgrimes int t_int; 10071556Srgrimes time_t t_timet; 10081556Srgrimes 10091556Srgrimes /* 10101556Srgrimes * check and repair truncated device and inode fields in the cpio 10111556Srgrimes * header 10121556Srgrimes */ 10131556Srgrimes if (map_dev(arcn, (u_long)BCPIO_MASK, (u_long)BCPIO_MASK) < 0) 10141556Srgrimes return(-1); 10151556Srgrimes 10161556Srgrimes if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR)) 10171556Srgrimes arcn->sb.st_rdev = 0; 1018164699Sru hd = &hdblk; 10191556Srgrimes 10201556Srgrimes switch(arcn->type) { 10211556Srgrimes case PAX_CTG: 10221556Srgrimes case PAX_REG: 10231556Srgrimes case PAX_HRG: 10241556Srgrimes /* 10251556Srgrimes * caller will copy file data to the archive. tell him how 10261556Srgrimes * much to pad. 10271556Srgrimes */ 10281556Srgrimes arcn->pad = BCPIO_PAD(arcn->sb.st_size); 10291556Srgrimes hd->h_filesize_1[0] = CHR_WR_0(arcn->sb.st_size); 10301556Srgrimes hd->h_filesize_1[1] = CHR_WR_1(arcn->sb.st_size); 10311556Srgrimes hd->h_filesize_2[0] = CHR_WR_2(arcn->sb.st_size); 10321556Srgrimes hd->h_filesize_2[1] = CHR_WR_3(arcn->sb.st_size); 10331556Srgrimes t_offt = (off_t)(SHRT_EXT(hd->h_filesize_1)); 10341556Srgrimes t_offt = (t_offt<<16) | ((off_t)(SHRT_EXT(hd->h_filesize_2))); 10351556Srgrimes if (arcn->sb.st_size != t_offt) { 103676017Skris paxwarn(1,"File is too large for bcpio format %s", 10371556Srgrimes arcn->org_name); 10381556Srgrimes return(1); 10391556Srgrimes } 10401556Srgrimes break; 10411556Srgrimes case PAX_SLK: 10421556Srgrimes /* 10431556Srgrimes * no file data for the caller to process, the file data has 10441556Srgrimes * the size of the link 10451556Srgrimes */ 10461556Srgrimes arcn->pad = 0L; 10471556Srgrimes hd->h_filesize_1[0] = CHR_WR_0(arcn->ln_nlen); 10481556Srgrimes hd->h_filesize_1[1] = CHR_WR_1(arcn->ln_nlen); 10491556Srgrimes hd->h_filesize_2[0] = CHR_WR_2(arcn->ln_nlen); 10501556Srgrimes hd->h_filesize_2[1] = CHR_WR_3(arcn->ln_nlen); 10511556Srgrimes t_int = (int)(SHRT_EXT(hd->h_filesize_1)); 10521556Srgrimes t_int = (t_int << 16) | ((int)(SHRT_EXT(hd->h_filesize_2))); 10531556Srgrimes if (arcn->ln_nlen != t_int) 10541556Srgrimes goto out; 10551556Srgrimes break; 10561556Srgrimes default: 10571556Srgrimes /* 10581556Srgrimes * no file data for the caller to process 10591556Srgrimes */ 10601556Srgrimes arcn->pad = 0L; 10611556Srgrimes hd->h_filesize_1[0] = (char)0; 10621556Srgrimes hd->h_filesize_1[1] = (char)0; 10631556Srgrimes hd->h_filesize_2[0] = (char)0; 10641556Srgrimes hd->h_filesize_2[1] = (char)0; 10651556Srgrimes break; 10661556Srgrimes } 10671556Srgrimes 10681556Srgrimes /* 10691556Srgrimes * build up the rest of the fields 10701556Srgrimes */ 10711556Srgrimes hd->h_magic[0] = CHR_WR_2(MAGIC); 10721556Srgrimes hd->h_magic[1] = CHR_WR_3(MAGIC); 10731556Srgrimes hd->h_dev[0] = CHR_WR_2(arcn->sb.st_dev); 10741556Srgrimes hd->h_dev[1] = CHR_WR_3(arcn->sb.st_dev); 10751556Srgrimes if (arcn->sb.st_dev != (dev_t)(SHRT_EXT(hd->h_dev))) 10761556Srgrimes goto out; 10771556Srgrimes hd->h_ino[0] = CHR_WR_2(arcn->sb.st_ino); 10781556Srgrimes hd->h_ino[1] = CHR_WR_3(arcn->sb.st_ino); 10791556Srgrimes if (arcn->sb.st_ino != (ino_t)(SHRT_EXT(hd->h_ino))) 10801556Srgrimes goto out; 10811556Srgrimes hd->h_mode[0] = CHR_WR_2(arcn->sb.st_mode); 10821556Srgrimes hd->h_mode[1] = CHR_WR_3(arcn->sb.st_mode); 10831556Srgrimes if (arcn->sb.st_mode != (mode_t)(SHRT_EXT(hd->h_mode))) 10841556Srgrimes goto out; 10851556Srgrimes hd->h_uid[0] = CHR_WR_2(arcn->sb.st_uid); 10861556Srgrimes hd->h_uid[1] = CHR_WR_3(arcn->sb.st_uid); 10871556Srgrimes if (arcn->sb.st_uid != (uid_t)(SHRT_EXT(hd->h_uid))) 10881556Srgrimes goto out; 10891556Srgrimes hd->h_gid[0] = CHR_WR_2(arcn->sb.st_gid); 10901556Srgrimes hd->h_gid[1] = CHR_WR_3(arcn->sb.st_gid); 10911556Srgrimes if (arcn->sb.st_gid != (gid_t)(SHRT_EXT(hd->h_gid))) 10921556Srgrimes goto out; 10931556Srgrimes hd->h_nlink[0] = CHR_WR_2(arcn->sb.st_nlink); 10941556Srgrimes hd->h_nlink[1] = CHR_WR_3(arcn->sb.st_nlink); 10951556Srgrimes if (arcn->sb.st_nlink != (nlink_t)(SHRT_EXT(hd->h_nlink))) 10961556Srgrimes goto out; 10971556Srgrimes hd->h_rdev[0] = CHR_WR_2(arcn->sb.st_rdev); 10981556Srgrimes hd->h_rdev[1] = CHR_WR_3(arcn->sb.st_rdev); 10991556Srgrimes if (arcn->sb.st_rdev != (dev_t)(SHRT_EXT(hd->h_rdev))) 11001556Srgrimes goto out; 11011556Srgrimes hd->h_mtime_1[0] = CHR_WR_0(arcn->sb.st_mtime); 11021556Srgrimes hd->h_mtime_1[1] = CHR_WR_1(arcn->sb.st_mtime); 11031556Srgrimes hd->h_mtime_2[0] = CHR_WR_2(arcn->sb.st_mtime); 11041556Srgrimes hd->h_mtime_2[1] = CHR_WR_3(arcn->sb.st_mtime); 11051556Srgrimes t_timet = (time_t)(SHRT_EXT(hd->h_mtime_1)); 11061556Srgrimes t_timet = (t_timet << 16) | ((time_t)(SHRT_EXT(hd->h_mtime_2))); 11071556Srgrimes if (arcn->sb.st_mtime != t_timet) 11081556Srgrimes goto out; 11091556Srgrimes nsz = arcn->nlen + 1; 11101556Srgrimes hd->h_namesize[0] = CHR_WR_2(nsz); 11111556Srgrimes hd->h_namesize[1] = CHR_WR_3(nsz); 11121556Srgrimes if (nsz != (int)(SHRT_EXT(hd->h_namesize))) 11131556Srgrimes goto out; 11141556Srgrimes 11151556Srgrimes /* 11161556Srgrimes * write the header, the file name and padding as required. 11171556Srgrimes */ 1118164699Sru if ((wr_rdbuf((char *)&hdblk, (int)sizeof(HD_BCPIO)) < 0) || 11191556Srgrimes (wr_rdbuf(arcn->name, nsz) < 0) || 11201556Srgrimes (wr_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)) { 112176017Skris paxwarn(1, "Could not write bcpio header for %s", arcn->org_name); 11221556Srgrimes return(-1); 11231556Srgrimes } 11241556Srgrimes 11251556Srgrimes /* 11261556Srgrimes * if we have file data, tell the caller we are done 11271556Srgrimes */ 11281556Srgrimes if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) || 11291556Srgrimes (arcn->type == PAX_HRG)) 11301556Srgrimes return(0); 11311556Srgrimes 11321556Srgrimes /* 11331556Srgrimes * if we are not a link, tell the caller we are done, go to next file 11341556Srgrimes */ 11351556Srgrimes if (arcn->type != PAX_SLK) 11361556Srgrimes return(1); 11371556Srgrimes 11381556Srgrimes /* 11391556Srgrimes * write the link name, tell the caller we are done. 11401556Srgrimes */ 11411556Srgrimes if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) || 11421556Srgrimes (wr_skip((off_t)(BCPIO_PAD(arcn->ln_nlen))) < 0)) { 114376017Skris paxwarn(1,"Could not write bcpio link name for %s",arcn->org_name); 11441556Srgrimes return(-1); 11451556Srgrimes } 11461556Srgrimes return(1); 11471556Srgrimes 11481556Srgrimes out: 11491556Srgrimes /* 11501556Srgrimes * header field is out of range 11511556Srgrimes */ 115276017Skris paxwarn(1,"Bcpio header field is too small for file %s", arcn->org_name); 11531556Srgrimes return(1); 11541556Srgrimes} 1155