|
|
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.