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