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