Annotation of coherent/d/usr/bin/pax/shipping/create.c, revision 1.1.1.1

1.1       root        1: /* $Source: /newbits/usr/bin/pax/shipping/RCS/create.c,v $
                      2:  *
                      3:  * $Revision: 1.2 $
                      4:  *
                      5:  * create.c - Create a tape archive. 
                      6:  *
                      7:  * DESCRIPTION
                      8:  *
                      9:  *     These functions are used to create/write and archive from an set of
                     10:  *     named files.
                     11:  *
                     12:  * AUTHOR
                     13:  *
                     14:  *             Mark H. Colburn, NAPS International ([email protected])
                     15:  *
                     16:  * Sponsored by The USENIX Association for public distribution. 
                     17:  *
                     18:  * Copyright (c) 1989 Mark H. Colburn.
                     19:  * All rights reserved.
                     20:  *
                     21:  * Redistribution and use in source and binary forms are permitted
                     22:  * provided that the above copyright notice is duplicated in all such 
                     23:  * forms and that any documentation, advertising materials, and other 
                     24:  * materials related to such distribution and use acknowledge that the 
                     25:  * software was developed * by Mark H. Colburn and sponsored by The 
                     26:  * USENIX Association. 
                     27:  *
                     28:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     29:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     30:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     31:  *
                     32:  * $Log:       create.c,v $
                     33:  * Revision 1.2  91/11/11  15:33:03  bin
                     34:  * update by vlad to fix bug with long filenames and SV/posix readability
                     35:  * 
                     36:  * Revision 1.1        91/02/05  11:55:38      bin
                     37:  * Initial revision
                     38:  * 
                     39:  * Revision 1.3  89/02/12  10:29:37  mark
                     40:  * Fixed misspelling of Replstr
                     41:  * 
                     42:  * Revision 1.2  89/02/12  10:04:17  mark
                     43:  * 1.2 release fixes
                     44:  * 
                     45:  * Revision 1.1  88/12/23  18:02:06  mark
                     46:  * Initial revision
                     47:  * 
                     48:  */
                     49: 
                     50: #ifndef lint
                     51: static char *ident = "$Id: create.c,v 1.2 91/11/11 15:33:03 bin Exp Locker: bin $";
                     52: static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
                     53: #endif /* ! lint */
                     54: 
                     55: 
                     56: /* Headers */
                     57: 
                     58: #include "pax.h"
                     59: 
                     60: 
                     61: /* Function Prototypes */
                     62: 
                     63: #if __STDC__
                     64: 
                     65: static void writetar(char *, Stat *);
                     66: static void writecpio(char *, Stat *);
                     67: static char tartype(int);
                     68: 
                     69: #else /* !__STDC__ */
                     70: 
                     71: static void writetar();
                     72: static void writecpio();
                     73: static char tartype();
                     74: 
                     75: #endif /* __STDC__ */
                     76: 
                     77: 
                     78: /* create_archive - create a tar archive.
                     79:  *
                     80:  * DESCRIPTION
                     81:  *
                     82:  *     Create_archive is used as an entry point to both create and append
                     83:  *     archives.  Create archive goes through the files specified by the
                     84:  *     user and writes each one to the archive if it can.  Create_archive
                     85:  *     knows how to write both cpio and tar headers and the padding which
                     86:  *     is needed for each type of archive.
                     87:  *
                     88:  * RETURNS
                     89:  *
                     90:  *     Always returns 0
                     91:  */
                     92: 
                     93: #if __STDC__
                     94: 
                     95: int create_archive(void)
                     96: 
                     97: #else
                     98: 
                     99: int create_archive()
                    100: 
                    101: #endif
                    102: {
                    103:     char            name[PATH_MAX + 1];
                    104:     Stat            sb;
                    105:     int             fd;
                    106: 
                    107:     while (name_next(name, &sb) != -1) {
                    108:        if ((fd = openin(name, &sb)) < 0) {
                    109:            /* FIXME: pax wants to exit here??? */
                    110:            continue;
                    111:        }
                    112:        if (rplhead != (Replstr *)NULL) {
                    113:            rpl_name(name);
                    114:            if (strlen(name) == 0) {
                    115:                continue;
                    116:            }
                    117:        }
                    118:        if (get_disposition("add", name) || get_newname(name, sizeof(name))) {
                    119:            /* skip file... */
                    120:            if (fd) {
                    121:                close(fd);
                    122:            }
                    123:            continue;
                    124:        } 
                    125: 
                    126:        if (!f_link && sb.sb_nlink > 1) {
                    127:            if (islink(name, &sb)) {
                    128:                sb.sb_size = 0;
                    129:            }
                    130:            linkto(name, &sb);
                    131:        }
                    132:        if (ar_format == TAR) {
                    133:            /* SV tar does not understand POSIX tar header.
                    134:             * Trailing '/' in directory name alows SV tar to unarchive
                    135:             * POSIX tar archive. So, we add '/' to the "name" if it is
                    136:             * a directory name.
                    137:             * SV tar will produce error messages, but
                    138:             * will do the job. Vlad 11-8-91
                    139:             */
                    140:            if ((sb.sb_stat.st_mode & S_IFMT) == S_IFDIR) {
                    141:                int     il;
                    142:                
                    143:                il = strlen(name);
                    144:                name[il++] = '/';
                    145:                name[il] = 0;
                    146:            }
                    147:            writetar(name, &sb);
                    148:        } else {
                    149:            writecpio(name, &sb);
                    150:        }
                    151:        if (fd) {
                    152:            outdata(fd, name, sb.sb_size);
                    153:        }
                    154:        if (f_verbose) {
                    155:            print_entry(name, &sb);
                    156:        }
                    157:     }
                    158: 
                    159:     write_eot();
                    160:     close_archive();
                    161:     return (0);
                    162: }
                    163: 
                    164: 
                    165: /* writetar - write a header block for a tar file
                    166:  *
                    167:  * DESCRIPTION
                    168:  *
                    169:  *     Make a header block for the file name whose stat info is in st.  
                    170:  *     Return header pointer for success, NULL if the name is too long.
                    171:  *
                    172:  *     The tar header block is structured as follows:
                    173:  *
                    174:  *             FIELD NAME      OFFSET          SIZE
                    175:  *             -------------|---------------|------
                    176:  *             name              0             100
                    177:  *             mode            100               8
                    178:  *             uid             108               8
                    179:  *             gid             116               8
                    180:  *             size            124              12
                    181:  *             mtime           136              12
                    182:  *             chksum          148               8
                    183:  *             typeflag        156               1
                    184:  *             linkname        157             100
                    185:  *             magic           257               6
                    186:  *             version         263               2
                    187:  *             uname           265              32
                    188:  *             gname           297              32
                    189:  *             devmajor        329               8
                    190:  *             devminor        337               8
                    191:  *             prefix          345             155
                    192:  *
                    193:  * PARAMETERS
                    194:  *
                    195:  *     char    *name   - name of file to create a header block for
                    196:  *     Stat    *asb    - pointer to the stat structure for the named file
                    197:  *
                    198:  */
                    199: 
                    200: #if __STDC__
                    201: 
                    202: static void writetar(char *name, Stat *asb)
                    203: 
                    204: #else
                    205:     
                    206: static void writetar(name, asb)
                    207: char           *name;
                    208: Stat           *asb;
                    209: 
                    210: #endif
                    211: {
                    212:     char          *p;
                    213:     char           *prefix = (char *)NULL;
                    214:     int             i;
                    215:     int             sum;
                    216:     char            hdr[BLOCKSIZE];
                    217:     Link           *from;
                    218: 
                    219:     memset(hdr, 0, BLOCKSIZE);
                    220:     if ((int) strlen(name) > 255) {
                    221:        warn(name, "name too long");
                    222:        return;
                    223:     } 
                    224:     /* 
                    225:      * If the pathname is longer than TNAMLEN, but less than 255, then
                    226:      * we can split it up into the prefix and the filename.
                    227:      */
                    228:     if (strlen(name) > 100) {
                    229:        prefix = name;
                    230:        name += 155;
                    231:        while (name > prefix && *name != '/') {
                    232:            name--;
                    233:        }
                    234: 
                    235:        /* no slash found....hmmm.... */
                    236:        if (name == prefix) {
                    237:            warn(prefix, "Name too long");
                    238:            return;
                    239:        }
                    240:        *name++ = '\0';
                    241:     }
                    242: 
                    243: #ifdef S_IFLNK
                    244:     if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
                    245:        strcpy(&hdr[157], asb->sb_link);
                    246:        asb->sb_size = 0;
                    247:     }
                    248: #endif
                    249:     strcpy(hdr, name);
                    250:     sprintf(&hdr[100], "%06o \0", asb->sb_mode & ~S_IFMT);
                    251:     sprintf(&hdr[108], "%06o \0", asb->sb_uid);
                    252:     sprintf(&hdr[116], "%06o \0", asb->sb_gid);
                    253:     sprintf(&hdr[124], "%011lo ", (long) asb->sb_size);
                    254:     sprintf(&hdr[136], "%011lo ", (long) asb->sb_mtime);
                    255:     strncpy(&hdr[148], "        ", 8);
                    256:     hdr[156] = tartype(asb->sb_mode);
                    257:     if (asb->sb_nlink > 1 && (from = linkfrom(name, asb)) != (Link *)NULL) {
                    258:        strcpy(&hdr[157], from->l_name);
                    259:        hdr[156] = LNKTYPE;
                    260:     }
                    261:     strcpy(&hdr[257], TMAGIC);
                    262:     strncpy(&hdr[263], TVERSION, 2);
                    263:     strcpy(&hdr[265], finduname((int) asb->sb_uid));
                    264:     strcpy(&hdr[297], findgname((int) asb->sb_gid));
                    265:     sprintf(&hdr[329], "%06o \0", major(asb->sb_rdev));
                    266:     sprintf(&hdr[337], "%06o \0", minor(asb->sb_rdev));
                    267:     if (prefix != (char *)NULL) {
                    268:        strncpy(&hdr[345], prefix, 155);
                    269:     }
                    270: 
                    271:     /* Calculate the checksum */
                    272: 
                    273:     sum = 0;
                    274:     p = hdr;
                    275:     for (i = 0; i < 500; i++) {
                    276:        sum += 0xFF & *p++;
                    277:     }
                    278: 
                    279:     /* Fill in the checksum field. */
                    280: 
                    281:     sprintf(&hdr[148], "%06o \0", sum);
                    282: 
                    283:     outwrite(hdr, BLOCKSIZE);
                    284: }
                    285: 
                    286: 
                    287: /* tartype - return tar file type from file mode
                    288:  *
                    289:  * DESCRIPTION
                    290:  *
                    291:  *     tartype returns the character which represents the type of file
                    292:  *     indicated by "mode". 
                    293:  *
                    294:  * PARAMETERS
                    295:  *
                    296:  *     int     mode    - file mode from a stat block
                    297:  *
                    298:  * RETURNS
                    299:  *
                    300:  *     The character which represents the particular file type in the 
                    301:  *     ustar standard headers.
                    302:  */
                    303: 
                    304: #if __STDC__
                    305: 
                    306: static char tartype(int mode)
                    307: 
                    308: #else
                    309:     
                    310: static char tartype(mode)
                    311: int        mode;
                    312: 
                    313: #endif
                    314: {
                    315:     switch (mode & S_IFMT) {
                    316: 
                    317: #ifdef S_IFCTG
                    318:     case S_IFCTG:
                    319:        return(CONTTYPE);
                    320: #endif
                    321: 
                    322:     case S_IFDIR:
                    323:        return (DIRTYPE);
                    324: 
                    325: #ifdef S_IFLNK
                    326:     case S_IFLNK:
                    327:        return (SYMTYPE);
                    328: #endif
                    329: 
                    330: #ifdef S_IFFIFO
                    331:     case S_IFIFO:
                    332:        return (FIFOTYPE);
                    333: #endif
                    334: 
                    335: #ifdef S_IFCHR
                    336:     case S_IFCHR:
                    337:        return (CHRTYPE);
                    338: #endif
                    339: 
                    340: #ifdef S_IFBLK
                    341:     case S_IFBLK:
                    342:        return (BLKTYPE);
                    343: #endif
                    344: 
                    345:     default:
                    346:        return (REGTYPE);
                    347:     }
                    348: }
                    349: 
                    350: 
                    351: /* writecpio - write a cpio archive header
                    352:  *
                    353:  * DESCRIPTION
                    354:  *
                    355:  *     Writes a new CPIO style archive header for the file specified.
                    356:  *
                    357:  * PARAMETERS
                    358:  *
                    359:  *     char    *name   - name of file to create a header block for
                    360:  *     Stat    *asb    - pointer to the stat structure for the named file
                    361:  */
                    362: 
                    363: #if __STDC__
                    364: 
                    365: static void writecpio(char *name, Stat *asb)
                    366: 
                    367: #else
                    368:     
                    369: static void writecpio(name, asb)
                    370: char           *name;
                    371: Stat           *asb;
                    372: 
                    373: #endif
                    374: {
                    375:     uint            namelen;
                    376:     char            header[M_STRLEN + H_STRLEN + 1];
                    377: 
                    378:     namelen = (uint) strlen(name) + 1;
                    379:     strcpy(header, M_ASCII);
                    380:     sprintf(header + M_STRLEN, "%06o%06o%06o%06o%06o",
                    381:            USH(asb->sb_dev), USH(asb->sb_ino), USH(asb->sb_mode), 
                    382:            USH(asb->sb_uid), USH(asb->sb_gid));
                    383:     sprintf(header + M_STRLEN + 30, "%06o%06o%011lo%06o%011lo",
                    384:            USH(asb->sb_nlink), USH(asb->sb_rdev),
                    385:            f_mtime ? asb->sb_mtime : time((time_t *) 0),
                    386:            namelen, asb->sb_size);
                    387:     outwrite(header, M_STRLEN + H_STRLEN);
                    388:     outwrite(name, namelen);
                    389: #ifdef S_IFLNK
                    390:     if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
                    391:        outwrite(asb->sb_link, (uint) asb->sb_size);
                    392:     }
                    393: #endif /* S_IFLNK */
                    394: }

unix.superglobalmegacorp.com

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