Annotation of researchv8dc/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:        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.