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

unix.superglobalmegacorp.com

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