Annotation of 43BSDTahoe/bin/cpio/cpio.c, revision 1.1.1.1

1.1       root        1: /*     Copyright (c) 1988 AT&T */
                      2: /*       All Rights Reserved   */
                      3: 
                      4: /*     THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T     */
                      5: /*     The copyright notice above does not evidence any        */
                      6: /*     actual or intended publication of such source code.     */
                      7: 
                      8: #ident "@(#)cpio:cpio.c        1.30.1.11"
                      9: /*     /sccs/src/cmd/s.cpio.c
                     10:        cpio.c  1.30.1.11       1/11/86 13:46:48
                     11:        Reworked cpio which uses getopt(3) to interpret flag arguments and
                     12:        changes reels to the save file name.
                     13:        Performance and size improvements.
                     14: */
                     15: 
                     16: /*     cpio    COMPILE:        cc -O cpio.c -s -i -o cpio -lgen -lerr
                     17:        cpio -- copy file collections
                     18: 
                     19: */
                     20: #include <errno.h>
                     21: #include <fcntl.h>
                     22: #include <memory.h>
                     23: #include <stdio.h>
                     24: #include <string.h>
                     25: #include <signal.h>
                     26: #include <varargs.h>
                     27: #include <sys/param.h>
                     28: #include <sys/types.h>
                     29: #include <sys/stat.h>
                     30: 
                     31: struct utimbuf {
                     32:        time_t  actime;
                     33:        time_t  modtime;
                     34: };
                     35: #ifndef S_IFIFO
                     36: #define        S_IFIFO 010000
                     37: #endif
                     38: 
                     39: #define EQ(x,y)        (strcmp(x,y)==0)
                     40: 
                     41:                                /* MKSHORT:  for VAX, Interdata, ...    */
                     42:                                /* Take a 4-byte long, lv, and turn it  */
                     43:                                /* into an array of two 2-byte shorts, v*/
                     44: #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];}
                     45: 
                     46: #define MAGIC  070707          /* cpio magic number */
                     47: #define BSMAGIC        0143561         /* byte-swapped cpio magic number */
                     48: #define IN     'i'             /* copy in */
                     49: #define OUT    'o'             /* copy out */
                     50: #define PASS   'p'             /* direct copy */
                     51: #define HDRSIZE        (Hdr.h_name - (char *)&Hdr)     /* header size minus filename field */
                     52: #define LINKS  500             /* no. of links allocated per bunch */
                     53: #define CHARS  76              /* ASCII header size minus filename field */
                     54: #define BUFSIZE 512            /* In u370, can't use BUFSIZ or BSIZE */
                     55: #define CPIOBSZ 4096           /* file read/write */
                     56: #define MK_USHORT(a)   (a & 00000177777)       /* Make unsigned shorts for portable  */
                     57:                                                /* header.  Hardware may only know    */
                     58:                                                /* integer operations and sign extend */
                     59:                                                /* the large unsigned short resulting */
                     60:                                                /* in 8 rather than 6 octal char in   */
                     61:                                                /* the header.                        */
                     62: 
                     63: static struct  stat    Statb, Xstatb;
                     64: 
                     65:        /* Cpio header format */
                     66: static struct header {
                     67:        short   h_magic;
                     68:        short   h_dev;
                     69:        ushort  h_ino;
                     70:        ushort  h_mode,
                     71:                h_uid,
                     72:                h_gid;
                     73:        short   h_nlink;
                     74:        short   h_rdev;
                     75:        short   h_mtime[2],
                     76:                h_namesize,
                     77:                h_filesize[2];
                     78:        char    h_name[256];
                     79: } Hdr;
                     80: 
                     81: char   Symlbuf[MAXPATHLEN + 1];        /* target of symbolic link */
                     82: static unsigned        Bufsize = BUFSIZE;              /* default record size */
                     83: static char    Buf[CPIOBSZ], *Cbuf;
                     84: static char    *Cp;
                     85: 
                     86: 
                     87: static
                     88: short  Option,
                     89:        Dir,
                     90:        Uncond,
                     91:        PassLink,
                     92:        Rename,
                     93:        Toc,
                     94:        Verbose,
                     95:        Mod_time,
                     96:        Acc_time,
                     97:        Cflag,
                     98:        fflag,
                     99:        Swap,
                    100:        byteswap,
                    101:        halfswap;
                    102: 
                    103: static
                    104: int    Ifile,
                    105:        Ofile,
                    106:        Input = 0,
                    107:        Output = 1;
                    108:                        /* sBlocks: short Blocks.  Cumulative character   */
                    109:                        /* count for short reads in bread().  Encountered */
                    110:                        /* with communication lines and pipes as in:      */
                    111:                        /* split -100 cpio_archive; cat xa* | cpio -icd   */
                    112: static
                    113: long   sBlocks,
                    114:        Blocks,
                    115:        Longfile,
                    116:        Longtime;
                    117: 
                    118: static
                    119: char   Fullname[256],
                    120:        Name[256];
                    121: static
                    122: int    Pathend;
                    123: static
                    124: char   *swfile;
                    125: static
                    126: char   *eommsg = "Change to part %d and press RETURN key. [q] ";
                    127: 
                    128: static
                    129: FILE   *Rtty,
                    130:        *Wtty;
                    131: static
                    132: char   ttyname[] = "/dev/tty";
                    133: 
                    134: static
                    135: char   **Pattern = 0;
                    136: static
                    137: char   Chdr[500];
                    138: static
                    139: short  Dev;
                    140: ushort Uid,
                    141:        A_directory,
                    142:        A_special,
                    143:        A_symlink,
                    144:        Filetype = S_IFMT;
                    145: 
                    146: extern errno;
                    147: extern void exit();
                    148: char   *malloc();
                    149: FILE   *popen();
                    150: 
                    151: static char *smemcpy();
                    152: 
                    153: static
                    154: union {
                    155:        long l;
                    156:        short s[2];
                    157:        char c[4];
                    158: } U;
                    159: 
                    160: /* for VAX, Interdata, ... */
                    161: static
                    162: long mklong(v)
                    163: short v[];
                    164: {
                    165:        U.l = 1;
                    166:        if(U.c[0])
                    167:                U.s[0] = v[1], U.s[1] = v[0];
                    168:        else
                    169:                U.s[0] = v[0], U.s[1] = v[1];
                    170:        return U.l;
                    171: }
                    172: 
                    173: main(argc, argv)
                    174: char **argv;
                    175: {
                    176:        register ct;
                    177:        long    filesz;
                    178:        int     symlsz;
                    179:        register char *fullp;
                    180:        register i;
                    181:        int ans;
                    182:        register char *symlinkp;
                    183:        short select;                   /* set when files are selected */
                    184:        extern char     *optarg;
                    185:        extern int      optind;
                    186: 
                    187:        signal(SIGSYS, SIG_IGN);
                    188:        if(argc <= 1 || *argv[1] != '-')
                    189:                usage();
                    190:        Uid = getuid();
                    191: 
                    192:        while( (ans = getopt( argc, argv, "aBC:ifopcdlmrSsbtuvM:6eI:O:")) != EOF ) {
                    193: 
                    194:                switch( ans ) {
                    195:                case 'a':               /* reset access time */
                    196:                        Acc_time++;
                    197:                        break;
                    198:                case 'B':               /* change record size to 5120 bytes */
                    199:                        Bufsize = 5120;
                    200:                        break;
                    201:                case 'C':               /* reset buffer size to arbitrary valu
                    202:                                        */
                    203:                        Bufsize = atoi( optarg );
                    204:                        if( Bufsize == 0 ) {
                    205:                                fperr("Illegal argument to -%c, '%s'",
                    206:                                        ans, optarg );
                    207:                                exit(2);
                    208:                        }
                    209:                        break;
                    210:                case 'i':
                    211:                        Option = IN;
                    212:                        break;
                    213:                case 'f':       /* copy files not matched by patterns */
                    214:                        fflag++;
                    215:                        break;
                    216:                case 'o':
                    217:                        Option = OUT;
                    218:                        break;
                    219:                case 'p':
                    220:                        Option = PASS;
                    221:                        break;
                    222:                case 'c':               /* ASCII header */
                    223:                        Cflag++;
                    224:                        break;
                    225:                case 'd':               /* create directories when needed */
                    226:                        Dir++;
                    227:                        break;
                    228:                case 'l':               /* link files, when necessary */
                    229:                        PassLink++;
                    230:                        break;
                    231:                case 'm':               /* retain mod time */
                    232:                        Mod_time++;
                    233:                        break;
                    234:                case 'r':               /* rename files interactively */
                    235:                        Rename++;
                    236:                        Rtty = fopen(ttyname, "r");
                    237:                        Wtty = fopen(ttyname, "w");
                    238:                        if(Rtty==NULL || Wtty==NULL) {
                    239:                                fperrno("Cannot rename (%s missing)",
                    240:                                        ttyname );
                    241:                                exit(2);
                    242:                        }
                    243:                        break;
                    244:                case 'S':               /* swap halfwords */
                    245:                        halfswap++;
                    246:                        Swap++;
                    247:                        break;
                    248:                case 's':               /* swap bytes */
                    249:                        byteswap++;
                    250:                        Swap++;
                    251:                        break;
                    252:                case 'b':               /* swap both bytes and halfwords */
                    253:                        halfswap++;
                    254:                        byteswap++;
                    255:                        Swap++;
                    256:                        break;
                    257:                case 't':               /* table of contents */
                    258:                        Toc++;
                    259:                        break;
                    260:                case 'u':               /* copy unconditionally */
                    261:                        Uncond++;
                    262:                        break;
                    263:                case 'v':               /* verbose - print out file names */
                    264:                        Verbose++;
                    265:                        break;
                    266:                case 'M':               /* alternate message for end-of-media */
                    267:                        eommsg = optarg;
                    268:                        break;
                    269:                case '6':               /* for old, sixth-edition files */
                    270:                        Filetype = 060000;
                    271:                        break;
                    272:                case 'I':
                    273:                        chkswfile( swfile, ans, Option );
                    274:                        if( (i = open( optarg, O_RDONLY ) ) < 0) {
                    275:                                fperrno("Cannot open <%s> for input", optarg);
                    276:                                exit(2);
                    277:                        }
                    278:                        if( dup2(i, Input ) < 0 ) {
                    279:                                fperrno("Cannot dup to standard input");
                    280:                                exit(2);
                    281:                        }
                    282:                        swfile = optarg;
                    283:                        break;
                    284:                case 'O':
                    285:                        chkswfile( swfile, ans, Option );
                    286:                        if( (i = open( optarg, O_WRONLY | O_CREAT | O_TRUNC,
                    287:                            0666 ) ) < 0) {
                    288:                                fperrno("Cannot open <%s> for output", optarg);
                    289:                                exit(2);
                    290:                        }
                    291:                        if( dup2(i, Output ) < 0 ) {
                    292:                                fperrno("Cannot dup to standard output");
                    293:                                exit(2);
                    294:                        }
                    295:                        swfile = optarg;
                    296:                        break;
                    297:                default:
                    298:                        usage();
                    299:                }
                    300:        }
                    301:        if(!Option) {
                    302:                (void) fprintf(stderr,
                    303:                    "Options must include one of -o, -i, or -p\n");
                    304:                exit(2);
                    305:        }
                    306: 
                    307:        if(Option == PASS) {
                    308:                if(Rename) {
                    309:                        (void) fprintf(stderr,
                    310:                            "Pass and Rename cannot be used together\n");
                    311:                        exit(2);
                    312:                }
                    313:                if( Bufsize != BUFSIZE ) {
                    314:                        fprintf( stderr, "`B' or `C' option is irrelevant with the '-p' option\n");
                    315:                        Bufsize = BUFSIZE;
                    316:                }
                    317: 
                    318:        }else  {
                    319:                Cp = Cbuf = (char *)malloc(Bufsize);
                    320:                if(Cp == NULL) {
                    321:                        perror("cpio");
                    322:                        exit(2);
                    323:                }
                    324:        }
                    325:        argc -= optind;
                    326:        argv += optind;
                    327: 
                    328:        switch(Option) {
                    329:        case OUT:
                    330:                if(argc != 0)
                    331:                        usage();
                    332:                /* get filename, copy header and file out */
                    333:                while(getname()) {
                    334:                        if( mklong(Hdr.h_filesize) == 0L) {
                    335:                                if( Cflag )
                    336:                                        bwrite(Chdr,CHARS+Hdr.h_namesize);
                    337:                                else
                    338:                                        bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
                    339:                                if(Verbose)
                    340:                                        (void) fprintf(stderr, "%s\n",
                    341:                                            Hdr.h_name);
                    342:                                continue;
                    343:                        } else if( A_symlink ) {
                    344:                                symlsz = (int) mklong(Hdr.h_filesize);
                    345:                                if (readlink(Hdr.h_name, Symlbuf, symlsz) < 0) {
                    346:                                        fperrno("Cannot read symbolic link <%s>",
                    347:                                            Hdr.h_name);
                    348:                                        continue;
                    349:                                }
                    350:                                Symlbuf[symlsz] = '\0';
                    351:                                bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
                    352:                                bwrite(Symlbuf, symlsz);
                    353:                                if(Verbose)
                    354:                                        (void) fprintf(stderr, "%s\n",
                    355:                                            Hdr.h_name);
                    356:                                continue;
                    357:                        }
                    358:                        if((Ifile = open(Hdr.h_name, 0)) < 0) {
                    359:                                fperrno("Cannot open <%s>", Hdr.h_name);
                    360:                                continue;
                    361:                        }
                    362:                        if ( Cflag )
                    363:                                bwrite(Chdr,CHARS+Hdr.h_namesize);
                    364:                        else
                    365:                                bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
                    366:                        for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= CPIOBSZ){
                    367:                                ct = filesz>CPIOBSZ? CPIOBSZ: filesz;
                    368:                                if(read(Ifile, Buf, ct) < 0) {
                    369:                                        fperrno("Cannot read %s", Hdr.h_name);
                    370:                                        continue;
                    371:                                }
                    372:                                bwrite(Buf,ct);
                    373:                        }
                    374:                        close(Ifile);
                    375:                        if(Acc_time) {
                    376:                                struct utimbuf utb;
                    377: 
                    378:                                utb.actime = Statb.st_atime;
                    379:                                utb.modtime = Statb.st_mtime;
                    380:                                (void)utime(Hdr.h_name, &utb);
                    381:                        }
                    382:                        if(Verbose)
                    383:                                (void) fprintf(stderr, "%s\n", Hdr.h_name);
                    384:                }
                    385: 
                    386:        /* copy trailer, after all files have been copied */
                    387:                strcpy(Hdr.h_name, "TRAILER!!!");
                    388:                Hdr.h_magic = MAGIC;
                    389:                MKSHORT(Hdr.h_filesize, 0L);
                    390:                Hdr.h_namesize = strlen("TRAILER!!!") + 1;
                    391:                if ( Cflag )  {
                    392:                        bintochar(0L);
                    393:                        bwrite(Chdr, CHARS+Hdr.h_namesize);
                    394:                }
                    395:                else
                    396:                        bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
                    397:                bwrite(Cbuf, Bufsize);
                    398:                break;
                    399: 
                    400:        case IN:
                    401:                if(argc > 0 ) { /* save patterns, if any */
                    402:                        Pattern = argv;
                    403:                }
                    404:                pwd();
                    405:                chkhdr();
                    406:                while(gethdr()) {
                    407:                        if (A_symlink) {
                    408:                                symlsz = (int) mklong(Hdr.h_filesize);
                    409:                                bread(Symlbuf, symlsz);
                    410:                                Symlbuf[symlsz] = '\0';
                    411:                                if( ckname(Hdr.h_name)  &&  !Toc)
                    412:                                        (void)openout(Hdr.h_name, Symlbuf);
                    413:                        } else {
                    414:                                if( (select = ckname(Hdr.h_name))  &&  !Toc )
                    415:                                        Ofile = openout(Hdr.h_name, (char *)0);
                    416:                                else
                    417:                                        Ofile = 0;
                    418:                                for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= CPIOBSZ){
                    419:                                        ct = filesz>CPIOBSZ? CPIOBSZ: filesz;
                    420:                                        bread(Buf, ct);
                    421:                                        if(Ofile) {
                    422:                                                if(Swap)
                    423:                                                       swap(Buf,ct,byteswap,halfswap);
                    424:                                                if(write(Ofile, Buf, ct) < 0) {
                    425:                                                 fperrno("Cannot write %s", Hdr.h_name);
                    426:                                                 continue;
                    427:                                                }
                    428:                                        }
                    429:                                }
                    430:                                if( Ofile ) {
                    431:                                        (void) close(Ofile);
                    432:                                        if(chmod(Hdr.h_name, Hdr.h_mode) < 0)
                    433:                                                fperrno("Cannot change mode of <%s>",
                    434:                                                    Hdr.h_name);
                    435:                                        set_time(Hdr.h_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
                    436:                                }
                    437:                        }
                    438:                        if(select) {
                    439:                                if(Verbose)
                    440:                                        if(Toc)
                    441:                                                pentry(Hdr.h_name);
                    442:                                        else
                    443:                                                puts(Hdr.h_name);
                    444:                                else if(Toc)
                    445:                                        puts(Hdr.h_name);
                    446:                        }
                    447:                }
                    448:                break;
                    449: 
                    450:        case PASS:              /* move files around */
                    451:                if(argc != 1)
                    452:                        usage();
                    453:                if(access(argv[0], 2) == -1) {
                    454:                        (void) fperrno("Cannot write in <%s>", argv[0]);
                    455:                        exit(2);
                    456:                }
                    457:                strcpy(Fullname, argv[0]);      /* destination directory */
                    458:                if(stat(Fullname, &Xstatb) < 0) {
                    459:                        fperrno("Cannot stat <%s>", Fullname);
                    460:                        exit(2);
                    461:                }
                    462:                if((Xstatb.st_mode&S_IFMT) != S_IFDIR) {
                    463:                        (void) fprintf(stderr, "<%s> is not a directory",
                    464:                            Fullname);
                    465:                        exit(2);
                    466:                }
                    467:                Dev = Xstatb.st_dev;
                    468:                if( Fullname[ strlen(Fullname) - 1 ] != '/' )
                    469:                        strcat(Fullname, "/");
                    470:                fullp = Fullname + strlen(Fullname);
                    471: 
                    472:                while(getname()) {
                    473:                        if (A_directory && !Dir)
                    474:                                fperr("Use `-d' option to copy <%s>",
                    475:                                        Hdr.h_name);
                    476:                        if(!ckname(Hdr.h_name))
                    477:                                continue;
                    478:                        i = 0;
                    479:                        while(Hdr.h_name[i] == '/')
                    480:                                i++;
                    481:                        strcpy(fullp, &(Hdr.h_name[i]));
                    482: 
                    483:                        if( PassLink  &&  !A_directory  &&  Dev == Statb.st_dev ) {
                    484:                                if(link(Hdr.h_name, Fullname) < 0) {
                    485:                                        switch(errno) {
                    486:                                                case ENOENT:
                    487:                                                        if(missdir(Fullname) != 0) {
                    488:                                                                fperrno("Cannot create directory for <%s>",
                    489:                                                                        Fullname);
                    490:                                                                continue;
                    491:                                                        }
                    492:                                                        break;
                    493:                                                case EEXIST:
                    494:                                                        if(unlink(Fullname) < 0) {
                    495:                                                                fperrno("Cannot unlink <%s>",
                    496:                                                                        Fullname);
                    497:                                                                continue;
                    498:                                                        }
                    499:                                                        break;
                    500:                                                default:
                    501:                                                        fperrno("Cannot link <%s> to <%s>",
                    502:                                                                Hdr.h_name, Fullname);
                    503:                                                        continue;
                    504:                                                }
                    505:                                        if(link(Hdr.h_name, Fullname) < 0) {
                    506:                                                fperrno("Cannot link <%s> to <%s>",
                    507:                                                        Hdr.h_name, Fullname);
                    508:                                                continue;
                    509:                                        }
                    510:                                }
                    511: 
                    512:                                goto ckverbose;
                    513:                        }
                    514:                        if( A_symlink ) {
                    515:                           symlsz = (int) mklong(Hdr.h_filesize);
                    516:                           if (readlink(Hdr.h_name, Symlbuf, symlsz) < 0) {
                    517:                                fperrno("Cannot read symbolic link <%s>",
                    518:                                    Hdr.h_name);
                    519:                                continue;
                    520:                           }
                    521:                           Symlbuf[symlsz] = '\0';
                    522:                           if(!openout(Fullname, Symlbuf))
                    523:                                continue;
                    524:                           Blocks += ((symlsz + (BUFSIZE - 1)) / BUFSIZE);
                    525:                           if(Verbose)
                    526:                                puts(Fullname);
                    527:                           continue;
                    528:                        }
                    529:                        if(!(Ofile = openout(Fullname, (char *)0)))
                    530:                                continue;
                    531:                        if((Ifile = open(Hdr.h_name, 0)) < 0) {
                    532:                                fperrno("Cannot open <%s>", Hdr.h_name);
                    533:                                close(Ofile);
                    534:                                continue;
                    535:                        }
                    536:                        filesz = Statb.st_size;
                    537:                        for(; filesz > 0; filesz -= CPIOBSZ) {
                    538:                                ct = filesz>CPIOBSZ? CPIOBSZ: filesz;
                    539:                                if(read(Ifile, Buf, ct) < 0) {
                    540:                                        fperrno("Cannot read %s", Hdr.h_name);
                    541:                                        break;
                    542:                                }
                    543:                                if(write(Ofile, Buf, ct) < 0) {
                    544:                                 fperrno("Cannot write %s", Hdr.h_name);
                    545:                                 break;
                    546:                                }
                    547:                                /* Removed u370 ifdef which caused cpio */
                    548:                                /* to report blocks in terms of 4096 bytes. */
                    549: 
                    550:                                Blocks += ((ct + (BUFSIZE - 1)) / BUFSIZE);
                    551:                        }
                    552:                        close(Ifile);
                    553:                        if(Acc_time) {
                    554:                                struct utimbuf utb;
                    555: 
                    556:                                utb.actime = Statb.st_atime;
                    557:                                utb.modtime = Statb.st_mtime;
                    558:                                (void)utime(Hdr.h_name, &utb);
                    559:                        }
                    560:                        if(Ofile) {
                    561:                                close(Ofile);
                    562:                                if(chmod(Fullname, Hdr.h_mode) < 0)
                    563:                                        fperrno("Cannot change mode of <%s>",
                    564:                                            Fullname);
                    565:                                set_time(Fullname, Statb.st_atime, mklong(Hdr.h_mtime));
                    566: ckverbose:
                    567:                                if(Verbose)
                    568:                                        puts(Fullname);
                    569:                        }
                    570:                }
                    571:        }
                    572:        /* print number of blocks actually copied */
                    573:        Blocks += ((sBlocks + (BUFSIZE - 1)) / BUFSIZE);
                    574:        (void) fprintf(stderr, "%ld blocks\n", Blocks * (Bufsize>>9));
                    575:        exit(0);
                    576: }
                    577: 
                    578: static
                    579: usage()
                    580: {
                    581:        (void) fprintf("Usage: %s\n     %s\n     %s\n     %s\n       %s\n",
                    582:            "cpio -o[acvB] <name-list >collection",
                    583:            "cpio -o[acvB] -Ocollection <name-list",
                    584:            "cpio -i[cdmrstuvfB6] [ pattern ... ] <collection",
                    585:            "cpio -i[cdmrstuvfB6] -Icollection [ pattern ... ]",
                    586:            "cpio -p[adlmruv] directory <name-list");
                    587: }
                    588: 
                    589: static
                    590: chkswfile( sp, c, option )
                    591: char   *sp;
                    592: char   c;
                    593: short  option;
                    594: {
                    595:        if( !option ) {
                    596:                fperr( "-%c must be specified before -%c option",
                    597:                        c == 'I' ? 'i' : 'o', c );
                    598:                exit(2);
                    599:        }
                    600:        if( (c == 'I'  &&  option != IN)  ||  (c == 'O'  &&  option != OUT) ) {
                    601:                fperr( "-%c option not permitted with -%c option", c,
                    602:                        option );
                    603:                exit(2);
                    604:        }
                    605:        if( !sp )
                    606:                return;
                    607:        fperr("No more than one -I or -O flag permitted");
                    608:        exit(2);
                    609: }
                    610: 
                    611: static
                    612: getname()              /* get file name, get info for header */
                    613: {
                    614:        register char *namep = Name;
                    615:        register ushort ftype;
                    616:        struct stat Lstatb;
                    617:        long tlong;
                    618: 
                    619:        for(;;) {
                    620:                if(gets(namep) == NULL)
                    621:                        return 0;
                    622:                while(*namep == '.' && namep[1] == '/') {
                    623:                        namep++;
                    624:                        while(*namep == '/') namep++;
                    625:                }
                    626:                strcpy(Hdr.h_name, namep);
                    627:                if(lstat(namep, &Statb) < 0) {
                    628:                        fperrno("Cannot stat <%s>", Hdr.h_name);
                    629:                        continue;
                    630:                }
                    631:                ftype = Statb.st_mode & Filetype;
                    632:                A_directory = (ftype == S_IFDIR);
                    633:                A_special = (ftype == S_IFBLK)
                    634:                        || (ftype == S_IFCHR)
                    635:                        || (ftype == S_IFIFO);
                    636:                A_symlink = (ftype == S_IFLNK);
                    637:                Hdr.h_magic = MAGIC;
                    638:                Hdr.h_namesize = strlen(Hdr.h_name) + 1;
                    639:                Hdr.h_uid = Statb.st_uid;
                    640:                Hdr.h_gid = Statb.st_gid;
                    641:                Hdr.h_dev = Statb.st_dev;
                    642:                Hdr.h_ino = Statb.st_ino;
                    643:                Hdr.h_mode = Statb.st_mode;
                    644:                MKSHORT(Hdr.h_mtime, Statb.st_mtime);
                    645:                Hdr.h_nlink = Statb.st_nlink;
                    646:                tlong = ((Hdr.h_mode&S_IFMT) == S_IFREG ||
                    647:                        (Hdr.h_mode&S_IFMT) == S_IFLNK)? Statb.st_size: 0L;
                    648:                MKSHORT(Hdr.h_filesize, tlong);
                    649:                Hdr.h_rdev = Statb.st_rdev;
                    650:                if( Cflag )
                    651:                        bintochar(tlong);
                    652:                return 1;
                    653:        }
                    654: }
                    655: 
                    656: static
                    657: bintochar(t)           /* ASCII header write */
                    658: long t;
                    659: {
                    660:        sprintf(Chdr,"%.6o%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.11lo%.6ho%.11lo%s",
                    661:                MAGIC, MK_USHORT(Statb.st_dev), MK_USHORT(Statb.st_ino), Statb.st_mode, Statb.st_uid,
                    662:                Statb.st_gid, Statb.st_nlink, MK_USHORT(Statb.st_rdev),
                    663:                Statb.st_mtime, (short)strlen(Hdr.h_name)+1, t, Hdr.h_name);
                    664: }
                    665: 
                    666: static
                    667: chartobin()            /* ASCII header read */
                    668: {
                    669:        sscanf(Chdr, "%6ho%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6ho%11lo",
                    670:                &Hdr.h_magic, &Hdr.h_dev, &Hdr.h_ino, &Hdr.h_mode, &Hdr.h_uid,
                    671:                &Hdr.h_gid, &Hdr.h_nlink, &Hdr.h_rdev, &Longtime,
                    672:                &Hdr.h_namesize, &Longfile);
                    673:        MKSHORT(Hdr.h_filesize, Longfile);
                    674:        MKSHORT(Hdr.h_mtime, Longtime);
                    675: }
                    676: 
                    677: 
                    678: /*     Check the header for the magic number.  Switch modes automatically to
                    679:        match the type of header found.
                    680: */
                    681: static
                    682: chkhdr()
                    683: {
                    684:        bread(Chdr, CHARS);
                    685:        chartobin();
                    686:        if( Hdr.h_magic == MAGIC )
                    687:                Cflag = 1;
                    688:        else {
                    689:                breread(&Hdr.h_magic, sizeof Hdr.h_magic);
                    690:                if( Hdr.h_magic == MAGIC || Hdr.h_magic == (short)BSMAGIC )
                    691:                        Cflag = 0;
                    692:                else {
                    693:                        fperr("This is not a cpio file.  Bad magic number.");
                    694:                        exit(2);
                    695:                }
                    696:        }
                    697:        breread(Chdr, 0);
                    698: }
                    699: 
                    700: 
                    701: static
                    702: gethdr()               /* get file headers */
                    703: {
                    704:        register ushort ftype;
                    705: 
                    706:        if (Cflag)  {
                    707:                bread(Chdr, CHARS);
                    708:                chartobin();
                    709:        }
                    710:        else
                    711:                bread(&Hdr, HDRSIZE);
                    712: 
                    713:        if(Hdr.h_magic == (short)BSMAGIC)
                    714:                swap((char *)&Hdr, HDRSIZE, 1, 0);
                    715:        else if( Hdr.h_magic != MAGIC ) {
                    716:                fperr("Out of phase--get help");
                    717:                exit(2);
                    718:        }
                    719:        bread(Hdr.h_name, Hdr.h_namesize);
                    720:        if(EQ(Hdr.h_name, "TRAILER!!!"))
                    721:                return 0;
                    722:        ftype = Hdr.h_mode & Filetype;
                    723:        A_directory = (ftype == S_IFDIR);
                    724:        A_special = (ftype == S_IFBLK)
                    725:                ||  (ftype == S_IFCHR)
                    726:                ||  (ftype == S_IFIFO);
                    727:        A_symlink = (ftype == S_IFLNK);
                    728:        return 1;
                    729: }
                    730: 
                    731: static
                    732: ckname(namep)  /* check filenames with patterns given on cmd line */
                    733: register char *namep;
                    734: {
                    735:        char    buf[sizeof Hdr.h_name];
                    736: 
                    737:        if(fflag ^ !nmatch(namep, Pattern)) {
                    738:                return 0;
                    739:        }
                    740:        if(Rename && !A_directory) {    /* rename interactively */
                    741:                fprintf(Wtty, "Rename <%s>\n", namep);
                    742:                fflush(Wtty);
                    743:                fgets(buf, sizeof buf, Rtty);
                    744:                if(feof(Rtty))
                    745:                        exit(2);
                    746:                buf[strlen(buf) - 1] = '\0';
                    747:                if(EQ(buf, "")) {
                    748:                        strcpy(namep,buf);
                    749:                        printf("Skipped\n");
                    750:                        return 0;
                    751:                }
                    752:                else if(EQ(buf, "."))
                    753:                        printf("Same name\n");
                    754:                else
                    755:                        strcpy(namep,buf);
                    756:        }
                    757:        return  1;
                    758: }
                    759: 
                    760: static
                    761: openout(namep, symlname)       /* open files for writing, set all necessary info */
                    762: register char *namep;
                    763: char *symlname;
                    764: {
                    765:        register f;
                    766:        register char *np;
                    767:        int ans;
                    768: 
                    769:        if(!strncmp(namep, "./", 2))
                    770:                namep += 2;
                    771:        np = namep;
                    772:        if(A_directory) {
                    773:                if( !Dir  ||  Rename  ||  EQ(namep, ".")  ||  EQ(namep, "..") )
                    774:                        /* do not consider . or .. files */
                    775:                        return 0;
                    776:                if(stat(namep, &Xstatb) == -1) {
                    777: 
                    778: /* try creating (only twice) */
                    779:                        ans = 0;
                    780:                        do {
                    781:                                if(mkdir(namep, Hdr.h_mode) != 0) {
                    782:                                        ans += 1;
                    783:                                }else {
                    784:                                        ans = 0;
                    785:                                        break;
                    786:                                }
                    787:                        }while(ans < 2 && missdir(namep) == 0);
                    788:                        if(ans == 1) {
                    789:                                fperrno("Cannot create directory for <%s>",
                    790:                                        namep);
                    791:                                return(0);
                    792:                        }else if(ans == 2) {
                    793:                                fperrno("Cannot create directory <%s>", namep);
                    794:                                return(0);
                    795:                        }
                    796:                }
                    797: 
                    798: ret:
                    799:                if(chmod(namep, Hdr.h_mode) < 0)
                    800:                        fperrno("Cannot change mode of <%s>", namep);
                    801:                if(Uid == 0)
                    802:                        if(chown(namep, Hdr.h_uid, Hdr.h_gid) < 0)
                    803:                                fperrno("Cannot change ownership of <%s>",
                    804:                                    namep);
                    805:                set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
                    806:                return 0;
                    807:        }
                    808:        if(Hdr.h_nlink > 1)
                    809:                if(!postml(namep, np))
                    810:                        return 0;
                    811:        if(lstat(namep, &Xstatb) == 0) {
                    812:                if(Uncond && !((!(Xstatb.st_mode & S_IWRITE) || A_special) && (Uid != 0))) {
                    813:                        if(unlink(namep) < 0) {
                    814:                                fperrno("cannot unlink current <%s>", namep);
                    815:                        }
                    816:                }
                    817:                if(!Uncond && (mklong(Hdr.h_mtime) <= Xstatb.st_mtime)) {
                    818:                /* There's a newer or same aged version of file on destination */
                    819:                        fperr("current <%s> newer or same age", np);
                    820:                        return 0;
                    821:                }
                    822:        }
                    823:        if( Option == PASS
                    824:                && Hdr.h_ino == Xstatb.st_ino
                    825:                && Hdr.h_dev == Xstatb.st_dev) {
                    826:                fperr("Attempt to pass file to self!");
                    827:                exit(2);
                    828:        }
                    829:        if(A_symlink) {
                    830: /* try symlinking (only twice) */
                    831:                ans = 0;
                    832:                do {
                    833:                        if(symlink(
                    834: symlname, namep) < 0) {
                    835:                                ans += 1;
                    836:                        }else {
                    837:                                ans = 0;
                    838:                                break;
                    839:                        }
                    840:                }while(ans < 2 && missdir(np) == 0);
                    841:                if(ans == 1) {
                    842:                        fperrno("Cannot create directory for <%s>", namep);
                    843:                        return(0);
                    844:                }else if(ans == 2) {
                    845:                        fperrno("Cannot symlink <%s> and <%s>", namep, symlname);
                    846:                        return(0);
                    847:                }
                    848: 
                    849:                return 0;
                    850:        }
                    851:        if(A_special) {
                    852:                if((Hdr.h_mode & Filetype) == S_IFIFO)
                    853:                        Hdr.h_rdev = 0;
                    854: 
                    855: /* try creating (only twice) */
                    856:                ans = 0;
                    857:                do {
                    858:                        if(mknod(namep, Hdr.h_mode, Hdr.h_rdev) < 0) {
                    859:                                ans += 1;
                    860:                        }else {
                    861:                                ans = 0;
                    862:                                break;
                    863:                        }
                    864:                }while(ans < 2 && missdir(np) == 0);
                    865:                if(ans == 1) {
                    866:                        fperrno("Cannot create directory for <%s>", namep);
                    867:                        return(0);
                    868:                }else if(ans == 2) {
                    869:                        fperrno("Cannot mknod <%s>", namep);
                    870:                        return(0);
                    871:                }
                    872: 
                    873:                goto ret;
                    874:        }
                    875: 
                    876: /* try creating (only twice) */
                    877:        ans = 0;
                    878:        do {
                    879:                if((f = creat(namep, Hdr.h_mode)) < 0) {
                    880:                        ans += 1;
                    881:                }else {
                    882:                        ans = 0;
                    883:                        break;
                    884:                }
                    885:        }while(ans < 2 && missdir(np) == 0);
                    886:        if(ans == 1) {
                    887:                fperrno("Cannot create directory for <%s>", namep);
                    888:                return(0);
                    889:        }else if(ans == 2) {
                    890:                fperrno("Cannot create <%s>", namep);
                    891:                return(0);
                    892:        }
                    893: 
                    894:        if(Uid == 0)
                    895:                if(chown(namep, Hdr.h_uid, Hdr.h_gid) < 0)
                    896:                        fperrno("Cannot change ownership of <%s>", namep);
                    897:        return f;
                    898: }
                    899: 
                    900: 
                    901: /*     Shared by bread() and breread()
                    902: */
                    903: static int     nleft = 0;      /* unread chars left in Cbuf */
                    904: static char    *ip;            /* pointer to next char to be read from Cbuf */
                    905: 
                    906: /*     Reread the current buffer Cbuf.
                    907:        A character count, c, of 0 simply resets the pointer so next bread gets
                    908:        the same data again.
                    909: */
                    910: static
                    911: breread(b, c)
                    912: char   *b;
                    913: int    c;
                    914: {
                    915:        ip = Cbuf;
                    916:        if( nleft )
                    917:                nleft = Bufsize;
                    918:        if( !c )
                    919:                return;
                    920:        bread(b, c);
                    921: }
                    922: 
                    923: static
                    924: bread(b, c)
                    925: register char  *b;
                    926: register int   c;
                    927: {
                    928:        register int    rv;
                    929:        register char   *p = ip;
                    930: 
                    931:        if( !Cflag ) {
                    932:                /* round c up to an even number */
                    933:                c = (c+1)/2;
                    934:                c *= 2;
                    935:        }
                    936:        while( c )  {
                    937:                if( nleft == 0 ) {
                    938:                        while( (rv = read(Input, Cbuf, Bufsize)) == 0 ) {
                    939:                                Input = chgreel(0, Input, rv);
                    940:                        }
                    941:                        if( rv == Bufsize ) {
                    942:                                nleft = Bufsize;
                    943:                                p = Cbuf;
                    944:                                ++Blocks;
                    945:                        }
                    946:                        else if( rv == -1 ) {
                    947:                                fperrno("Read error on archive");
                    948:                                exit(2);
                    949:                        }
                    950:                        else if( rv < Bufsize ) {       /* short read */
                    951:                                smemcpy( &Cbuf[ Bufsize - rv ], Cbuf, rv );
                    952:                                nleft = rv;
                    953:                                p = &Cbuf[ Bufsize - rv ];
                    954:                                sBlocks += rv;
                    955:                        }
                    956:                }
                    957:                if( nleft <= c ) {
                    958:                        memcpy( b, p, nleft );
                    959:                        c -= nleft;
                    960:                        b += nleft;
                    961:                        p += nleft;
                    962:                        nleft = 0;
                    963:                }
                    964:                else {
                    965:                        memcpy( b, p, c );
                    966:                        nleft -= c;
                    967:                        b += c;
                    968:                        p += c;
                    969:                        c = 0;
                    970:                }
                    971:        }
                    972:        ip = p;
                    973: }
                    974: 
                    975: 
                    976: static
                    977: bwrite(rp, c)
                    978: register char *rp;
                    979: register c;
                    980: {
                    981:        register char   *cp = Cp;
                    982:        static unsigned Ccnt = 0;
                    983:        register unsigned Cleft;
                    984:        register int    rv;
                    985: 
                    986:        if( !Cflag ) {
                    987:                /* round c up to an even number */
                    988:                c = (c+1)/2;
                    989:                c *= 2;
                    990:        }
                    991:        while( c )  {
                    992:                if( (Cleft = Bufsize - Ccnt) <= c ) {
                    993:                        memcpy( cp, rp, Cleft );
                    994:                        rv = write(Output, Cbuf, Bufsize);
                    995:                        if( rv == 0  ||  ( rv == -1  &&  errno == ENXIO ) ) {
                    996:                                rv = eomchgreel();
                    997:                        }
                    998:                        if( rv == Bufsize ) {
                    999:                                Ccnt = 0;
                   1000:                                cp = Cbuf;
                   1001:                        }
                   1002:                        else if( rv == -1 ) {
                   1003:                                fperrno("Write error on archive");
                   1004:                                exit(2);
                   1005:                        }
                   1006:                        else if( rv < Bufsize ) {
                   1007:                                Output = chgreel(1, Output, 0);
                   1008:                                smemcpy( Cbuf, &Cbuf[ Bufsize - rv ], rv );
                   1009:                                Ccnt = Bufsize - rv;
                   1010:                                cp = &Cbuf[ rv ];
                   1011:                        }
                   1012:                        ++Blocks;
                   1013:                        rp += Cleft;
                   1014:                        c -= Cleft;
                   1015:                }
                   1016:                else {
                   1017:                        memcpy( cp, rp, c );
                   1018:                        Ccnt += c;
                   1019:                        cp += c;
                   1020:                        rp += c;
                   1021:                        c = 0;
                   1022:                }
                   1023:        }
                   1024:        Cp = cp;
                   1025: }
                   1026: 
                   1027: 
                   1028: static int     reelcount = 1;  /* used below and in chgreel() */
                   1029: 
                   1030: /*     Change reel due to reaching end-of-media.
                   1031:        Keep trying to get a successful write before considering the
                   1032:        change-of-reel as successful.
                   1033: */
                   1034: static
                   1035: int
                   1036: eomchgreel()
                   1037: {
                   1038:        int     rv;
                   1039: 
                   1040:        while( 1 ) {
                   1041:                Output = chgreel(1, Output, 0);
                   1042:                rv = write(Output, Cbuf, Bufsize);
                   1043:                if( rv == Bufsize )
                   1044:                        return  rv;
                   1045:                if( rv == -1 )
                   1046:                        fperrno( "Unable to write this medium" );
                   1047:                else
                   1048:                        fperr( "Unable to write this medium: Premature EOF" );
                   1049:                (void) fprintf(stderr, "Try again.\n");
                   1050:                reelcount--;
                   1051:        }
                   1052:        /*NOTREACHED*/
                   1053: }
                   1054: 
                   1055: 
                   1056: static
                   1057: postml(namep, np)              /* linking funtion:  Postml() is called after */
                   1058: register char *namep, *np;     /* namep is created.  Postml() checks to see  */
                   1059: {                              /* if namep should be linked to np.  If so,   */
                   1060:                                /* postml() removes the independent instance  */
                   1061:        register i;             /* of namep and links namep to np.            */
                   1062:        static struct ml {
                   1063:                short   m_dev;
                   1064:                ushort  m_ino;
                   1065:                char    m_name[2];
                   1066:        } **ml = 0;
                   1067:        register struct ml      *mlp;
                   1068:        static unsigned mlsize = 0;
                   1069:        static unsigned mlinks = 0;
                   1070:        char            *lnamep;
                   1071:        int             ans;
                   1072: 
                   1073:        if( !ml ) {
                   1074:                mlsize = LINKS;
                   1075:                ml = (struct ml **) malloc(mlsize * sizeof(struct ml));
                   1076:        }
                   1077:        else if( mlinks == mlsize ) {
                   1078:                mlsize += LINKS;
                   1079:                ml = (struct ml **) realloc((char *) ml,
                   1080:                    mlsize * sizeof(struct ml));
                   1081:        }
                   1082:        if (ml == NULL) {
                   1083:                fperr("Out of memory for links");
                   1084:                exit(2);
                   1085:        }
                   1086:        for(i = 0; i < mlinks; ++i) {
                   1087:                mlp = ml[i];
                   1088:                if(mlp->m_ino==Hdr.h_ino  &&  mlp->m_dev==Hdr.h_dev) {
                   1089:                        if(Verbose)
                   1090:                          printf("%s linked to %s\n", ml[i]->m_name,
                   1091:                                np);
                   1092:                        unlink(namep);
                   1093:                        if(Option == IN && *(mlp->m_name) != '/') {
                   1094:                                Fullname[Pathend] = '\0';
                   1095:                                strcat(Fullname, mlp->m_name);
                   1096:                                lnamep = Fullname;
                   1097:                        }
                   1098:                        lnamep = mlp->m_name;
                   1099: 
                   1100: /* try linking (only twice) */
                   1101:                        ans = 0;
                   1102:                        do {
                   1103:                                if(link(lnamep, namep) < 0) {
                   1104:                                        ans += 1;
                   1105:                                }else {
                   1106:                                        ans = 0;
                   1107:                                        break;
                   1108:                                }
                   1109:                        }while(ans < 2 && missdir(np) == 0);
                   1110:                        if(ans == 1) {
                   1111:                                fperrno("Cannot create directory for <%s>", np);
                   1112:                                return(0);
                   1113:                        }else if(ans == 2) {
                   1114:                                fperrno("Cannot link <%s> & <%s>", lnamep, np);
                   1115:                                return(0);
                   1116:                        }
                   1117: 
                   1118:                        set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
                   1119:                        return 0;
                   1120:                }
                   1121:        }
                   1122:        if( !(ml[mlinks] = (struct ml *)malloc(strlen(np) + 2 + sizeof(struct ml)))) {
                   1123:                static int first=1;
                   1124: 
                   1125:                if(first)
                   1126:                        fperr("Out of memory for links");
                   1127:                first = 0;
                   1128:                return 1;
                   1129:        }
                   1130:        ml[mlinks]->m_dev = Hdr.h_dev;
                   1131:        ml[mlinks]->m_ino = Hdr.h_ino;
                   1132:        strcpy(ml[mlinks]->m_name, np);
                   1133:        ++mlinks;
                   1134:        return 1;
                   1135: }
                   1136: 
                   1137: static
                   1138: pentry(namep)          /* print verbose table of contents */
                   1139: register char *namep;
                   1140: {
                   1141: 
                   1142:        static short lastid = -1;
                   1143: #include <pwd.h>
                   1144:        static struct passwd *pw;
                   1145:        struct passwd *getpwuid();
                   1146:        static char tbuf[32];
                   1147:        char *ctime();
                   1148: 
                   1149:        printf("%-7o", MK_USHORT(Hdr.h_mode));
                   1150:        if(lastid == Hdr.h_uid)
                   1151:                printf("%-6s", pw->pw_name);
                   1152:        else {
                   1153:                setpwent();
                   1154:                if(pw = getpwuid((int)Hdr.h_uid)) {
                   1155:                        printf("%-6s", pw->pw_name);
                   1156:                        lastid = Hdr.h_uid;
                   1157:                } else {
                   1158:                        printf("%-6d", Hdr.h_uid);
                   1159:                        lastid = -1;
                   1160:                }
                   1161:        }
                   1162:        printf("%7ld ", mklong(Hdr.h_filesize));
                   1163:        U.l = mklong(Hdr.h_mtime);
                   1164:        strcpy(tbuf, ctime((long *)&U.l));
                   1165:        tbuf[24] = '\0';
                   1166:        printf(" %s  %s", &tbuf[4], namep);
                   1167:        if (A_symlink)
                   1168:                printf(" -> %s", Symlbuf);
                   1169:        putchar('\n');
                   1170: }
                   1171: 
                   1172:                /* pattern matching functions */
                   1173: static
                   1174: nmatch(s, pat)
                   1175: char *s, **pat;
                   1176: {
                   1177:        if( !pat )
                   1178:                return 1;
                   1179:        while(*pat) {
                   1180:                if((**pat == '!' && !gmatch(s, *pat+1))
                   1181:                || gmatch(s, *pat))
                   1182:                        return 1;
                   1183:                ++pat;
                   1184:        }
                   1185:        return 0;
                   1186: }
                   1187: 
                   1188: 
                   1189: static
                   1190: gmatch(s, p)
                   1191: register char *s, *p;
                   1192: {
                   1193:        register int c;
                   1194:        register cc, ok, lc, scc;
                   1195: 
                   1196:        scc = *s;
                   1197:        lc = 077777;
                   1198:        switch (c = *p) {
                   1199: 
                   1200:        case '[':
                   1201:                ok = 0;
                   1202:                while (cc = *++p) {
                   1203:                        switch (cc) {
                   1204: 
                   1205:                        case ']':
                   1206:                                if (ok)
                   1207:                                        return(gmatch(++s, ++p));
                   1208:                                else
                   1209:                                        return(0);
                   1210: 
                   1211:                        case '-':
                   1212:                                ok |= ((lc <= scc) && (scc <= (cc=p[1])));
                   1213:                        }
                   1214:                        if (scc==(lc=cc)) ok++;
                   1215:                }
                   1216:                return(0);
                   1217: 
                   1218:        case '?':
                   1219:        caseq:
                   1220:                if(scc) return(gmatch(++s, ++p));
                   1221:                return(0);
                   1222:        case '*':
                   1223:                return(umatch(s, ++p));
                   1224:        case 0:
                   1225:                return(!scc);
                   1226:        }
                   1227:        if (c==scc) goto caseq;
                   1228:        return(0);
                   1229: }
                   1230: 
                   1231: 
                   1232: 
                   1233: static
                   1234: umatch(s, p)
                   1235: register char *s, *p;
                   1236: {
                   1237:        if(*p==0) return(1);
                   1238:        while(*s)
                   1239:                if (gmatch(s++,p)) return(1);
                   1240:        return(0);
                   1241: }
                   1242: 
                   1243: swap(buf, bytecount, bytes, halfwords) /* swap halfwords, bytes or both */
                   1244: char *buf;
                   1245: int bytecount;
                   1246: int bytes, halfwords;
                   1247: {
                   1248:        register int count;
                   1249:        int n, i;
                   1250: 
                   1251:        if(bytes) {
                   1252:                register union swpbytes {
                   1253:                        short   shortw;
                   1254:                        char    charv[2];
                   1255:                } *pbuf;
                   1256:                register char c;
                   1257: 
                   1258:                count = bytecount;
                   1259:                pbuf = (union swpbytes *)buf;
                   1260:                if (count % sizeof(union swpbytes))
                   1261:                        pbuf->charv[count] = 0;
                   1262:                count = (count + (sizeof(union swpbytes) - 1)) / sizeof(union swpbytes);
                   1263:                while (count--) {
                   1264:                        c = pbuf->charv[0];
                   1265:                        pbuf->charv[0] = pbuf->charv[1];
                   1266:                        pbuf->charv[1] = c;
                   1267:                        ++pbuf;
                   1268:                }
                   1269:        }
                   1270:        if (halfwords) {
                   1271:                register union swphalf {
                   1272:                        long    longw;
                   1273:                        short   shortv[2];
                   1274:                        char    charv[4];
                   1275:                } *pbuf;
                   1276:                register short cc;
                   1277: 
                   1278:                count = bytecount;
                   1279:                pbuf = (union swphalf *)buf;
                   1280:                if (n = count % sizeof(union swphalf))
                   1281:                        if(bytes && n % 2)
                   1282:                                for(i = count + 1; i <= count + (sizeof(union swphalf) - n); i++)
                   1283:                                        pbuf->charv[i] = 0;
                   1284:                        else
                   1285:                                for (i = count; i < count + (sizeof(union swphalf) - n); i++)
                   1286:                                        pbuf->charv[i] = 0;
                   1287:                count = (count + (sizeof(union swphalf) - 1)) / sizeof(union swphalf);
                   1288:                while (count--) {
                   1289:                        cc = pbuf->shortv[0];
                   1290:                        pbuf->shortv[0] = pbuf->shortv[1];
                   1291:                        pbuf->shortv[1] = cc;
                   1292:                        ++pbuf;
                   1293:                }
                   1294:        }
                   1295: }
                   1296: 
                   1297: 
                   1298: static
                   1299: set_time(namep, atime, mtime)  /* set access and modification times */
                   1300: register char *namep;
                   1301: time_t atime, mtime;
                   1302: {
                   1303:        static struct utimbuf timevec;
                   1304: 
                   1305:        if(!Mod_time)
                   1306:                return;
                   1307:        timevec.actime = atime;
                   1308:        timevec.modtime = mtime;
                   1309:        (void)utime(namep, &timevec);
                   1310: }
                   1311: 
                   1312: 
                   1313: 
                   1314: static
                   1315: chgreel(x, fl, rv)
                   1316: {
                   1317:        register f;
                   1318:        char str[BUFSIZ];
                   1319:        struct stat statb;
                   1320: 
                   1321:        fstat(fl, &statb);
                   1322:        if((statb.st_mode&S_IFMT) != S_IFCHR) {
                   1323:                fperrno("Can't %s: ", x? "write output": "read input");
                   1324:                exit(2);
                   1325:        }
                   1326:        if( rv == 0  ||
                   1327:                ( rv == -1  &&  ( errno == ENOSPC  ||  errno == ENXIO ) ) )
                   1328:                fperr( "\007Reached end of medium on %s",
                   1329:                        x? "output":"input" );
                   1330:        else {
                   1331:                fperrno( "\007Encountered an error on %s",
                   1332:                        x? "output":"input" );
                   1333:                exit(2);
                   1334:        }
                   1335:        if( Rtty == NULL ) {
                   1336:                Rtty = fopen(ttyname, "r");
                   1337:                if( Rtty == NULL ) {
                   1338:                        fperrno("Cannot prompt (can't open %s)", ttyname);
                   1339:                        exit(2);
                   1340:                }
                   1341:        }
                   1342:        close(fl);
                   1343:        reelcount++;
                   1344: again:
                   1345:        if( swfile ) {
                   1346:            askagain:
                   1347:                fperr( eommsg, reelcount );
                   1348:                fgets(str, sizeof str, Rtty);
                   1349:                switch( *str ) {
                   1350:                case '\n':
                   1351:                        strcpy( str, swfile );
                   1352:                        break;
                   1353:                case 'q':
                   1354:                        exit(2);
                   1355:                default:
                   1356:                        goto askagain;
                   1357:                }
                   1358:        }
                   1359:        else {
                   1360:                fperr("If you want to go on, type device/file name when ready.");
                   1361:                fgets(str, sizeof str, Rtty);
                   1362:                str[strlen(str) - 1] = '\0';
                   1363:                if(!*str)
                   1364:                        exit(2);
                   1365:        }
                   1366:        if((f = open(str, x? 1: 0)) < 0) {
                   1367:                fperrno("Can't open <%s>", str);
                   1368:                goto again;
                   1369:        }
                   1370:        return f;
                   1371: }
                   1372: 
                   1373: 
                   1374: 
                   1375: static
                   1376: missdir(namep)
                   1377: register char *namep;
                   1378: {
                   1379:        register char *np;
                   1380:        register ct = 2;
                   1381: 
                   1382:        for(np = namep; *np; ++np)
                   1383:                if(*np == '/') {
                   1384:                        if(np == namep) continue;       /* skip over 'root slash' */
                   1385:                        *np = '\0';
                   1386:                        if(stat(namep, &Xstatb) == -1) {
                   1387:                                if(Dir) {
                   1388:                                        if((ct = mkdir(namep, 0777)) != 0) {
                   1389:                                                *np = '/';
                   1390:                                                return(ct);
                   1391:                                        }
                   1392:                                }else {
                   1393:                                        fperr("missing 'd' option");
                   1394:                                        return(-1);
                   1395:                                }
                   1396:                        }
                   1397:                        *np = '/';
                   1398:                }
                   1399:        if (ct == 2) ct = 0;            /* the file already exists */
                   1400:        return ct;
                   1401: }
                   1402: 
                   1403: 
                   1404: 
                   1405: static
                   1406: pwd()          /* get working directory */
                   1407: {
                   1408:        if (getwd(Fullname) == 0) {
                   1409:                (void)fprintf(stderr, "cpio: %s\n",
                   1410:                    Fullname);
                   1411:                exit(2);
                   1412:        }
                   1413:        Pathend = strlen(Fullname);
                   1414:        Fullname[Pathend++] = '/';
                   1415:        Fullname[Pathend] = '\0';
                   1416: }
                   1417: 
                   1418: 
                   1419: /*
                   1420:        print message on the stderr
                   1421: */
                   1422: static
                   1423: fperr( va_alist )
                   1424: va_dcl
                   1425: {
                   1426:        va_list args;
                   1427:        char    *fmt;
                   1428: 
                   1429:        va_start( args );
                   1430:        fprintf( stderr, "cpio: ");
                   1431:        fmt = va_arg( args, char * );
                   1432:        vfprintf( stderr, fmt, args );
                   1433:        putc( '\n', stderr);
                   1434:        fflush( stderr );
                   1435: }
                   1436: 
                   1437: /*
                   1438:        print message on the stderr followed by error number and meaning.
                   1439: */
                   1440: static
                   1441: fperrno( va_alist )
                   1442: va_dcl
                   1443: {
                   1444:        va_list args;
                   1445:        char    *fmt;
                   1446: 
                   1447:        va_start( args );
                   1448:        fprintf( stderr, "cpio: ");
                   1449:        fmt = va_arg( args, char * );
                   1450:        vfprintf( stderr, fmt, args );
                   1451:        fprintf( stderr, ": " );
                   1452:        fflush( stderr );
                   1453:        perror("");
                   1454: }
                   1455: 
                   1456: 
                   1457: /*     Safe memory copy.
                   1458:        Fast if the to and from strings do not overlap,
                   1459:        slower but safe if they do.
                   1460: */
                   1461: 
                   1462: static char *
                   1463: smemcpy( to, from, count )
                   1464: register char          *to, *from;
                   1465: register unsigned      count;
                   1466: {
                   1467:        char    *savedto;
                   1468: 
                   1469:        if( &to[ count ] <= from  ||  &from[ count ] <= to )
                   1470:                return  memcpy( to, from, count );
                   1471: 
                   1472:        if( to == from )
                   1473:                return  to;
                   1474: 
                   1475:        savedto = to;
                   1476:        if( to < from )
                   1477:                while( count-- )
                   1478:                        *(to++) = *(from++);
                   1479:        else {
                   1480:                to += count;
                   1481:                from += count;
                   1482:                while( count-- )
                   1483:                        *(--to) = *(--from);
                   1484:        }
                   1485: 
                   1486:        return  savedto;
                   1487: }
                   1488: 
                   1489: extern int _doprnt();
                   1490: 
                   1491: /*VARARGS2*/
                   1492: int
                   1493: vfprintf(iop, format, ap)
                   1494: FILE *iop;
                   1495: char *format;
                   1496: va_list ap;
                   1497: {
                   1498:        register int count;
                   1499: 
                   1500:        if (!(iop->_flag | _IOWRT)) {
                   1501:                /* if no write flag */
                   1502:                if (iop->_flag | _IORW) {
                   1503:                        /* if ok, cause read-write */
                   1504:                        iop->_flag |= _IOWRT;
                   1505:                } else {
                   1506:                        /* else error */
                   1507:                        return EOF;
                   1508:                }
                   1509:        }
                   1510:        count = _doprnt(format, ap, iop);
                   1511:        return(ferror(iop)? EOF: count);
                   1512: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.