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