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