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

unix.superglobalmegacorp.com

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