Annotation of researchv10no/cmd/asd/package.c, revision 1.1

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

unix.superglobalmegacorp.com

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