|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.