cpio.c

Go to the documentation of this file.
00001 /*-
00002  * Copyright (c) 1992 Keith Muller.
00003  * Copyright (c) 1992, 1993
00004  *      The Regents of the University of California.  All rights reserved.
00005  *
00006  * This code is derived from software contributed to Berkeley by
00007  * Keith Muller of the University of California, San Diego.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted provided that the following conditions
00011  * are met:
00012  * 1. Redistributions of source code must retain the above copyright
00013  *    notice, this list of conditions and the following disclaimer.
00014  * 2. Redistributions in binary form must reproduce the above copyright
00015  *    notice, this list of conditions and the following disclaimer in the
00016  *    documentation and/or other materials provided with the distribution.
00017  * 4. Neither the name of the University nor the names of its contributors
00018  *    may be used to endorse or promote products derived from this software
00019  *    without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00022  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00025  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00026  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00027  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00028  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  */
00033 
00034 #ifndef lint
00035 #if 0
00036 static char sccsid[] = "@(#)cpio.c      8.1 (Berkeley) 5/31/93";
00037 #endif
00038 #endif /* not lint */
00039 
00040 #include <sys/types.h>
00041 #include <sys/time.h>
00042 #include <sys/stat.h>
00043 #include <string.h>
00044 #include <stdint.h>
00045 #include <stdio.h>
00046 #include <unistd.h>
00047 #include <stdlib.h>
00048 #include "pax.h"
00049 #include "cpio.h"
00050 #include "extern.h"
00051 
00052 static int rd_nm(ARCHD *, int);
00053 static int rd_ln_nm(ARCHD *);
00054 static int com_rd(ARCHD *);
00055 
00056 /*
00057  * Routines which support the different cpio versions
00058  */
00059 
00060 static int swp_head;            /* binary cpio header byte swap */
00061 
00062 /*
00063  * Routines common to all versions of cpio
00064  */
00065 
00066 /*
00067  * cpio_strd()
00068  *      Fire up the hard link detection code
00069  * Return:
00070  *      0 if ok -1 otherwise (the return values of lnk_start())
00071  */
00072 
00073 int
00074 cpio_strd(void)
00075 {
00076         return(lnk_start());
00077 }
00078 
00079 /*
00080  * cpio_trail()
00081  *      Called to determine if a header block is a valid trailer. We are
00082  *      passed the block, the in_sync flag (which tells us we are in resync
00083  *      mode; looking for a valid header), and cnt (which starts at zero)
00084  *      which is used to count the number of empty blocks we have seen so far.
00085  * Return:
00086  *      0 if a valid trailer, -1 if not a valid trailer,
00087  */
00088 
00089 int
00090 cpio_trail(ARCHD *arcn)
00091 {
00092         /*
00093          * look for trailer id in file we are about to process
00094          */
00095         if ((strcmp(arcn->name, TRAILER) == 0) && (arcn->sb.st_size == 0))
00096                 return(0);
00097         return(-1);
00098 }
00099 
00100 /*
00101  * com_rd()
00102  *      operations common to all cpio read functions.
00103  * Return:
00104  *      0
00105  */
00106 
00107 static int
00108 com_rd(ARCHD *arcn)
00109 {
00110         arcn->skip = 0;
00111         arcn->pat = NULL;
00112         arcn->org_name = arcn->name;
00113         switch(arcn->sb.st_mode & C_IFMT) {
00114         case C_ISFIFO:
00115                 arcn->type = PAX_FIF;
00116                 break;
00117         case C_ISDIR:
00118                 arcn->type = PAX_DIR;
00119                 break;
00120         case C_ISBLK:
00121                 arcn->type = PAX_BLK;
00122                 break;
00123         case C_ISCHR:
00124                 arcn->type = PAX_CHR;
00125                 break;
00126         case C_ISLNK:
00127                 arcn->type = PAX_SLK;
00128                 break;
00129         case C_ISOCK:
00130                 arcn->type = PAX_SCK;
00131                 break;
00132         case C_ISCTG:
00133         case C_ISREG:
00134         default:
00135                 /*
00136                  * we have file data, set up skip (pad is set in the format
00137                  * specific sections)
00138                  */
00139                 arcn->sb.st_mode = (arcn->sb.st_mode & 0xfff) | C_ISREG;
00140                 arcn->type = PAX_REG;
00141                 arcn->skip = arcn->sb.st_size;
00142                 break;
00143         }
00144         if (chk_lnk(arcn) < 0)
00145                 return(-1);
00146         return(0);
00147 }
00148 
00149 /*
00150  * cpio_end_wr()
00151  *      write the special file with the name trailer in the proper format
00152  * Return:
00153  *      result of the write of the trailer from the cpio specific write func
00154  */
00155 
00156 int
00157 cpio_endwr(void)
00158 {
00159         ARCHD last;
00160 
00161         /*
00162          * create a trailer request and call the proper format write function
00163          */
00164         memset(&last, 0, sizeof(last));
00165         last.nlen = sizeof(TRAILER) - 1;
00166         last.type = PAX_REG;
00167         last.sb.st_nlink = 1;
00168         (void)strcpy(last.name, TRAILER);
00169         return((*frmt->wr)(&last));
00170 }
00171 
00172 /*
00173  * rd_nam()
00174  *      read in the file name which follows the cpio header
00175  * Return:
00176  *      0 if ok, -1 otherwise
00177  */
00178 
00179 static int
00180 rd_nm(ARCHD *arcn, int nsz)
00181 {
00182         /*
00183          * do not even try bogus values
00184          */
00185         if ((nsz == 0) || (nsz > (int)sizeof(arcn->name))) {
00186                 paxwarn(1, "Cpio file name length %d is out of range", nsz);
00187                 return(-1);
00188         }
00189 
00190         /*
00191          * read the name and make sure it is not empty and is \0 terminated
00192          */
00193         if ((rd_wrbuf(arcn->name,nsz) != nsz) || (arcn->name[nsz-1] != '\0') ||
00194             (arcn->name[0] == '\0')) {
00195                 paxwarn(1, "Cpio file name in header is corrupted");
00196                 return(-1);
00197         }
00198         return(0);
00199 }
00200 
00201 /*
00202  * rd_ln_nm()
00203  *      read in the link name for a file with links. The link name is stored
00204  *      like file data (and is NOT \0 terminated!)
00205  * Return:
00206  *      0 if ok, -1 otherwise
00207  */
00208 
00209 static int
00210 rd_ln_nm(ARCHD *arcn)
00211 {
00212         /*
00213          * check the length specified for bogus values
00214          */
00215         if ((arcn->sb.st_size == 0) ||
00216             ((size_t)arcn->sb.st_size >= sizeof(arcn->ln_name))) {
00217 #               ifdef NET2_STAT
00218                 paxwarn(1, "Cpio link name length is invalid: %lu",
00219                     arcn->sb.st_size);
00220 #               else
00221                 paxwarn(1, "Cpio link name length is invalid: %ju",
00222                     (uintmax_t)arcn->sb.st_size);
00223 #               endif
00224                 return(-1);
00225         }
00226 
00227         /*
00228          * read in the link name and \0 terminate it
00229          */
00230         if (rd_wrbuf(arcn->ln_name, (int)arcn->sb.st_size) !=
00231             (int)arcn->sb.st_size) {
00232                 paxwarn(1, "Cpio link name read error");
00233                 return(-1);
00234         }
00235         arcn->ln_nlen = arcn->sb.st_size;
00236         arcn->ln_name[arcn->ln_nlen] = '\0';
00237 
00238         /*
00239          * watch out for those empty link names
00240          */
00241         if (arcn->ln_name[0] == '\0') {
00242                 paxwarn(1, "Cpio link name is corrupt");
00243                 return(-1);
00244         }
00245         return(0);
00246 }
00247 
00248 /*
00249  * Routines common to the extended byte oriented cpio format
00250  */
00251 
00252 /*
00253  * cpio_id()
00254  *      determine if a block given to us is a valid extended byte oriented
00255  *      cpio header
00256  * Return:
00257  *      0 if a valid header, -1 otherwise
00258  */
00259 
00260 int
00261 cpio_id(char *blk, int size)
00262 {
00263         if ((size < (int)sizeof(HD_CPIO)) ||
00264             (strncmp(blk, AMAGIC, sizeof(AMAGIC) - 1) != 0))
00265                 return(-1);
00266         return(0);
00267 }
00268 
00269 /*
00270  * cpio_rd()
00271  *      determine if a buffer is a byte oriented extended cpio archive entry.
00272  *      convert and store the values in the ARCHD parameter.
00273  * Return:
00274  *      0 if a valid header, -1 otherwise.
00275  */
00276 
00277 int
00278 cpio_rd(ARCHD *arcn, char *buf)
00279 {
00280         int nsz;
00281         HD_CPIO *hd;
00282 
00283         /*
00284          * check that this is a valid header, if not return -1
00285          */
00286         if (cpio_id(buf, sizeof(HD_CPIO)) < 0)
00287                 return(-1);
00288         hd = (HD_CPIO *)buf;
00289 
00290         /*
00291          * byte oriented cpio (posix) does not have padding! extract the octal
00292          * ascii fields from the header
00293          */
00294         arcn->pad = 0L;
00295         arcn->sb.st_dev = (dev_t)asc_ul(hd->c_dev, sizeof(hd->c_dev), OCT);
00296         arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), OCT);
00297         arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), OCT);
00298         arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), OCT);
00299         arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), OCT);
00300         arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
00301             OCT);
00302         arcn->sb.st_rdev = (dev_t)asc_ul(hd->c_rdev, sizeof(hd->c_rdev), OCT);
00303 #ifdef NET2_STAT
00304         arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime, sizeof(hd->c_mtime),
00305             OCT);
00306 #else
00307         arcn->sb.st_mtime = (time_t)asc_uqd(hd->c_mtime, sizeof(hd->c_mtime),
00308             OCT);
00309 #endif
00310         arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
00311 #ifdef NET2_STAT
00312         arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,sizeof(hd->c_filesize),
00313             OCT);
00314 #else
00315         arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,sizeof(hd->c_filesize),
00316             OCT);
00317 #endif
00318 
00319         /*
00320          * check name size and if valid, read in the name of this entry (name
00321          * follows header in the archive)
00322          */
00323         if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),OCT)) < 2)
00324                 return(-1);
00325         arcn->nlen = nsz - 1;
00326         if (rd_nm(arcn, nsz) < 0)
00327                 return(-1);
00328 
00329         if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
00330                 /*
00331                  * no link name to read for this file
00332                  */
00333                 arcn->ln_nlen = 0;
00334                 arcn->ln_name[0] = '\0';
00335                 return(com_rd(arcn));
00336         }
00337 
00338         /*
00339          * check link name size and read in the link name. Link names are
00340          * stored like file data.
00341          */
00342         if (rd_ln_nm(arcn) < 0)
00343                 return(-1);
00344 
00345         /*
00346          * we have a valid header (with a link)
00347          */
00348         return(com_rd(arcn));
00349 }
00350 
00351 /*
00352  * cpio_endrd()
00353  *      no cleanup needed here, just return size of the trailer (for append)
00354  * Return:
00355  *      size of trailer header in this format
00356  */
00357 
00358 off_t
00359 cpio_endrd(void)
00360 {
00361         return((off_t)(sizeof(HD_CPIO) + sizeof(TRAILER)));
00362 }
00363 
00364 /*
00365  * cpio_stwr()
00366  *      start up the device mapping table
00367  * Return:
00368  *      0 if ok, -1 otherwise (what dev_start() returns)
00369  */
00370 
00371 int
00372 cpio_stwr(void)
00373 {
00374         return(dev_start());
00375 }
00376 
00377 /*
00378  * cpio_wr()
00379  *      copy the data in the ARCHD to buffer in extended byte oriented cpio
00380  *      format.
00381  * Return
00382  *      0 if file has data to be written after the header, 1 if file has NO
00383  *      data to write after the header, -1 if archive write failed
00384  */
00385 
00386 int
00387 cpio_wr(ARCHD *arcn)
00388 {
00389         HD_CPIO *hd;
00390         int nsz;
00391         char hdblk[sizeof(HD_CPIO)];
00392 
00393         /*
00394          * check and repair truncated device and inode fields in the header
00395          */
00396         if (map_dev(arcn, (u_long)CPIO_MASK, (u_long)CPIO_MASK) < 0)
00397                 return(-1);
00398 
00399         arcn->pad = 0L;
00400         nsz = arcn->nlen + 1;
00401         hd = (HD_CPIO *)hdblk;
00402         if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
00403                 arcn->sb.st_rdev = 0;
00404 
00405         switch(arcn->type) {
00406         case PAX_CTG:
00407         case PAX_REG:
00408         case PAX_HRG:
00409                 /*
00410                  * set data size for file data
00411                  */
00412 #               ifdef NET2_STAT
00413                 if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
00414                     sizeof(hd->c_filesize), OCT)) {
00415 #               else
00416                 if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize,
00417                     sizeof(hd->c_filesize), OCT)) {
00418 #               endif
00419                         paxwarn(1,"File is too large for cpio format %s",
00420                             arcn->org_name);
00421                         return(1);
00422                 }
00423                 break;
00424         case PAX_SLK:
00425                 /*
00426                  * set data size to hold link name
00427                  */
00428                 if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize,
00429                     sizeof(hd->c_filesize), OCT))
00430                         goto out;
00431                 break;
00432         default:
00433                 /*
00434                  * all other file types have no file data
00435                  */
00436                 if (ul_asc((u_long)0, hd->c_filesize, sizeof(hd->c_filesize),
00437                      OCT))
00438                         goto out;
00439                 break;
00440         }
00441 
00442         /*
00443          * copy the values to the header using octal ascii
00444          */
00445         if (ul_asc((u_long)MAGIC, hd->c_magic, sizeof(hd->c_magic), OCT) ||
00446             ul_asc((u_long)arcn->sb.st_dev, hd->c_dev, sizeof(hd->c_dev),
00447                 OCT) ||
00448             ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
00449                 OCT) ||
00450             ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
00451                 OCT) ||
00452             ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
00453                 OCT) ||
00454             ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
00455                 OCT) ||
00456             ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
00457                  OCT) ||
00458             ul_asc((u_long)arcn->sb.st_rdev, hd->c_rdev, sizeof(hd->c_rdev),
00459                 OCT) ||
00460             ul_asc((u_long)arcn->sb.st_mtime,hd->c_mtime,sizeof(hd->c_mtime),
00461                 OCT) ||
00462             ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), OCT))
00463                 goto out;
00464 
00465         /*
00466          * write the file name to the archive
00467          */
00468         if ((wr_rdbuf(hdblk, (int)sizeof(HD_CPIO)) < 0) ||
00469             (wr_rdbuf(arcn->name, nsz) < 0)) {
00470                 paxwarn(1, "Unable to write cpio header for %s", arcn->org_name);
00471                 return(-1);
00472         }
00473 
00474         /*
00475          * if this file has data, we are done. The caller will write the file
00476          * data, if we are link tell caller we are done, go to next file
00477          */
00478         if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
00479             (arcn->type == PAX_HRG))
00480                 return(0);
00481         if (arcn->type != PAX_SLK)
00482                 return(1);
00483 
00484         /*
00485          * write the link name to the archive, tell the caller to go to the
00486          * next file as we are done.
00487          */
00488         if (wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) {
00489                 paxwarn(1,"Unable to write cpio link name for %s",arcn->org_name);
00490                 return(-1);
00491         }
00492         return(1);
00493 
00494     out:
00495         /*
00496          * header field is out of range
00497          */
00498         paxwarn(1, "Cpio header field is too small to store file %s",
00499             arcn->org_name);
00500         return(1);
00501 }
00502 
00503 /*
00504  * Routines common to the system VR4 version of cpio (with/without file CRC)
00505  */
00506 
00507 /*
00508  * vcpio_id()
00509  *      determine if a block given to us is a valid system VR4 cpio header
00510  *      WITHOUT crc. WATCH it the magic cookies are in OCTAL, the header
00511  *      uses HEX
00512  * Return:
00513  *      0 if a valid header, -1 otherwise
00514  */
00515 
00516 int
00517 vcpio_id(char *blk, int size)
00518 {
00519         if ((size < (int)sizeof(HD_VCPIO)) ||
00520             (strncmp(blk, AVMAGIC, sizeof(AVMAGIC) - 1) != 0))
00521                 return(-1);
00522         return(0);
00523 }
00524 
00525 /*
00526  * crc_id()
00527  *      determine if a block given to us is a valid system VR4 cpio header
00528  *      WITH crc. WATCH it the magic cookies are in OCTAL the header uses HEX
00529  * Return:
00530  *      0 if a valid header, -1 otherwise
00531  */
00532 
00533 int
00534 crc_id(char *blk, int size)
00535 {
00536         if ((size < (int)sizeof(HD_VCPIO)) ||
00537             (strncmp(blk, AVCMAGIC, (int)sizeof(AVCMAGIC) - 1) != 0))
00538                 return(-1);
00539         return(0);
00540 }
00541 
00542 /*
00543  * crc_strd()
00544  w      set file data CRC calculations. Fire up the hard link detection code
00545  * Return:
00546  *      0 if ok -1 otherwise (the return values of lnk_start())
00547  */
00548 
00549 int
00550 crc_strd(void)
00551 {
00552         docrc = 1;
00553         return(lnk_start());
00554 }
00555 
00556 /*
00557  * vcpio_rd()
00558  *      determine if a buffer is a system VR4 archive entry. (with/without CRC)
00559  *      convert and store the values in the ARCHD parameter.
00560  * Return:
00561  *      0 if a valid header, -1 otherwise.
00562  */
00563 
00564 int
00565 vcpio_rd(ARCHD *arcn, char *buf)
00566 {
00567         HD_VCPIO *hd;
00568         dev_t devminor;
00569         dev_t devmajor;
00570         int nsz;
00571 
00572         /*
00573          * during the id phase it was determined if we were using CRC, use the
00574          * proper id routine.
00575          */
00576         if (docrc) {
00577                 if (crc_id(buf, sizeof(HD_VCPIO)) < 0)
00578                         return(-1);
00579         } else {
00580                 if (vcpio_id(buf, sizeof(HD_VCPIO)) < 0)
00581                         return(-1);
00582         }
00583 
00584         hd = (HD_VCPIO *)buf;
00585         arcn->pad = 0L;
00586 
00587         /*
00588          * extract the hex ascii fields from the header
00589          */
00590         arcn->sb.st_ino = (ino_t)asc_ul(hd->c_ino, sizeof(hd->c_ino), HEX);
00591         arcn->sb.st_mode = (mode_t)asc_ul(hd->c_mode, sizeof(hd->c_mode), HEX);
00592         arcn->sb.st_uid = (uid_t)asc_ul(hd->c_uid, sizeof(hd->c_uid), HEX);
00593         arcn->sb.st_gid = (gid_t)asc_ul(hd->c_gid, sizeof(hd->c_gid), HEX);
00594 #ifdef NET2_STAT
00595         arcn->sb.st_mtime = (time_t)asc_ul(hd->c_mtime,sizeof(hd->c_mtime),HEX);
00596 #else
00597         arcn->sb.st_mtime = (time_t)asc_uqd(hd->c_mtime,sizeof(hd->c_mtime),HEX);
00598 #endif
00599         arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
00600 #ifdef NET2_STAT
00601         arcn->sb.st_size = (off_t)asc_ul(hd->c_filesize,
00602             sizeof(hd->c_filesize), HEX);
00603 #else
00604         arcn->sb.st_size = (off_t)asc_uqd(hd->c_filesize,
00605             sizeof(hd->c_filesize), HEX);
00606 #endif
00607         arcn->sb.st_nlink = (nlink_t)asc_ul(hd->c_nlink, sizeof(hd->c_nlink),
00608             HEX);
00609         devmajor = (dev_t)asc_ul(hd->c_maj, sizeof(hd->c_maj), HEX);
00610         devminor = (dev_t)asc_ul(hd->c_min, sizeof(hd->c_min), HEX);
00611         arcn->sb.st_dev = TODEV(devmajor, devminor);
00612         devmajor = (dev_t)asc_ul(hd->c_rmaj, sizeof(hd->c_maj), HEX);
00613         devminor = (dev_t)asc_ul(hd->c_rmin, sizeof(hd->c_min), HEX);
00614         arcn->sb.st_rdev = TODEV(devmajor, devminor);
00615         arcn->crc = asc_ul(hd->c_chksum, sizeof(hd->c_chksum), HEX);
00616 
00617         /*
00618          * check the length of the file name, if ok read it in, return -1 if
00619          * bogus
00620          */
00621         if ((nsz = (int)asc_ul(hd->c_namesize,sizeof(hd->c_namesize),HEX)) < 2)
00622                 return(-1);
00623         arcn->nlen = nsz - 1;
00624         if (rd_nm(arcn, nsz) < 0)
00625                 return(-1);
00626 
00627         /*
00628          * skip padding. header + filename is aligned to 4 byte boundries
00629          */
00630         if (rd_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)
00631                 return(-1);
00632 
00633         /*
00634          * if not a link (or a file with no data), calculate pad size (for
00635          * padding which follows the file data), clear the link name and return
00636          */
00637         if (((arcn->sb.st_mode&C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)) {
00638                 /*
00639                  * we have a valid header (not a link)
00640                  */
00641                 arcn->ln_nlen = 0;
00642                 arcn->ln_name[0] = '\0';
00643                 arcn->pad = VCPIO_PAD(arcn->sb.st_size);
00644                 return(com_rd(arcn));
00645         }
00646 
00647         /*
00648          * read in the link name and skip over the padding
00649          */
00650         if ((rd_ln_nm(arcn) < 0) ||
00651             (rd_skip((off_t)(VCPIO_PAD(arcn->sb.st_size))) < 0))
00652                 return(-1);
00653 
00654         /*
00655          * we have a valid header (with a link)
00656          */
00657         return(com_rd(arcn));
00658 }
00659 
00660 /*
00661  * vcpio_endrd()
00662  *      no cleanup needed here, just return size of the trailer (for append)
00663  * Return:
00664  *      size of trailer header in this format
00665  */
00666 
00667 off_t
00668 vcpio_endrd(void)
00669 {
00670         return((off_t)(sizeof(HD_VCPIO) + sizeof(TRAILER) +
00671                 (VCPIO_PAD(sizeof(HD_VCPIO) + sizeof(TRAILER)))));
00672 }
00673 
00674 /*
00675  * crc_stwr()
00676  *      start up the device mapping table, enable crc file calculation
00677  * Return:
00678  *      0 if ok, -1 otherwise (what dev_start() returns)
00679  */
00680 
00681 int
00682 crc_stwr(void)
00683 {
00684         docrc = 1;
00685         return(dev_start());
00686 }
00687 
00688 /*
00689  * vcpio_wr()
00690  *      copy the data in the ARCHD to buffer in system VR4 cpio
00691  *      (with/without crc) format.
00692  * Return
00693  *      0 if file has data to be written after the header, 1 if file has
00694  *      NO data to write after the header, -1 if archive write failed
00695  */
00696 
00697 int
00698 vcpio_wr(ARCHD *arcn)
00699 {
00700         HD_VCPIO *hd;
00701         unsigned int nsz;
00702         char hdblk[sizeof(HD_VCPIO)];
00703 
00704         /*
00705          * check and repair truncated device and inode fields in the cpio
00706          * header
00707          */
00708         if (map_dev(arcn, (u_long)VCPIO_MASK, (u_long)VCPIO_MASK) < 0)
00709                 return(-1);
00710         nsz = arcn->nlen + 1;
00711         hd = (HD_VCPIO *)hdblk;
00712         if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
00713                 arcn->sb.st_rdev = 0;
00714 
00715         /*
00716          * add the proper magic value depending whether we were asked for
00717          * file data crc's, and the crc if needed.
00718          */
00719         if (docrc) {
00720                 if (ul_asc((u_long)VCMAGIC, hd->c_magic, sizeof(hd->c_magic),
00721                         OCT) ||
00722                     ul_asc((u_long)arcn->crc,hd->c_chksum,sizeof(hd->c_chksum),
00723                         HEX))
00724                         goto out;
00725         } else {
00726                 if (ul_asc((u_long)VMAGIC, hd->c_magic, sizeof(hd->c_magic),
00727                         OCT) ||
00728                     ul_asc((u_long)0L, hd->c_chksum, sizeof(hd->c_chksum),HEX))
00729                         goto out;
00730         }
00731 
00732         switch(arcn->type) {
00733         case PAX_CTG:
00734         case PAX_REG:
00735         case PAX_HRG:
00736                 /*
00737                  * caller will copy file data to the archive. tell him how
00738                  * much to pad.
00739                  */
00740                 arcn->pad = VCPIO_PAD(arcn->sb.st_size);
00741 #               ifdef NET2_STAT
00742                 if (ul_asc((u_long)arcn->sb.st_size, hd->c_filesize,
00743                     sizeof(hd->c_filesize), HEX)) {
00744 #               else
00745                 if (uqd_asc((u_quad_t)arcn->sb.st_size, hd->c_filesize,
00746                     sizeof(hd->c_filesize), HEX)) {
00747 #               endif
00748                         paxwarn(1,"File is too large for sv4cpio format %s",
00749                             arcn->org_name);
00750                         return(1);
00751                 }
00752                 break;
00753         case PAX_SLK:
00754                 /*
00755                  * no file data for the caller to process, the file data has
00756                  * the size of the link
00757                  */
00758                 arcn->pad = 0L;
00759                 if (ul_asc((u_long)arcn->ln_nlen, hd->c_filesize,
00760                     sizeof(hd->c_filesize), HEX))
00761                         goto out;
00762                 break;
00763         default:
00764                 /*
00765                  * no file data for the caller to process
00766                  */
00767                 arcn->pad = 0L;
00768                 if (ul_asc((u_long)0L, hd->c_filesize, sizeof(hd->c_filesize),
00769                     HEX))
00770                         goto out;
00771                 break;
00772         }
00773 
00774         /*
00775          * set the other fields in the header
00776          */
00777         if (ul_asc((u_long)arcn->sb.st_ino, hd->c_ino, sizeof(hd->c_ino),
00778                 HEX) ||
00779             ul_asc((u_long)arcn->sb.st_mode, hd->c_mode, sizeof(hd->c_mode),
00780                 HEX) ||
00781             ul_asc((u_long)arcn->sb.st_uid, hd->c_uid, sizeof(hd->c_uid),
00782                 HEX) ||
00783             ul_asc((u_long)arcn->sb.st_gid, hd->c_gid, sizeof(hd->c_gid),
00784                 HEX) ||
00785             ul_asc((u_long)arcn->sb.st_mtime, hd->c_mtime, sizeof(hd->c_mtime),
00786                 HEX) ||
00787             ul_asc((u_long)arcn->sb.st_nlink, hd->c_nlink, sizeof(hd->c_nlink),
00788                 HEX) ||
00789             ul_asc((u_long)major(arcn->sb.st_dev),hd->c_maj, sizeof(hd->c_maj),
00790                 HEX) ||
00791             ul_asc((u_long)minor(arcn->sb.st_dev),hd->c_min, sizeof(hd->c_min),
00792                 HEX) ||
00793             ul_asc((u_long)major(arcn->sb.st_rdev),hd->c_rmaj,sizeof(hd->c_maj),
00794                 HEX) ||
00795             ul_asc((u_long)minor(arcn->sb.st_rdev),hd->c_rmin,sizeof(hd->c_min),
00796                 HEX) ||
00797             ul_asc((u_long)nsz, hd->c_namesize, sizeof(hd->c_namesize), HEX))
00798                 goto out;
00799 
00800         /*
00801          * write the header, the file name and padding as required.
00802          */
00803         if ((wr_rdbuf(hdblk, (int)sizeof(HD_VCPIO)) < 0) ||
00804             (wr_rdbuf(arcn->name, (int)nsz) < 0)  ||
00805             (wr_skip((off_t)(VCPIO_PAD(sizeof(HD_VCPIO) + nsz))) < 0)) {
00806                 paxwarn(1,"Could not write sv4cpio header for %s",arcn->org_name);
00807                 return(-1);
00808         }
00809 
00810         /*
00811          * if we have file data, tell the caller we are done, copy the file
00812          */
00813         if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
00814             (arcn->type == PAX_HRG))
00815                 return(0);
00816 
00817         /*
00818          * if we are not a link, tell the caller we are done, go to next file
00819          */
00820         if (arcn->type != PAX_SLK)
00821                 return(1);
00822 
00823         /*
00824          * write the link name, tell the caller we are done.
00825          */
00826         if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
00827             (wr_skip((off_t)(VCPIO_PAD(arcn->ln_nlen))) < 0)) {
00828                 paxwarn(1,"Could not write sv4cpio link name for %s",
00829                     arcn->org_name);
00830                 return(-1);
00831         }
00832         return(1);
00833 
00834     out:
00835         /*
00836          * header field is out of range
00837          */
00838         paxwarn(1,"Sv4cpio header field is too small for file %s",arcn->org_name);
00839         return(1);
00840 }
00841 
00842 /*
00843  * Routines common to the old binary header cpio
00844  */
00845 
00846 /*
00847  * bcpio_id()
00848  *      determine if a block given to us is an old binary cpio header
00849  *      (with/without header byte swapping)
00850  * Return:
00851  *      0 if a valid header, -1 otherwise
00852  */
00853 
00854 int
00855 bcpio_id(char *blk, int size)
00856 {
00857         if (size < (int)sizeof(HD_BCPIO))
00858                 return(-1);
00859 
00860         /*
00861          * check both normal and byte swapped magic cookies
00862          */
00863         if (((u_short)SHRT_EXT(blk)) == MAGIC)
00864                 return(0);
00865         if (((u_short)RSHRT_EXT(blk)) == MAGIC) {
00866                 if (!swp_head)
00867                         ++swp_head;
00868                 return(0);
00869         }
00870         return(-1);
00871 }
00872 
00873 /*
00874  * bcpio_rd()
00875  *      determine if a buffer is an old binary archive entry. (It may have byte
00876  *      swapped header) convert and store the values in the ARCHD parameter.
00877  *      This is a very old header format and should not really be used.
00878  * Return:
00879  *      0 if a valid header, -1 otherwise.
00880  */
00881 
00882 int
00883 bcpio_rd(ARCHD *arcn, char *buf)
00884 {
00885         HD_BCPIO *hd;
00886         int nsz;
00887 
00888         /*
00889          * check the header
00890          */
00891         if (bcpio_id(buf, sizeof(HD_BCPIO)) < 0)
00892                 return(-1);
00893 
00894         arcn->pad = 0L;
00895         hd = (HD_BCPIO *)buf;
00896         if (swp_head) {
00897                 /*
00898                  * header has swapped bytes on 16 bit boundaries
00899                  */
00900                 arcn->sb.st_dev = (dev_t)(RSHRT_EXT(hd->h_dev));
00901                 arcn->sb.st_ino = (ino_t)(RSHRT_EXT(hd->h_ino));
00902                 arcn->sb.st_mode = (mode_t)(RSHRT_EXT(hd->h_mode));
00903                 arcn->sb.st_uid = (uid_t)(RSHRT_EXT(hd->h_uid));
00904                 arcn->sb.st_gid = (gid_t)(RSHRT_EXT(hd->h_gid));
00905                 arcn->sb.st_nlink = (nlink_t)(RSHRT_EXT(hd->h_nlink));
00906                 arcn->sb.st_rdev = (dev_t)(RSHRT_EXT(hd->h_rdev));
00907                 arcn->sb.st_mtime = (time_t)(RSHRT_EXT(hd->h_mtime_1));
00908                 arcn->sb.st_mtime =  (arcn->sb.st_mtime << 16) |
00909                         ((time_t)(RSHRT_EXT(hd->h_mtime_2)));
00910                 arcn->sb.st_size = (off_t)(RSHRT_EXT(hd->h_filesize_1));
00911                 arcn->sb.st_size = (arcn->sb.st_size << 16) |
00912                         ((off_t)(RSHRT_EXT(hd->h_filesize_2)));
00913                 nsz = (int)(RSHRT_EXT(hd->h_namesize));
00914         } else {
00915                 arcn->sb.st_dev = (dev_t)(SHRT_EXT(hd->h_dev));
00916                 arcn->sb.st_ino = (ino_t)(SHRT_EXT(hd->h_ino));
00917                 arcn->sb.st_mode = (mode_t)(SHRT_EXT(hd->h_mode));
00918                 arcn->sb.st_uid = (uid_t)(SHRT_EXT(hd->h_uid));
00919                 arcn->sb.st_gid = (gid_t)(SHRT_EXT(hd->h_gid));
00920                 arcn->sb.st_nlink = (nlink_t)(SHRT_EXT(hd->h_nlink));
00921                 arcn->sb.st_rdev = (dev_t)(SHRT_EXT(hd->h_rdev));
00922                 arcn->sb.st_mtime = (time_t)(SHRT_EXT(hd->h_mtime_1));
00923                 arcn->sb.st_mtime =  (arcn->sb.st_mtime << 16) |
00924                         ((time_t)(SHRT_EXT(hd->h_mtime_2)));
00925                 arcn->sb.st_size = (off_t)(SHRT_EXT(hd->h_filesize_1));
00926                 arcn->sb.st_size = (arcn->sb.st_size << 16) |
00927                         ((off_t)(SHRT_EXT(hd->h_filesize_2)));
00928                 nsz = (int)(SHRT_EXT(hd->h_namesize));
00929         }
00930         arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
00931 
00932         /*
00933          * check the file name size, if bogus give up. otherwise read the file
00934          * name
00935          */
00936         if (nsz < 2)
00937                 return(-1);
00938         arcn->nlen = nsz - 1;
00939         if (rd_nm(arcn, nsz) < 0)
00940                 return(-1);
00941 
00942         /*
00943          * header + file name are aligned to 2 byte boundries, skip if needed
00944          */
00945         if (rd_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)
00946                 return(-1);
00947 
00948         /*
00949          * if not a link (or a file with no data), calculate pad size (for
00950          * padding which follows the file data), clear the link name and return
00951          */
00952         if (((arcn->sb.st_mode & C_IFMT) != C_ISLNK)||(arcn->sb.st_size == 0)){
00953                 /*
00954                  * we have a valid header (not a link)
00955                  */
00956                 arcn->ln_nlen = 0;
00957                 arcn->ln_name[0] = '\0';
00958                 arcn->pad = BCPIO_PAD(arcn->sb.st_size);
00959                 return(com_rd(arcn));
00960         }
00961 
00962         if ((rd_ln_nm(arcn) < 0) ||
00963             (rd_skip((off_t)(BCPIO_PAD(arcn->sb.st_size))) < 0))
00964                 return(-1);
00965 
00966         /*
00967          * we have a valid header (with a link)
00968          */
00969         return(com_rd(arcn));
00970 }
00971 
00972 /*
00973  * bcpio_endrd()
00974  *      no cleanup needed here, just return size of the trailer (for append)
00975  * Return:
00976  *      size of trailer header in this format
00977  */
00978 
00979 off_t
00980 bcpio_endrd(void)
00981 {
00982         return((off_t)(sizeof(HD_BCPIO) + sizeof(TRAILER) +
00983                 (BCPIO_PAD(sizeof(HD_BCPIO) + sizeof(TRAILER)))));
00984 }
00985 
00986 /*
00987  * bcpio_wr()
00988  *      copy the data in the ARCHD to buffer in old binary cpio format
00989  *      There is a real chance of field overflow with this critter. So we
00990  *      always check the conversion is ok. nobody in his their right mind
00991  *      should write an achive in this format...
00992  * Return
00993  *      0 if file has data to be written after the header, 1 if file has NO
00994  *      data to write after the header, -1 if archive write failed
00995  */
00996 
00997 int
00998 bcpio_wr(ARCHD *arcn)
00999 {
01000         HD_BCPIO *hd;
01001         int nsz;
01002         char hdblk[sizeof(HD_BCPIO)];
01003         off_t t_offt;
01004         int t_int;
01005         time_t t_timet;
01006 
01007         /*
01008          * check and repair truncated device and inode fields in the cpio
01009          * header
01010          */
01011         if (map_dev(arcn, (u_long)BCPIO_MASK, (u_long)BCPIO_MASK) < 0)
01012                 return(-1);
01013 
01014         if ((arcn->type != PAX_BLK) && (arcn->type != PAX_CHR))
01015                 arcn->sb.st_rdev = 0;
01016         hd = (HD_BCPIO *)hdblk;
01017 
01018         switch(arcn->type) {
01019         case PAX_CTG:
01020         case PAX_REG:
01021         case PAX_HRG:
01022                 /*
01023                  * caller will copy file data to the archive. tell him how
01024                  * much to pad.
01025                  */
01026                 arcn->pad = BCPIO_PAD(arcn->sb.st_size);
01027                 hd->h_filesize_1[0] = CHR_WR_0(arcn->sb.st_size);
01028                 hd->h_filesize_1[1] = CHR_WR_1(arcn->sb.st_size);
01029                 hd->h_filesize_2[0] = CHR_WR_2(arcn->sb.st_size);
01030                 hd->h_filesize_2[1] = CHR_WR_3(arcn->sb.st_size);
01031                 t_offt = (off_t)(SHRT_EXT(hd->h_filesize_1));
01032                 t_offt = (t_offt<<16) | ((off_t)(SHRT_EXT(hd->h_filesize_2)));
01033                 if (arcn->sb.st_size != t_offt) {
01034                         paxwarn(1,"File is too large for bcpio format %s",
01035                             arcn->org_name);
01036                         return(1);
01037                 }
01038                 break;
01039         case PAX_SLK:
01040                 /*
01041                  * no file data for the caller to process, the file data has
01042                  * the size of the link
01043                  */
01044                 arcn->pad = 0L;
01045                 hd->h_filesize_1[0] = CHR_WR_0(arcn->ln_nlen);
01046                 hd->h_filesize_1[1] = CHR_WR_1(arcn->ln_nlen);
01047                 hd->h_filesize_2[0] = CHR_WR_2(arcn->ln_nlen);
01048                 hd->h_filesize_2[1] = CHR_WR_3(arcn->ln_nlen);
01049                 t_int = (int)(SHRT_EXT(hd->h_filesize_1));
01050                 t_int = (t_int << 16) | ((int)(SHRT_EXT(hd->h_filesize_2)));
01051                 if (arcn->ln_nlen != t_int)
01052                         goto out;
01053                 break;
01054         default:
01055                 /*
01056                  * no file data for the caller to process
01057                  */
01058                 arcn->pad = 0L;
01059                 hd->h_filesize_1[0] = (char)0;
01060                 hd->h_filesize_1[1] = (char)0;
01061                 hd->h_filesize_2[0] = (char)0;
01062                 hd->h_filesize_2[1] = (char)0;
01063                 break;
01064         }
01065 
01066         /*
01067          * build up the rest of the fields
01068          */
01069         hd->h_magic[0] = CHR_WR_2(MAGIC);
01070         hd->h_magic[1] = CHR_WR_3(MAGIC);
01071         hd->h_dev[0] = CHR_WR_2(arcn->sb.st_dev);
01072         hd->h_dev[1] = CHR_WR_3(arcn->sb.st_dev);
01073         if (arcn->sb.st_dev != (dev_t)(SHRT_EXT(hd->h_dev)))
01074                 goto out;
01075         hd->h_ino[0] = CHR_WR_2(arcn->sb.st_ino);
01076         hd->h_ino[1] = CHR_WR_3(arcn->sb.st_ino);
01077         if (arcn->sb.st_ino != (ino_t)(SHRT_EXT(hd->h_ino)))
01078                 goto out;
01079         hd->h_mode[0] = CHR_WR_2(arcn->sb.st_mode);
01080         hd->h_mode[1] = CHR_WR_3(arcn->sb.st_mode);
01081         if (arcn->sb.st_mode != (mode_t)(SHRT_EXT(hd->h_mode)))
01082                 goto out;
01083         hd->h_uid[0] = CHR_WR_2(arcn->sb.st_uid);
01084         hd->h_uid[1] = CHR_WR_3(arcn->sb.st_uid);
01085         if (arcn->sb.st_uid != (uid_t)(SHRT_EXT(hd->h_uid)))
01086                 goto out;
01087         hd->h_gid[0] = CHR_WR_2(arcn->sb.st_gid);
01088         hd->h_gid[1] = CHR_WR_3(arcn->sb.st_gid);
01089         if (arcn->sb.st_gid != (gid_t)(SHRT_EXT(hd->h_gid)))
01090                 goto out;
01091         hd->h_nlink[0] = CHR_WR_2(arcn->sb.st_nlink);
01092         hd->h_nlink[1] = CHR_WR_3(arcn->sb.st_nlink);
01093         if (arcn->sb.st_nlink != (nlink_t)(SHRT_EXT(hd->h_nlink)))
01094                 goto out;
01095         hd->h_rdev[0] = CHR_WR_2(arcn->sb.st_rdev);
01096         hd->h_rdev[1] = CHR_WR_3(arcn->sb.st_rdev);
01097         if (arcn->sb.st_rdev != (dev_t)(SHRT_EXT(hd->h_rdev)))
01098                 goto out;
01099         hd->h_mtime_1[0] = CHR_WR_0(arcn->sb.st_mtime);
01100         hd->h_mtime_1[1] = CHR_WR_1(arcn->sb.st_mtime);
01101         hd->h_mtime_2[0] = CHR_WR_2(arcn->sb.st_mtime);
01102         hd->h_mtime_2[1] = CHR_WR_3(arcn->sb.st_mtime);
01103         t_timet = (time_t)(SHRT_EXT(hd->h_mtime_1));
01104         t_timet =  (t_timet << 16) | ((time_t)(SHRT_EXT(hd->h_mtime_2)));
01105         if (arcn->sb.st_mtime != t_timet)
01106                 goto out;
01107         nsz = arcn->nlen + 1;
01108         hd->h_namesize[0] = CHR_WR_2(nsz);
01109         hd->h_namesize[1] = CHR_WR_3(nsz);
01110         if (nsz != (int)(SHRT_EXT(hd->h_namesize)))
01111                 goto out;
01112 
01113         /*
01114          * write the header, the file name and padding as required.
01115          */
01116         if ((wr_rdbuf(hdblk, (int)sizeof(HD_BCPIO)) < 0) ||
01117             (wr_rdbuf(arcn->name, nsz) < 0) ||
01118             (wr_skip((off_t)(BCPIO_PAD(sizeof(HD_BCPIO) + nsz))) < 0)) {
01119                 paxwarn(1, "Could not write bcpio header for %s", arcn->org_name);
01120                 return(-1);
01121         }
01122 
01123         /*
01124          * if we have file data, tell the caller we are done
01125          */
01126         if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG) ||
01127             (arcn->type == PAX_HRG))
01128                 return(0);
01129 
01130         /*
01131          * if we are not a link, tell the caller we are done, go to next file
01132          */
01133         if (arcn->type != PAX_SLK)
01134                 return(1);
01135 
01136         /*
01137          * write the link name, tell the caller we are done.
01138          */
01139         if ((wr_rdbuf(arcn->ln_name, arcn->ln_nlen) < 0) ||
01140             (wr_skip((off_t)(BCPIO_PAD(arcn->ln_nlen))) < 0)) {
01141                 paxwarn(1,"Could not write bcpio link name for %s",arcn->org_name);
01142                 return(-1);
01143         }
01144         return(1);
01145 
01146     out:
01147         /*
01148          * header field is out of range
01149          */
01150         paxwarn(1,"Bcpio header field is too small for file %s", arcn->org_name);
01151         return(1);
01152 }

Generated on Fri Apr 14 22:57:01 2006 for minix by  doxygen 1.4.6