|
|
1.1 root 1: /* $Source: /src386/usr/bin/pax/create.c,v $
2: *
3: * $Revision: 1.1 $
4: *
5: * create.c - Create a tape archive.
6: *
7: * DESCRIPTION
8: *
9: * These functions are used to create/write and archive from an set of
10: * named files.
11: *
12: * AUTHOR
13: *
14: * Mark H. Colburn, NAPS International ([email protected])
15: *
16: * Sponsored by The USENIX Association for public distribution.
17: *
18: * Copyright (c) 1989 Mark H. Colburn.
19: * All rights reserved.
20: *
21: * Redistribution and use in source and binary forms are permitted
22: * provided that the above copyright notice is duplicated in all such
23: * forms and that any documentation, advertising materials, and other
24: * materials related to such distribution and use acknowledge that the
25: * software was developed * by Mark H. Colburn and sponsored by The
26: * USENIX Association.
27: *
28: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
29: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
30: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
31: *
32: * $Log: create.c,v $
33: * Revision 1.1 92/08/28 08:02:01 bin
34: * Initial revision
35: *
36: * Revision 1.1 89/02/14 16:47:48 jep
37: * Initial revision
38: *
39: * Revision 1.1 88/12/23 18:02:06 mark
40: * Initial revision
41: *
42: */
43:
44: #ifndef lint
45: static char *ident = "$Id: create.c,v 1.1 92/08/28 08:02:01 bin Exp Locker: bin $";
46: static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
47: #endif /* ! lint */
48:
49:
50: /* Headers */
51:
52: #include "pax.h"
53:
54:
55: /* Function Prototypes */
56:
57: #if __STDC__
58:
59: static void writetar(char *, Stat *);
60: static void writecpio(char *, Stat *);
61: static char tartype(int);
62:
63: #else /* !__STDC__ */
64:
65: static void writetar();
66: static void writecpio();
67: static char tartype();
68:
69: #endif /* __STDC__ */
70:
71:
72: /* create_archive - create a tar archive.
73: *
74: * DESCRIPTION
75: *
76: * Create_archive is used as an entry point to both create and append
77: * archives. Create archive goes through the files specified by the
78: * user and writes each one to the archive if it can. Create_archive
79: * knows how to write both cpio and tar headers and the padding which
80: * is needed for each type of archive.
81: *
82: * RETURNS
83: *
84: * Always returns 0
85: */
86:
87: #if __STDC__
88:
89: int create_archive(void)
90:
91: #else
92:
93: int create_archive()
94:
95: #endif
96: {
97: char name[PATH_MAX + 1];
98: Stat sb;
99: int fd;
100:
101: while (name_next(name, &sb) != -1) {
102: if ((fd = openin(name, &sb)) < 0) {
103: /* FIXME: pax wants to exit here??? */
104: continue;
105: }
106:
107: if (rplhead != (Replstr *)NULL) {
108: rpl_name(name);
109: if (strlen(name) == 0) {
110: continue;
111: }
112: }
113: if (get_disposition("add", name) || get_newname(name, sizeof(name))) {
114: /* skip file... */
115: if (fd) {
116: close(fd);
117: }
118: continue;
119: }
120:
121: if (!f_link && sb.sb_nlink > 1) {
122: if (islink(name, &sb)) {
123: sb.sb_size = 0;
124: }
125: linkto(name, &sb);
126: }
127: if (ar_format == TAR) {
128: /* SV tar does not understand POSIX tar header.
129: * Trailing '/' in directory name alows SV tar to unarchive
130: * POSIX tar archive. So, we add '/' to the "name" if it is
131: * a directory name.
132: * SV tar will produce error messages, but
133: * will do the job. Vlad 11-8-91
134: */
135: if ((sb.sb_stat.st_mode & S_IFMT) == S_IFDIR) {
136: int il;
137:
138: il = strlen(name);
139: name[il++] = '/';
140: name[il] = 0;
141: }
142: writetar(name, &sb);
143: } else {
144: writecpio(name, &sb);
145: }
146: if (fd) {
147: outdata(fd, name, sb.sb_size);
148: }
149: if (f_verbose) {
150: print_entry(name, &sb);
151: }
152: }
153:
154: write_eot();
155: close_archive();
156: return (0);
157: }
158:
159:
160: /* writetar - write a header block for a tar file
161: *
162: * DESCRIPTION
163: *
164: * Make a header block for the file name whose stat info is in st.
165: * Return header pointer for success, NULL if the name is too long.
166: *
167: * The tar header block is structured as follows:
168: *
169: * FIELD NAME OFFSET SIZE
170: * -------------|---------------|------
171: * name 0 100
172: * mode 100 8
173: * uid 108 8
174: * gid 116 8
175: * size 124 12
176: * mtime 136 12
177: * chksum 148 8
178: * typeflag 156 1
179: * linkname 157 100
180: * magic 257 6
181: * version 263 2
182: * uname 265 32
183: * gname 297 32
184: * devmajor 329 8
185: * devminor 337 8
186: * prefix 345 155
187: *
188: * PARAMETERS
189: *
190: * char *name - name of file to create a header block for
191: * Stat *asb - pointer to the stat structure for the named file
192: *
193: */
194:
195: #if __STDC__
196:
197: static void writetar(char *name, Stat *asb)
198:
199: #else
200:
201: static void writetar(name, asb)
202: char *name;
203: Stat *asb;
204:
205: #endif
206: {
207: char *p;
208: char *prefix = (char *)NULL;
209: int i;
210: int sum;
211: char hdr[BLOCKSIZE];
212: Link *from;
213:
214: memset(hdr, 0, BLOCKSIZE);
215: if (strlen(name) > 255) {
216: warn(name, "name too long");
217: return;
218: }
219:
220: /*
221: * If the pathname is longer than TNAMLEN, but less than 255, then
222: * we can split it up into the prefix and the filename.
223: */
224: if (strlen(name) > 100) {
225: prefix = name;
226: name += 155;
227: while (name > prefix && *name != '/') {
228: name--;
229: }
230:
231: /* no slash found....hmmm.... */
232: if (name == prefix) {
233: warn(prefix, "Name too long");
234: return;
235: }
236: *name++ = '\0';
237: }
238:
239: #ifdef S_IFLNK
240: if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
241: strcpy(&hdr[157], asb->sb_link);
242: asb->sb_size = 0;
243: }
244: #endif
245: strcpy(hdr, name);
246: sprintf(&hdr[100], "%06o \0", asb->sb_mode & ~S_IFMT);
247: sprintf(&hdr[108], "%06o \0", asb->sb_uid);
248: sprintf(&hdr[116], "%06o \0", asb->sb_gid);
249: sprintf(&hdr[124], "%011lo ", (long) asb->sb_size);
250: sprintf(&hdr[136], "%011lo ", (long) asb->sb_mtime);
251: strncpy(&hdr[148], " ", 8);
252: hdr[156] = tartype(asb->sb_mode);
253: if (asb->sb_nlink > 1 && (from = linkfrom(name, asb)) != (Link *)NULL) {
254: strcpy(&hdr[157], from->l_name);
255: hdr[156] = LNKTYPE;
256: }
257: strcpy(&hdr[257], TMAGIC);
258: strncpy(&hdr[263], TVERSION, 2);
259: strcpy(&hdr[265], finduname((int) asb->sb_uid));
260: strcpy(&hdr[297], findgname((int) asb->sb_gid));
261: sprintf(&hdr[329], "%06o \0", major(asb->sb_rdev));
262: sprintf(&hdr[337], "%06o \0", minor(asb->sb_rdev));
263: if (prefix != (char *)NULL) {
264: strncpy(&hdr[345], prefix, 155);
265: }
266:
267: /* Calculate the checksum */
268:
269: sum = 0;
270: p = hdr;
271: for (i = 0; i < 500; i++) {
272: sum += 0xFF & *p++;
273: }
274:
275: /* Fill in the checksum field. */
276:
277: sprintf(&hdr[148], "%06o \0", sum);
278:
279: outwrite(hdr, BLOCKSIZE);
280: }
281:
282:
283: /* tartype - return tar file type from file mode
284: *
285: * DESCRIPTION
286: *
287: * tartype returns the character which represents the type of file
288: * indicated by "mode".
289: *
290: * PARAMETERS
291: *
292: * int mode - file mode from a stat block
293: *
294: * RETURNS
295: *
296: * The character which represents the particular file type in the
297: * ustar standard headers.
298: */
299:
300: #if __STDC__
301:
302: static char tartype(int mode)
303:
304: #else
305:
306: static char tartype(mode)
307: int mode;
308:
309: #endif
310: {
311: switch (mode & S_IFMT) {
312:
313: #ifdef S_IFCTG
314: case S_IFCTG:
315: return(CONTTYPE);
316: #endif
317:
318: case S_IFDIR:
319: return (DIRTYPE);
320:
321: #ifdef S_IFLNK
322: case S_IFLNK:
323: return (SYMTYPE);
324: #endif
325:
326: #ifdef S_IFFIFO
327: case S_IFIFO:
328: return (FIFOTYPE);
329: #endif
330:
331: #ifdef S_IFCHR
332: case S_IFCHR:
333: return (CHRTYPE);
334: #endif
335:
336: #ifdef S_IFBLK
337: case S_IFBLK:
338: return (BLKTYPE);
339: #endif
340:
341: default:
342: return (REGTYPE);
343: }
344: }
345:
346:
347: /* writecpio - write a cpio archive header
348: *
349: * DESCRIPTION
350: *
351: * Writes a new CPIO style archive header for the file specified.
352: *
353: * PARAMETERS
354: *
355: * char *name - name of file to create a header block for
356: * Stat *asb - pointer to the stat structure for the named file
357: */
358:
359: #if __STDC__
360:
361: static void writecpio(char *name, Stat *asb)
362:
363: #else
364:
365: static void writecpio(name, asb)
366: char *name;
367: Stat *asb;
368:
369: #endif
370: {
371: uint namelen;
372: char header[M_STRLEN + H_STRLEN + 1];
373:
374: namelen = (uint) strlen(name) + 1;
375: strcpy(header, M_ASCII);
376: sprintf(header + M_STRLEN, "%06o%06o%06o%06o%06o",
377: USH(asb->sb_dev), USH(asb->sb_ino), USH(asb->sb_mode),
378: USH(asb->sb_uid), USH(asb->sb_gid));
379: sprintf(header + M_STRLEN + 30, "%06o%06o%011lo%06o%011lo",
380: USH(asb->sb_nlink), USH(asb->sb_rdev),
381: f_mtime ? asb->sb_mtime : time((time_t *) 0),
382: namelen, asb->sb_size);
383: outwrite(header, M_STRLEN + H_STRLEN);
384: outwrite(name, namelen);
385: #ifdef S_IFLNK
386: if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
387: outwrite(asb->sb_link, (uint) asb->sb_size);
388: }
389: #endif /* S_IFLNK */
390: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.