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