1 /* @(#)props.c 1.65 19/01/07 Copyright 1994-2019 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)props.c 1.65 19/01/07 Copyright 1994-2019 J. Schilling";
6 #endif
7 /*
8 * Set up properties for different archive types
9 *
10 * NOTE that part of the information in struct propertiesis available more
11 * than once. This is needed as different parts of the source need the
12 * information in different ways. Partly for performance reasons, partly
13 * because one method of storing the information is inappropriate for all
14 * places in the source.
15 *
16 * If you add new features or information related to the fields
17 * pr_flags/pr_nflags or the fields pr_xftypetab[]/pr_typeflagtab[]
18 * take care of possible problems due to this fact.
19 *
20 * Copyright (c) 1994-2019 J. Schilling
21 */
22 /*
23 * The contents of this file are subject to the terms of the
24 * Common Development and Distribution License, Version 1.0 only
25 * (the "License"). You may not use this file except in compliance
26 * with the License.
27 *
28 * See the file CDDL.Schily.txt in this distribution for details.
29 * A copy of the CDDL is also available via the Internet at
30 * http://www.opensource.org/licenses/cddl1.txt
31 *
32 * When distributing Covered Code, include this CDDL HEADER in each
33 * file and include the License file CDDL.Schily.txt from this distribution.
34 */
35
36 #include <schily/stdio.h>
37 #include "star.h"
38 #include "props.h"
39 #include "table.h"
40 #include "diff.h"
41 #include <schily/standard.h>
42 #define GT_COMERR /* #define comerr gtcomerr */
43 #define GT_ERROR /* #define error gterror */
44 #include <schily/schily.h>
45 #include "starsubs.h"
46
47 extern BOOL debug;
48 extern BOOL dodump;
49
50 struct properties props;
51
52 EXPORT void setprops __PR((long htype));
53 EXPORT void printprops __PR((void));
54 LOCAL void prsettypeflags __PR((char *types, int typeflag));
55
56 EXPORT void
setprops(htype)57 setprops(htype)
58 long htype;
59 {
60 fillbytes(props.pr_typeflagtab, sizeof (props.pr_typeflagtab), '\0');
61
62 switch (H_TYPE(htype)) {
63
64 case H_STAR: /* Old star format (1985) */
65 props.pr_maxsize = 0;
66 props.pr_hdrsize = TAR_HDRSZ;
67 props.pr_flags = PR_LOCAL_STAR|PR_SPARSE|PR_VOLHDR|PR_BASE256;
68 props.pr_xhdflags = 0;
69 props.pr_xhmask = 0;
70 props.pr_fillc = ' '; /* Use old tar octal format */
71 props.pr_xc = 'x'; /* Use POSIX.1-2001 x-hdr */
72 props.pr_pad = 0;
73 props.pr_diffmask = 0L;
74 props.pr_nflags =
75 PR_POSIX_SPLIT|PR_PREFIX_REUSED|PR_LONG_NAMES;
76 #ifdef HAVE_FCHDIR
77 props.pr_maxnamelen = INT_MAX;
78 props.pr_maxlnamelen = INT_MAX;
79 #else
80 props.pr_maxnamelen = PATH_MAX;
81 props.pr_maxlnamelen = PATH_MAX;
82 #endif
83 props.pr_maxsname = NAMSIZ;
84 props.pr_maxslname = NAMSIZ;
85 props.pr_maxprefix = PFXSIZ;
86 props.pr_sparse_in_hdr = 0;
87 /*
88 * The STAR format extensions from 1986 archive nearly any UNIX file type
89 */
90 movebytes(xtstar_tab, props.pr_xftypetab, sizeof (props.pr_xftypetab));
91
92 /*
93 * The STAR format is pre-POSIX but supports many POSIX/GNU
94 * extensions.
95 */
96 prsettypeflags("01234567gxIKLMSV", TF_VALIDTYPE);
97 prsettypeflags("gxKL", TF_XHEADERS);
98 break;
99
100 case H_XSTAR: /* ext P-1988 format (1994) */
101 case H_XUSTAR: /* ext ^ no "tar" sig (1998) */
102 case H_EXUSTAR: /* ext P-2001 format (2001) */
103 props.pr_maxsize = 0;
104 props.pr_hdrsize = TAR_HDRSZ;
105 props.pr_flags =
106 PR_POSIX_OCTAL|PR_LOCAL_STAR|PR_SPARSE|
107 PR_MULTIVOL|PR_VOLHDR|PR_BASE256;
108 props.pr_xhdflags = 0;
109 props.pr_xhmask = 0;
110 if (H_TYPE(htype) == H_XUSTAR || H_TYPE(htype) == H_EXUSTAR) {
111 props.pr_flags |= (PR_XHDR|PR_VU_XHDR);
112 props.pr_xhmask = ~0; /* xustar/exustar supp. all */
113 }
114 if (H_TYPE(htype) == H_EXUSTAR) {
115 props.pr_flags |= PR_LINK_DATA;
116 props.pr_xhdflags |= (XF_ATIME|XF_CTIME|XF_MTIME);
117 }
118 props.pr_fillc = '0'; /* Use ustar octal format */
119 props.pr_xc = 'x'; /* Use POSIX.1-2001 x-hdr */
120 props.pr_pad = 0;
121 props.pr_diffmask = 0L;
122 props.pr_nflags =
123 PR_POSIX_SPLIT|PR_PREFIX_REUSED|PR_LONG_NAMES;
124 #ifdef HAVE_FCHDIR
125 props.pr_maxnamelen = INT_MAX;
126 props.pr_maxlnamelen = INT_MAX;
127 #else
128 props.pr_maxnamelen = PATH_MAX;
129 props.pr_maxlnamelen = PATH_MAX;
130 #endif
131 props.pr_maxsname = NAMSIZ;
132 props.pr_maxslname = NAMSIZ;
133 props.pr_maxprefix = 130;
134 props.pr_sparse_in_hdr = 0;
135 /*
136 * As long as we don't support the POSIX.1-2001 speudo 'x' file
137 * We can only archive file types from the USTAR list and
138 * sparse files as well as
139 * meta files (regular files without archived content).
140 */
141 movebytes(xtustar_tab, props.pr_xftypetab, sizeof (props.pr_xftypetab));
142 props.pr_xftypetab[XT_SPARSE] = 1;
143 props.pr_xftypetab[XT_META] = 1;
144
145 /*
146 * Extended PAX format may allow more filetypes in a vendor
147 * unique extension of the POSIX.1-2001 extended headers.
148 * XXX As we currently only add the SCHILY.filetype headers
149 * XXX if -dump has been specified, we can only allow more
150 * XXX filetypes in this case.
151 */
152 if (dodump && H_TYPE(htype) == H_EXUSTAR)
153 movebytes(xtexustar_tab, props.pr_xftypetab, sizeof (props.pr_xftypetab));
154
155 /*
156 * The X-STAR format family is POSIX with extensions.
157 */
158 prsettypeflags("01234567gxIKLMSV", TF_VALIDTYPE);
159 prsettypeflags("gxKL", TF_XHEADERS);
160 break;
161
162 case H_PAX: /* ieee 1003.1-2001 ext ustar */
163 case H_EPAX: /* ieee 1003.1-2001 ext ustar + xheader */
164 case H_USTAR: /* ieee 1003.1-1988 ustar */
165 case H_SUNTAR: /* Sun's tar from Solaris 7-9 */
166 props.pr_maxsize = MAXOCTAL11;
167 props.pr_hdrsize = TAR_HDRSZ;
168 props.pr_flags = PR_POSIX_OCTAL;
169 if (H_TYPE(htype) == H_PAX ||
170 H_TYPE(htype) == H_EPAX ||
171 H_TYPE(htype) == H_SUNTAR) {
172 props.pr_maxsize = 0;
173 props.pr_flags |= PR_XHDR;
174 }
175 props.pr_xhdflags = 0;
176 props.pr_xhmask = 0;
177 if (H_TYPE(htype) == H_PAX ||
178 H_TYPE(htype) == H_EPAX)
179 props.pr_xhmask = XF_POSIX;
180 if (H_TYPE(htype) == H_EPAX) {
181 props.pr_xhdflags |= (XF_ATIME|XF_CTIME|XF_MTIME);
182 }
183 props.pr_fillc = '0'; /* Use ustar octal format */
184 props.pr_xc = 'x'; /* Use POSIX.1-2001 x-hdr */
185 props.pr_pad = 0;
186 if (H_TYPE(htype) == H_SUNTAR) {
187 props.pr_flags |= PR_VU_XHDR;
188 props.pr_xhdflags = XF_MTIME;
189 props.pr_xhmask = XF_MTIME|XF_UID|XF_UNAME|
190 XF_GID|XF_GNAME|
191 XF_PATH|XF_LINKPATH|
192 XF_SIZE|XF_DEVMAJOR|XF_DEVMINOR;
193 props.pr_xc = 'X'; /* Use Sun Solaris X-hdr */
194 }
195 props.pr_diffmask = (D_SPARS|D_ATIME|D_CTIME);
196 if (H_TYPE(htype) == H_PAX ||
197 H_TYPE(htype) == H_EPAX) {
198 props.pr_diffmask = 0L;
199 }
200 props.pr_nflags = PR_POSIX_SPLIT;
201 props.pr_maxnamelen = NAMSIZ + 1 + PFXSIZ; /* 256 */
202 props.pr_maxlnamelen = NAMSIZ;
203 if (H_TYPE(htype) == H_PAX ||
204 H_TYPE(htype) == H_EPAX ||
205 H_TYPE(htype) == H_SUNTAR) {
206 props.pr_nflags |= PR_LONG_NAMES;
207 #ifdef HAVE_FCHDIR
208 props.pr_maxnamelen = INT_MAX;
209 props.pr_maxlnamelen = INT_MAX;
210 #else
211 props.pr_maxnamelen = PATH_MAX;
212 props.pr_maxlnamelen = PATH_MAX;
213 #endif
214 }
215 if (H_TYPE(htype) == H_SUNTAR) {
216 props.pr_maxnamelen = PATH_MAX;
217 props.pr_maxlnamelen = PATH_MAX;
218 }
219 props.pr_maxsname = NAMSIZ;
220 props.pr_maxslname = NAMSIZ;
221 props.pr_maxprefix = PFXSIZ;
222 props.pr_sparse_in_hdr = 0;
223 /*
224 * USTAR is limited to 7 basic file types
225 */
226 movebytes(xtustar_tab, props.pr_xftypetab, sizeof (props.pr_xftypetab));
227
228 /*
229 * Even the USTAR format should support POSIX extension headers.
230 */
231 prsettypeflags("01234567gx", TF_VALIDTYPE);
232 prsettypeflags("gx", TF_XHEADERS);
233 if (H_TYPE(htype) == H_SUNTAR) {
234 prsettypeflags("01234567gxX", TF_VALIDTYPE);
235 prsettypeflags("gxX", TF_XHEADERS);
236 }
237 break;
238
239 case H_GNUTAR: /* gnu tar format (1989) */
240 props.pr_maxsize = 0;
241 props.pr_hdrsize = TAR_HDRSZ;
242 props.pr_flags =
243 PR_LOCAL_GNU|PR_SPARSE|PR_GNU_SPARSE_BUG|PR_VOLHDR|PR_BASE256;
244 props.pr_xhdflags = 0;
245 props.pr_xhmask = 0;
246 props.pr_fillc = ' '; /* Use old tar octal format */
247 props.pr_xc = 'x'; /* Really ??? */
248 props.pr_pad = 0;
249 props.pr_diffmask = 0L;
250 props.pr_nflags = PR_LONG_NAMES;
251 #ifdef HAVE_FCHDIR
252 /*
253 * GNU tar cannot extract archives with long path names but
254 * under some conditions creates them. For this reason, it
255 * does not seem to be a problem if we do not prevent to
256 * create "gnutar" archives with long path names.
257 */
258 props.pr_maxnamelen = INT_MAX;
259 props.pr_maxlnamelen = INT_MAX;
260 #else
261 props.pr_maxnamelen = PATH_MAX;
262 props.pr_maxlnamelen = PATH_MAX;
263 #endif
264 props.pr_maxsname = NAMSIZ-1;
265 props.pr_maxslname = NAMSIZ-1;
266 props.pr_maxprefix = 0;
267 props.pr_sparse_in_hdr = SPARSE_IN_HDR;
268 /*
269 * GNU tar is limited to the USTAR file types + sparse files
270 */
271 movebytes(xtustar_tab, props.pr_xftypetab, sizeof (props.pr_xftypetab));
272 props.pr_xftypetab[XT_SPARSE] = 1;
273
274 prsettypeflags("01234567DKLMNSV", TF_VALIDTYPE);
275 prsettypeflags("KL", TF_XHEADERS);
276 break;
277
278 default:
279 errmsgno(EX_BAD, "setprops: unexpected header type %ld '%s' (%s).\n",
280 htype,
281 hdr_name(htype),
282 hdr_text(htype));
283 errmsgno(EX_BAD, "setprops: defaulting to '%s' (%s).\n",
284 hdr_name(H_OTAR),
285 hdr_text(H_OTAR));
286 /* FALLTHRU */
287 case H_UNDEF: /* from star main read mode */
288 case H_TAR: /* tar with unknown format */
289 case H_V7TAR: /* tar old UNIX V7 format */
290 case H_OTAR: /* tar old BSD format (1978) */
291 /*
292 * Since the large file summit was in 1995, we may assume
293 * that any large file aware TAR implementation must be POSIX
294 * compliant too. The only known exception is GNU tar which
295 * is recognised separately.
296 * Limit max file size to the max that is supported
297 * by non large file aware systems.
298 */
299 props.pr_maxsize = MAXNONLARGEFILE;
300 props.pr_hdrsize = TAR_HDRSZ;
301 props.pr_flags = 0;
302 props.pr_xhdflags = 0;
303 props.pr_xhmask = 0;
304 props.pr_fillc = ' '; /* Use old tar octal format */
305 props.pr_xc = 'x'; /* Really ??? */
306 props.pr_pad = 0;
307 props.pr_diffmask = (D_SPARS|D_ATIME|D_CTIME);
308 props.pr_nflags = PR_DUMB_EOF;
309 props.pr_maxnamelen = NAMSIZ-1;
310 props.pr_maxlnamelen = NAMSIZ-1;
311 props.pr_maxsname = NAMSIZ-1;
312 props.pr_maxslname = NAMSIZ-1;
313 props.pr_maxprefix = 0;
314 props.pr_sparse_in_hdr = 0;
315 /*
316 * Only a very limited set of file types (file,symlink,dir)
317 */
318 if (H_TYPE(htype) == H_V7TAR)
319 movebytes(xtv7tar_tab, props.pr_xftypetab, sizeof (props.pr_xftypetab));
320 else
321 movebytes(xttar_tab, props.pr_xftypetab, sizeof (props.pr_xftypetab));
322
323 /*
324 * Old BSD tar does no know about file types beyond "012" but
325 * the USTAR basic format has been designed to be compatible
326 * with the old tar format.
327 * OLD UNIX V7 tar does not know anything but plain files and
328 * hard links. Note that we never see H_TYPE(htype) == H_V7TAR
329 * in extract mode.
330 */
331 if (H_TYPE(htype) == H_V7TAR)
332 prsettypeflags("01", TF_VALIDTYPE);
333 else
334 prsettypeflags("01234567", TF_VALIDTYPE);
335 prsettypeflags("", TF_XHEADERS);
336 break;
337
338 case H_BAR: /* Sun bar format */
339 props.pr_maxsize = MAXNONLARGEFILE; /* bar is pre-largefile */
340 props.pr_hdrsize = BAR_HDRSZ;
341 props.pr_flags = 0;
342 props.pr_xhdflags = 0;
343 props.pr_xhmask = 0;
344 props.pr_fillc = ' '; /* Use old tar octal format */
345 props.pr_xc = 'x'; /* Really ??? */
346 props.pr_pad = 0;
347 props.pr_diffmask = (D_SPARS|D_ATIME|D_CTIME);
348 props.pr_nflags = PR_DUMB_EOF;
349 props.pr_maxnamelen = PATH_MAX;
350 props.pr_maxlnamelen = PATH_MAX;
351 props.pr_maxsname = NAMSIZ-1; /* XXX Really ??? */
352 props.pr_maxslname = NAMSIZ-1; /* XXX Really ??? */
353 props.pr_maxprefix = 0;
354 props.pr_sparse_in_hdr = 0;
355 /*
356 * BAR is limited to 7 basic file types
357 */
358 movebytes(xtcpio_tab, props.pr_xftypetab, sizeof (props.pr_xftypetab));
359 props.pr_xftypetab[XT_SOCK] = 0;
360 break;
361
362 case H_CPIO_BIN:
363 props.pr_maxsize = MAXNONLARGEFILE;
364 props.pr_hdrsize = CPIOBIN_HDRSZ;
365 props.pr_flags = PR_CPIO;
366 props.pr_xhdflags = 0;
367 props.pr_xhmask = 0;
368 props.pr_fillc = '0';
369 props.pr_xc = 'x'; /* Not needed */
370 props.pr_pad = 1;
371 props.pr_diffmask = (D_SPARS|D_ATIME|D_CTIME);
372 props.pr_nflags = PR_LONG_NAMES;
373 props.pr_maxnamelen = 256;
374 props.pr_maxlnamelen = PATH_MAX;
375 props.pr_maxsname = NAMSIZ-1; /* XXX Really ??? */
376 props.pr_maxslname = NAMSIZ-1; /* XXX Really ??? */
377 props.pr_maxprefix = 0;
378 props.pr_sparse_in_hdr = 0;
379 /*
380 * CPIO is limited to 7 basic file types
381 */
382 movebytes(xtcpio_tab, props.pr_xftypetab, sizeof (props.pr_xftypetab));
383 props.pr_xftypetab[XT_SOCK] = 0;
384 break;
385
386 case H_CPIO_CHR:
387 case H_CPIO_ODC:
388 props.pr_maxsize = MAXOCTAL11;
389 props.pr_hdrsize = CPIOODC_HDRSZ;
390 props.pr_flags = PR_CPIO;
391 props.pr_xhdflags = 0;
392 props.pr_xhmask = 0;
393 props.pr_fillc = '0';
394 props.pr_xc = 'x'; /* Not needed */
395 props.pr_pad = 0;
396 props.pr_diffmask = (D_SPARS|D_ATIME|D_CTIME);
397 props.pr_nflags = PR_LONG_NAMES;
398 props.pr_maxnamelen = PATH_MAX;
399 props.pr_maxlnamelen = PATH_MAX;
400 props.pr_maxsname = NAMSIZ-1; /* XXX Really ??? */
401 props.pr_maxslname = NAMSIZ-1; /* XXX Really ??? */
402 props.pr_maxprefix = 0;
403 props.pr_sparse_in_hdr = 0;
404 /*
405 * CPIO is limited to 7 basic file types + sockets
406 */
407 movebytes(xtcpio_tab, props.pr_xftypetab, sizeof (props.pr_xftypetab));
408
409 if (H_TYPE(htype) == H_CPIO_ODC) {
410 /*
411 * Be compatible to the useless SYSv cpio -Hodc
412 * limitations.
413 */
414 props.pr_maxnamelen = 255;
415 props.pr_xftypetab[XT_SOCK] = 0;
416 }
417 break;
418
419 case H_CPIO_ASC:
420 case H_CPIO_ACRC:
421 props.pr_maxsize = (unsigned long)0xFFFFFFFF;
422 props.pr_hdrsize = CPIOCRC_HDRSZ;
423 props.pr_flags = PR_CPIO | PR_SV_CPIO_LINKS;
424 props.pr_xhdflags = 0;
425 props.pr_xhmask = 0;
426 props.pr_fillc = '0';
427 props.pr_xc = 'x'; /* Not needed */
428 props.pr_pad = 3;
429 props.pr_diffmask = (D_SPARS|D_ATIME|D_CTIME);
430 props.pr_nflags = PR_LONG_NAMES;
431 props.pr_maxnamelen = PATH_MAX;
432 props.pr_maxlnamelen = PATH_MAX;
433 props.pr_maxsname = NAMSIZ-1; /* XXX Really ??? */
434 props.pr_maxslname = NAMSIZ-1; /* XXX Really ??? */
435 props.pr_maxprefix = 0;
436 props.pr_sparse_in_hdr = 0;
437 /*
438 * CPIO is limited to 7 basic file types
439 */
440 movebytes(xtcpio_tab, props.pr_xftypetab, sizeof (props.pr_xftypetab));
441 props.pr_xftypetab[XT_SOCK] = 0;
442 break;
443 }
444 if (debug) printprops();
445 }
446
447 EXPORT void
printprops()448 printprops()
449 {
450 extern long hdrtype;
451 error("hdrtype: %s (%ld)\n", hdr_name(hdrtype), hdrtype);
452 if (props.pr_maxsize)
453 error("pr_maxsize: %llu\n", (Ullong)props.pr_maxsize);
454 else
455 error("pr_maxsize: unlimited\n");
456 error("pr_flags: 0x%X\n", props.pr_flags);
457 error("pr_xhdflags: 0x%X\n", props.pr_xhdflags);
458 error("pr_xhmask: 0x%X\n", props.pr_xhmask);
459 error("pr_fillc: '%c'\n", props.pr_fillc);
460 prdiffopts(stderr, "pr_diffmask: ", props.pr_diffmask);
461 error("pr_nflags: 0x%X\n", props.pr_nflags);
462 error("pr_maxnamelen: %d\n", props.pr_maxnamelen);
463 error("pr_maxlnamelen: %d\n", props.pr_maxlnamelen);
464 error("pr_maxsname: %d\n", props.pr_maxsname);
465 error("pr_maxslname: %d\n", props.pr_maxslname);
466 error("pr_maxprefix: %d\n", props.pr_maxprefix);
467 error("pr_sparse_in_hdr: %d\n", props.pr_sparse_in_hdr);
468 }
469
470 LOCAL void
prsettypeflags(types,typeflag)471 prsettypeflags(types, typeflag)
472 char *types;
473 int typeflag;
474 {
475 register Uchar *ucp = (Uchar *)types;
476
477 /*
478 * 'Otar' flag for plain file is always a valid typeflag.
479 */
480 if (typeflag == TF_VALIDTYPE)
481 props.pr_typeflagtab[0] = typeflag;
482
483 while (*ucp != '\0')
484 props.pr_typeflagtab[*ucp++] |= typeflag;
485 }
486