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