Annotation of researchv10no/cmd/odist/opkg/package.c, revision 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.