cpio.c revision 46684
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 * 3. All advertising materials mentioning features or use of this software 181556Srgrimes * must display the following acknowledgement: 191556Srgrimes * This product includes software developed by the University of 201556Srgrimes * California, Berkeley and its contributors. 211556Srgrimes * 4. Neither the name of the University nor the names of its contributors 221556Srgrimes * may be used to endorse or promote products derived from this software 231556Srgrimes * without specific prior written permission. 241556Srgrimes * 251556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 271556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 301556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 311556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 321556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 331556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 341556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 351556Srgrimes * SUCH DAMAGE. 361556Srgrimes */ 371556Srgrimes 381556Srgrimes#ifndef lint 3936049Scharnier#if 0 4036049Scharnierstatic char sccsid[] = "@(#)cpio.c 8.1 (Berkeley) 5/31/93"; 4136049Scharnier#endif 4236049Scharnierstatic const char rcsid[] = 4346684Skris "$Id: cpio.c,v 1.10 1998/05/15 06:27:38 charnier Exp $"; 441556Srgrimes#endif /* not lint */ 451556Srgrimes 461556Srgrimes#include <sys/types.h> 471556Srgrimes#include <sys/time.h> 481556Srgrimes#include <sys/stat.h> 491556Srgrimes#include <string.h> 501556Srgrimes#include <stdio.h> 511556Srgrimes#include <unistd.h> 521556Srgrimes#include <stdlib.h> 531556Srgrimes#include "pax.h" 541556Srgrimes#include "cpio.h" 551556Srgrimes#include "extern.h" 561556Srgrimes 571556Srgrimesstatic int rd_nm __P((register ARCHD *, int)); 581556Srgrimesstatic int rd_ln_nm __P((register ARCHD *)); 591556Srgrimesstatic int com_rd __P((register ARCHD *)); 601556Srgrimes 611556Srgrimes/* 621556Srgrimes * Routines which support the different cpio versions 631556Srgrimes */ 641556Srgrimes 651556Srgrimesstatic int swp_head; /* binary cpio header byte swap */ 661556Srgrimes 671556Srgrimes/* 681556Srgrimes * Routines common to all versions of cpio 691556Srgrimes */ 701556Srgrimes 711556Srgrimes/* 721556Srgrimes * cpio_strd() 731556Srgrimes * Fire up the hard link detection code 741556Srgrimes * Return: 751556Srgrimes * 0 if ok -1 otherwise (the return values of lnk_start()) 761556Srgrimes */ 771556Srgrimes 781556Srgrimes#if __STDC__ 791556Srgrimesint 801556Srgrimescpio_strd(void) 811556Srgrimes#else 821556Srgrimesint 831556Srgrimescpio_strd() 841556Srgrimes#endif 851556Srgrimes{ 861556Srgrimes return(lnk_start()); 871556Srgrimes} 881556Srgrimes 891556Srgrimes/* 901556Srgrimes * cpio_trail() 911556Srgrimes * Called to determine if a header block is a valid trailer. We are 921556Srgrimes * passed the block, the in_sync flag (which tells us we are in resync 931556Srgrimes * mode; looking for a valid header), and cnt (which starts at zero) 941556Srgrimes * which is used to count the number of empty blocks we have seen so far. 951556Srgrimes * Return: 968855Srgrimes * 0 if a valid trailer, -1 if not a valid trailer, 971556Srgrimes */ 981556Srgrimes 991556Srgrimes#if __STDC__ 1001556Srgrimesint 1011556Srgrimescpio_trail(register ARCHD *arcn) 1021556Srgrimes#else 1031556Srgrimesint 1041556Srgrimescpio_trail(arcn) 1051556Srgrimes register ARCHD *arcn; 1061556Srgrimes#endif 1071556Srgrimes{ 1081556Srgrimes /* 1091556Srgrimes * look for trailer id in file we are about to process 1101556Srgrimes */ 1111556Srgrimes if ((strcmp(arcn->name, TRAILER) == 0) && (arcn->sb.st_size == 0)) 1121556Srgrimes return(0); 1131556Srgrimes return(-1); 1141556Srgrimes} 1151556Srgrimes 1161556Srgrimes/* 1171556Srgrimes * com_rd() 1181556Srgrimes * operations common to all cpio read functions. 1191556Srgrimes * Return: 1201556Srgrimes * 0 1211556Srgrimes */ 1221556Srgrimes 1231556Srgrimes#if __STDC__ 1241556Srgrimesstatic int 1251556Srgrimescom_rd(register ARCHD *arcn) 1261556Srgrimes#else 1271556Srgrimesstatic int 1281556Srgrimescom_rd(arcn) 1291556Srgrimes register ARCHD *arcn; 1301556Srgrimes#endif 1311556Srgrimes{ 1321556Srgrimes arcn->skip = 0; 1331556Srgrimes arcn->pat = NULL; 1341556Srgrimes arcn->org_name = arcn->name; 1351556Srgrimes switch(arcn->sb.st_mode & C_IFMT) { 1361556Srgrimes case C_ISFIFO: 1371556Srgrimes arcn->type = PAX_FIF; 1381556Srgrimes break; 1391556Srgrimes case C_ISDIR: 1401556Srgrimes arcn->type = PAX_DIR; 1411556Srgrimes break; 1421556Srgrimes case C_ISBLK: 1431556Srgrimes arcn->type = PAX_BLK; 1441556Srgrimes break; 1451556Srgrimes case C_ISCHR: 1461556Srgrimes arcn->type = PAX_CHR; 1471556Srgrimes break; 1481556Srgrimes case C_ISLNK: 1491556Srgrimes arcn->type = PAX_SLK; 1501556Srgrimes break; 1511556Srgrimes case C_ISOCK: 1521556Srgrimes arcn->type = PAX_SCK; 1531556Srgrimes break; 1541556Srgrimes case C_ISCTG: 1551556Srgrimes case C_ISREG: 1561556Srgrimes default: 1571556Srgrimes /* 1581556Srgrimes * we have file data, set up skip (pad is set in the format 1591556Srgrimes * specific sections) 1601556Srgrimes */ 1611556Srgrimes arcn->sb.st_mode = (arcn->sb.st_mode & 0xfff) | C_ISREG; 1621556Srgrimes arcn->type = PAX_REG; 1631556Srgrimes arcn->skip = arcn->sb.st_size; 1641556Srgrimes break; 1651556Srgrimes } 1661556Srgrimes if (chk_lnk(arcn) < 0) 1671556Srgrimes return(-1); 1681556Srgrimes return(0); 1691556Srgrimes} 1701556Srgrimes 1711556Srgrimes/* 1721556Srgrimes * cpio_end_wr() 1731556Srgrimes * write the special file with the name trailer in the proper format 1741556Srgrimes * Return: 1751556Srgrimes * result of the write of the trailer from the cpio specific write func 1761556Srgrimes */ 1771556Srgrimes 1781556Srgrimes#if __STDC__ 1791556Srgrimesint 1801556Srgrimescpio_endwr(void) 1811556Srgrimes#else 1821556Srgrimesint 1831556Srgrimescpio_endwr() 1841556Srgrimes#endif 1851556Srgrimes{ 1861556Srgrimes ARCHD last; 1871556Srgrimes 1881556Srgrimes /* 1891556Srgrimes * create a trailer request and call the proper format write function 1901556Srgrimes */ 1911556Srgrimes bzero((char *)&last, sizeof(last)); 1921556Srgrimes last.nlen = sizeof(TRAILER) - 1; 1931556Srgrimes last.type = PAX_REG; 1941556Srgrimes last.sb.st_nlink = 1; 1951556Srgrimes (void)strcpy(last.name, TRAILER); 1961556Srgrimes return((*frmt->wr)(&last)); 1971556Srgrimes} 1981556Srgrimes 1991556Srgrimes/* 2001556Srgrimes * rd_nam() 2011556Srgrimes * read in the file name which follows the cpio header 2021556Srgrimes * Return: 2031556Srgrimes * 0 if ok, -1 otherwise 2041556Srgrimes */ 2051556Srgrimes 2061556Srgrimes#if __STDC__ 2071556Srgrimesstatic int 2081556Srgrimesrd_nm(register ARCHD *arcn, int nsz) 2091556Srgrimes#else 2101556Srgrimesstatic int 2111556Srgrimesrd_nm(arcn, nsz) 2121556Srgrimes register ARCHD *arcn; 2131556Srgrimes int nsz; 2141556Srgrimes#endif 2151556Srgrimes{ 2161556Srgrimes /* 2171556Srgrimes * do not even try bogus values 2181556Srgrimes */ 2191556Srgrimes if ((nsz == 0) || (nsz > sizeof(arcn->name))) { 22028904Ssos pax_warn(1, "Cpio file name length %d is out of range", nsz); 2211556Srgrimes return(-1); 2221556Srgrimes } 2231556Srgrimes 2241556Srgrimes /* 2251556Srgrimes * read the name and make sure it is not empty and is \0 terminated 2261556Srgrimes */ 2271556Srgrimes if ((rd_wrbuf(arcn->name,nsz) != nsz) || (arcn->name[nsz-1] != '\0') || 2281556Srgrimes (arcn->name[0] == '\0')) { 22928904Ssos pax_warn(1, "Cpio file name in header is corrupted"); 2301556Srgrimes return(-1); 2311556Srgrimes } 2321556Srgrimes return(0); 2331556Srgrimes} 2341556Srgrimes 2351556Srgrimes/* 2361556Srgrimes * rd_ln_nm() 2371556Srgrimes * read in the link name for a file with links. The link name is stored 2381556Srgrimes * like file data (and is NOT \0 terminated!) 2391556Srgrimes * Return: 2401556Srgrimes * 0 if ok, -1 otherwise 2411556Srgrimes */ 2421556Srgrimes 2431556Srgrimes#if __STDC__ 2441556Srgrimesstatic int 2451556Srgrimesrd_ln_nm(register ARCHD *arcn) 2461556Srgrimes#else 2471556Srgrimesstatic int 2481556Srgrimesrd_ln_nm(arcn) 2491556Srgrimes register ARCHD *arcn; 2501556Srgrimes#endif 2511556Srgrimes{ 2521556Srgrimes /* 2531556Srgrimes * check the length specified for bogus values 2541556Srgrimes */ 2551556Srgrimes if ((arcn->sb.st_size == 0) || 2561556Srgrimes (arcn->sb.st_size >= sizeof(arcn->ln_name))) { 2571556Srgrimes# ifdef NET2_STAT 25828904Ssos pax_warn(1, "Cpio link name length is invalid: %lu", 2591556Srgrimes arcn->sb.st_size); 2601556Srgrimes# else 26128904Ssos pax_warn(1, "Cpio link name length is invalid: %qu", 2621556Srgrimes arcn->sb.st_size); 2631556Srgrimes# endif 2641556Srgrimes return(-1); 2651556Srgrimes } 2661556Srgrimes 2671556Srgrimes /* 2681556Srgrimes * read in the link name and \0 terminate it 2691556Srgrimes */ 2701556Srgrimes if (rd_wrbuf(arcn->ln_name, (int)arcn->sb.st_size) != 2711556Srgrimes (int)arcn->sb.st_size) { 27228904Ssos pax_warn(1, "Cpio link name read error"); 2731556Srgrimes return(-1); 2741556Srgrimes } 2751556Srgrimes arcn->ln_nlen = arcn->sb.st_size; 2761556Srgrimes arcn->ln_name[arcn->ln_nlen] = '\0'; 2771556Srgrimes 2781556Srgrimes /* 2791556Srgrimes * watch out for those empty link names 2801556Srgrimes */ 2811556Srgrimes if (arcn->ln_name[0] == '\0') { 28228904Ssos pax_warn(1, "Cpio link name is corrupt"); 2831556Srgrimes return(-1); 2841556Srgrimes } 2851556Srgrimes return(0); 2861556Srgrimes} 2871556Srgrimes 2881556Srgrimes/* 2891556Srgrimes * Routines common to the extended byte oriented cpio format 2901556Srgrimes */ 2911556Srgrimes 2921556Srgrimes/* 2931556Srgrimes * cpio_id() 2941556Srgrimes * determine if a block given to us is a valid extended byte oriented 2951556Srgrimes * cpio header 2961556Srgrimes * Return: 2971556Srgrimes * 0 if a valid header, -1 otherwise 2981556Srgrimes */ 2991556Srgrimes 3001556Srgrimes#if __STDC__ 3011556Srgrimesint 3021556Srgrimescpio_id(char *blk, int size) 3031556Srgrimes#else 3041556Srgrimesint 3051556Srgrimescpio_id(blk, size) 3061556Srgrimes char *blk; 3071556Srgrimes int size; 3081556Srgrimes#endif 3091556Srgrimes{ 3101556Srgrimes if ((size < sizeof(HD_CPIO)) || 3111556Srgrimes (strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0)) 3121556Srgrimes return(-1); 3131556Srgrimes return(0); 3141556Srgrimes} 3151556Srgrimes 3161556Srgrimes/* 3171556Srgrimes * cpio_rd() 3181556Srgrimes * determine if a buffer is a byte oriented extended cpio archive entry. 3191556Srgrimes * convert and store the values in the ARCHD parameter. 3201556Srgrimes * Return: 3211556Srgrimes * 0 if a valid header, -1 otherwise. 3221556Srgrimes */ 3231556Srgrimes 3241556Srgrimes#if __STDC__ 3251556Srgrimesint 3261556Srgrimescpio_rd(register ARCHD *arcn, register char *buf) 3271556Srgrimes#else 3281556Srgrimesint 3291556Srgrimescpio_rd(arcn, buf) 3301556Srgrimes register ARCHD *arcn; 3311556Srgrimes register char *buf; 3321556Srgrimes#endif 3331556Srgrimes{ 3341556Srgrimes register int nsz; 3351556Srgrimes register HD_CPIO *hd; 3361556Srgrimes 3371556Srgrimes /* 3381556Srgrimes * check that this is a valid header, if not return -1 3391556Srgrimes */ 3401556Srgrimes if (cpio_id(buf, sizeof(HD_CPIO)) < 0) 3411556Srgrimes return(-1); 3421556Srgrimes hd = (HD_CPIO *)buf; 3431556Srgrimes 3441556Srgrimes /* 3451556Srgrimes * byte oriented cpio (posix) does not have padding! extract the octal 3461556Srgrimes * ascii fields from the header 3471556Srgrimes */ 3481556Srgrimes arcn->pad = 0L; 3491556Srgrimes arcn->sb.st_dev = (dev_t)asc_ul(hd->c_dev, sizeof(hd->c_dev), OCT); 3501556Srgrimes arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), OCT); 3511556Srgrimes arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), OCT); 3521556Srgrimes arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), OCT); 3531556Srgrimes arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), OCT); 3541556Srgrimes arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink), 3551556Srgrimes OCT); 3561556Srgrimes arcn->sb.st_rdev = (dev_t)asc_ul(hd->c_rdev, sizeof(hd->c_rdev), OCT); 3571556Srgrimes arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime), 3581556Srgrimes OCT); 3591556Srgrimes arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 3601556Srgrimes# ifdef NET2_STAT 3611556Srgrimes arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,sizeof(hd->c_filesize), 3621556Srgrimes OCT); 3631556Srgrimes# else 3641556Srgrimes arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,sizeof(hd->c_filesize), 3651556Srgrimes OCT); 3661556Srgrimes# endif 3671556Srgrimes 3681556Srgrimes /* 3691556Srgrimes * check name size and if valid, read in the name of this entry (name 3701556Srgrimes * follows header in the archive) 3711556Srgrimes */ 3721556Srgrimes if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2) 3731556Srgrimes return(-1); 3741556Srgrimes arcn->nlen = nsz - 1; 3751556Srgrimes if (rd_nm(arcn, nsz) < 0) 3761556Srgrimes return(-1); 3771556Srgrimes 3781556Srgrimes if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) { 3791556Srgrimes /* 3801556Srgrimes * no link name to read for this file 3811556Srgrimes */ 3821556Srgrimes arcn->ln_nlen = 0; 3831556Srgrimes arcn->ln_name[0] = '\0'; 3841556Srgrimes return(com_rd(arcn)); 3851556Srgrimes } 3861556Srgrimes 3871556Srgrimes /* 3881556Srgrimes * check link name size and read in the link name. Link names are 3891556Srgrimes * stored like file data. 3901556Srgrimes */ 3911556Srgrimes if (rd_ln_nm(arcn) < 0) 3921556Srgrimes return(-1); 3931556Srgrimes 3941556Srgrimes /* 3951556Srgrimes * we have a valid header (with a link) 3961556Srgrimes */ 3971556Srgrimes return(com_rd(arcn)); 3981556Srgrimes} 3991556Srgrimes 4001556Srgrimes/* 4011556Srgrimes * cpio_endrd() 4021556Srgrimes * no cleanup needed here, just return size of the trailer (for append) 4031556Srgrimes * Return: 4041556Srgrimes * size of trailer header in this format 4051556Srgrimes */ 4061556Srgrimes 4071556Srgrimes#if __STDC__ 4081556Srgrimesoff_t 4091556Srgrimescpio_endrd(void) 4101556Srgrimes#else 4111556Srgrimesoff_t 4121556Srgrimescpio_endrd() 4131556Srgrimes#endif 4141556Srgrimes{ 4151556Srgrimes return((off_t)(sizeof(HD_CPIO) + sizeof(TRAILER))); 4161556Srgrimes} 4171556Srgrimes 4181556Srgrimes/* 4191556Srgrimes * cpio_stwr() 4201556Srgrimes * start up the device mapping table 4211556Srgrimes * Return: 4221556Srgrimes * 0 if ok, -1 otherwise (what dev_start() returns) 4231556Srgrimes */ 4241556Srgrimes 4251556Srgrimes#if __STDC__ 4261556Srgrimesint 4271556Srgrimescpio_stwr(void) 4281556Srgrimes#else 4291556Srgrimesint 4301556Srgrimescpio_stwr() 4311556Srgrimes#endif 4321556Srgrimes{ 4331556Srgrimes return(dev_start()); 4341556Srgrimes} 4351556Srgrimes 4361556Srgrimes/* 4371556Srgrimes * cpio_wr() 4381556Srgrimes * copy the data in the ARCHD to buffer in extended byte oriented cpio 4391556Srgrimes * format. 4401556Srgrimes * Return 4411556Srgrimes * 0 if file has data to be written after the header, 1 if file has NO 4421556Srgrimes * data to write after the header, -1 if archive write failed 4431556Srgrimes */ 4441556Srgrimes 4451556Srgrimes#if __STDC__ 4461556Srgrimesint 4471556Srgrimescpio_wr(register ARCHD *arcn) 4481556Srgrimes#else 4491556Srgrimesint 4501556Srgrimescpio_wr(arcn) 4511556Srgrimes register ARCHD *arcn; 4521556Srgrimes#endif 4531556Srgrimes{ 4541556Srgrimes register HD_CPIO *hd; 4551556Srgrimes register int nsz; 4561556Srgrimes char hdblk[sizeof(HD_CPIO)]; 4571556Srgrimes 4581556Srgrimes /* 4591556Srgrimes * check and repair truncated device and inode fields in the header 4601556Srgrimes */ 4611556Srgrimes if (map_dev(arcn, (u_long)CPIO_MASK, (u_long)CPIO_MASK) < 0) 4621556Srgrimes return(-1); 4631556Srgrimes 4641556Srgrimes arcn->pad = 0L; 4651556Srgrimes nsz = arcn->nlen + 1; 4661556Srgrimes hd = (HD_CPIO *)hdblk; 4671556Srgrimes if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR)) 4681556Srgrimes arcn->sb.st_rdev = 0; 4691556Srgrimes 4701556Srgrimes switch(arcn->type) { 4711556Srgrimes case PAX_CTG: 4721556Srgrimes case PAX_REG: 4731556Srgrimes case PAX_HRG: 4741556Srgrimes /* 4751556Srgrimes * set data size for file data 4761556Srgrimes */ 4771556Srgrimes# ifdef NET2_STAT 4781556Srgrimes if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize, 4791556Srgrimes sizeof(hd->c_filesize), OCT)) { 4801556Srgrimes# else 4811556Srgrimes if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize, 4821556Srgrimes sizeof(hd->c_filesize), OCT)) { 4831556Srgrimes# endif 48428904Ssos pax_warn(1,"File is too large for cpio format %s", 4851556Srgrimes arcn->org_name); 4861556Srgrimes return(1); 4871556Srgrimes } 4881556Srgrimes break; 4891556Srgrimes case PAX_SLK: 4901556Srgrimes /* 4911556Srgrimes * set data size to hold link name 4921556Srgrimes */ 4931556Srgrimes if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize, 4941556Srgrimes sizeof(hd->c_filesize), OCT)) 4951556Srgrimes goto out; 4961556Srgrimes break; 4971556Srgrimes default: 4981556Srgrimes /* 4991556Srgrimes * all other file types have no file data 5001556Srgrimes */ 5011556Srgrimes if (ul_asc((u_long)0, hd->c_filesize, sizeof(hd->c_filesize), 5021556Srgrimes OCT)) 5031556Srgrimes goto out; 5041556Srgrimes break; 5051556Srgrimes } 5061556Srgrimes 5071556Srgrimes /* 5081556Srgrimes * copy the values to the header using octal ascii 5091556Srgrimes */ 5101556Srgrimes if (ul_asc((u_long)MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) || 5111556Srgrimes ul_asc((u_long)arcn->sb.st_dev, hd->c_dev, sizeof(hd->c_dev), 5121556Srgrimes OCT) || 5131556Srgrimes ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino), 5141556Srgrimes OCT) || 5151556Srgrimes ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode), 5161556Srgrimes OCT) || 5171556Srgrimes ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid), 5181556Srgrimes OCT) || 5191556Srgrimes ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid), 5201556Srgrimes OCT) || 5211556Srgrimes ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink), 5221556Srgrimes OCT) || 5231556Srgrimes ul_asc((u_long)arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev), 5241556Srgrimes OCT) || 5251556Srgrimes ul_asc((u_long)arcn->sb.st_mtime,hd->c_mtime,sizeof(hd->c_mtime), 5261556Srgrimes OCT) || 5271556Srgrimes ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT)) 5281556Srgrimes goto out; 5291556Srgrimes 5301556Srgrimes /* 5311556Srgrimes * write the file name to the archive 5321556Srgrimes */ 5331556Srgrimes if ((wr_rdbuf(hdblk, (int)sizeof(HD_CPIO)) < 0) || 5341556Srgrimes (wr_rdbuf(arcn->name, nsz) < 0)) { 53528904Ssos pax_warn(1, "Unable to write cpio header for %s", arcn->org_name); 5361556Srgrimes return(-1); 5371556Srgrimes } 5381556Srgrimes 5391556Srgrimes /* 5401556Srgrimes * if this file has data, we are done. The caller will write the file 5411556Srgrimes * data, if we are link tell caller we are done, go to next file 5421556Srgrimes */ 5431556Srgrimes if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) || 5441556Srgrimes (arcn->type == PAX_HRG)) 5451556Srgrimes return(0); 5461556Srgrimes if (arcn->type != PAX_SLK) 5471556Srgrimes return(1); 5481556Srgrimes 5491556Srgrimes /* 5501556Srgrimes * write the link name to the archive, tell the caller to go to the 5511556Srgrimes * next file as we are done. 5521556Srgrimes */ 5531556Srgrimes if (wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) { 55428904Ssos pax_warn(1,"Unable to write cpio link name for %s",arcn->org_name); 5551556Srgrimes return(-1); 5561556Srgrimes } 5571556Srgrimes return(1); 5581556Srgrimes 5591556Srgrimes out: 5601556Srgrimes /* 5611556Srgrimes * header field is out of range 5621556Srgrimes */ 56328904Ssos pax_warn(1, "Cpio header field is too small to store file %s", 5641556Srgrimes arcn->org_name); 5651556Srgrimes return(1); 5661556Srgrimes} 5671556Srgrimes 5681556Srgrimes/* 5691556Srgrimes * Routines common to the system VR4 version of cpio (with/without file CRC) 5701556Srgrimes */ 5711556Srgrimes 5721556Srgrimes/* 5731556Srgrimes * vcpio_id() 5741556Srgrimes * determine if a block given to us is a valid system VR4 cpio header 5758855Srgrimes * WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header 5761556Srgrimes * uses HEX 5771556Srgrimes * Return: 5781556Srgrimes * 0 if a valid header, -1 otherwise 5791556Srgrimes */ 5801556Srgrimes 5811556Srgrimes#if __STDC__ 5821556Srgrimesint 5831556Srgrimesvcpio_id(char *blk, int size) 5841556Srgrimes#else 5851556Srgrimesint 5861556Srgrimesvcpio_id(blk, size) 5871556Srgrimes char *blk; 5881556Srgrimes int size; 5891556Srgrimes#endif 5901556Srgrimes{ 5911556Srgrimes if ((size < sizeof(HD_VCPIO)) || 5921556Srgrimes (strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0)) 5931556Srgrimes return(-1); 5941556Srgrimes return(0); 5951556Srgrimes} 5961556Srgrimes 5971556Srgrimes/* 5981556Srgrimes * crc_id() 5991556Srgrimes * determine if a block given to us is a valid system VR4 cpio header 6001556Srgrimes * WITH crc. WATCH it the magic cookies are in OCTAL the header uses HEX 6011556Srgrimes * Return: 6021556Srgrimes * 0 if a valid header, -1 otherwise 6031556Srgrimes */ 6041556Srgrimes 6051556Srgrimes#if __STDC__ 6061556Srgrimesint 6071556Srgrimescrc_id(char *blk, int size) 6081556Srgrimes#else 6091556Srgrimesint 6101556Srgrimescrc_id(blk, size) 6111556Srgrimes char *blk; 6121556Srgrimes int size; 6131556Srgrimes#endif 6141556Srgrimes{ 6151556Srgrimes if ((size < sizeof(HD_VCPIO)) || 6161556Srgrimes (strncmp(blk, AVCMAGIC, sizeof(AVCMAGIC) - 1) != 0)) 6171556Srgrimes return(-1); 6181556Srgrimes return(0); 6191556Srgrimes} 6201556Srgrimes 6211556Srgrimes/* 6221556Srgrimes * crc_strd() 6231556Srgrimes w set file data CRC calculations. Fire up the hard link detection code 6241556Srgrimes * Return: 6251556Srgrimes * 0 if ok -1 otherwise (the return values of lnk_start()) 6261556Srgrimes */ 6271556Srgrimes 6281556Srgrimes#if __STDC__ 6291556Srgrimesint 6301556Srgrimescrc_strd(void) 6311556Srgrimes#else 6321556Srgrimesint 6331556Srgrimescrc_strd() 6341556Srgrimes#endif 6351556Srgrimes{ 6361556Srgrimes docrc = 1; 6371556Srgrimes return(lnk_start()); 6381556Srgrimes} 6391556Srgrimes 6401556Srgrimes/* 6411556Srgrimes * vcpio_rd() 6421556Srgrimes * determine if a buffer is a system VR4 archive entry. (with/without CRC) 6431556Srgrimes * convert and store the values in the ARCHD parameter. 6441556Srgrimes * Return: 6451556Srgrimes * 0 if a valid header, -1 otherwise. 6461556Srgrimes */ 6471556Srgrimes 6481556Srgrimes#if __STDC__ 6491556Srgrimesint 6501556Srgrimesvcpio_rd(register ARCHD *arcn, register char *buf) 6511556Srgrimes#else 6521556Srgrimesint 6531556Srgrimesvcpio_rd(arcn, buf) 6541556Srgrimes register ARCHD *arcn; 6551556Srgrimes register char *buf; 6561556Srgrimes#endif 6571556Srgrimes{ 6581556Srgrimes register HD_VCPIO *hd; 6591556Srgrimes dev_t devminor; 6601556Srgrimes dev_t devmajor; 6611556Srgrimes register int nsz; 6621556Srgrimes 6631556Srgrimes /* 6641556Srgrimes * during the id phase it was determined if we were using CRC, use the 6651556Srgrimes * proper id routine. 6661556Srgrimes */ 6671556Srgrimes if (docrc) { 6681556Srgrimes if (crc_id(buf, sizeof(HD_VCPIO)) < 0) 6691556Srgrimes return(-1); 6701556Srgrimes } else { 6711556Srgrimes if (vcpio_id(buf, sizeof(HD_VCPIO)) < 0) 6721556Srgrimes return(-1); 6731556Srgrimes } 6741556Srgrimes 6751556Srgrimes hd = (HD_VCPIO *)buf; 6761556Srgrimes arcn->pad = 0L; 6771556Srgrimes 6781556Srgrimes /* 6791556Srgrimes * extract the hex ascii fields from the header 6801556Srgrimes */ 6811556Srgrimes arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), HEX); 6821556Srgrimes arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), HEX); 6831556Srgrimes arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), HEX); 6841556Srgrimes arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX); 6851556Srgrimes arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX); 6861556Srgrimes arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 6871556Srgrimes# ifdef NET2_STAT 6881556Srgrimes arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize, 6891556Srgrimes sizeof(hd->c_filesize), HEX); 6901556Srgrimes# else 6911556Srgrimes arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize, 6921556Srgrimes sizeof(hd->c_filesize), HEX); 6931556Srgrimes# endif 6941556Srgrimes arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink), 6951556Srgrimes HEX); 6961556Srgrimes devmajor = (dev_t)asc_ul(hd->c_maj, sizeof(hd->c_maj), HEX); 6971556Srgrimes devminor = (dev_t)asc_ul(hd->c_min, sizeof(hd->c_min), HEX); 6981556Srgrimes arcn->sb.st_dev = TODEV(devmajor, devminor); 6991556Srgrimes devmajor = (dev_t)asc_ul(hd->c_rmaj, sizeof(hd->c_maj), HEX); 7001556Srgrimes devminor = (dev_t)asc_ul(hd->c_rmin, sizeof(hd->c_min), HEX); 7011556Srgrimes arcn->sb.st_rdev = TODEV(devmajor, devminor); 7021556Srgrimes arcn->crc = asc_ul(hd->c_chksum, sizeof(hd->c_chksum), HEX); 7031556Srgrimes 7041556Srgrimes /* 7051556Srgrimes * check the length of the file name, if ok read it in, return -1 if 7061556Srgrimes * bogus 7071556Srgrimes */ 7081556Srgrimes if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2) 7091556Srgrimes return(-1); 7101556Srgrimes arcn->nlen = nsz - 1; 7111556Srgrimes if (rd_nm(arcn, nsz) < 0) 7121556Srgrimes return(-1); 7131556Srgrimes 7141556Srgrimes /* 7151556Srgrimes * skip padding. header + filename is aligned to 4 byte boundries 7161556Srgrimes */ 7171556Srgrimes if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0) 7181556Srgrimes return(-1); 7191556Srgrimes 7201556Srgrimes /* 7211556Srgrimes * if not a link (or a file with no data), calculate pad size (for 7221556Srgrimes * padding which follows the file data), clear the link name and return 7231556Srgrimes */ 7241556Srgrimes if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) { 7251556Srgrimes /* 7261556Srgrimes * we have a valid header (not a link) 7271556Srgrimes */ 7281556Srgrimes arcn->ln_nlen = 0; 7291556Srgrimes arcn->ln_name[0] = '\0'; 7301556Srgrimes arcn->pad = VCPIO_PAD(arcn->sb.st_size); 7311556Srgrimes return(com_rd(arcn)); 7321556Srgrimes } 7331556Srgrimes 7341556Srgrimes /* 7351556Srgrimes * read in the link name and skip over the padding 7361556Srgrimes */ 7371556Srgrimes if ((rd_ln_nm(arcn) < 0) || 7381556Srgrimes (rd_skip((off_t)(VCPIO_PAD(arcn->sb.st_size))) < 0)) 7391556Srgrimes return(-1); 7401556Srgrimes 7411556Srgrimes /* 7421556Srgrimes * we have a valid header (with a link) 7431556Srgrimes */ 7441556Srgrimes return(com_rd(arcn)); 7451556Srgrimes} 7461556Srgrimes 7471556Srgrimes/* 7481556Srgrimes * vcpio_endrd() 7491556Srgrimes * no cleanup needed here, just return size of the trailer (for append) 7501556Srgrimes * Return: 7511556Srgrimes * size of trailer header in this format 7521556Srgrimes */ 7531556Srgrimes 7541556Srgrimes#if __STDC__ 7551556Srgrimesoff_t 7561556Srgrimesvcpio_endrd(void) 7571556Srgrimes#else 7581556Srgrimesoff_t 7591556Srgrimesvcpio_endrd() 7601556Srgrimes#endif 7611556Srgrimes{ 7621556Srgrimes return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) + 7631556Srgrimes (VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER))))); 7641556Srgrimes} 7651556Srgrimes 7661556Srgrimes/* 7671556Srgrimes * crc_stwr() 7681556Srgrimes * start up the device mapping table, enable crc file calculation 7691556Srgrimes * Return: 7701556Srgrimes * 0 if ok, -1 otherwise (what dev_start() returns) 7711556Srgrimes */ 7721556Srgrimes 7731556Srgrimes#if __STDC__ 7741556Srgrimesint 7751556Srgrimescrc_stwr(void) 7761556Srgrimes#else 7771556Srgrimesint 7781556Srgrimescrc_stwr() 7791556Srgrimes#endif 7801556Srgrimes{ 7811556Srgrimes docrc = 1; 7821556Srgrimes return(dev_start()); 7831556Srgrimes} 7841556Srgrimes 7851556Srgrimes/* 7861556Srgrimes * vcpio_wr() 7871556Srgrimes * copy the data in the ARCHD to buffer in system VR4 cpio 7881556Srgrimes * (with/without crc) format. 7891556Srgrimes * Return 7901556Srgrimes * 0 if file has data to be written after the header, 1 if file has 7911556Srgrimes * NO data to write after the header, -1 if archive write failed 7921556Srgrimes */ 7931556Srgrimes 7941556Srgrimes#if __STDC__ 7951556Srgrimesint 7961556Srgrimesvcpio_wr(register ARCHD *arcn) 7971556Srgrimes#else 7981556Srgrimesint 7991556Srgrimesvcpio_wr(arcn) 8001556Srgrimes register ARCHD *arcn; 8011556Srgrimes#endif 8021556Srgrimes{ 8031556Srgrimes register HD_VCPIO *hd; 8041556Srgrimes unsigned int nsz; 8051556Srgrimes char hdblk[sizeof(HD_VCPIO)]; 8061556Srgrimes 8071556Srgrimes /* 8081556Srgrimes * check and repair truncated device and inode fields in the cpio 8091556Srgrimes * header 8101556Srgrimes */ 8111556Srgrimes if (map_dev(arcn, (u_long)VCPIO_MASK, (u_long)VCPIO_MASK) < 0) 8121556Srgrimes return(-1); 8131556Srgrimes nsz = arcn->nlen + 1; 8141556Srgrimes hd = (HD_VCPIO *)hdblk; 8151556Srgrimes if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR)) 8161556Srgrimes arcn->sb.st_rdev = 0; 8171556Srgrimes 8181556Srgrimes /* 8191556Srgrimes * add the proper magic value depending whether we were asked for 8201556Srgrimes * file data crc's, and the crc if needed. 8211556Srgrimes */ 8221556Srgrimes if (docrc) { 8231556Srgrimes if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic), 8241556Srgrimes OCT) || 8251556Srgrimes ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum), 8261556Srgrimes HEX)) 8271556Srgrimes goto out; 8281556Srgrimes } else { 8291556Srgrimes if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic), 8301556Srgrimes OCT) || 8311556Srgrimes ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX)) 8321556Srgrimes goto out; 8331556Srgrimes } 8341556Srgrimes 8351556Srgrimes switch(arcn->type) { 8361556Srgrimes case PAX_CTG: 8371556Srgrimes case PAX_REG: 8381556Srgrimes case PAX_HRG: 8391556Srgrimes /* 8401556Srgrimes * caller will copy file data to the archive. tell him how 8411556Srgrimes * much to pad. 8421556Srgrimes */ 8431556Srgrimes arcn->pad = VCPIO_PAD(arcn->sb.st_size); 8441556Srgrimes# ifdef NET2_STAT 8451556Srgrimes if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize, 8461556Srgrimes sizeof(hd->c_filesize), HEX)) { 8471556Srgrimes# else 8481556Srgrimes if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize, 8491556Srgrimes sizeof(hd->c_filesize), HEX)) { 8501556Srgrimes# endif 85128904Ssos pax_warn(1,"File is too large for sv4cpio format %s", 8521556Srgrimes arcn->org_name); 8531556Srgrimes return(1); 8541556Srgrimes } 8551556Srgrimes break; 8561556Srgrimes case PAX_SLK: 8571556Srgrimes /* 8581556Srgrimes * no file data for the caller to process, the file data has 8591556Srgrimes * the size of the link 8601556Srgrimes */ 8611556Srgrimes arcn->pad = 0L; 8621556Srgrimes if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize, 8631556Srgrimes sizeof(hd->c_filesize), HEX)) 8641556Srgrimes goto out; 8651556Srgrimes break; 8661556Srgrimes default: 8671556Srgrimes /* 8681556Srgrimes * no file data for the caller to process 8691556Srgrimes */ 8701556Srgrimes arcn->pad = 0L; 8711556Srgrimes if (ul_asc((u_long)0L, hd->c_filesize, sizeof(hd->c_filesize), 8721556Srgrimes HEX)) 8731556Srgrimes goto out; 8741556Srgrimes break; 8751556Srgrimes } 8761556Srgrimes 8771556Srgrimes /* 8781556Srgrimes * set the other fields in the header 8791556Srgrimes */ 8801556Srgrimes if (ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino), 8811556Srgrimes HEX) || 8821556Srgrimes ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode), 8831556Srgrimes HEX) || 8841556Srgrimes ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid), 8851556Srgrimes HEX) || 8861556Srgrimes ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid), 8871556Srgrimes HEX) || 8881556Srgrimes ul_asc((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime), 8891556Srgrimes HEX) || 8901556Srgrimes ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink), 8911556Srgrimes HEX) || 8921556Srgrimes ul_asc((u_long)MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj), 8931556Srgrimes HEX) || 8941556Srgrimes ul_asc((u_long)MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min), 8951556Srgrimes HEX) || 8961556Srgrimes ul_asc((u_long)MAJOR(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj), 8971556Srgrimes HEX) || 8981556Srgrimes ul_asc((u_long)MINOR(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min), 8991556Srgrimes HEX) || 9001556Srgrimes ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX)) 9011556Srgrimes goto out; 9021556Srgrimes 9031556Srgrimes /* 9041556Srgrimes * write the header, the file name and padding as required. 9051556Srgrimes */ 9061556Srgrimes if ((wr_rdbuf(hdblk, (int)sizeof(HD_VCPIO)) < 0) || 9071556Srgrimes (wr_rdbuf(arcn->name, (int)nsz) < 0) || 9081556Srgrimes (wr_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)) { 90928904Ssos pax_warn(1,"Could not write sv4cpio header for %s",arcn->org_name); 9101556Srgrimes return(-1); 9111556Srgrimes } 9121556Srgrimes 9131556Srgrimes /* 9141556Srgrimes * if we have file data, tell the caller we are done, copy the file 9151556Srgrimes */ 9161556Srgrimes if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) || 9171556Srgrimes (arcn->type == PAX_HRG)) 9181556Srgrimes return(0); 9191556Srgrimes 9201556Srgrimes /* 9211556Srgrimes * if we are not a link, tell the caller we are done, go to next file 9221556Srgrimes */ 9231556Srgrimes if (arcn->type != PAX_SLK) 9241556Srgrimes return(1); 9251556Srgrimes 9261556Srgrimes /* 9271556Srgrimes * write the link name, tell the caller we are done. 9281556Srgrimes */ 9291556Srgrimes if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) || 9301556Srgrimes (wr_skip((off_t)(VCPIO_PAD(arcn->ln_nlen))) < 0)) { 93128904Ssos pax_warn(1,"Could not write sv4cpio link name for %s", 9321556Srgrimes arcn->org_name); 9331556Srgrimes return(-1); 9341556Srgrimes } 9351556Srgrimes return(1); 9361556Srgrimes 9371556Srgrimes out: 9381556Srgrimes /* 9391556Srgrimes * header field is out of range 9401556Srgrimes */ 94128904Ssos pax_warn(1,"Sv4cpio header field is too small for file %s",arcn->org_name); 9421556Srgrimes return(1); 9431556Srgrimes} 9441556Srgrimes 9451556Srgrimes/* 9461556Srgrimes * Routines common to the old binary header cpio 9471556Srgrimes */ 9481556Srgrimes 9491556Srgrimes/* 9501556Srgrimes * bcpio_id() 9511556Srgrimes * determine if a block given to us is a old binary cpio header 9521556Srgrimes * (with/without header byte swapping) 9531556Srgrimes * Return: 9541556Srgrimes * 0 if a valid header, -1 otherwise 9551556Srgrimes */ 9561556Srgrimes 9571556Srgrimes#if __STDC__ 9581556Srgrimesint 9591556Srgrimesbcpio_id(char *blk, int size) 9601556Srgrimes#else 9611556Srgrimesint 9621556Srgrimesbcpio_id(blk, size) 9631556Srgrimes char *blk; 9641556Srgrimes int size; 9651556Srgrimes#endif 9661556Srgrimes{ 9671556Srgrimes if (size < sizeof(HD_BCPIO)) 9681556Srgrimes return(-1); 9691556Srgrimes 9701556Srgrimes /* 9711556Srgrimes * check both normal and byte swapped magic cookies 9721556Srgrimes */ 9731556Srgrimes if (((u_short)SHRT_EXT(blk)) == MAGIC) 9741556Srgrimes return(0); 9751556Srgrimes if (((u_short)RSHRT_EXT(blk)) == MAGIC) { 9761556Srgrimes if (!swp_head) 9771556Srgrimes ++swp_head; 9781556Srgrimes return(0); 9791556Srgrimes } 9801556Srgrimes return(-1); 9811556Srgrimes} 9821556Srgrimes 9831556Srgrimes/* 9841556Srgrimes * bcpio_rd() 9851556Srgrimes * determine if a buffer is a old binary archive entry. (it may have byte 9861556Srgrimes * swapped header) convert and store the values in the ARCHD parameter. 9871556Srgrimes * This is a very old header format and should not really be used. 9881556Srgrimes * Return: 9891556Srgrimes * 0 if a valid header, -1 otherwise. 9901556Srgrimes */ 9911556Srgrimes 9921556Srgrimes#if __STDC__ 9931556Srgrimesint 9941556Srgrimesbcpio_rd(register ARCHD *arcn, register char *buf) 9951556Srgrimes#else 9961556Srgrimesint 9971556Srgrimesbcpio_rd(arcn, buf) 9981556Srgrimes register ARCHD *arcn; 9991556Srgrimes register char *buf; 10001556Srgrimes#endif 10011556Srgrimes{ 10021556Srgrimes register HD_BCPIO *hd; 10031556Srgrimes register int nsz; 10041556Srgrimes 10051556Srgrimes /* 10061556Srgrimes * check the header 10071556Srgrimes */ 10081556Srgrimes if (bcpio_id(buf, sizeof(HD_BCPIO)) < 0) 10091556Srgrimes return(-1); 10101556Srgrimes 10111556Srgrimes arcn->pad = 0L; 10121556Srgrimes hd = (HD_BCPIO *)buf; 10131556Srgrimes if (swp_head) { 10141556Srgrimes /* 101546684Skris * header has swapped bytes on 16 bit boundaries 10161556Srgrimes */ 10171556Srgrimes arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev)); 10181556Srgrimes arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino)); 10191556Srgrimes arcn->sb.st_mode = (mode_t)(RSHRT_EXT(hd->h_mode)); 10201556Srgrimes arcn->sb.st_uid = (uid_t)(RSHRT_EXT(hd->h_uid)); 10211556Srgrimes arcn->sb.st_gid = (gid_t)(RSHRT_EXT(hd->h_gid)); 10221556Srgrimes arcn->sb.st_nlink = (nlink_t)(RSHRT_EXT(hd->h_nlink)); 10231556Srgrimes arcn->sb.st_rdev = (dev_t)(RSHRT_EXT(hd->h_rdev)); 10241556Srgrimes arcn->sb.st_mtime = (time_t)(RSHRT_EXT(hd->h_mtime_1)); 10251556Srgrimes arcn->sb.st_mtime = (arcn->sb.st_mtime << 16) | 10261556Srgrimes ((time_t)(RSHRT_EXT(hd->h_mtime_2))); 10271556Srgrimes arcn->sb.st_size = (off_t)(RSHRT_EXT(hd->h_filesize_1)); 10281556Srgrimes arcn->sb.st_size = (arcn->sb.st_size << 16) | 10291556Srgrimes ((off_t)(RSHRT_EXT(hd->h_filesize_2))); 10301556Srgrimes nsz = (int)(RSHRT_EXT(hd->h_namesize)); 10311556Srgrimes } else { 10321556Srgrimes arcn->sb.st_dev = (dev_t)(SHRT_EXT(hd->h_dev)); 10331556Srgrimes arcn->sb.st_ino = (ino_t)(SHRT_EXT(hd->h_ino)); 10341556Srgrimes arcn->sb.st_mode = (mode_t)(SHRT_EXT(hd->h_mode)); 10351556Srgrimes arcn->sb.st_uid = (uid_t)(SHRT_EXT(hd->h_uid)); 10361556Srgrimes arcn->sb.st_gid = (gid_t)(SHRT_EXT(hd->h_gid)); 10371556Srgrimes arcn->sb.st_nlink = (nlink_t)(SHRT_EXT(hd->h_nlink)); 10381556Srgrimes arcn->sb.st_rdev = (dev_t)(SHRT_EXT(hd->h_rdev)); 10391556Srgrimes arcn->sb.st_mtime = (time_t)(SHRT_EXT(hd->h_mtime_1)); 10401556Srgrimes arcn->sb.st_mtime = (arcn->sb.st_mtime << 16) | 10411556Srgrimes ((time_t)(SHRT_EXT(hd->h_mtime_2))); 10421556Srgrimes arcn->sb.st_size = (off_t)(SHRT_EXT(hd->h_filesize_1)); 10431556Srgrimes arcn->sb.st_size = (arcn->sb.st_size << 16) | 10441556Srgrimes ((off_t)(SHRT_EXT(hd->h_filesize_2))); 10451556Srgrimes nsz = (int)(SHRT_EXT(hd->h_namesize)); 10461556Srgrimes } 10471556Srgrimes arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 10481556Srgrimes 10491556Srgrimes /* 10501556Srgrimes * check the file name size, if bogus give up. otherwise read the file 10511556Srgrimes * name 10521556Srgrimes */ 10531556Srgrimes if (nsz < 2) 10541556Srgrimes return(-1); 10551556Srgrimes arcn->nlen = nsz - 1; 10561556Srgrimes if (rd_nm(arcn, nsz) < 0) 10571556Srgrimes return(-1); 10581556Srgrimes 10591556Srgrimes /* 10601556Srgrimes * header + file name are aligned to 2 byte boundries, skip if needed 10611556Srgrimes */ 10621556Srgrimes if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0) 10631556Srgrimes return(-1); 10641556Srgrimes 10651556Srgrimes /* 10661556Srgrimes * if not a link (or a file with no data), calculate pad size (for 10671556Srgrimes * padding which follows the file data), clear the link name and return 10681556Srgrimes */ 10691556Srgrimes if (((arcn->sb.st_mode & C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)){ 10701556Srgrimes /* 10711556Srgrimes * we have a valid header (not a link) 10721556Srgrimes */ 10731556Srgrimes arcn->ln_nlen = 0; 10741556Srgrimes arcn->ln_name[0] = '\0'; 10751556Srgrimes arcn->pad = BCPIO_PAD(arcn->sb.st_size); 10761556Srgrimes return(com_rd(arcn)); 10771556Srgrimes } 10781556Srgrimes 10791556Srgrimes if ((rd_ln_nm(arcn) < 0) || 10801556Srgrimes (rd_skip((off_t)(BCPIO_PAD(arcn->sb.st_size))) < 0)) 10811556Srgrimes return(-1); 10821556Srgrimes 10831556Srgrimes /* 10841556Srgrimes * we have a valid header (with a link) 10851556Srgrimes */ 10861556Srgrimes return(com_rd(arcn)); 10871556Srgrimes} 10881556Srgrimes 10891556Srgrimes/* 10901556Srgrimes * bcpio_endrd() 10911556Srgrimes * no cleanup needed here, just return size of the trailer (for append) 10921556Srgrimes * Return: 10931556Srgrimes * size of trailer header in this format 10941556Srgrimes */ 10951556Srgrimes 10961556Srgrimes#if __STDC__ 10971556Srgrimesoff_t 10981556Srgrimesbcpio_endrd(void) 10991556Srgrimes#else 11001556Srgrimesoff_t 11011556Srgrimesbcpio_endrd() 11021556Srgrimes#endif 11031556Srgrimes{ 11041556Srgrimes return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) + 11051556Srgrimes (BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER))))); 11061556Srgrimes} 11071556Srgrimes 11081556Srgrimes/* 11091556Srgrimes * bcpio_wr() 11101556Srgrimes * copy the data in the ARCHD to buffer in old binary cpio format 11111556Srgrimes * There is a real chance of field overflow with this critter. So we 11121556Srgrimes * always check the conversion is ok. nobody in his their right mind 11131556Srgrimes * should write an achive in this format... 11141556Srgrimes * Return 11151556Srgrimes * 0 if file has data to be written after the header, 1 if file has NO 11161556Srgrimes * data to write after the header, -1 if archive write failed 11171556Srgrimes */ 11181556Srgrimes 11191556Srgrimes#if __STDC__ 11201556Srgrimesint 11211556Srgrimesbcpio_wr(register ARCHD *arcn) 11221556Srgrimes#else 11231556Srgrimesint 11241556Srgrimesbcpio_wr(arcn) 11251556Srgrimes register ARCHD *arcn; 11261556Srgrimes#endif 11271556Srgrimes{ 11281556Srgrimes register HD_BCPIO *hd; 11291556Srgrimes register int nsz; 11301556Srgrimes char hdblk[sizeof(HD_BCPIO)]; 11311556Srgrimes off_t t_offt; 11321556Srgrimes int t_int; 11331556Srgrimes time_t t_timet; 11341556Srgrimes 11351556Srgrimes /* 11361556Srgrimes * check and repair truncated device and inode fields in the cpio 11371556Srgrimes * header 11381556Srgrimes */ 11391556Srgrimes if (map_dev(arcn, (u_long)BCPIO_MASK, (u_long)BCPIO_MASK) < 0) 11401556Srgrimes return(-1); 11411556Srgrimes 11421556Srgrimes if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR)) 11431556Srgrimes arcn->sb.st_rdev = 0; 11441556Srgrimes hd = (HD_BCPIO *)hdblk; 11451556Srgrimes 11461556Srgrimes switch(arcn->type) { 11471556Srgrimes case PAX_CTG: 11481556Srgrimes case PAX_REG: 11491556Srgrimes case PAX_HRG: 11501556Srgrimes /* 11511556Srgrimes * caller will copy file data to the archive. tell him how 11521556Srgrimes * much to pad. 11531556Srgrimes */ 11541556Srgrimes arcn->pad = BCPIO_PAD(arcn->sb.st_size); 11551556Srgrimes hd->h_filesize_1[0] = CHR_WR_0(arcn->sb.st_size); 11561556Srgrimes hd->h_filesize_1[1] = CHR_WR_1(arcn->sb.st_size); 11571556Srgrimes hd->h_filesize_2[0] = CHR_WR_2(arcn->sb.st_size); 11581556Srgrimes hd->h_filesize_2[1] = CHR_WR_3(arcn->sb.st_size); 11591556Srgrimes t_offt = (off_t)(SHRT_EXT(hd->h_filesize_1)); 11601556Srgrimes t_offt = (t_offt<<16) | ((off_t)(SHRT_EXT(hd->h_filesize_2))); 11611556Srgrimes if (arcn->sb.st_size != t_offt) { 116228904Ssos pax_warn(1,"File is too large for bcpio format %s", 11631556Srgrimes arcn->org_name); 11641556Srgrimes return(1); 11651556Srgrimes } 11661556Srgrimes break; 11671556Srgrimes case PAX_SLK: 11681556Srgrimes /* 11691556Srgrimes * no file data for the caller to process, the file data has 11701556Srgrimes * the size of the link 11711556Srgrimes */ 11721556Srgrimes arcn->pad = 0L; 11731556Srgrimes hd->h_filesize_1[0] = CHR_WR_0(arcn->ln_nlen); 11741556Srgrimes hd->h_filesize_1[1] = CHR_WR_1(arcn->ln_nlen); 11751556Srgrimes hd->h_filesize_2[0] = CHR_WR_2(arcn->ln_nlen); 11761556Srgrimes hd->h_filesize_2[1] = CHR_WR_3(arcn->ln_nlen); 11771556Srgrimes t_int = (int)(SHRT_EXT(hd->h_filesize_1)); 11781556Srgrimes t_int = (t_int << 16) | ((int)(SHRT_EXT(hd->h_filesize_2))); 11791556Srgrimes if (arcn->ln_nlen != t_int) 11801556Srgrimes goto out; 11811556Srgrimes break; 11821556Srgrimes default: 11831556Srgrimes /* 11841556Srgrimes * no file data for the caller to process 11851556Srgrimes */ 11861556Srgrimes arcn->pad = 0L; 11871556Srgrimes hd->h_filesize_1[0] = (char)0; 11881556Srgrimes hd->h_filesize_1[1] = (char)0; 11891556Srgrimes hd->h_filesize_2[0] = (char)0; 11901556Srgrimes hd->h_filesize_2[1] = (char)0; 11911556Srgrimes break; 11921556Srgrimes } 11931556Srgrimes 11941556Srgrimes /* 11951556Srgrimes * build up the rest of the fields 11961556Srgrimes */ 11971556Srgrimes hd->h_magic[0] = CHR_WR_2(MAGIC); 11981556Srgrimes hd->h_magic[1] = CHR_WR_3(MAGIC); 11991556Srgrimes hd->h_dev[0] = CHR_WR_2(arcn->sb.st_dev); 12001556Srgrimes hd->h_dev[1] = CHR_WR_3(arcn->sb.st_dev); 12011556Srgrimes if (arcn->sb.st_dev != (dev_t)(SHRT_EXT(hd->h_dev))) 12021556Srgrimes goto out; 12031556Srgrimes hd->h_ino[0] = CHR_WR_2(arcn->sb.st_ino); 12041556Srgrimes hd->h_ino[1] = CHR_WR_3(arcn->sb.st_ino); 12051556Srgrimes if (arcn->sb.st_ino != (ino_t)(SHRT_EXT(hd->h_ino))) 12061556Srgrimes goto out; 12071556Srgrimes hd->h_mode[0] = CHR_WR_2(arcn->sb.st_mode); 12081556Srgrimes hd->h_mode[1] = CHR_WR_3(arcn->sb.st_mode); 12091556Srgrimes if (arcn->sb.st_mode != (mode_t)(SHRT_EXT(hd->h_mode))) 12101556Srgrimes goto out; 12111556Srgrimes hd->h_uid[0] = CHR_WR_2(arcn->sb.st_uid); 12121556Srgrimes hd->h_uid[1] = CHR_WR_3(arcn->sb.st_uid); 12131556Srgrimes if (arcn->sb.st_uid != (uid_t)(SHRT_EXT(hd->h_uid))) 12141556Srgrimes goto out; 12151556Srgrimes hd->h_gid[0] = CHR_WR_2(arcn->sb.st_gid); 12161556Srgrimes hd->h_gid[1] = CHR_WR_3(arcn->sb.st_gid); 12171556Srgrimes if (arcn->sb.st_gid != (gid_t)(SHRT_EXT(hd->h_gid))) 12181556Srgrimes goto out; 12191556Srgrimes hd->h_nlink[0] = CHR_WR_2(arcn->sb.st_nlink); 12201556Srgrimes hd->h_nlink[1] = CHR_WR_3(arcn->sb.st_nlink); 12211556Srgrimes if (arcn->sb.st_nlink != (nlink_t)(SHRT_EXT(hd->h_nlink))) 12221556Srgrimes goto out; 12231556Srgrimes hd->h_rdev[0] = CHR_WR_2(arcn->sb.st_rdev); 12241556Srgrimes hd->h_rdev[1] = CHR_WR_3(arcn->sb.st_rdev); 12251556Srgrimes if (arcn->sb.st_rdev != (dev_t)(SHRT_EXT(hd->h_rdev))) 12261556Srgrimes goto out; 12271556Srgrimes hd->h_mtime_1[0] = CHR_WR_0(arcn->sb.st_mtime); 12281556Srgrimes hd->h_mtime_1[1] = CHR_WR_1(arcn->sb.st_mtime); 12291556Srgrimes hd->h_mtime_2[0] = CHR_WR_2(arcn->sb.st_mtime); 12301556Srgrimes hd->h_mtime_2[1] = CHR_WR_3(arcn->sb.st_mtime); 12311556Srgrimes t_timet = (time_t)(SHRT_EXT(hd->h_mtime_1)); 12321556Srgrimes t_timet = (t_timet << 16) | ((time_t)(SHRT_EXT(hd->h_mtime_2))); 12331556Srgrimes if (arcn->sb.st_mtime != t_timet) 12341556Srgrimes goto out; 12351556Srgrimes nsz = arcn->nlen + 1; 12361556Srgrimes hd->h_namesize[0] = CHR_WR_2(nsz); 12371556Srgrimes hd->h_namesize[1] = CHR_WR_3(nsz); 12381556Srgrimes if (nsz != (int)(SHRT_EXT(hd->h_namesize))) 12391556Srgrimes goto out; 12401556Srgrimes 12411556Srgrimes /* 12421556Srgrimes * write the header, the file name and padding as required. 12431556Srgrimes */ 12441556Srgrimes if ((wr_rdbuf(hdblk, (int)sizeof(HD_BCPIO)) < 0) || 12451556Srgrimes (wr_rdbuf(arcn->name, nsz) < 0) || 12461556Srgrimes (wr_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)) { 124728904Ssos pax_warn(1, "Could not write bcpio header for %s", arcn->org_name); 12481556Srgrimes return(-1); 12491556Srgrimes } 12501556Srgrimes 12511556Srgrimes /* 12521556Srgrimes * if we have file data, tell the caller we are done 12531556Srgrimes */ 12541556Srgrimes if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) || 12551556Srgrimes (arcn->type == PAX_HRG)) 12561556Srgrimes return(0); 12571556Srgrimes 12581556Srgrimes /* 12591556Srgrimes * if we are not a link, tell the caller we are done, go to next file 12601556Srgrimes */ 12611556Srgrimes if (arcn->type != PAX_SLK) 12621556Srgrimes return(1); 12631556Srgrimes 12641556Srgrimes /* 12651556Srgrimes * write the link name, tell the caller we are done. 12661556Srgrimes */ 12671556Srgrimes if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) || 12681556Srgrimes (wr_skip((off_t)(BCPIO_PAD(arcn->ln_nlen))) < 0)) { 126928904Ssos pax_warn(1,"Could not write bcpio link name for %s",arcn->org_name); 12701556Srgrimes return(-1); 12711556Srgrimes } 12721556Srgrimes return(1); 12731556Srgrimes 12741556Srgrimes out: 12751556Srgrimes /* 12761556Srgrimes * header field is out of range 12771556Srgrimes */ 127828904Ssos pax_warn(1,"Bcpio header field is too small for file %s", arcn->org_name); 12791556Srgrimes return(1); 12801556Srgrimes} 1281