cpio.c revision 3044
198944Sobrien/*- 298944Sobrien * Copyright (c) 1992 Keith Muller. 3130803Smarcel * Copyright (c) 1992, 1993 498944Sobrien * The Regents of the University of California. All rights reserved. 598944Sobrien * 698944Sobrien * This code is derived from software contributed to Berkeley by 798944Sobrien * Keith Muller of the University of California, San Diego. 898944Sobrien * 998944Sobrien * Redistribution and use in source and binary forms, with or without 1098944Sobrien * modification, are permitted provided that the following conditions 1198944Sobrien * are met: 1298944Sobrien * 1. Redistributions of source code must retain the above copyright 1398944Sobrien * notice, this list of conditions and the following disclaimer. 1498944Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1598944Sobrien * notice, this list of conditions and the following disclaimer in the 1698944Sobrien * documentation and/or other materials provided with the distribution. 1798944Sobrien * 3. All advertising materials mentioning features or use of this software 1898944Sobrien * must display the following acknowledgement: 1998944Sobrien * This product includes software developed by the University of 2098944Sobrien * California, Berkeley and its contributors. 2198944Sobrien * 4. Neither the name of the University nor the names of its contributors 2298944Sobrien * may be used to endorse or promote products derived from this software 23130803Smarcel * without specific prior written permission. 24130803Smarcel * 2598944Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2698944Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2798944Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2898944Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29130803Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30130803Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31130803Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32130803Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33130803Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34130803Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35130803Smarcel * SUCH DAMAGE. 3698944Sobrien * 37130803Smarcel * $Id$ 38130803Smarcel */ 39130803Smarcel 4098944Sobrien#ifndef lint 4198944Sobrienstatic char sccsid[] = "@(#)cpio.c 8.1 (Berkeley) 5/31/93"; 4298944Sobrien#endif /* not lint */ 4398944Sobrien 4498944Sobrien#include <sys/types.h> 4598944Sobrien#include <sys/time.h> 4698944Sobrien#include <sys/stat.h> 4798944Sobrien#include <sys/param.h> 4898944Sobrien#include <string.h> 49130803Smarcel#include <ctype.h> 50130803Smarcel#include <stdio.h> 51130803Smarcel#include <unistd.h> 52130803Smarcel#include <stdlib.h> 5398944Sobrien#include "pax.h" 5498944Sobrien#include "cpio.h" 5598944Sobrien#include "extern.h" 5698944Sobrien 57130803Smarcelstatic int rd_nm __P((register ARCHD *, int)); 5898944Sobrienstatic int rd_ln_nm __P((register ARCHD *)); 5998944Sobrienstatic int com_rd __P((register ARCHD *)); 6098944Sobrien 6198944Sobrien/* 6298944Sobrien * Routines which support the different cpio versions 6398944Sobrien */ 6498944Sobrien 6598944Sobrienstatic int swp_head; /* binary cpio header byte swap */ 6698944Sobrien 6798944Sobrien/* 6898944Sobrien * Routines common to all versions of cpio 6998944Sobrien */ 7098944Sobrien 7198944Sobrien/* 7298944Sobrien * cpio_strd() 7398944Sobrien * Fire up the hard link detection code 7498944Sobrien * Return: 7598944Sobrien * 0 if ok -1 otherwise (the return values of lnk_start()) 7698944Sobrien */ 7798944Sobrien 7898944Sobrien#if __STDC__ 7998944Sobrienint 8098944Sobriencpio_strd(void) 8198944Sobrien#else 8298944Sobrienint 83130803Smarcelcpio_strd() 84130803Smarcel#endif 85130803Smarcel{ 86130803Smarcel return(lnk_start()); 8798944Sobrien} 88130803Smarcel 89130803Smarcel/* 90130803Smarcel * cpio_trail() 91130803Smarcel * Called to determine if a header block is a valid trailer. We are 9298944Sobrien * passed the block, the in_sync flag (which tells us we are in resync 93130803Smarcel * mode; looking for a valid header), and cnt (which starts at zero) 94130803Smarcel * which is used to count the number of empty blocks we have seen so far. 95130803Smarcel * Return: 9698944Sobrien * 0 if a valid trailer, -1 if not a valid trailer, 9798944Sobrien */ 9898944Sobrien 9998944Sobrien#if __STDC__ 10098944Sobrienint 10198944Sobriencpio_trail(register ARCHD *arcn) 10298944Sobrien#else 10398944Sobrienint 10498944Sobriencpio_trail(arcn) 10598944Sobrien register ARCHD *arcn; 10698944Sobrien#endif 10798944Sobrien{ 10898944Sobrien /* 10998944Sobrien * look for trailer id in file we are about to process 11098944Sobrien */ 11198944Sobrien if ((strcmp(arcn->name, TRAILER) == 0) && (arcn->sb.st_size == 0)) 11298944Sobrien return(0); 11398944Sobrien return(-1); 11498944Sobrien} 11598944Sobrien 11698944Sobrien/* 11798944Sobrien * com_rd() 11898944Sobrien * operations common to all cpio read functions. 11998944Sobrien * Return: 12098944Sobrien * 0 12198944Sobrien */ 12298944Sobrien 12398944Sobrien#if __STDC__ 12498944Sobrienstatic int 12598944Sobriencom_rd(register ARCHD *arcn) 12698944Sobrien#else 12798944Sobrienstatic int 12898944Sobriencom_rd(arcn) 12998944Sobrien register ARCHD *arcn; 13098944Sobrien#endif 13198944Sobrien{ 13298944Sobrien arcn->skip = 0; 13398944Sobrien arcn->pat = NULL; 13498944Sobrien arcn->org_name = arcn->name; 13598944Sobrien switch(arcn->sb.st_mode & C_IFMT) { 13698944Sobrien case C_ISFIFO: 13798944Sobrien arcn->type = PAX_FIF; 13898944Sobrien break; 13998944Sobrien case C_ISDIR: 14098944Sobrien arcn->type = PAX_DIR; 14198944Sobrien break; 14298944Sobrien case C_ISBLK: 14398944Sobrien arcn->type = PAX_BLK; 14498944Sobrien break; 14598944Sobrien case C_ISCHR: 14698944Sobrien arcn->type = PAX_CHR; 14798944Sobrien break; 14898944Sobrien case C_ISLNK: 14998944Sobrien arcn->type = PAX_SLK; 15098944Sobrien break; 15198944Sobrien case C_ISOCK: 15298944Sobrien arcn->type = PAX_SCK; 15398944Sobrien break; 15498944Sobrien case C_ISCTG: 15598944Sobrien case C_ISREG: 15698944Sobrien default: 15798944Sobrien /* 15898944Sobrien * we have file data, set up skip (pad is set in the format 15998944Sobrien * specific sections) 16098944Sobrien */ 16198944Sobrien arcn->sb.st_mode = (arcn->sb.st_mode & 0xfff) | C_ISREG; 16298944Sobrien arcn->type = PAX_REG; 16398944Sobrien arcn->skip = arcn->sb.st_size; 16498944Sobrien break; 16598944Sobrien } 16698944Sobrien if (chk_lnk(arcn) < 0) 16798944Sobrien return(-1); 16898944Sobrien return(0); 16998944Sobrien} 17098944Sobrien 17198944Sobrien/* 17298944Sobrien * cpio_end_wr() 17398944Sobrien * write the special file with the name trailer in the proper format 17498944Sobrien * Return: 17598944Sobrien * result of the write of the trailer from the cpio specific write func 17698944Sobrien */ 17798944Sobrien 17898944Sobrien#if __STDC__ 17998944Sobrienint 18098944Sobriencpio_endwr(void) 18198944Sobrien#else 18298944Sobrienint 18398944Sobriencpio_endwr() 18498944Sobrien#endif 18598944Sobrien{ 18698944Sobrien ARCHD last; 18798944Sobrien 18898944Sobrien /* 18998944Sobrien * create a trailer request and call the proper format write function 19098944Sobrien */ 19198944Sobrien bzero((char *)&last, sizeof(last)); 19298944Sobrien last.nlen = sizeof(TRAILER) - 1; 19398944Sobrien last.type = PAX_REG; 19498944Sobrien last.sb.st_nlink = 1; 19598944Sobrien (void)strcpy(last.name, TRAILER); 19698944Sobrien return((*frmt->wr)(&last)); 19798944Sobrien} 19898944Sobrien 19998944Sobrien/* 20098944Sobrien * rd_nam() 20198944Sobrien * read in the file name which follows the cpio header 20298944Sobrien * Return: 20398944Sobrien * 0 if ok, -1 otherwise 20498944Sobrien */ 20598944Sobrien 20698944Sobrien#if __STDC__ 20798944Sobrienstatic int 20898944Sobrienrd_nm(register ARCHD *arcn, int nsz) 20998944Sobrien#else 21098944Sobrienstatic int 21198944Sobrienrd_nm(arcn, nsz) 21298944Sobrien register ARCHD *arcn; 21398944Sobrien int nsz; 21498944Sobrien#endif 21598944Sobrien{ 21698944Sobrien /* 21798944Sobrien * do not even try bogus values 21898944Sobrien */ 21998944Sobrien if ((nsz == 0) || (nsz > sizeof(arcn->name))) { 22098944Sobrien warn(1, "Cpio file name length %d is out of range", nsz); 22198944Sobrien return(-1); 22298944Sobrien } 22398944Sobrien 22498944Sobrien /* 22598944Sobrien * read the name and make sure it is not empty and is \0 terminated 22698944Sobrien */ 22798944Sobrien if ((rd_wrbuf(arcn->name,nsz) != nsz) || (arcn->name[nsz-1] != '\0') || 22898944Sobrien (arcn->name[0] == '\0')) { 22998944Sobrien warn(1, "Cpio file name in header is corrupted"); 230130803Smarcel return(-1); 23198944Sobrien } 23298944Sobrien return(0); 23398944Sobrien} 23498944Sobrien 23598944Sobrien/* 23698944Sobrien * rd_ln_nm() 23798944Sobrien * read in the link name for a file with links. The link name is stored 238130803Smarcel * like file data (and is NOT \0 terminated!) 239130803Smarcel * Return: 240130803Smarcel * 0 if ok, -1 otherwise 241130803Smarcel */ 242130803Smarcel 243130803Smarcel#if __STDC__ 244130803Smarcelstatic int 245130803Smarcelrd_ln_nm(register ARCHD *arcn) 246130803Smarcel#else 247130803Smarcelstatic int 248130803Smarcelrd_ln_nm(arcn) 24998944Sobrien register ARCHD *arcn; 250130803Smarcel#endif 251130803Smarcel{ 252130803Smarcel /* 253130803Smarcel * check the length specified for bogus values 254130803Smarcel */ 255130803Smarcel if ((arcn->sb.st_size == 0) || 25698944Sobrien (arcn->sb.st_size >= sizeof(arcn->ln_name))) { 25798944Sobrien# ifdef NET2_STAT 25898944Sobrien warn(1, "Cpio link name length is invalid: %lu", 25998944Sobrien arcn->sb.st_size); 26098944Sobrien# else 26198944Sobrien warn(1, "Cpio link name length is invalid: %qu", 26298944Sobrien arcn->sb.st_size); 26398944Sobrien# endif 26498944Sobrien return(-1); 26598944Sobrien } 26698944Sobrien 26798944Sobrien /* 26898944Sobrien * read in the link name and \0 terminate it 26998944Sobrien */ 270130803Smarcel if (rd_wrbuf(arcn->ln_name, (int)arcn->sb.st_size) != 27198944Sobrien (int)arcn->sb.st_size) { 27298944Sobrien warn(1, "Cpio link name read error"); 27398944Sobrien return(-1); 27498944Sobrien } 27598944Sobrien arcn->ln_nlen = arcn->sb.st_size; 27698944Sobrien arcn->ln_name[arcn->ln_nlen] = '\0'; 27798944Sobrien 27898944Sobrien /* 27998944Sobrien * watch out for those empty link names 28098944Sobrien */ 28198944Sobrien if (arcn->ln_name[0] == '\0') { 28298944Sobrien warn(1, "Cpio link name is corrupt"); 28398944Sobrien return(-1); 28498944Sobrien } 28598944Sobrien return(0); 28698944Sobrien} 28798944Sobrien 28898944Sobrien/* 28998944Sobrien * Routines common to the extended byte oriented cpio format 29098944Sobrien */ 29198944Sobrien 29298944Sobrien/* 29398944Sobrien * cpio_id() 29498944Sobrien * determine if a block given to us is a valid extended byte oriented 29598944Sobrien * cpio header 29698944Sobrien * Return: 29798944Sobrien * 0 if a valid header, -1 otherwise 29898944Sobrien */ 29998944Sobrien 30098944Sobrien#if __STDC__ 30198944Sobrienint 30298944Sobriencpio_id(char *blk, int size) 30398944Sobrien#else 30498944Sobrienint 30598944Sobriencpio_id(blk, size) 30698944Sobrien char *blk; 30798944Sobrien int size; 30898944Sobrien#endif 30998944Sobrien{ 31098944Sobrien if ((size < sizeof(HD_CPIO)) || 31198944Sobrien (strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0)) 31298944Sobrien return(-1); 31398944Sobrien return(0); 31498944Sobrien} 31598944Sobrien 31698944Sobrien/* 31798944Sobrien * cpio_rd() 31898944Sobrien * determine if a buffer is a byte oriented extended cpio archive entry. 319130803Smarcel * convert and store the values in the ARCHD parameter. 32098944Sobrien * Return: 32198944Sobrien * 0 if a valid header, -1 otherwise. 32298944Sobrien */ 32398944Sobrien 32498944Sobrien#if __STDC__ 32598944Sobrienint 32698944Sobriencpio_rd(register ARCHD *arcn, register char *buf) 32798944Sobrien#else 32898944Sobrienint 32998944Sobriencpio_rd(arcn, buf) 33098944Sobrien register ARCHD *arcn; 33198944Sobrien register char *buf; 33298944Sobrien#endif 33398944Sobrien{ 33498944Sobrien register int nsz; 33598944Sobrien register HD_CPIO *hd; 33698944Sobrien 33798944Sobrien /* 33898944Sobrien * check that this is a valid header, if not return -1 33998944Sobrien */ 34098944Sobrien if (cpio_id(buf, sizeof(HD_CPIO)) < 0) 34198944Sobrien return(-1); 34298944Sobrien hd = (HD_CPIO *)buf; 34398944Sobrien 34498944Sobrien /* 34598944Sobrien * byte oriented cpio (posix) does not have padding! extract the octal 34698944Sobrien * ascii fields from the header 34798944Sobrien */ 34898944Sobrien arcn->pad = 0L; 34998944Sobrien arcn->sb.st_dev = (dev_t)asc_ul(hd->c_dev, sizeof(hd->c_dev), OCT); 35098944Sobrien arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), OCT); 35198944Sobrien arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), OCT); 35298944Sobrien arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), OCT); 35398944Sobrien arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), OCT); 35498944Sobrien arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink), 35598944Sobrien OCT); 35698944Sobrien arcn->sb.st_rdev = (dev_t)asc_ul(hd->c_rdev, sizeof(hd->c_rdev), OCT); 35798944Sobrien arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime), 35898944Sobrien OCT); 35998944Sobrien arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 36098944Sobrien# ifdef NET2_STAT 36198944Sobrien arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,sizeof(hd->c_filesize), 36298944Sobrien OCT); 36398944Sobrien# else 36498944Sobrien arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,sizeof(hd->c_filesize), 36598944Sobrien OCT); 36698944Sobrien# endif 36798944Sobrien 36898944Sobrien /* 36998944Sobrien * check name size and if valid, read in the name of this entry (name 37098944Sobrien * follows header in the archive) 37198944Sobrien */ 37298944Sobrien if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2) 37398944Sobrien return(-1); 37498944Sobrien arcn->nlen = nsz - 1; 37598944Sobrien if (rd_nm(arcn, nsz) < 0) 37698944Sobrien return(-1); 37798944Sobrien 37898944Sobrien if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) { 37998944Sobrien /* 38098944Sobrien * no link name to read for this file 38198944Sobrien */ 38298944Sobrien arcn->ln_nlen = 0; 38398944Sobrien arcn->ln_name[0] = '\0'; 38498944Sobrien return(com_rd(arcn)); 38598944Sobrien } 38698944Sobrien 38798944Sobrien /* 38898944Sobrien * check link name size and read in the link name. Link names are 38998944Sobrien * stored like file data. 39098944Sobrien */ 39198944Sobrien if (rd_ln_nm(arcn) < 0) 39298944Sobrien return(-1); 39398944Sobrien 39498944Sobrien /* 39598944Sobrien * we have a valid header (with a link) 39698944Sobrien */ 39798944Sobrien return(com_rd(arcn)); 39898944Sobrien} 39998944Sobrien 40098944Sobrien/* 40198944Sobrien * cpio_endrd() 40298944Sobrien * no cleanup needed here, just return size of the trailer (for append) 40398944Sobrien * Return: 40498944Sobrien * size of trailer header in this format 40598944Sobrien */ 40698944Sobrien 40798944Sobrien#if __STDC__ 40898944Sobrienoff_t 40998944Sobriencpio_endrd(void) 41098944Sobrien#else 41198944Sobrienoff_t 41298944Sobriencpio_endrd() 41398944Sobrien#endif 41498944Sobrien{ 41598944Sobrien return((off_t)(sizeof(HD_CPIO) + sizeof(TRAILER))); 41698944Sobrien} 41798944Sobrien 41898944Sobrien/* 41998944Sobrien * cpio_stwr() 42098944Sobrien * start up the device mapping table 42198944Sobrien * Return: 42298944Sobrien * 0 if ok, -1 otherwise (what dev_start() returns) 42398944Sobrien */ 42498944Sobrien 42598944Sobrien#if __STDC__ 42698944Sobrienint 42798944Sobriencpio_stwr(void) 42898944Sobrien#else 42998944Sobrienint 43098944Sobriencpio_stwr() 43198944Sobrien#endif 43298944Sobrien{ 43398944Sobrien return(dev_start()); 43498944Sobrien} 43598944Sobrien 43698944Sobrien/* 43798944Sobrien * cpio_wr() 43898944Sobrien * copy the data in the ARCHD to buffer in extended byte oriented cpio 43998944Sobrien * format. 44098944Sobrien * Return 44198944Sobrien * 0 if file has data to be written after the header, 1 if file has NO 44298944Sobrien * data to write after the header, -1 if archive write failed 44398944Sobrien */ 44498944Sobrien 44598944Sobrien#if __STDC__ 44698944Sobrienint 44798944Sobriencpio_wr(register ARCHD *arcn) 44898944Sobrien#else 44998944Sobrienint 45098944Sobriencpio_wr(arcn) 45198944Sobrien register ARCHD *arcn; 45298944Sobrien#endif 45398944Sobrien{ 45498944Sobrien register HD_CPIO *hd; 45598944Sobrien register int nsz; 45698944Sobrien char hdblk[sizeof(HD_CPIO)]; 45798944Sobrien 45898944Sobrien /* 459130803Smarcel * check and repair truncated device and inode fields in the header 46098944Sobrien */ 46198944Sobrien if (map_dev(arcn, (u_long)CPIO_MASK, (u_long)CPIO_MASK) < 0) 46298944Sobrien return(-1); 46398944Sobrien 46498944Sobrien arcn->pad = 0L; 46598944Sobrien nsz = arcn->nlen + 1; 46698944Sobrien hd = (HD_CPIO *)hdblk; 46798944Sobrien if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR)) 46898944Sobrien arcn->sb.st_rdev = 0; 46998944Sobrien 47098944Sobrien switch(arcn->type) { 47198944Sobrien case PAX_CTG: 47298944Sobrien case PAX_REG: 47398944Sobrien case PAX_HRG: 47498944Sobrien /* 47598944Sobrien * set data size for file data 47698944Sobrien */ 47798944Sobrien# ifdef NET2_STAT 47898944Sobrien if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize, 47998944Sobrien sizeof(hd->c_filesize), OCT)) { 48098944Sobrien# else 48198944Sobrien if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize, 48298944Sobrien sizeof(hd->c_filesize), OCT)) { 48398944Sobrien# endif 48498944Sobrien warn(1,"File is too large for cpio format %s", 48598944Sobrien arcn->org_name); 48698944Sobrien return(1); 48798944Sobrien } 48898944Sobrien break; 48998944Sobrien case PAX_SLK: 49098944Sobrien /* 49198944Sobrien * set data size to hold link name 49298944Sobrien */ 49398944Sobrien if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize, 49498944Sobrien sizeof(hd->c_filesize), OCT)) 49598944Sobrien goto out; 49698944Sobrien break; 49798944Sobrien default: 49898944Sobrien /* 49998944Sobrien * all other file types have no file data 50098944Sobrien */ 50198944Sobrien if (ul_asc((u_long)0, hd->c_filesize, sizeof(hd->c_filesize), 50298944Sobrien OCT)) 50398944Sobrien goto out; 50498944Sobrien break; 50598944Sobrien } 50698944Sobrien 50798944Sobrien /* 50898944Sobrien * copy the values to the header using octal ascii 50998944Sobrien */ 51098944Sobrien if (ul_asc((u_long)MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) || 51198944Sobrien ul_asc((u_long)arcn->sb.st_dev, hd->c_dev, sizeof(hd->c_dev), 51298944Sobrien OCT) || 51398944Sobrien ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino), 514130803Smarcel OCT) || 515130803Smarcel ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode), 516130803Smarcel OCT) || 51798944Sobrien ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid), 518130803Smarcel OCT) || 519130803Smarcel ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid), 52098944Sobrien OCT) || 521130803Smarcel ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink), 522130803Smarcel OCT) || 523130803Smarcel ul_asc((u_long)arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev), 524130803Smarcel OCT) || 525130803Smarcel ul_asc((u_long)arcn->sb.st_mtime,hd->c_mtime,sizeof(hd->c_mtime), 526130803Smarcel OCT) || 52798944Sobrien ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT)) 528130803Smarcel goto out; 52998944Sobrien 530130803Smarcel /* 53198944Sobrien * write the file name to the archive 53298944Sobrien */ 53398944Sobrien if ((wr_rdbuf(hdblk, (int)sizeof(HD_CPIO)) < 0) || 53498944Sobrien (wr_rdbuf(arcn->name, nsz) < 0)) { 53598944Sobrien warn(1, "Unable to write cpio header for %s", arcn->org_name); 53698944Sobrien return(-1); 53798944Sobrien } 53898944Sobrien 53998944Sobrien /* 54098944Sobrien * if this file has data, we are done. The caller will write the file 54198944Sobrien * data, if we are link tell caller we are done, go to next file 54298944Sobrien */ 54398944Sobrien if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) || 54498944Sobrien (arcn->type == PAX_HRG)) 54598944Sobrien return(0); 54698944Sobrien if (arcn->type != PAX_SLK) 547130803Smarcel return(1); 548130803Smarcel 549130803Smarcel /* 550130803Smarcel * write the link name to the archive, tell the caller to go to the 551130803Smarcel * next file as we are done. 552130803Smarcel */ 553130803Smarcel if (wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) { 554130803Smarcel warn(1,"Unable to write cpio link name for %s",arcn->org_name); 555130803Smarcel return(-1); 556130803Smarcel } 557130803Smarcel return(1); 558130803Smarcel 559130803Smarcel out: 560130803Smarcel /* 561130803Smarcel * header field is out of range 562130803Smarcel */ 563130803Smarcel warn(1, "Cpio header field is too small to store file %s", 564130803Smarcel arcn->org_name); 565130803Smarcel return(1); 566130803Smarcel} 567130803Smarcel 568130803Smarcel/* 569130803Smarcel * Routines common to the system VR4 version of cpio (with/without file CRC) 570130803Smarcel */ 571130803Smarcel 572130803Smarcel/* 573130803Smarcel * vcpio_id() 574130803Smarcel * determine if a block given to us is a valid system VR4 cpio header 575130803Smarcel * WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header 576130803Smarcel * uses HEX 577130803Smarcel * Return: 578130803Smarcel * 0 if a valid header, -1 otherwise 579130803Smarcel */ 580130803Smarcel 581130803Smarcel#if __STDC__ 582130803Smarcelint 583130803Smarcelvcpio_id(char *blk, int size) 584130803Smarcel#else 585130803Smarcelint 586130803Smarcelvcpio_id(blk, size) 587130803Smarcel char *blk; 588130803Smarcel int size; 589130803Smarcel#endif 590130803Smarcel{ 591130803Smarcel if ((size < sizeof(HD_VCPIO)) || 592130803Smarcel (strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0)) 593130803Smarcel return(-1); 594130803Smarcel return(0); 595130803Smarcel} 596130803Smarcel 597130803Smarcel/* 598130803Smarcel * crc_id() 599130803Smarcel * determine if a block given to us is a valid system VR4 cpio header 600130803Smarcel * WITH crc. WATCH it the magic cookies are in OCTAL the header uses HEX 601130803Smarcel * Return: 602130803Smarcel * 0 if a valid header, -1 otherwise 603130803Smarcel */ 604130803Smarcel 605130803Smarcel#if __STDC__ 606130803Smarcelint 607130803Smarcelcrc_id(char *blk, int size) 608130803Smarcel#else 609130803Smarcelint 610130803Smarcelcrc_id(blk, size) 611130803Smarcel char *blk; 612130803Smarcel int size; 613130803Smarcel#endif 614130803Smarcel{ 615130803Smarcel if ((size < sizeof(HD_VCPIO)) || 616130803Smarcel (strncmp(blk, AVCMAGIC, sizeof(AVCMAGIC) - 1) != 0)) 617130803Smarcel return(-1); 618130803Smarcel return(0); 619130803Smarcel} 620130803Smarcel 621130803Smarcel/* 622130803Smarcel * crc_strd() 623130803Smarcel w set file data CRC calculations. Fire up the hard link detection code 624130803Smarcel * Return: 625130803Smarcel * 0 if ok -1 otherwise (the return values of lnk_start()) 626130803Smarcel */ 627130803Smarcel 628130803Smarcel#if __STDC__ 629130803Smarcelint 630130803Smarcelcrc_strd(void) 631130803Smarcel#else 632130803Smarcelint 633130803Smarcelcrc_strd() 634130803Smarcel#endif 635130803Smarcel{ 636130803Smarcel docrc = 1; 637130803Smarcel return(lnk_start()); 638130803Smarcel} 639130803Smarcel 640130803Smarcel/* 641130803Smarcel * vcpio_rd() 642130803Smarcel * determine if a buffer is a system VR4 archive entry. (with/without CRC) 643130803Smarcel * convert and store the values in the ARCHD parameter. 644130803Smarcel * Return: 645130803Smarcel * 0 if a valid header, -1 otherwise. 646130803Smarcel */ 647130803Smarcel 648130803Smarcel#if __STDC__ 649130803Smarcelint 650130803Smarcelvcpio_rd(register ARCHD *arcn, register char *buf) 651130803Smarcel#else 652130803Smarcelint 653130803Smarcelvcpio_rd(arcn, buf) 654130803Smarcel register ARCHD *arcn; 655130803Smarcel register char *buf; 656130803Smarcel#endif 657130803Smarcel{ 658130803Smarcel register HD_VCPIO *hd; 659130803Smarcel dev_t devminor; 660130803Smarcel dev_t devmajor; 661130803Smarcel register int nsz; 662130803Smarcel 663130803Smarcel /* 664130803Smarcel * during the id phase it was determined if we were using CRC, use the 665130803Smarcel * proper id routine. 666130803Smarcel */ 667130803Smarcel if (docrc) { 668130803Smarcel if (crc_id(buf, sizeof(HD_VCPIO)) < 0) 669130803Smarcel return(-1); 670130803Smarcel } else { 671130803Smarcel if (vcpio_id(buf, sizeof(HD_VCPIO)) < 0) 672130803Smarcel return(-1); 673130803Smarcel } 674130803Smarcel 675130803Smarcel hd = (HD_VCPIO *)buf; 676130803Smarcel arcn->pad = 0L; 677130803Smarcel 678130803Smarcel /* 679130803Smarcel * extract the hex ascii fields from the header 680130803Smarcel */ 681130803Smarcel arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), HEX); 682130803Smarcel arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), HEX); 683130803Smarcel arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), HEX); 684130803Smarcel arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX); 685130803Smarcel arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX); 686130803Smarcel arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 687130803Smarcel# ifdef NET2_STAT 688130803Smarcel arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize, 689130803Smarcel sizeof(hd->c_filesize), HEX); 690130803Smarcel# else 691130803Smarcel arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize, 692130803Smarcel sizeof(hd->c_filesize), HEX); 693130803Smarcel# endif 694130803Smarcel arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink), 695130803Smarcel HEX); 696130803Smarcel devmajor = (dev_t)asc_ul(hd->c_maj, sizeof(hd->c_maj), HEX); 697130803Smarcel devminor = (dev_t)asc_ul(hd->c_min, sizeof(hd->c_min), HEX); 698130803Smarcel arcn->sb.st_dev = TODEV(devmajor, devminor); 699130803Smarcel devmajor = (dev_t)asc_ul(hd->c_rmaj, sizeof(hd->c_maj), HEX); 700130803Smarcel devminor = (dev_t)asc_ul(hd->c_rmin, sizeof(hd->c_min), HEX); 701130803Smarcel arcn->sb.st_rdev = TODEV(devmajor, devminor); 702130803Smarcel arcn->crc = asc_ul(hd->c_chksum, sizeof(hd->c_chksum), HEX); 703130803Smarcel 704130803Smarcel /* 705130803Smarcel * check the length of the file name, if ok read it in, return -1 if 706130803Smarcel * bogus 707130803Smarcel */ 708130803Smarcel if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2) 709130803Smarcel return(-1); 710130803Smarcel arcn->nlen = nsz - 1; 711130803Smarcel if (rd_nm(arcn, nsz) < 0) 712130803Smarcel return(-1); 713130803Smarcel 714130803Smarcel /* 715130803Smarcel * skip padding. header + filename is aligned to 4 byte boundries 716130803Smarcel */ 717130803Smarcel if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0) 718130803Smarcel return(-1); 719130803Smarcel 720130803Smarcel /* 721130803Smarcel * if not a link (or a file with no data), calculate pad size (for 722130803Smarcel * padding which follows the file data), clear the link name and return 723130803Smarcel */ 724130803Smarcel if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) { 725130803Smarcel /* 726130803Smarcel * we have a valid header (not a link) 727130803Smarcel */ 728130803Smarcel arcn->ln_nlen = 0; 729130803Smarcel arcn->ln_name[0] = '\0'; 730130803Smarcel arcn->pad = VCPIO_PAD(arcn->sb.st_size); 731130803Smarcel return(com_rd(arcn)); 732130803Smarcel } 733130803Smarcel 734130803Smarcel /* 735130803Smarcel * read in the link name and skip over the padding 736130803Smarcel */ 737130803Smarcel if ((rd_ln_nm(arcn) < 0) || 738130803Smarcel (rd_skip((off_t)(VCPIO_PAD(arcn->sb.st_size))) < 0)) 739130803Smarcel return(-1); 740130803Smarcel 741130803Smarcel /* 742130803Smarcel * we have a valid header (with a link) 743130803Smarcel */ 744130803Smarcel return(com_rd(arcn)); 745130803Smarcel} 746130803Smarcel 747130803Smarcel/* 748130803Smarcel * vcpio_endrd() 749130803Smarcel * no cleanup needed here, just return size of the trailer (for append) 750130803Smarcel * Return: 751130803Smarcel * size of trailer header in this format 752130803Smarcel */ 753130803Smarcel 754130803Smarcel#if __STDC__ 755130803Smarceloff_t 756130803Smarcelvcpio_endrd(void) 757130803Smarcel#else 758130803Smarceloff_t 759130803Smarcelvcpio_endrd() 760130803Smarcel#endif 761130803Smarcel{ 762130803Smarcel return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) + 763130803Smarcel (VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER))))); 764130803Smarcel} 765130803Smarcel 766130803Smarcel/* 767130803Smarcel * crc_stwr() 768130803Smarcel * start up the device mapping table, enable crc file calculation 769130803Smarcel * Return: 770130803Smarcel * 0 if ok, -1 otherwise (what dev_start() returns) 771130803Smarcel */ 772130803Smarcel 773130803Smarcel#if __STDC__ 774130803Smarcelint 775130803Smarcelcrc_stwr(void) 776130803Smarcel#else 777130803Smarcelint 778130803Smarcelcrc_stwr() 779130803Smarcel#endif 780130803Smarcel{ 781130803Smarcel docrc = 1; 782130803Smarcel return(dev_start()); 783130803Smarcel} 784130803Smarcel 785130803Smarcel/* 786130803Smarcel * vcpio_wr() 787130803Smarcel * copy the data in the ARCHD to buffer in system VR4 cpio 788130803Smarcel * (with/without crc) format. 789130803Smarcel * Return 790130803Smarcel * 0 if file has data to be written after the header, 1 if file has 791130803Smarcel * NO data to write after the header, -1 if archive write failed 792130803Smarcel */ 793130803Smarcel 794130803Smarcel#if __STDC__ 795130803Smarcelint 796130803Smarcelvcpio_wr(register ARCHD *arcn) 797130803Smarcel#else 798130803Smarcelint 799130803Smarcelvcpio_wr(arcn) 800130803Smarcel register ARCHD *arcn; 801130803Smarcel#endif 802130803Smarcel{ 803130803Smarcel register HD_VCPIO *hd; 804130803Smarcel unsigned int nsz; 805130803Smarcel char hdblk[sizeof(HD_VCPIO)]; 806130803Smarcel 807130803Smarcel /* 808130803Smarcel * check and repair truncated device and inode fields in the cpio 809130803Smarcel * header 810130803Smarcel */ 811130803Smarcel if (map_dev(arcn, (u_long)VCPIO_MASK, (u_long)VCPIO_MASK) < 0) 812130803Smarcel return(-1); 813130803Smarcel nsz = arcn->nlen + 1; 814130803Smarcel hd = (HD_VCPIO *)hdblk; 815130803Smarcel if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR)) 816130803Smarcel arcn->sb.st_rdev = 0; 817130803Smarcel 818130803Smarcel /* 819130803Smarcel * add the proper magic value depending whether we were asked for 820130803Smarcel * file data crc's, and the crc if needed. 821130803Smarcel */ 822130803Smarcel if (docrc) { 823130803Smarcel if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic), 824130803Smarcel OCT) || 825130803Smarcel ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum), 826130803Smarcel HEX)) 827130803Smarcel goto out; 828130803Smarcel } else { 829130803Smarcel if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic), 830130803Smarcel OCT) || 831130803Smarcel ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX)) 832130803Smarcel goto out; 833130803Smarcel } 834130803Smarcel 835130803Smarcel switch(arcn->type) { 836130803Smarcel case PAX_CTG: 837130803Smarcel case PAX_REG: 838130803Smarcel case PAX_HRG: 839130803Smarcel /* 840130803Smarcel * caller will copy file data to the archive. tell him how 841130803Smarcel * much to pad. 842130803Smarcel */ 843130803Smarcel arcn->pad = VCPIO_PAD(arcn->sb.st_size); 844130803Smarcel# ifdef NET2_STAT 845130803Smarcel if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize, 846130803Smarcel sizeof(hd->c_filesize), HEX)) { 847130803Smarcel# else 848130803Smarcel if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize, 849130803Smarcel sizeof(hd->c_filesize), HEX)) { 850130803Smarcel# endif 851130803Smarcel warn(1,"File is too large for sv4cpio format %s", 852130803Smarcel arcn->org_name); 853130803Smarcel return(1); 854130803Smarcel } 855130803Smarcel break; 856130803Smarcel case PAX_SLK: 857130803Smarcel /* 858130803Smarcel * no file data for the caller to process, the file data has 859130803Smarcel * the size of the link 860130803Smarcel */ 861130803Smarcel arcn->pad = 0L; 862130803Smarcel if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize, 863130803Smarcel sizeof(hd->c_filesize), HEX)) 864130803Smarcel goto out; 865130803Smarcel break; 866130803Smarcel default: 867130803Smarcel /* 868130803Smarcel * no file data for the caller to process 869130803Smarcel */ 870130803Smarcel arcn->pad = 0L; 871130803Smarcel if (ul_asc((u_long)0L, hd->c_filesize, sizeof(hd->c_filesize), 872130803Smarcel HEX)) 873130803Smarcel goto out; 874130803Smarcel break; 875130803Smarcel } 876130803Smarcel 877130803Smarcel /* 878130803Smarcel * set the other fields in the header 879130803Smarcel */ 880130803Smarcel if (ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino), 881130803Smarcel HEX) || 882130803Smarcel ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode), 883130803Smarcel HEX) || 884130803Smarcel ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid), 885130803Smarcel HEX) || 886130803Smarcel ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid), 887130803Smarcel HEX) || 888130803Smarcel ul_asc((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime), 889130803Smarcel HEX) || 890130803Smarcel ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink), 891130803Smarcel HEX) || 892130803Smarcel ul_asc((u_long)MAJOR(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj), 893130803Smarcel HEX) || 894130803Smarcel ul_asc((u_long)MINOR(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min), 895130803Smarcel HEX) || 896130803Smarcel ul_asc((u_long)MAJOR(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj), 897130803Smarcel HEX) || 898130803Smarcel ul_asc((u_long)MINOR(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min), 899130803Smarcel HEX) || 900130803Smarcel ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX)) 901130803Smarcel goto out; 902130803Smarcel 903130803Smarcel /* 904130803Smarcel * write the header, the file name and padding as required. 905130803Smarcel */ 906130803Smarcel if ((wr_rdbuf(hdblk, (int)sizeof(HD_VCPIO)) < 0) || 907130803Smarcel (wr_rdbuf(arcn->name, (int)nsz) < 0) || 908130803Smarcel (wr_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)) { 909130803Smarcel warn(1,"Could not write sv4cpio header for %s",arcn->org_name); 910130803Smarcel return(-1); 911130803Smarcel } 912130803Smarcel 913130803Smarcel /* 914130803Smarcel * if we have file data, tell the caller we are done, copy the file 915130803Smarcel */ 916130803Smarcel if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) || 917130803Smarcel (arcn->type == PAX_HRG)) 918130803Smarcel return(0); 91998944Sobrien 92098944Sobrien /* 92198944Sobrien * if we are not a link, tell the caller we are done, go to next file 92298944Sobrien */ 92398944Sobrien if (arcn->type != PAX_SLK) 92498944Sobrien return(1); 92598944Sobrien 92698944Sobrien /* 92798944Sobrien * write the link name, tell the caller we are done. 92898944Sobrien */ 92998944Sobrien if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) || 93098944Sobrien (wr_skip((off_t)(VCPIO_PAD(arcn->ln_nlen))) < 0)) { 93198944Sobrien warn(1,"Could not write sv4cpio link name for %s", 93298944Sobrien arcn->org_name); 93398944Sobrien return(-1); 93498944Sobrien } 93598944Sobrien return(1); 93698944Sobrien 93798944Sobrien out: 93898944Sobrien /* 93998944Sobrien * header field is out of range 94098944Sobrien */ 94198944Sobrien warn(1,"Sv4cpio header field is too small for file %s",arcn->org_name); 94298944Sobrien return(1); 94398944Sobrien} 94498944Sobrien 94598944Sobrien/* 94698944Sobrien * Routines common to the old binary header cpio 94798944Sobrien */ 94898944Sobrien 94998944Sobrien/* 95098944Sobrien * bcpio_id() 95198944Sobrien * determine if a block given to us is a old binary cpio header 95298944Sobrien * (with/without header byte swapping) 95398944Sobrien * Return: 95498944Sobrien * 0 if a valid header, -1 otherwise 95598944Sobrien */ 95698944Sobrien 95798944Sobrien#if __STDC__ 95898944Sobrienint 95998944Sobrienbcpio_id(char *blk, int size) 96098944Sobrien#else 96198944Sobrienint 96298944Sobrienbcpio_id(blk, size) 96398944Sobrien char *blk; 96498944Sobrien int size; 96598944Sobrien#endif 96698944Sobrien{ 96798944Sobrien if (size < sizeof(HD_BCPIO)) 96898944Sobrien return(-1); 96998944Sobrien 97098944Sobrien /* 97198944Sobrien * check both normal and byte swapped magic cookies 97298944Sobrien */ 97398944Sobrien if (((u_short)SHRT_EXT(blk)) == MAGIC) 97498944Sobrien return(0); 97598944Sobrien if (((u_short)RSHRT_EXT(blk)) == MAGIC) { 97698944Sobrien if (!swp_head) 97798944Sobrien ++swp_head; 97898944Sobrien return(0); 97998944Sobrien } 98098944Sobrien return(-1); 98198944Sobrien} 98298944Sobrien 98398944Sobrien/* 98498944Sobrien * bcpio_rd() 98598944Sobrien * determine if a buffer is a old binary archive entry. (it may have byte 986130803Smarcel * swapped header) convert and store the values in the ARCHD parameter. 987130803Smarcel * This is a very old header format and should not really be used. 988130803Smarcel * Return: 989130803Smarcel * 0 if a valid header, -1 otherwise. 990130803Smarcel */ 99198944Sobrien 992130803Smarcel#if __STDC__ 993130803Smarcelint 994130803Smarcelbcpio_rd(register ARCHD *arcn, register char *buf) 995130803Smarcel#else 996130803Smarcelint 997130803Smarcelbcpio_rd(arcn, buf) 998130803Smarcel register ARCHD *arcn; 999130803Smarcel register char *buf; 1000130803Smarcel#endif 1001130803Smarcel{ 100298944Sobrien register HD_BCPIO *hd; 100398944Sobrien register int nsz; 100498944Sobrien 100598944Sobrien /* 100698944Sobrien * check the header 100798944Sobrien */ 100898944Sobrien if (bcpio_id(buf, sizeof(HD_BCPIO)) < 0) 100998944Sobrien return(-1); 101098944Sobrien 101198944Sobrien arcn->pad = 0L; 101298944Sobrien hd = (HD_BCPIO *)buf; 101398944Sobrien if (swp_head) { 101498944Sobrien /* 101598944Sobrien * header has swapped bytes on 16 bit boundries 101698944Sobrien */ 1017130803Smarcel arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev)); 1018130803Smarcel arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino)); 101998944Sobrien arcn->sb.st_mode = (mode_t)(RSHRT_EXT(hd->h_mode)); 102098944Sobrien arcn->sb.st_uid = (uid_t)(RSHRT_EXT(hd->h_uid)); 102198944Sobrien arcn->sb.st_gid = (gid_t)(RSHRT_EXT(hd->h_gid)); 102298944Sobrien arcn->sb.st_nlink = (nlink_t)(RSHRT_EXT(hd->h_nlink)); 102398944Sobrien arcn->sb.st_rdev = (dev_t)(RSHRT_EXT(hd->h_rdev)); 102498944Sobrien arcn->sb.st_mtime = (time_t)(RSHRT_EXT(hd->h_mtime_1)); 102598944Sobrien arcn->sb.st_mtime = (arcn->sb.st_mtime << 16) | 102698944Sobrien ((time_t)(RSHRT_EXT(hd->h_mtime_2))); 102798944Sobrien arcn->sb.st_size = (off_t)(RSHRT_EXT(hd->h_filesize_1)); 102898944Sobrien arcn->sb.st_size = (arcn->sb.st_size << 16) | 102998944Sobrien ((off_t)(RSHRT_EXT(hd->h_filesize_2))); 103098944Sobrien nsz = (int)(RSHRT_EXT(hd->h_namesize)); 103198944Sobrien } else { 103298944Sobrien arcn->sb.st_dev = (dev_t)(SHRT_EXT(hd->h_dev)); 103398944Sobrien arcn->sb.st_ino = (ino_t)(SHRT_EXT(hd->h_ino)); 103498944Sobrien arcn->sb.st_mode = (mode_t)(SHRT_EXT(hd->h_mode)); 103598944Sobrien arcn->sb.st_uid = (uid_t)(SHRT_EXT(hd->h_uid)); 103698944Sobrien arcn->sb.st_gid = (gid_t)(SHRT_EXT(hd->h_gid)); 103798944Sobrien arcn->sb.st_nlink = (nlink_t)(SHRT_EXT(hd->h_nlink)); 103898944Sobrien arcn->sb.st_rdev = (dev_t)(SHRT_EXT(hd->h_rdev)); 103998944Sobrien arcn->sb.st_mtime = (time_t)(SHRT_EXT(hd->h_mtime_1)); 104098944Sobrien arcn->sb.st_mtime = (arcn->sb.st_mtime << 16) | 104198944Sobrien ((time_t)(SHRT_EXT(hd->h_mtime_2))); 104298944Sobrien arcn->sb.st_size = (off_t)(SHRT_EXT(hd->h_filesize_1)); 104398944Sobrien arcn->sb.st_size = (arcn->sb.st_size << 16) | 104498944Sobrien ((off_t)(SHRT_EXT(hd->h_filesize_2))); 104598944Sobrien nsz = (int)(SHRT_EXT(hd->h_namesize)); 104698944Sobrien } 104798944Sobrien arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 104898944Sobrien 104998944Sobrien /* 105098944Sobrien * check the file name size, if bogus give up. otherwise read the file 105198944Sobrien * name 105298944Sobrien */ 105398944Sobrien if (nsz < 2) 105498944Sobrien return(-1); 105598944Sobrien arcn->nlen = nsz - 1; 105698944Sobrien if (rd_nm(arcn, nsz) < 0) 105798944Sobrien return(-1); 105898944Sobrien 105998944Sobrien /* 106098944Sobrien * header + file name are aligned to 2 byte boundries, skip if needed 106198944Sobrien */ 106298944Sobrien if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0) 106398944Sobrien return(-1); 106498944Sobrien 106598944Sobrien /* 106698944Sobrien * if not a link (or a file with no data), calculate pad size (for 106798944Sobrien * padding which follows the file data), clear the link name and return 106898944Sobrien */ 106998944Sobrien if (((arcn->sb.st_mode & C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)){ 107098944Sobrien /* 107198944Sobrien * we have a valid header (not a link) 107298944Sobrien */ 107398944Sobrien arcn->ln_nlen = 0; 107498944Sobrien arcn->ln_name[0] = '\0'; 107598944Sobrien arcn->pad = BCPIO_PAD(arcn->sb.st_size); 107698944Sobrien return(com_rd(arcn)); 107798944Sobrien } 107898944Sobrien 107998944Sobrien if ((rd_ln_nm(arcn) < 0) || 108098944Sobrien (rd_skip((off_t)(BCPIO_PAD(arcn->sb.st_size))) < 0)) 108198944Sobrien return(-1); 108298944Sobrien 108398944Sobrien /* 108498944Sobrien * we have a valid header (with a link) 108598944Sobrien */ 1086130803Smarcel return(com_rd(arcn)); 108798944Sobrien} 108898944Sobrien 108998944Sobrien/* 109098944Sobrien * bcpio_endrd() 109198944Sobrien * no cleanup needed here, just return size of the trailer (for append) 109298944Sobrien * Return: 109398944Sobrien * size of trailer header in this format 109498944Sobrien */ 109598944Sobrien 109698944Sobrien#if __STDC__ 109798944Sobrienoff_t 109898944Sobrienbcpio_endrd(void) 109998944Sobrien#else 110098944Sobrienoff_t 110198944Sobrienbcpio_endrd() 110298944Sobrien#endif 110398944Sobrien{ 110498944Sobrien return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) + 110598944Sobrien (BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER))))); 110698944Sobrien} 110798944Sobrien 110898944Sobrien/* 110998944Sobrien * bcpio_wr() 111098944Sobrien * copy the data in the ARCHD to buffer in old binary cpio format 1111130803Smarcel * There is a real chance of field overflow with this critter. So we 111298944Sobrien * always check the conversion is ok. nobody in his their right mind 111398944Sobrien * should write an achive in this format... 111498944Sobrien * Return 1115130803Smarcel * 0 if file has data to be written after the header, 1 if file has NO 111698944Sobrien * data to write after the header, -1 if archive write failed 111798944Sobrien */ 111898944Sobrien 111998944Sobrien#if __STDC__ 112098944Sobrienint 112198944Sobrienbcpio_wr(register ARCHD *arcn) 112298944Sobrien#else 112398944Sobrienint 112498944Sobrienbcpio_wr(arcn) 112598944Sobrien register ARCHD *arcn; 112698944Sobrien#endif 112798944Sobrien{ 112898944Sobrien register HD_BCPIO *hd; 112998944Sobrien register int nsz; 113098944Sobrien char hdblk[sizeof(HD_BCPIO)]; 113198944Sobrien off_t t_offt; 113298944Sobrien int t_int; 113398944Sobrien time_t t_timet; 113498944Sobrien 113598944Sobrien /* 113698944Sobrien * check and repair truncated device and inode fields in the cpio 113798944Sobrien * header 113898944Sobrien */ 113998944Sobrien if (map_dev(arcn, (u_long)BCPIO_MASK, (u_long)BCPIO_MASK) < 0) 114098944Sobrien return(-1); 114198944Sobrien 114298944Sobrien if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR)) 114398944Sobrien arcn->sb.st_rdev = 0; 114498944Sobrien hd = (HD_BCPIO *)hdblk; 114598944Sobrien 114698944Sobrien switch(arcn->type) { 114798944Sobrien case PAX_CTG: 114898944Sobrien case PAX_REG: 114998944Sobrien case PAX_HRG: 115098944Sobrien /* 115198944Sobrien * caller will copy file data to the archive. tell him how 115298944Sobrien * much to pad. 115398944Sobrien */ 115498944Sobrien arcn->pad = BCPIO_PAD(arcn->sb.st_size); 115598944Sobrien hd->h_filesize_1[0] = CHR_WR_0(arcn->sb.st_size); 115698944Sobrien hd->h_filesize_1[1] = CHR_WR_1(arcn->sb.st_size); 115798944Sobrien hd->h_filesize_2[0] = CHR_WR_2(arcn->sb.st_size); 115898944Sobrien hd->h_filesize_2[1] = CHR_WR_3(arcn->sb.st_size); 115998944Sobrien t_offt = (off_t)(SHRT_EXT(hd->h_filesize_1)); 116098944Sobrien t_offt = (t_offt<<16) | ((off_t)(SHRT_EXT(hd->h_filesize_2))); 116198944Sobrien if (arcn->sb.st_size != t_offt) { 116298944Sobrien warn(1,"File is too large for bcpio format %s", 116398944Sobrien arcn->org_name); 116498944Sobrien return(1); 116598944Sobrien } 116698944Sobrien break; 116798944Sobrien case PAX_SLK: 116898944Sobrien /* 116998944Sobrien * no file data for the caller to process, the file data has 117098944Sobrien * the size of the link 117198944Sobrien */ 117298944Sobrien arcn->pad = 0L; 117398944Sobrien hd->h_filesize_1[0] = CHR_WR_0(arcn->ln_nlen); 117498944Sobrien hd->h_filesize_1[1] = CHR_WR_1(arcn->ln_nlen); 117598944Sobrien hd->h_filesize_2[0] = CHR_WR_2(arcn->ln_nlen); 117698944Sobrien hd->h_filesize_2[1] = CHR_WR_3(arcn->ln_nlen); 117798944Sobrien t_int = (int)(SHRT_EXT(hd->h_filesize_1)); 117898944Sobrien t_int = (t_int << 16) | ((int)(SHRT_EXT(hd->h_filesize_2))); 117998944Sobrien if (arcn->ln_nlen != t_int) 118098944Sobrien goto out; 118198944Sobrien break; 118298944Sobrien default: 118398944Sobrien /* 118498944Sobrien * no file data for the caller to process 118598944Sobrien */ 118698944Sobrien arcn->pad = 0L; 118798944Sobrien hd->h_filesize_1[0] = (char)0; 118898944Sobrien hd->h_filesize_1[1] = (char)0; 118998944Sobrien hd->h_filesize_2[0] = (char)0; 119098944Sobrien hd->h_filesize_2[1] = (char)0; 119198944Sobrien break; 119298944Sobrien } 119398944Sobrien 119498944Sobrien /* 119598944Sobrien * build up the rest of the fields 119698944Sobrien */ 119798944Sobrien hd->h_magic[0] = CHR_WR_2(MAGIC); 119898944Sobrien hd->h_magic[1] = CHR_WR_3(MAGIC); 119998944Sobrien hd->h_dev[0] = CHR_WR_2(arcn->sb.st_dev); 120098944Sobrien hd->h_dev[1] = CHR_WR_3(arcn->sb.st_dev); 120198944Sobrien if (arcn->sb.st_dev != (dev_t)(SHRT_EXT(hd->h_dev))) 120298944Sobrien goto out; 120398944Sobrien hd->h_ino[0] = CHR_WR_2(arcn->sb.st_ino); 120498944Sobrien hd->h_ino[1] = CHR_WR_3(arcn->sb.st_ino); 120598944Sobrien if (arcn->sb.st_ino != (ino_t)(SHRT_EXT(hd->h_ino))) 120698944Sobrien goto out; 120798944Sobrien hd->h_mode[0] = CHR_WR_2(arcn->sb.st_mode); 120898944Sobrien hd->h_mode[1] = CHR_WR_3(arcn->sb.st_mode); 120998944Sobrien if (arcn->sb.st_mode != (mode_t)(SHRT_EXT(hd->h_mode))) 121098944Sobrien goto out; 121198944Sobrien hd->h_uid[0] = CHR_WR_2(arcn->sb.st_uid); 121298944Sobrien hd->h_uid[1] = CHR_WR_3(arcn->sb.st_uid); 121398944Sobrien if (arcn->sb.st_uid != (uid_t)(SHRT_EXT(hd->h_uid))) 121498944Sobrien goto out; 1215130803Smarcel hd->h_gid[0] = CHR_WR_2(arcn->sb.st_gid); 121698944Sobrien hd->h_gid[1] = CHR_WR_3(arcn->sb.st_gid); 1217130803Smarcel if (arcn->sb.st_gid != (gid_t)(SHRT_EXT(hd->h_gid))) 121898944Sobrien goto out; 1219130803Smarcel hd->h_nlink[0] = CHR_WR_2(arcn->sb.st_nlink); 1220130803Smarcel hd->h_nlink[1] = CHR_WR_3(arcn->sb.st_nlink); 1221130803Smarcel if (arcn->sb.st_nlink != (nlink_t)(SHRT_EXT(hd->h_nlink))) 1222130803Smarcel goto out; 1223130803Smarcel hd->h_rdev[0] = CHR_WR_2(arcn->sb.st_rdev); 1224130803Smarcel hd->h_rdev[1] = CHR_WR_3(arcn->sb.st_rdev); 1225130803Smarcel if (arcn->sb.st_rdev != (dev_t)(SHRT_EXT(hd->h_rdev))) 1226130803Smarcel goto out; 1227130803Smarcel hd->h_mtime_1[0] = CHR_WR_0(arcn->sb.st_mtime); 1228130803Smarcel hd->h_mtime_1[1] = CHR_WR_1(arcn->sb.st_mtime); 1229130803Smarcel hd->h_mtime_2[0] = CHR_WR_2(arcn->sb.st_mtime); 1230130803Smarcel hd->h_mtime_2[1] = CHR_WR_3(arcn->sb.st_mtime); 1231130803Smarcel t_timet = (time_t)(SHRT_EXT(hd->h_mtime_1)); 1232130803Smarcel t_timet = (t_timet << 16) | ((time_t)(SHRT_EXT(hd->h_mtime_2))); 1233130803Smarcel if (arcn->sb.st_mtime != t_timet) 1234130803Smarcel goto out; 1235130803Smarcel nsz = arcn->nlen + 1; 1236130803Smarcel hd->h_namesize[0] = CHR_WR_2(nsz); 1237130803Smarcel hd->h_namesize[1] = CHR_WR_3(nsz); 1238130803Smarcel if (nsz != (int)(SHRT_EXT(hd->h_namesize))) 1239130803Smarcel goto out; 1240130803Smarcel 1241130803Smarcel /* 1242130803Smarcel * write the header, the file name and padding as required. 1243130803Smarcel */ 1244130803Smarcel if ((wr_rdbuf(hdblk, (int)sizeof(HD_BCPIO)) < 0) || 1245130803Smarcel (wr_rdbuf(arcn->name, nsz) < 0) || 1246130803Smarcel (wr_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)) { 1247130803Smarcel warn(1, "Could not write bcpio header for %s", arcn->org_name); 1248130803Smarcel return(-1); 1249130803Smarcel } 1250130803Smarcel 1251130803Smarcel /* 1252130803Smarcel * if we have file data, tell the caller we are done 1253130803Smarcel */ 1254130803Smarcel if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) || 1255130803Smarcel (arcn->type == PAX_HRG)) 1256130803Smarcel return(0); 1257130803Smarcel 1258130803Smarcel /* 1259130803Smarcel * if we are not a link, tell the caller we are done, go to next file 1260130803Smarcel */ 1261130803Smarcel if (arcn->type != PAX_SLK) 1262130803Smarcel return(1); 1263130803Smarcel 126498944Sobrien /* 126598944Sobrien * write the link name, tell the caller we are done. 126698944Sobrien */ 126798944Sobrien if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) || 126898944Sobrien (wr_skip((off_t)(BCPIO_PAD(arcn->ln_nlen))) < 0)) { 126998944Sobrien warn(1,"Could not write bcpio link name for %s",arcn->org_name); 127098944Sobrien return(-1); 127198944Sobrien } 127298944Sobrien return(1); 127398944Sobrien 127498944Sobrien out: 1275130803Smarcel /* 127698944Sobrien * header field is out of range 127798944Sobrien */ 127898944Sobrien warn(1,"Bcpio header field is too small for file %s", arcn->org_name); 127998944Sobrien return(1); 128098944Sobrien} 1281130803Smarcel