1 /* $Source: /u/mark/src/pax/RCS/create.c,v $
2 *
3 * $Revision: 1.3 $
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 (mark@jhereg.mn.org)
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.3 89/02/12 10:29:37 mark
34 * Fixed misspelling of Replstr
35 *
36 * Revision 1.2 89/02/12 10:04:17 mark
37 * 1.2 release fixes
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.3 89/02/12 10:29:37 mark Exp Locker: mark $";
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 #ifdef __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 #ifdef __STDC__
88
create_archive(void)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 writetar(name, &sb);
129 } else {
130 writecpio(name, &sb);
131 }
132 if (fd) {
133 outdata(fd, name, sb.sb_size);
134 }
135 if (f_verbose) {
136 print_entry(name, &sb);
137 }
138 }
139
140 write_eot();
141 close_archive();
142 return (0);
143 }
144
145
146 /* writetar - write a header block for a tar file
147 *
148 * DESCRIPTION
149 *
150 * Make a header block for the file name whose stat info is in st.
151 * Return header pointer for success, NULL if the name is too long.
152 *
153 * The tar header block is structured as follows:
154 *
155 * FIELD NAME OFFSET SIZE
156 * -------------|---------------|------
157 * name 0 100
158 * mode 100 8
159 * uid 108 8
160 * gid 116 8
161 * size 124 12
162 * mtime 136 12
163 * chksum 148 8
164 * typeflag 156 1
165 * linkname 157 100
166 * magic 257 6
167 * version 263 2
168 * uname 265 32
169 * gname 297 32
170 * devmajor 329 8
171 * devminor 337 8
172 * prefix 345 155
173 *
174 * PARAMETERS
175 *
176 * char *name - name of file to create a header block for
177 * Stat *asb - pointer to the stat structure for the named file
178 *
179 */
180
181 #ifdef __STDC__
182
writetar(char * name,Stat * asb)183 static void writetar(char *name, Stat *asb)
184
185 #else
186
187 static void writetar(name, asb)
188 char *name;
189 Stat *asb;
190
191 #endif
192 {
193 char *p;
194 char *prefix = (char *)NULL;
195 int i;
196 int sum;
197 char hdr[BLOCKSIZE];
198 Link *from;
199
200 memset(hdr, 0, BLOCKSIZE);
201 if (strlen(name) > 255) {
202 warn(name, "name too long");
203 return;
204 }
205
206 /*
207 * If the pathname is longer than TNAMLEN, but less than 255, then
208 * we can split it up into the prefix and the filename.
209 */
210 if (strlen(name) > 100) {
211 prefix = name;
212 name += 155;
213 while (name > prefix && *name != '/') {
214 name--;
215 }
216
217 /* no slash found....hmmm.... */
218 if (name == prefix) {
219 warn(prefix, "Name too long");
220 return;
221 }
222 *name++ = '\0';
223 }
224
225 #ifdef S_IFLNK
226 if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
227 strcpy(&hdr[157], asb->sb_link);
228 asb->sb_size = 0;
229 }
230 #endif
231 strcpy(hdr, name);
232 sprintf(&hdr[100], "%06o \0", asb->sb_mode & ~S_IFMT);
233 sprintf(&hdr[108], "%06o \0", asb->sb_uid);
234 sprintf(&hdr[116], "%06o \0", asb->sb_gid);
235 sprintf(&hdr[124], "%011lo ", (long) asb->sb_size);
236 sprintf(&hdr[136], "%011lo ", (long) asb->sb_mtime);
237 strncpy(&hdr[148], " ", 8);
238 hdr[156] = tartype(asb->sb_mode);
239 if (asb->sb_nlink > 1 && (from = linkfrom(name, asb)) != (Link *)NULL) {
240 strcpy(&hdr[157], from->l_name);
241 hdr[156] = LNKTYPE;
242 }
243 strcpy(&hdr[257], TMAGIC);
244 strncpy(&hdr[263], TVERSION, 2);
245 strcpy(&hdr[265], finduname((int) asb->sb_uid));
246 strcpy(&hdr[297], findgname((int) asb->sb_gid));
247 sprintf(&hdr[329], "%06o \0", major(asb->sb_rdev));
248 sprintf(&hdr[337], "%06o \0", minor(asb->sb_rdev));
249 if (prefix != (char *)NULL) {
250 strncpy(&hdr[345], prefix, 155);
251 }
252
253 /* Calculate the checksum */
254
255 sum = 0;
256 p = hdr;
257 for (i = 0; i < 500; i++) {
258 sum += 0xFF & *p++;
259 }
260
261 /* Fill in the checksum field. */
262
263 sprintf(&hdr[148], "%06o \0", sum);
264
265 outwrite(hdr, BLOCKSIZE);
266 }
267
268
269 /* tartype - return tar file type from file mode
270 *
271 * DESCRIPTION
272 *
273 * tartype returns the character which represents the type of file
274 * indicated by "mode".
275 *
276 * PARAMETERS
277 *
278 * int mode - file mode from a stat block
279 *
280 * RETURNS
281 *
282 * The character which represents the particular file type in the
283 * ustar standard headers.
284 */
285
286 #ifdef __STDC__
287
tartype(int mode)288 static char tartype(int mode)
289
290 #else
291
292 static char tartype(mode)
293 int mode;
294
295 #endif
296 {
297 switch (mode & S_IFMT) {
298
299 #ifdef S_IFCTG
300 case S_IFCTG:
301 return(CONTTYPE);
302 #endif
303
304 case S_IFDIR:
305 return (DIRTYPE);
306
307 #ifdef S_IFLNK
308 case S_IFLNK:
309 return (SYMTYPE);
310 #endif
311
312 #ifdef S_IFFIFO
313 case S_IFIFO:
314 return (FIFOTYPE);
315 #endif
316
317 #ifdef S_IFCHR
318 case S_IFCHR:
319 return (CHRTYPE);
320 #endif
321
322 #ifdef S_IFBLK
323 case S_IFBLK:
324 return (BLKTYPE);
325 #endif
326
327 default:
328 return (REGTYPE);
329 }
330 }
331
332
333 /* writecpio - write a cpio archive header
334 *
335 * DESCRIPTION
336 *
337 * Writes a new CPIO style archive header for the file specified.
338 *
339 * PARAMETERS
340 *
341 * char *name - name of file to create a header block for
342 * Stat *asb - pointer to the stat structure for the named file
343 */
344
345 #ifdef __STDC__
346
writecpio(char * name,Stat * asb)347 static void writecpio(char *name, Stat *asb)
348
349 #else
350
351 static void writecpio(name, asb)
352 char *name;
353 Stat *asb;
354
355 #endif
356 {
357 uint namelen;
358 char header[M_STRLEN + H_STRLEN + 1];
359
360 namelen = (uint) strlen(name) + 1;
361 strcpy(header, M_ASCII);
362 sprintf(header + M_STRLEN, "%06o%06o%06o%06o%06o",
363 USH(asb->sb_dev), USH(asb->sb_ino), USH(asb->sb_mode),
364 USH(asb->sb_uid), USH(asb->sb_gid));
365 sprintf(header + M_STRLEN + 30, "%06o%06o%011lo%06o%011lo",
366 #ifdef _POSIX_SOURCE
367 USH(asb->sb_nlink), USH(0),
368 #else
369 USH(asb->sb_nlink), USH(asb->sb_rdev),
370 #endif
371 f_mtime ? asb->sb_mtime : time((time_t *) 0),
372 namelen, asb->sb_size);
373 outwrite(header, M_STRLEN + H_STRLEN);
374 outwrite(name, namelen);
375 #ifdef S_IFLNK
376 if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
377 outwrite(asb->sb_link, (uint) asb->sb_size);
378 }
379 #endif /* S_IFLNK */
380 }
381