📄 cpio.c
字号:
# ifndef lintstatic char *sccsid = "@(#)cpio.c 4.4 (ULTRIX) 4/11/91";# endif /* not lint *//************************************************************************ * * * Copyright (c) 1984 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* * cpio.c * Modification History * ------------ ------- * * 09-Apr-91 lambert * Add "compatability mode" (-C flag) to be able to * read old, "pre-CLD 126 era" binary archives. * * 07-Feb-91 lambert * Further fix for CLD #126, mentioned below. Cpio * was changed to simply not archive files with inodes * greater than those representable in 18 bits. This * was deemed unacceptable. Since the inode numbers in * the archive are not really used (upon extraction the * archived inode #'s cannot be replicated - that's a * function of the underlying filesystem) the algorith * was changed to use an "internal" inode * number for files. A map of inodes with multiple links * was also created, to facilitate maintaining links on * extraction from the archive. Additionally, the inode * counter is kept on a "per device" basis (based on the * dev number returned by stat()) so cpio can support up * to 256K distinct inodes per device. * * Changed EOT message, per Andy's request. * * 18-Sep-90 carito * Fixed negative uid and gid values. Specifically, * extracted sixteen least-significant-bits. See * sprintf(). QAR 03546 Version 4FT1 10-JAN-1990 * service request A900110-1109 * * 08-Aug-90 kegel * Upgraded *_ino from ushort to ino_t (ulong) * and fixed related sscanf to pick up a long * instead of a short; ditto related printf. * A CLD reported that files were being mistakenly * linked during extraction because of wrap-around * in the 16-bit inode numbers used within cpio. * CLD #126 MUH_01595 * * Also, added code for "MAGIC" fix in cpio.h to * meet XPG3. This fixes the problem for which Digital * has a temporary waiver. MAGIC was defined as an * octal number (070707) in cpio.h; XPG3 expects * it to be an octal string ("070707"). Look for * MAGIC and imagic to find the changes - trivial. * * 07-Feb-90 lambert * Changed declaration of "m_ino" in postml() routine * from type short to type ushort due to conflict with * ushort type of "h_ino" in cpio header. * * 10-Jan-90 lambert * Added code for "Pflag" processing to support (non-)use * of umask when writing out files. Also added support * for named pipes. * * 29-Sep-89 lambert * Added reference to X/Open compliant <cpio.h> file. * * 20-Aug-89 lambert * Fixed null pointer problem in main(). * * 27-Sep-88 lambert * Added code to ensure symbolic "linked to" file name * is correct (routine: main(), line 475). (V24_QAR #533) * * 24-Aug-87 fries * Corrected bug to provide correct name * length for symbolic link data. * (SMU-01690) * * 5-Jan-87 fries * Completed adding symbolic link support * to PASS, IN and OUT functions. * Cleaned up code and commented. * * 12-Nov-86 robin * Added symbolic link support to IN and * OUT functions. * * 29-May-86 fries * Added copyright notice. * * 29-May-86 fries * corrected typo utime to utimes * */#include <stdio.h>#include <signal.h>#include <sys/file.h>#include <limits.h>#include <cpio.h>#include <errno.h>#ifdef RT#include <rt/macro.h>#include <rt/types.h>#include <rt/stat.h>#else#include <sys/types.h>#include <sys/stat.h>#endif#define EQ(x,y) (strcmp(x,y)==0)/* for VAX, Interdata, ... */#define MKSHORT(v,lv) {U.l=1L;if(U.c[0]) U.l=lv,v[0]=U.s[1],v[1]=U.s[0]; else U.l=lv,v[0]=U.s[0],v[1]=U.s[1];}#define IN 1 /* copy in */#define OUT 2 /* copy out */#define PASS 3 /* directory copy */#define HDRSIZE (Hdr.h_name - (char *)&Hdr) /* header size minus filename field */#define O_HDRSIZE (O_Hdr.h_name - (char *)&O_Hdr) /* Old header size minus filename field */#define LINKS 1000 /* max no. of links allowed */#define CHARS 76 /* ASCII header size */ /* minus filename field */#define BUFSIZE 512 /* In u370, can't use BUFSIZ nor BSIZE */#define CPIOBSZ 4096 /* file read/write */#define printd if(debug) fprintf/* if debug mode(see int below) */#define STAT(n,d) (Slink)?lstat(n,d):stat(n,d) /* type of stat to use */int debug=0; /* flag to signal debug mode */#ifdef RTextern long filespace;#endif#define OCTAL 8 /* for MAGIC/imagic fix */#define MAXDEVS 1000 /* max # of h_dev entries per archive */ /* (needed for "inode too big" fix) */struct stat Statb, Xstatb; /* file stat structure *//* Cpio header format */struct header { short h_magic, h_dev; ino_t h_ino; ushort h_mode, h_uid, h_gid; short h_nlink, h_rdev, h_mtime[2], h_namesize, h_filesize[2]; char h_name[256];} Hdr;/* Old Cpio header format */struct old_header { short h_magic, h_dev; ushort h_ino, /* Note difference between old + new headers */ h_mode, h_uid, h_gid; short h_nlink, h_rdev, h_mtime[2], h_namesize, h_filesize[2]; char h_name[256];} O_Hdr;unsigned Bufsize = BUFSIZE;/* default record size */short Buf[CPIOBSZ/2], *Dbuf; /* 2048 byte buffer */char BBuf[CPIOBSZ], *Cbuf; /* Character Mode buffer */char *Cptr; /* general use char. ptr.*/int Wct, Wc, Symct; /* Counts(words, bytes, and */ /* # of bytes in symbolic link */short *Wp; /* Word Pointer(!Cflag) */char *Cp; /* Character Pointer(Cflag) */unsigned imagic; /* integer form of MAGIC from cpio.h */struct linkbuf { ino_t real_ino; dev_t devnum; ino_t fake_ino; struct linkbuf *next_lbp;} *lbp;long internal_ino[MAXDEVS]; /* "internal" inode number */short devlist[MAXDEVS]; /* list of dev #s encountered */short devidx = 0; /* global index into devlist array */short last_dev_seen = 0; /* more device indexing noise */ino_t next_ino(); /* make pcc shutup about redeclarations */#ifdef RTshort Actual_size[2];#endif/* Flags */short Option, Dir, Uncond, Link, Rename, Toc, Slink, Verbose, Select, Mod_time, Acc_time, Cflag, C_mode, fflag, Pflag,#ifdef RT Extent,#endif Swap, byteswap, bothswap, halfswap;/* file descriptors */int Ifile, Ofile, Input = 0, Output = 1;long Blocks, Longfile, Longtime;char Fullname[256], Name[256];int Pathend;/* File Pointers for tty read and write */FILE *Rtty, *Wtty;char *Pattern[100];char Strhdr[500];char *Chdr = Strhdr;char symstring[BUFSIZE*2];/* Device # , uid #, gid # & Type of File */short Dev, Uid, Gid, A_directory, A_special, A_symlink,#ifdef RT One_extent, Multi_extent,#endif Filetype = S_IFMT;/* External Globals */extern errno;/* External Functions */char *malloc();FILE *popen();union { long l; short s[2]; char c[4]; } U;/* for VAX, Interdata, ... */long mklong(v)short v[];{ U.l = 1; if(U.c[0]) U.s[0] = v[1], U.s[1] = v[0]; else U.s[0] = v[0], U.s[1] = v[1]; return U.l;}/* Main Code Entry Point */main(argc, argv) int argc; char **argv;{ char *namep; register ct; long filesz; register char *fullp; register i; int ans, oumask; signal(SIGSYS, 1); imagic = (unsigned) strtoul(MAGIC, NULL, OCTAL ); /* check for options signaller */ if(argc < 2) usage(); /* get uid */ Uid = getuid(); /* save old user mask and set to zero */ oumask = umask(0); /* get group id */ Gid = getgid(); /* set default for patterns to match */ Pattern[0] = "*"; /* handle options */ while(*++argv[1]) { switch(*argv[1]) { case 'a': /* reset access time */ Acc_time++; break; case 'B': /* change record size to 5120 bytes */ Bufsize = 5120; break; case 'i': /* input data */ Option = IN; if(argc > 2 ) { /* save patterns, if any */ for(i = 0; (i+2) < argc; ++i) Pattern[i] = argv[i+2]; } break; case 'f': /* copy all except patterns */ fflag++; break; case 'k': /* read/create symbolic links */ Slink++; break; case 'o': /* output data */ if(argc != 2) usage(); Option = OUT; break; case 'P': /* POSIX mode */ Pflag++; break; case 'p': /* directory copy */ if(argc != 3) usage(); if(access(argv[2], 2) == -1) {accerr: fprintf(stderr,"cannot write in <%s>\n", argv[2]); exit(2); } /* destination directory */ strcpy(Fullname, argv[2]); strcat(Fullname, "/"); /* Check for name being a directory */ stat(Fullname, &Xstatb); if((Xstatb.st_mode&S_IFMT) != S_IFDIR) goto accerr; Option = PASS; Dev = Xstatb.st_dev; break; case 'c': /* ASCII header */ Cflag++; break; case 'C': /* Compatability mode - use old header */ C_mode++; break; case 'd': /* create directories when needed */ Dir++; break; case 'l': /* link files, when necessary */ Link++; break; case 'm': /* retain mod time */ Mod_time++; break; case 'r': /* rename files interactively */ Rename++; Rtty = fopen("/dev/tty", "r"); Wtty = fopen("/dev/tty", "w"); if(Rtty==NULL || Wtty==NULL) { fprintf(stderr, "Cannot rename (/dev/tty missing)\n"); exit(2); } break; case 'S': /* swap halfwords */ halfswap++; Swap++; break; case 's': /* swap bytes */ byteswap++; Swap++; break; case 'b': /* swap bytes and halfwords */ bothswap++; Swap++; break; case 't': /* table of contents */ Toc++; break; case 'u': /* copy unconditionally */ Uncond++; break; case 'v': /* verbose table of contents */ Verbose++; break; case 'V': /* big Verbose mode */ Verbose++; debug++; /* set "debug" int (see above) */ break; case '6': /* for old, sixth-edition files */ Filetype = 060000; break;#ifdef RT case 'e': Extent++; break;#endif default: usage(); } } /* Check that the user specified input, output or pass */ if(!Option) { fprintf(stderr,"Options must include o|i|p\n"); exit(2); } /* Only allow compatability mode when reading in */ if (Option != IN && C_mode) { fprintf(stderr, "-C only valid on copy in operations - ignored\n"); C_mode = 0; }#ifdef RT setio(-1,1); /* turn on physio */#endif /* if Pflag specified, and user is not root, reset mask to what it was originally (POSIX/XOPEN mode) */ if ((Pflag) && (Uid != 0)) umask(oumask); /* If directory copy and Rename selected together... */ if(Option == PASS) { if(Rename) { fprintf(stderr,"Pass and Rename cannot be used together\n"); exit(2); } if(Bufsize == 5120) { printf("`B' option is irrelevant with the '-p' option\n"); printf("Setting Input/Output blocking to %d bytes to a record\n", BUFSIZE); Bufsize = BUFSIZE; } }else { if(Cflag) Cp = Cbuf = (char *)malloc(Bufsize); else Wp = Dbuf = (short *)malloc(Bufsize); } Wct = Bufsize >> 1; /* set word count */ Wc = Bufsize; /* and byte count */ /* Perform OUTPUT, INPUT, or PASS operations */ switch(Option) { case OUT: /* get filename, copy header and file out */ while(getname()) { if(A_symlink){ Symct=readlink(Hdr.h_name, Cflag? BBuf:(char *)Buf, Cflag? sizeof(BBuf): sizeof(Buf)); if (Symct < 0) { perror("cpio"); fprintf(stderr,"Cannot read %s\n", Hdr.h_name); continue; } strncpy(symstring,Cflag ? (char *)BBuf : (char *)Buf,Symct); Cptr = Cflag ? (char *)BBuf : (char *) Buf; Cptr[Symct] = '\0' ; symstring[Symct]='\0'; printd(stderr,"Smyct %d\n BUF: %s\n symstring %s\n namesize %d\n filesize %d\n", Symct,(Cflag?(char *)BBuf:(char *)Buf),symstring,Hdr.h_namesize,Hdr.h_filesize[1]); /* Write the header */ if ( Cflag ) writehdr(Chdr,CHARS+Hdr.h_namesize); else bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); Cflag? writehdr(BBuf,(int) mklong(Hdr.h_filesize)): bwrite(Buf,(int) mklong(Hdr.h_filesize)); goto setout; } if( mklong(Hdr.h_filesize) == 0L) { if( Cflag ) writehdr(Chdr,CHARS+Hdr.h_namesize); else bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);#ifdef RT if (One_extent || Multi_extent) { actsize(0); if( Cflag ) writehdr(Chdr,CHARS+Hdr.h_namesize); else bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); }#endif continue; } if((Ifile = open(Hdr.h_name,O_RDONLY )) < 0) { fprintf(stderr,"<%s> ?\n", Hdr.h_name); continue; } if ( Cflag ) writehdr(Chdr,CHARS+Hdr.h_namesize); else bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);#ifdef RT if (One_extent || Multi_extent) { actsize(Ifile); if(Cflag) writehdr(Chdr,CHARS+Hdr.h_namesize); else bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); Hdr.h_filesize[0] = Actual_size[0]; Hdr.h_filesize[1] = Actual_size[1]; }#endif for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= CPIOBSZ){ ct = filesz>CPIOBSZ? CPIOBSZ: filesz; if(read(Ifile, Cflag? BBuf: (char *)Buf, ct) < 0) { fprintf(stderr,"Cannot read %s\n", Hdr.h_name); continue; } Cflag? writehdr(BBuf,ct): bwrite(Buf,ct); } close(Ifile);setout: if(Acc_time) utimes(Hdr.h_name, &Statb.st_atime); if(Verbose) fprintf(stderr,"%s\n", Hdr.h_name); } /* Output the TRAILER data... */ /* copy trailer, after all files have been copied */ strcpy(Hdr.h_name, "TRAILER!!!"); Hdr.h_magic = imagic; MKSHORT(Hdr.h_filesize, 0L); Hdr.h_namesize = strlen("TRAILER!!!") + 1; if ( Cflag ) { bintochar(0L); writehdr(Chdr,CHARS+Hdr.h_namesize); } else bwrite(&Hdr, HDRSIZE+Hdr.h_namesize); Cflag? writehdr(Cbuf, Bufsize): bwrite(Dbuf, Bufsize); break; case IN:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -