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