Annotation of researchv10no/cmd/odist/opkg/package.c, revision 1.1.1.1

1.1       root        1: #include "asd.h"
                      2: #include <string.h>
                      3: #include <time.h>
                      4: #include <unistd.h>
                      5: #include "ftw.h"
                      6: 
                      7: FILE *tf;
                      8: static Sig_typ sigsav;
                      9: static int rc;
                     10: static char tfname[L_tmpnam];
                     11: static struct stat outsb;
                     12: static struct pack *pkhead, *pktail;
                     13: 
                     14: /*
                     15:  *     The following structure helps keep track of things being packaged.
                     16:  *     iname is the internal name of the component -- in other words,
                     17:  *     the archive element name.  ename is the (short) pathname of the
                     18:  *     file.  The structures are chained by the "link" field.  All the
                     19:  *     other fields are copies of things returned by "stat" and are
                     20:  *     used mostly to make sure nothing changed while we were packaging.
                     21:  *     head and tail point to the first and last items in the chain.
                     22:  *     The first item is known to refer to the "Instructions" component.
                     23:  */
                     24: struct pack {
                     25:        char *iname;
                     26:        char *ename;
                     27:        struct pack *link;
                     28:        dev_t dev;
                     29:        ino_t ino;
                     30:        int uid, gid, mode;
                     31:        time_t time;
                     32:        off_t size;
                     33: };
                     34: 
                     35: /*
                     36:  *     Prepare to build a package.  The package will appear on stdout.
                     37:  *     The argument is nonzero if remarks are to be read.
                     38:  */
                     39: 
                     40: static void
                     41: delete(int arg)
                     42: {
                     43:        unlink (tfname);
                     44:        exit (3);
                     45: }
                     46: 
                     47: void
                     48: pkgstart(void)
                     49: {
                     50:        struct stat pks;
                     51: 
                     52:        rc = 0;
                     53: 
                     54:        nchk (fstat (fileno (stdout), &outsb));
                     55: 
                     56:        /* establish a temporary file to hold the instruction information */
                     57:        tmpnam (tfname);
                     58:        tf = fopen (tfname, "w");
                     59:        sigsav = signal (SIGINT, SIG_IGN);
                     60:        if (sigsav != SIG_IGN)
                     61:                signal (SIGINT, delete);
                     62:        nchk (chmod (tfname, 0644));
                     63:        schk ((char *) tf);
                     64: 
                     65:        /* create the initial element in the component chain */
                     66:        pkhead = pktail = new (struct pack);
                     67:        pkhead->iname = copy (instr);
                     68:        pkhead->ename = copy (tfname);
                     69:        pkhead->time = 0;
                     70:        pkhead->link = NULL;
                     71:        pkhead->uid = getuid();
                     72:        nchk (fstat (fileno(tf), &pks));
                     73:        pkhead->gid = pks.st_gid;
                     74:        pkhead->mode = 0100644;
                     75: }
                     76: 
                     77: static int consider(char *, struct stat *, int, struct FTW *);
                     78: 
                     79: /*
                     80:  *     put a file (or directory) into a package
                     81:  */
                     82: void
                     83: pkgfile (char *file)
                     84: {
                     85:        register int x;
                     86:        struct stat sb;
                     87: 
                     88:        /* if the file is truly not present, generate a remove request */
                     89: #ifdef S_IFLNK
                     90:        if (lstat (file, &sb) < 0 && errno == ENOENT) {
                     91: #else
                     92:        if (stat (file, &sb) < 0 && errno == ENOENT) {
                     93: #endif
                     94:                fprintf (tf, "r ");
                     95:                putpath (tf, transname (file));
                     96:                putc ('\n', tf);
                     97:        } else {
                     98:                x = ftw (file, consider, 8);
                     99:                if (x != 0) {
                    100:                        rc++;
                    101:                        if (x == -1)
                    102:                                perror (file);
                    103:                }
                    104:        }
                    105: }
                    106: 
                    107: /*
                    108:  *     we are done building a package.  This writes the actual file
                    109:  *     contents, so make sure the files are still around
                    110:  */
                    111: int
                    112: pkgend(void)
                    113: {
                    114:        register struct pack *pack;
                    115:        struct stat s;
                    116: 
                    117:        /* write 'x' or 'X' execution item if requested */
                    118:        if (xstr) {
                    119:                fprintf (tf, "x ");
                    120:                putpath (tf, xstr);
                    121:                fprintf (tf, "\n");
                    122:        }
                    123:        if (Xstr) {
                    124:                fprintf (tf, "X ");
                    125:                putpath (tf, Xstr);
                    126:                fprintf (tf, "\n");
                    127:        }
                    128: 
                    129:        /* we now know how long the first component is */
                    130:        pkhead->size = ftell (tf);
                    131: 
                    132:        /* we no longer need to write the temporary file */
                    133:        fclose (tf);
                    134: 
                    135:        /* describe the temp file correctly so it will pass later checks */
                    136:        if (pkhead->time == 0)
                    137:                (void) time (&pkhead->time);
                    138:        nchk (stat (tfname, &s));
                    139:        pkhead->dev = s.st_dev;
                    140:        pkhead->ino = s.st_ino;
                    141: 
                    142:        /*
                    143:         * write the files out into an archive
                    144:         */
                    145: 
                    146:        /* first the archive header */
                    147:        printf (ARMAG);
                    148: 
                    149:        /*
                    150:         *      run through the list, creating the archive components
                    151:         *      and deleting the list entries.  One iteration per component.
                    152:         *      We know there is at least one component, because the
                    153:         *      "Instructions" component must be represented.
                    154:         */
                    155:        do {
                    156:                struct ar_hdr ah;
                    157:                char buf[30];
                    158:                register int c;
                    159: 
                    160:                /* "pack" is the package component under consideration */
                    161:                pack = pkhead;
                    162: 
                    163:                if (pack->iname) {      /* non-regular file entry, no data */
                    164: 
                    165:                        /* log it if requested */
                    166:                        if (vflag)
                    167:                                fprintf (stderr, "package %s\n",
                    168:                                    strcmp (pack->iname, instr)? pack->ename: instr);
                    169: 
                    170:                        /* write the archive element header */
                    171: 
                    172: #              define ent(a,x) sprintf(buf, "%-*s", sizeof(ah.a), x); \
                    173:                        strncpy (ah.a, buf, sizeof (ah.a))
                    174:                        ent (ar_name, pack->iname);
                    175:                        ent (ar_fmag, ARFMAG);
                    176: #              undef ent
                    177: 
                    178: #              define ent(a,x) sprintf(buf, "%*ld", sizeof(ah.a), (long) x); \
                    179:                        strncpy (ah.a, buf, sizeof (ah.a))
                    180:                        ent (ar_date, pack->time);
                    181:                        ent (ar_uid, pack->uid);
                    182:                        ent (ar_gid, pack->gid);
                    183:                        ent (ar_size, pack->size);
                    184: #              undef ent
                    185: 
                    186: #              define ent(a,x) sprintf(buf, "%*o", sizeof(ah.a), x); \
                    187:                        strncpy (ah.a, buf, sizeof (ah.a))
                    188:                        ent (ar_mode, pack->mode);
                    189: #              undef ent
                    190: 
                    191:                        fwrite ((char *) &ah, sizeof (ah), 1, stdout);
                    192: 
                    193:                        /* write the archive element itself */
                    194:                        tf = fopen (pack->ename, "r");
                    195:                        if (tf == NULL) {
                    196:                                perror (pack->iname);
                    197:                                exit (1);
                    198:                        }
                    199: 
                    200:                        while ((c = getc (tf)) != EOF)
                    201:                                putchar (c);
                    202:                        
                    203:                        /* if things now don't match, complain */
                    204:                        if (fstat (fileno (tf), &s) < 0 || s.st_size != pack->size ||
                    205:                            (s.st_mtime != pack->time && strcmp (pack->iname, instr)) ||
                    206:                            s.st_dev != pack->dev || s.st_ino != pack->ino ||
                    207:                            s.st_uid != pack->uid || s.st_gid != pack->gid ||
                    208:                            (s.st_mode & 07777) != (pack->mode & 07777)) {
                    209:                                fprintf (stderr, "phase error on %s\n",
                    210:                                    pack->ename);
                    211:                                rc++;
                    212:                        }
                    213: 
                    214:                        fclose (tf);
                    215: 
                    216:                        if (pack->size & 1)
                    217:                                putchar ('\n');
                    218:                }
                    219:                
                    220:                /* delete the element, move on to the next */
                    221:                if (pack->iname) free (pack->iname);
                    222:                free (pack->ename);
                    223:                pkhead = pack->link;
                    224:                free ((char *) pack);
                    225:        } while (pkhead);
                    226: 
                    227:        /* zap the tail pointer for general cleanliness */
                    228:        pktail = NULL;
                    229: 
                    230:        nchk (unlink (tfname));
                    231:        signal (SIGINT, sigsav);
                    232: 
                    233:        return rc;
                    234: }
                    235: 
                    236: static void hdrsub(char *, struct stat *);
                    237: static char *iname(char *);
                    238: 
                    239: /* internal function for package creation */
                    240: static int
                    241: consider (char *name, struct stat *buf, int type, struct FTW *ftw)
                    242: {
                    243:        register struct pack *pack;
                    244:        register int mode;
                    245:        char *biname;
                    246: #ifdef S_ISLNK
                    247:        char *slname;
                    248: #endif
                    249: 
                    250:        switch (type) {
                    251:        case FTW_D:
                    252:                fprintf (tf, "d %-*.4o ", MAXCOMP, buf->st_mode & 07777);
                    253:                hdrsub (name, buf);
                    254:                fprintf (tf, "\n");
                    255:                break;
                    256: 
                    257:        case FTW_SL:
                    258:                if (ftw->level == 0) {
                    259:                        ftw->quit = FTW_FOLLOW;
                    260:                        return 0;
                    261:                }
                    262:                /* fall through */
                    263: 
                    264:        case FTW_F:
                    265:                mode = buf->st_mode;
                    266: 
                    267:                /* Has this file already appeared?  If so, it's a link */
                    268:                for (pack = pkhead->link; pack; pack = pack->link) {
                    269:                        if (buf->st_dev == pack->dev &&
                    270:                            buf->st_ino == pack->ino) {
                    271:                                fprintf (tf, "l %s ", transname (pack->ename));
                    272:                                fprintf (tf, "%s\n", transname (name));
                    273:                                return 0;
                    274:                        }
                    275:                }
                    276: 
                    277:                if (S_ISREG(mode)) {
                    278:                        /* refuse to package the standard output */
                    279:                        if (buf->st_dev == outsb.st_dev &&
                    280:                            buf->st_ino == outsb.st_ino) {
                    281:                                fprintf (stderr, "skipping output file %s\n",
                    282:                                    fullname (name));
                    283:                                return 0;
                    284:                        }
                    285:                        biname = iname (name);
                    286:                        fprintf (tf, "f ");
                    287:                        putpath (tf, biname);
                    288:                        fprintf (tf, " ");
                    289:                        hdrsub (name, buf);
                    290:                        fprintf (tf, "\n");
                    291:                }
                    292: #ifdef S_ISLNK
                    293:                else if (S_ISLNK(mode)) {
                    294:                        slname = alloc((unsigned)buf->st_size+1);
                    295:                        slname[buf->st_size] = '\0';
                    296:                        if (readlink(name, slname, buf->st_size) !=
                    297:                            buf->st_size) {
                    298:                                perror(name);
                    299:                                return (0);
                    300:                        }
                    301:                        fprintf (tf, "s %s ", transname (slname));
                    302:                        fprintf (tf, "%s\n", transname (name));
                    303:                        biname = NULL;
                    304:                }
                    305: #endif
                    306: #if 0 /* We don't handle special files any more.  */
                    307:                else if (S_ISBLK(mode) || S_ISCHR(mode)) {
                    308:                        fprintf (tf, "%c %#o %d %d ",
                    309:                            mode == S_IFBLK? 'b': 'c',
                    310:                            buf->st_mode & 07777,
                    311:                            major (buf->st_rdev),
                    312:                            minor (buf->st_rdev));
                    313:                        hdrsub (name, buf);
                    314:                        fprintf (tf, "\n");
                    315:                        biname = NULL;
                    316:                }
                    317: #endif
                    318:                else {
                    319:                        fprintf (stderr, "%s: unrecognized file type\n",
                    320:                                 fullname (name));
                    321:                        break;
                    322:                }
                    323: 
                    324: 
                    325:                /* package the file */
                    326:                pack = new (struct pack);
                    327:                pack->ename = copy (name);
                    328:                pack->dev = buf->st_dev;
                    329:                pack->ino = buf->st_ino;
                    330:                pack->uid = buf->st_uid;
                    331:                pack->gid = buf->st_gid;
                    332:                pack->time = buf->st_mtime;
                    333:                if (pack->time > pkhead->time)
                    334:                        pkhead->time = pack->time;
                    335:                pack->size = buf->st_size;
                    336:                pack->mode = buf->st_mode;
                    337:                pack->link = NULL;
                    338:                pack->iname = biname;
                    339:                pktail->link = pack;
                    340:                pktail = pack;
                    341:                break;
                    342: 
                    343:        case FTW_DNR:
                    344:                fprintf (stderr, "cannot read directory %s\n", name);
                    345:                return 1;
                    346: 
                    347:        case FTW_NS:
                    348:                fprintf (stderr, "cannot stat %s\n", name);
                    349:                return 1;
                    350: 
                    351:        case FTW_DP:
                    352:                break;
                    353: 
                    354:        default:
                    355:                fprintf (stderr, "impossible code %d from ftw\n", type);
                    356:                exit (1);
                    357:        }
                    358:        return 0;
                    359: }
                    360: 
                    361: static void
                    362: hdrsub (char *name, struct stat *buf)
                    363: {
                    364:        putpath (tf, uidstr (buf->st_uid));
                    365:        putc ('\t', tf);
                    366:        putpath (tf, gidstr (buf->st_gid));
                    367:        putc ('\t', tf);
                    368:        putpath (tf, transname (name));
                    369: }
                    370: 
                    371: /*
                    372:  *     generate a unique internal name for a file
                    373:  */
                    374: static char *
                    375: iname (char *s)
                    376: {
                    377:        register char *p;
                    378:        register char *lastcomp;
                    379:        register struct pack *pack;
                    380:        char trial[MAXCOMP+1];
                    381: 
                    382:        /* point lastcomp at the last pathname component */
                    383:        lastcomp = s;
                    384:        for (p = s; *p; p++) {
                    385:                if (*p == '/')
                    386:                        lastcomp = p + 1;
                    387:        }
                    388: 
                    389:        /* if the name is acceptably short, modify it slightly */
                    390:        if (strlen (lastcomp) <= MAXCOMP) {
                    391: 
                    392:                char prefix[MAXCOMP+1], suffix[MAXCOMP+1], num[30];
                    393:                register int n;
                    394: 
                    395:                /* split the name, remove unprintables */
                    396:                strcpy (prefix, lastcomp);
                    397:                for (p = prefix; *p; p++)
                    398:                        if (*p == ' ' || !isprint (*p))
                    399:                                *p = '$';
                    400:                suffix[0] = '\0';
                    401:                p = strrchr (prefix, '.');
                    402:                if (p != NULL) {
                    403:                        strcpy (suffix, p);
                    404:                        *p = '\0';
                    405:                }
                    406: 
                    407:                /* generate trial names until we run out of space */
                    408:                for (n = 0, num[0] = '\0';
                    409:                    strlen(prefix) + strlen(suffix) + strlen(num) <= MAXCOMP;
                    410:                    n++, sprintf (num, "%.0d", n)) {
                    411:                        
                    412:                        /* generate the trial name */
                    413:                        strcpy (trial, prefix);
                    414:                        strcat (trial, num);
                    415:                        strcat (trial, suffix);
                    416: 
                    417:                        /* if the name is unique, we're done */
                    418:                        pack = pkhead;
                    419:                        while (pack != NULL && strcmp (pack->iname, trial) != 0)
                    420:                                pack = pack->link;
                    421:                        if (pack == NULL)
                    422:                                return copy(trial);
                    423: 
                    424:                }
                    425:        }
                    426: 
                    427:        /* punt -- generate a completely new name */
                    428:        do {
                    429:                static int tempno;
                    430: 
                    431:                tempno++;
                    432:                sprintf (trial, "Temp%d", tempno);
                    433:                pack = pkhead;
                    434:                while (pack != NULL && strcmp (trial, pack->iname) != 0)
                    435:                        pack = pack->link;
                    436:        } while (pack != NULL);
                    437:        return copy(trial);
                    438: }

unix.superglobalmegacorp.com

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