1/*-
2 * Copyright (c) 1992 Keith Muller.
3 * Copyright (c) 1992, 1993
4 *	The Regents of the University of California.  All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Keith Muller of the University of California, San Diego.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35#if 0
36static const char sccsid[] = "@(#)tar.c	8.2 (Berkeley) 4/18/94";
37#else
38static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: tar.c,v 1.34 2004/10/23 19:34:14 otto Exp $";
39#endif
40#endif /* not lint */
41
42#include <sys/types.h>
43#include <sys/time.h>
44#include <sys/stat.h>
45#include <sys/param.h>
46#include <string.h>
47#include <stdio.h>
48#include <unistd.h>
49#include <stdlib.h>
50#include "pax.h"
51#include "extern.h"
52#include "tar.h"
53#include <fnmatch.h>
54#include <regex.h>
55#include "pat_rep.h"
56#include <errno.h>
57
58/*
59 * This file implements the -x pax format support; it is incomplete.
60 * Known missing features include:
61 *	many -o options for "copy" mode are not implemented (only path=)
62 *	many format specifiers for -o listopt are not implemented
63 *	-o listopt option should work for all archive formats, not just -x pax
64 * This file was originally derived from the file tar.c. You should
65 * 'diff' it to that file to see how much of the -x pax format has been implemented.
66 */
67
68char pax_eh_datablk[4*1024];
69int pax_read_or_list_mode = 0;
70int want_a_m_time_headers = 0;
71int want_linkdata = 0;
72
73int pax_invalid_action = 0;
74char *	pax_invalid_action_write_path = NULL;
75char *	pax_invalid_action_write_cwd = NULL;
76
77char
78	*path_g,	*path_x,	*path_g_current,	*path_x_current,
79	*uname_g,	*uname_x,	*uname_g_current,	*uname_x_current,
80	*gname_g,	*gname_x,	*gname_g_current,	*gname_x_current,
81	*comment_g,	*comment_x,	*comment_g_current,	*comment_x_current,
82	*charset_g,	*charset_x,	*charset_g_current,	*charset_x_current,
83	*atime_g,	*atime_x,	*atime_g_current,	*atime_x_current,
84	*gid_g,		*gid_x,		*gid_g_current,		*gid_x_current,
85	*linkpath_g,	*linkpath_x,	*linkpath_g_current,	*linkpath_x_current,
86	*mtime_g,	*mtime_x,	*mtime_g_current,	*mtime_x_current,
87	*size_g,	*size_x,	*size_g_current,	*size_x_current,
88	*uid_g,		*uid_x,		*uid_g_current,		*uid_x_current;
89
90char	*header_name_g_requested = NULL,
91	*header_name_x_requested = NULL;
92
93char	*header_name_g = "/tmp/GlobalHead.%p.%n",
94	*header_name_x = "%d/PaxHeaders.%p/%f";
95
96int	nglobal_headers = 0;
97char	*pax_list_opt_format;
98
99#define O_OPTION_ACTION_NOTIMPL		0
100#define O_OPTION_ACTION_INVALID		1
101#define O_OPTION_ACTION_DELETE		2
102#define O_OPTION_ACTION_STORE_HEADER	3
103#define O_OPTION_ACTION_TIMES		4
104#define O_OPTION_ACTION_HEADER_NAME	5
105#define O_OPTION_ACTION_LISTOPT		6
106#define O_OPTION_ACTION_LINKDATA	7
107
108#define O_OPTION_ACTION_IGNORE		8
109#define O_OPTION_ACTION_ERROR		9
110#define O_OPTION_ACTION_STORE_HEADER2	10
111
112#define ATTRSRC_FROM_NOWHERE		0
113#define ATTRSRC_FROM_X_O_OPTION		1
114#define ATTRSRC_FROM_G_O_OPTION		2
115#define ATTRSRC_FROM_X_HEADER		3
116#define ATTRSRC_FROM_G_HEADER		4
117
118#define KW_PATH_CASE	0
119#define KW_SKIP_CASE	-1
120
121typedef struct {
122	char *	name;
123	int	len;
124	int	active;			/* 1 means active, 0 means deleted via -o delete=		*/
125	int	cmdline_action;
126	int	header_action;
127	/* next 2 entries only used by store_header actions						*/
128	char **	g_value;		/* -o keyword= value						*/
129	char **	x_value;		/* -o keyword:= value						*/
130	char **	g_value_current;	/* keyword= value found in Global extended header		*/
131	char **	x_value_current;	/* keyword= value found in extended header			*/
132	int	header_inx;		/* starting index of header field this keyword represents	*/
133	int	header_len;		/* length of header field this keyword represents		*/
134					/* If negative, special cases line path=			*/
135} O_OPTION_TYPE;
136
137O_OPTION_TYPE o_option_table[] = {
138	{ "atime",	5,	1,	O_OPTION_ACTION_STORE_HEADER, O_OPTION_ACTION_STORE_HEADER,
139	&atime_g,	&atime_x,	&atime_g_current,	&atime_x_current,	0,	KW_SKIP_CASE	},
140	{ "charset",	7,	1,	O_OPTION_ACTION_STORE_HEADER, O_OPTION_ACTION_IGNORE,
141	&charset_g,	&charset_x,	&charset_g_current,	&charset_x_current,	0,	KW_SKIP_CASE	},
142	{ "comment",	7,	1,	O_OPTION_ACTION_STORE_HEADER, O_OPTION_ACTION_IGNORE,
143	&comment_g,	&comment_x,	&comment_g_current,	&comment_x_current,	0,	KW_SKIP_CASE	},
144	{ "gid",	3,	1,	O_OPTION_ACTION_STORE_HEADER2, O_OPTION_ACTION_STORE_HEADER2,
145	&gid_g,		&gid_x,		&gid_g_current,		&gid_x_current	,	116,	8		},
146	{ "gname",	5,	1,	O_OPTION_ACTION_STORE_HEADER2, O_OPTION_ACTION_STORE_HEADER2,
147	&gname_g,	&gname_x,	&gname_g_current,	&gname_x_current,	297,	32		},
148	{ "linkpath",	8,	1,	O_OPTION_ACTION_STORE_HEADER, O_OPTION_ACTION_STORE_HEADER,
149	&linkpath_g,	&linkpath_x,	&linkpath_g_current,	&linkpath_x_current,	0,	KW_SKIP_CASE	},
150	{ "mtime",	5,	1,	O_OPTION_ACTION_STORE_HEADER, O_OPTION_ACTION_STORE_HEADER,
151	&mtime_g,	&mtime_x,	&mtime_g_current,	&mtime_x_current,	136,	KW_SKIP_CASE	},
152	{ "path",	4,	1,	O_OPTION_ACTION_STORE_HEADER, O_OPTION_ACTION_STORE_HEADER,
153	&path_g,	&path_x,	&path_g_current,	&path_x_current,	0,	KW_PATH_CASE	},
154	{ "size",	4,	1,	O_OPTION_ACTION_STORE_HEADER, O_OPTION_ACTION_STORE_HEADER,
155	&size_g,	&size_x,	&size_g_current,	&size_x_current,	124,	KW_SKIP_CASE	},
156	{ "uid",	3,	1,	O_OPTION_ACTION_STORE_HEADER2, O_OPTION_ACTION_STORE_HEADER2,
157	&uid_g,		&uid_x,		&uid_g_current,		&uid_x_current,		108,	8		},
158	{ "uname",	5,	1,	O_OPTION_ACTION_STORE_HEADER2, O_OPTION_ACTION_STORE_HEADER2,
159	&uname_g,	&uname_x,	&uname_g_current,	&uname_x_current,	265,	32		},
160
161	{ "exthdr.name",  11,	1,	O_OPTION_ACTION_HEADER_NAME,	O_OPTION_ACTION_ERROR,
162	&header_name_x, &header_name_x_requested,	NULL,	NULL,	0,	KW_SKIP_CASE	},
163	{ "globexthdr.name", 15, 1,	O_OPTION_ACTION_HEADER_NAME,	O_OPTION_ACTION_ERROR,
164	&header_name_g, &header_name_g_requested,	NULL,	NULL,	0,	KW_SKIP_CASE	},
165
166	{ "delete",	6,	1,	O_OPTION_ACTION_DELETE,	 O_OPTION_ACTION_ERROR,
167	NULL,		NULL,		NULL,			NULL,	0,	KW_SKIP_CASE	},
168	{ "invalid",	7,	1,	O_OPTION_ACTION_INVALID,	 O_OPTION_ACTION_ERROR,
169	NULL,		NULL,		NULL,			NULL,	0,	KW_SKIP_CASE	},
170	{ "linkdata",	8,	1,	O_OPTION_ACTION_LINKDATA,	 O_OPTION_ACTION_ERROR,
171	NULL,		NULL,		NULL,			NULL,	0,	KW_SKIP_CASE	}, /* Test 241 */
172	{ "listopt",	7,	1,	O_OPTION_ACTION_LISTOPT,	 O_OPTION_ACTION_ERROR,
173	&pax_list_opt_format, NULL,	NULL,			NULL,	0,	KW_SKIP_CASE	}, /* Test 242 */
174		/* Note: listopt is supposed to apply for all formats, not just -x pax only	*/
175	{ "times",	5,	1,	O_OPTION_ACTION_TIMES,	 O_OPTION_ACTION_ERROR,
176	NULL,		NULL,		NULL,			NULL,	0,	KW_SKIP_CASE	},
177};
178
179int ext_header_inx,
180    global_ext_header_inx;
181
182/* Make these tables big enough to handle lots of -o options, not just one per table entry */
183int ext_header_entry       [4*sizeof(o_option_table)/sizeof(O_OPTION_TYPE)],
184    global_ext_header_entry[4*sizeof(o_option_table)/sizeof(O_OPTION_TYPE)];
185
186/*
187 * Routines for reading, writing and header identify of various versions of pax
188 */
189
190static size_t expandname(char *, size_t, char **, const char *, size_t);
191static u_long pax_chksm(char *, int);
192static char *name_split(char *, int);
193static int ul_oct(u_long, char *, int, int);
194#ifndef LONG_OFF_T
195static int uqd_oct(u_quad_t, char *, int, int);
196#endif
197
198static uid_t uid_nobody;
199static uid_t uid_warn;
200static gid_t gid_nobody;
201static gid_t gid_warn;
202
203/*
204 * Routines common to all versions of pax
205 */
206
207/*
208 * ul_oct()
209 *	convert an unsigned long to an octal string. many oddball field
210 *	termination characters are used by the various versions of tar in the
211 *	different fields. term selects which kind to use. str is '0' padded
212 *	at the front to len. we are unable to use only one format as many old
213 *	tar readers are very cranky about this.
214 * Return:
215 *	0 if the number fit into the string, -1 otherwise
216 */
217
218static int
219ul_oct(u_long val, char *str, int len, int term)
220{
221	char *pt;
222
223	/*
224	 * term selects the appropriate character(s) for the end of the string
225	 */
226	pt = str + len - 1;
227	switch (term) {
228	case 3:
229		*pt-- = '\0';
230		break;
231	case 2:
232		*pt-- = ' ';
233		*pt-- = '\0';
234		break;
235	case 1:
236		*pt-- = ' ';
237		break;
238	case 0:
239	default:
240		*pt-- = '\0';
241		*pt-- = ' ';
242		break;
243	}
244
245	/*
246	 * convert and blank pad if there is space
247	 */
248	while (pt >= str) {
249		*pt-- = '0' + (char)(val & 0x7);
250		if ((val = val >> 3) == (u_long)0)
251			break;
252	}
253
254	while (pt >= str)
255		*pt-- = '0';
256	if (val != (u_long)0)
257		return(-1);
258	return(0);
259}
260
261#ifndef LONG_OFF_T
262/*
263 * uqd_oct()
264 *	convert an u_quad_t to an octal string. one of many oddball field
265 *	termination characters are used by the various versions of tar in the
266 *	different fields. term selects which kind to use. str is '0' padded
267 *	at the front to len. we are unable to use only one format as many old
268 *	tar readers are very cranky about this.
269 * Return:
270 *	0 if the number fit into the string, -1 otherwise
271 */
272
273static int
274uqd_oct(u_quad_t val, char *str, int len, int term)
275{
276	char *pt;
277
278	/*
279	 * term selects the appropriate character(s) for the end of the string
280	 */
281	pt = str + len - 1;
282	switch (term) {
283	case 3:
284		*pt-- = '\0';
285		break;
286	case 2:
287		*pt-- = ' ';
288		*pt-- = '\0';
289		break;
290	case 1:
291		*pt-- = ' ';
292		break;
293	case 0:
294	default:
295		*pt-- = '\0';
296		*pt-- = ' ';
297		break;
298	}
299
300	/*
301	 * convert and blank pad if there is space
302	 */
303	while (pt >= str) {
304		*pt-- = '0' + (char)(val & 0x7);
305		if ((val = val >> 3) == 0)
306			break;
307	}
308
309	while (pt >= str)
310		*pt-- = '0';
311	if (val != (u_quad_t)0)
312		return(-1);
313	return(0);
314}
315#endif
316
317/*
318 * pax_chksm()
319 *	calculate the checksum for a pax block counting the checksum field as
320 *	all blanks (BLNKSUM is that value pre-calculated, the sum of 8 blanks).
321 *	NOTE: we use len to short circuit summing 0's on write since we ALWAYS
322 *	pad headers with 0.
323 * Return:
324 *	unsigned long checksum
325 */
326
327static u_long
328pax_chksm(char *blk, int len)
329{
330	char *stop;
331	char *pt;
332	u_long chksm = BLNKSUM;	/* initial value is checksum field sum */
333
334	/*
335	 * add the part of the block before the checksum field
336	 */
337	pt = blk;
338	stop = blk + CHK_OFFSET;
339	while (pt < stop)
340		chksm += (u_long)(*pt++ & 0xff);
341	/*
342	 * move past the checksum field and keep going, spec counts the
343	 * checksum field as the sum of 8 blanks (which is pre-computed as
344	 * BLNKSUM).
345	 * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding
346	 * starts, no point in summing zero's)
347	 */
348	pt += CHK_LEN;
349	stop = blk + len;
350	while (pt < stop)
351		chksm += (u_long)(*pt++ & 0xff);
352	return(chksm);
353}
354
355void
356pax_format_list_output(ARCHD *arcn, time_t now, FILE *fp, int term)
357{
358	/* parse specified listopt format */
359	char *nextpercent, *nextchar;
360	char buf[4*1024];
361	int pos, cpylen;
362	char *fname;
363
364	nextpercent = strchr(pax_list_opt_format,'%');
365	if (nextpercent==NULL) {
366		/* Strange case: no specifiers? */
367	 	safe_print(pax_list_opt_format, fp);
368		(void)putc(term, fp);
369		(void)fflush(fp);
370		return;
371	}
372	pos = nextpercent-pax_list_opt_format;
373	memcpy(buf,pax_list_opt_format, pos);
374	while (nextpercent++) {
375		switch (*nextpercent) {
376		case 'F':
377			fname = arcn->name;
378			cpylen = strlen(fname);
379			memcpy(&buf[pos],fname,cpylen);
380			pos+= cpylen;
381			break;
382		case 'D':
383		case 'T':
384		case 'M':
385		case 'L':
386		default:
387			paxwarn(1, "Unimplemented listopt format: %c",*nextpercent);
388			break;
389		}
390		nextpercent++;
391		if (*nextpercent=='\0') {
392			break;
393		}
394		nextchar = nextpercent;
395		nextpercent = strchr(nextpercent,'%');
396		if (nextpercent==NULL) {
397			cpylen = strlen(nextchar);
398		} else {
399			cpylen = nextpercent - nextchar;
400		}
401		memcpy(&buf[pos],nextchar, cpylen);
402		pos += cpylen;
403	}
404	buf[pos]='\0';
405 	safe_print(&buf[0], fp);
406	(void)putc(term, fp);
407	(void)fflush(fp);
408	return;
409}
410
411void
412cleanup_pax_invalid_action()
413{
414	switch (pax_invalid_action) {
415	case PAX_INVALID_ACTION_BYPASS:
416	case PAX_INVALID_ACTION_RENAME:
417		break;
418	case PAX_INVALID_ACTION_WRITE:
419		pax_invalid_action_write_path = NULL;
420		if (pax_invalid_action_write_cwd) {
421			free(pax_invalid_action_write_cwd);
422			pax_invalid_action_write_cwd = NULL;
423		}
424		break;
425	case PAX_INVALID_ACTION_UTF8:
426	default:
427		paxwarn(1, "pax_invalid_action not implemented:%d", pax_invalid_action);
428	}
429}
430
431void
432record_pax_invalid_action_results(ARCHD * arcn, char * fixed_path)
433{
434	switch (pax_invalid_action) {
435	case PAX_INVALID_ACTION_BYPASS:
436	case PAX_INVALID_ACTION_RENAME:
437		break;
438	case PAX_INVALID_ACTION_WRITE:
439		pax_invalid_action_write_path = fixed_path;
440		pax_invalid_action_write_cwd  = strdup(arcn->name);
441		pax_invalid_action_write_cwd[fixed_path-arcn->name-1] = '\0';
442		break;
443	case PAX_INVALID_ACTION_UTF8:
444	default:
445		paxwarn(1, "pax_invalid_action not implemented:%d", pax_invalid_action);
446	}
447}
448
449int
450perform_pax_invalid_action(ARCHD * arcn, int err)
451{
452	int rc = 0;
453	switch (pax_invalid_action) {
454	case PAX_INVALID_ACTION_BYPASS:
455		rc = -1;
456		break;
457	case PAX_INVALID_ACTION_RENAME:
458		rc = tty_rename(arcn);
459		break;
460	case PAX_INVALID_ACTION_WRITE:
461		pax_invalid_action_write_path = NULL;
462		pax_invalid_action_write_cwd = NULL;
463		rc = 2;
464		break;
465	case PAX_INVALID_ACTION_UTF8:
466	default:
467		paxwarn(1, "pax_invalid_action not implemented:%d", pax_invalid_action);
468		rc = -1;	/* do nothing? */
469	}
470	return rc;
471}
472
473static void
474delete_keywords(char * pattern)
475{
476	int i;
477	/* loop over all keywords, marking any matched as deleted */
478	for (i = 0; i < sizeof(o_option_table)/sizeof(O_OPTION_TYPE); i++) {
479		if (fnmatch(pattern, o_option_table[i].name, 0) == 0) {
480			/* Found option: mark deleted */
481			o_option_table[i].active = 0;
482		}
483	}
484}
485
486/*
487 * pax_opt()
488 *	handle pax format specific -o options
489 * Return:
490 *	0 if ok -1 otherwise
491 */
492
493int
494pax_opt(void)
495{
496	OPLIST *opt;
497	int got_option = 0;
498
499	while ((opt = opt_next()) != NULL) {
500		int i;
501		got_option = -1;
502		pax_invalid_action = PAX_INVALID_ACTION_BYPASS; /* Default for pax format */
503		/* look up opt->name */
504		for (i = 0; i < sizeof(o_option_table)/sizeof(O_OPTION_TYPE); i++) {
505			if (strncasecmp(opt->name, o_option_table[i].name, o_option_table[i].len) == 0) {
506				/* Found option: see if already set */
507				/* Save it away */
508				got_option = 1;
509				switch (o_option_table[i].cmdline_action) {
510				case O_OPTION_ACTION_INVALID:
511					if (opt->separator != SEP_EQ) {
512						paxwarn(1,"-o %s= option requires '=' separator: option ignored",
513								opt->name);
514						break;
515					}
516					if (opt->value) {
517						if (strncasecmp(opt->value,"bypass",6) == 0) {
518							pax_invalid_action = PAX_INVALID_ACTION_BYPASS;
519						} else if (strncasecmp(opt->value,"rename",6) == 0) {
520							pax_invalid_action = PAX_INVALID_ACTION_RENAME;
521						} else if (strncasecmp(opt->value,"UTF-8",5) == 0) {
522							pax_invalid_action = PAX_INVALID_ACTION_UTF8;
523						} else if (strncasecmp(opt->value,"write",5) == 0) {
524							pax_invalid_action = PAX_INVALID_ACTION_WRITE;
525						} else {
526							paxwarn(1,"Invalid action %s not recognized: option ignored",
527								opt->value);
528						}
529					} else {
530						paxwarn(1,"Invalid action RHS not specified: option ignored");
531					}
532					break;
533				case O_OPTION_ACTION_DELETE:
534					if (opt->separator != SEP_EQ) {
535						paxwarn(1,"-o %s= option requires '=' separator: option ignored",
536								opt->name);
537						break;
538					}
539					/* Mark all matches as deleted */
540					/* can have multiple -o delete= patterns */
541					delete_keywords(opt->value);
542					break;
543				case O_OPTION_ACTION_STORE_HEADER2:
544					if(pax_read_or_list_mode) pids = 1;	/* Force -p o for these options */
545				case O_OPTION_ACTION_STORE_HEADER:
546					if (o_option_table[i].g_value == NULL ||
547					    o_option_table[i].x_value == NULL ) {
548						paxwarn(1,"-o option not implemented: %s=%s",
549								opt->name, opt->value);
550					} else {
551						if (opt->separator == SEP_EQ) {
552							*(o_option_table[i].g_value) = opt->value;
553							global_ext_header_entry[global_ext_header_inx++] = i;
554                				} else if (opt->separator == SEP_COLONEQ ) {
555							*(o_option_table[i].x_value) = opt->value;
556							ext_header_entry       [ext_header_inx++] = i;
557				                } else {        /* SEP_NONE */
558							paxwarn(1,"-o %s option is missing value", opt->name);
559				                }
560					}
561					break;
562				case O_OPTION_ACTION_TIMES:
563					if (opt->separator != SEP_NONE) {
564						paxwarn(1,"-o %s option takes no value: option ignored", opt->name);
565						break;
566					}
567					want_a_m_time_headers = 1;
568					break;
569				case O_OPTION_ACTION_LINKDATA:
570					if (opt->separator != SEP_NONE) {
571						paxwarn(1,"-o %s option takes no value: option ignored", opt->name);
572						break;
573					}
574					want_linkdata = 1;
575					break;
576				case O_OPTION_ACTION_HEADER_NAME:
577					if (opt->separator != SEP_EQ) {
578						paxwarn(1,"-o %s= option requires '=' separator: option ignored",
579								opt->name);
580						break;
581					}
582					*(o_option_table[i].g_value) = opt->value;
583					*(o_option_table[i].x_value) = "YES";
584					break;
585				case O_OPTION_ACTION_LISTOPT:
586					if (opt->separator != SEP_EQ) {
587						paxwarn(1,"-o %s= option requires '=' separator: option ignored",
588								opt->name);
589						break;
590					}
591					*(o_option_table[i].g_value) = opt->value;
592					break;
593				case O_OPTION_ACTION_NOTIMPL:
594				default:
595					paxwarn(1,"pax format -o option not yet implemented: %s=%s",
596						    opt->name, opt->value);
597					break;
598				}
599				break;
600			}
601		}
602		if (got_option == -1) {
603			paxwarn(1,"pax format -o option not recognized: %s=%s",
604			    opt->name, opt->value);
605		}
606	}
607	return(0);
608}
609
610static int
611expand_extended_headers(ARCHD *arcn, HD_USTAR *hd)
612{
613	char mybuf[BLKMULT];
614	HD_USTAR *myhd;
615	char * current_value;
616	int path_replaced = 0;
617	int i, len;
618
619	myhd = hd;
620	while (myhd->typeflag == PAXGTYPE ||  myhd->typeflag == PAXXTYPE) {
621		char *name, *str;
622		int size, nbytes, inx;
623		size = asc_ul(myhd->size, sizeof(myhd->size), OCT);
624		if (size > sizeof(mybuf)) {
625			paxwarn(1,"extended header buffer overflow");
626			exit(1);
627		}
628		nbytes = rd_wrbuf(mybuf, size);
629		if (nbytes != size) {
630			paxwarn(1,"extended header data read failure: nbytes=%d, size=%d\n",
631				nbytes, size);
632			exit(1);
633		}
634		/*
635		printf("Read 1 extended header: type=%c, size=%d\n",
636				myhd->typeflag, size);
637		*/
638		inx=0;
639		/* loop over buffer collecting attributes  */
640		while (nbytes > 0) {
641			int got_option = -1;
642			int nentries = sscanf(&mybuf[inx],"%d ", &len);
643			if (nentries != 1) {
644				paxwarn(1,"Extended header failure: length");
645				exit(1);
646			}
647			if (len < 0 || (inx+len-1 >= sizeof(mybuf))) {
648				paxwarn(1, "Extended header failure: invalid length (%d)", len);
649				exit(1);
650			}
651			if (mybuf[inx+len-1] != '\n') {
652				paxwarn(1,"Extended header failure: missed newline");
653				exit(1);
654			} else
655				mybuf[inx+len-1] = '\0';
656			name = strchr(&mybuf[inx],' ');
657			if (name) name++;
658			else {
659				paxwarn(1,"Extended header failure: missing space");
660				exit(1);
661			}
662			str = strchr(name,'=');
663			if (str) {
664				*str++='\0'; /* end of name */
665			} else {
666				paxwarn(1,"Extended header failure: missing RHS string");
667				exit(1);
668			}
669			for (i = 0; i < sizeof(o_option_table)/sizeof(O_OPTION_TYPE); i++) {
670				if (strncasecmp(name, o_option_table[i].name, o_option_table[i].len) == 0) {
671					/* Found option: see if already set TBD */
672					/* Save it away */
673					got_option = i;
674					break;
675				}
676			}
677			if (got_option == -1) {
678				paxwarn(1,"Unrecognized header keyword: %s",name);
679			} else {
680				/* Determine precedence of -o and header attributes */
681				int found_value = ATTRSRC_FROM_NOWHERE;
682				current_value = NULL;
683				if (myhd->typeflag == PAXXTYPE) {
684					if (*o_option_table[got_option].x_value) {
685						current_value = *o_option_table[got_option].x_value;
686						found_value = ATTRSRC_FROM_X_O_OPTION;
687					} else {
688						current_value = str;
689						found_value = ATTRSRC_FROM_X_HEADER;
690					}
691				} else if (myhd->typeflag == PAXGTYPE) {
692					if (*o_option_table[got_option].g_value) {
693						current_value = *o_option_table[got_option].g_value;
694						found_value = ATTRSRC_FROM_G_O_OPTION;
695					} else {
696						current_value = str;
697						found_value = ATTRSRC_FROM_G_HEADER;
698					}
699				} else {
700					paxwarn(1,"Unsupported header type:%c",myhd->typeflag);
701				}
702				if (current_value) {
703					/* Save this attribute value for use later */
704					switch (o_option_table[got_option].header_action) {
705					case O_OPTION_ACTION_IGNORE:
706						paxwarn(1,"ignoring header keyword: %s",name);
707						break;
708					case O_OPTION_ACTION_STORE_HEADER2:
709					case O_OPTION_ACTION_STORE_HEADER:
710						switch (found_value) {
711						case ATTRSRC_FROM_NOWHERE: /* shouldn't happen */
712							paxwarn(1, "internal error: value from nowhere");
713							break;
714						case ATTRSRC_FROM_X_O_OPTION:
715						case ATTRSRC_FROM_G_O_OPTION:
716							break;
717						case ATTRSRC_FROM_X_HEADER:
718							current_value = strdup(current_value);
719							if(*o_option_table[got_option].x_value_current)
720								free(*o_option_table[got_option].x_value_current);
721							*o_option_table[got_option].x_value_current = current_value;
722							break;
723						case ATTRSRC_FROM_G_HEADER:
724							current_value = strdup(current_value);
725							if(*o_option_table[got_option].g_value_current)
726								free(*o_option_table[got_option].g_value_current);
727							*o_option_table[got_option].g_value_current = current_value;
728							break;
729						}
730						break;
731					case O_OPTION_ACTION_ERROR:
732					default:
733						paxwarn(1,"Unsupported extended header attribute: %s=%s",
734							name, str);
735					}
736				}
737			}
738			inx+=len;
739			nbytes -= len;
740		}
741
742		/* position file at next header */
743		(void)rd_skip(TAR_PAD(size));
744
745		/* read next header */
746		nbytes = rd_wrbuf(mybuf, frmt->hsz);
747		if (nbytes != frmt->hsz) {
748			paxwarn(1,"extended header read failure: nbytes=%d, size=%d\n",
749				nbytes, frmt->hsz);
750		}
751		myhd = ((HD_USTAR *)mybuf);
752		/* repeat until no more extended headers */
753	}
754
755	/* The header about to be returned must now be updated using all the extended
756	   header values collected and any command line options */
757	/* Acceleration: check during command option processing. If there are no -o
758	   options, and no changes from any header, do not need to run through this loop. */
759
760	current_value = NULL;
761	for (i = 0; i < sizeof(o_option_table)/sizeof(O_OPTION_TYPE); i++) {
762		int header_len, free_it;
763		if (!o_option_table[i].active) continue; /* deleted keywords */
764		header_len = o_option_table[i].header_len;
765		free_it = 0;
766		if (header_len >= 0) {	/* Normal keywords */
767			current_value = *o_option_table[i].x_value;
768			if (!current_value) {	/* No -o := */
769				current_value = *o_option_table[i].x_value_current;
770				if (current_value) {
771					/* Must remove it: x header values not valid beyond this header */
772					*o_option_table[i].x_value_current = NULL;
773					free_it = 1;
774				} else {	/* No x values, try globals */
775					current_value = *o_option_table[i].g_value;
776					if (!current_value)
777						current_value = *o_option_table[i].g_value_current;
778				}
779			}
780			if (current_value) {
781				/* Update current header with this value */
782				/*
783				printf ("Found current_value:%s for %s,  pids=%d\n",
784					current_value, o_option_table[i].name, pids);
785				*/
786				len = strlen(current_value);
787				if (header_len == KW_PATH_CASE) {	/* Special case for path keyword */
788					path_replaced = 1;
789					arcn->nlen = len;
790					strlcpy(arcn->name,current_value,sizeof(arcn->name));
791				} else {
792					if (len > header_len) {
793						paxwarn(1," length of string from extended header bigger than header field:"
794							" THAT won't work!\n");
795					} else {
796						char * p = (char *) myhd;
797						memcpy(&p[o_option_table[i].header_inx],
798							current_value, len);
799						if (len != header_len) {
800							/* pad with ? */
801							p[o_option_table[i].header_inx+len] = '\0';
802						}
803					}
804				}
805			}
806			if (free_it) free(current_value);
807		}
808	}
809
810	if (myhd==hd) return(path_replaced);
811
812	/* must put new header into memory of original */
813	memcpy(hd, myhd, sizeof(HD_USTAR));
814
815	return(path_replaced);
816}
817
818/*
819 * pax_id()
820 *	determine if a block given to us is a valid pax header. We have to
821 *	be on the lookout for those pesky blocks of all zero's
822 * Return:
823 *	0 if a ustar header, -1 otherwise
824 */
825
826int
827pax_id(char *blk, int size)
828{
829	HD_USTAR *hd;
830
831	if (size < BLKMULT)
832		return(-1);
833	hd = (HD_USTAR *)blk;
834
835	/*
836	 * check for block of zero's first, a simple and fast test then check
837	 * ustar magic cookie. We should use TMAGLEN, but some USTAR archive
838	 * programs are fouled up and create archives missing the \0. Last we
839	 * check the checksum. If ok we have to assume it is a valid header.
840	 */
841	if (hd->name[0] == '\0')
842		return(-1);
843	if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0)
844		return(-1);
845	if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != pax_chksm(blk,BLKMULT))
846		return(-1);
847	if ((hd->typeflag != PAXXTYPE) && (hd->typeflag != PAXGTYPE)) {
848		/* Not explicitly pax format, but at least ustar */
849		if (act==LIST || act==EXTRACT) {
850			/* Although insufficient evidence, call it pax format */
851			return(0);
852		}
853		return(-1);
854	}
855	pax_invalid_action = PAX_INVALID_ACTION_BYPASS; /* Default for pax format */
856	return(0);
857}
858
859/*
860 * pax_rd()
861 *	extract the values out of block already determined to be a pax header.
862 *	store the values in the ARCHD parameter.
863 * Return:
864 *	0
865 */
866
867int
868pax_rd(ARCHD *arcn, char *buf)
869{
870	HD_USTAR *hd;
871	int cnt = 0;
872	int check_path;
873	dev_t devmajor;
874	dev_t devminor;
875
876	/*
877	 * we only get proper sized buffers
878	 */
879	if (pax_id(buf, BLKMULT) < 0)
880		return(-1);
881
882	memset(arcn, 0, sizeof(*arcn));
883	arcn->org_name = arcn->name;
884	arcn->sb.st_nlink = 1;
885	hd = (HD_USTAR *)buf;
886
887	check_path = expand_extended_headers(arcn, hd);
888
889	if (check_path) {
890		/*
891		 * pathname derived from extended head or -o option;
892		 * full name is in one string, but length may exceed
893		 * max path so be careful.
894		 */
895		if (arcn->nlen > sizeof(arcn->name)) {
896			paxwarn(1,"pathname from extended header info  doesn't fit! (len=%d)\n",
897				arcn->nlen);
898		}
899	} else {
900		/*
901		 * see if the filename is split into two parts. if so, join the parts.
902		 * we copy the prefix first and add a / between the prefix and name.
903		 */
904		char *dest = arcn->name;
905		if (*(hd->prefix) != '\0') {
906			cnt = strlcpy(dest, hd->prefix, sizeof(arcn->name) - 1);
907			dest += cnt;
908			*dest++ = '/';
909			cnt++;
910		} else {
911			cnt = 0;
912		}
913
914		if (hd->typeflag != LONGLINKTYPE && hd->typeflag != LONGNAMETYPE) {
915			arcn->nlen = cnt + expandname(dest, sizeof(arcn->name) - cnt,
916			    &gnu_name_string, hd->name, sizeof(hd->name));
917			arcn->ln_nlen = expandname(arcn->ln_name, sizeof(arcn->ln_name),
918			    &gnu_link_string, hd->linkname, sizeof(hd->linkname));
919		}
920	}
921
922	/*
923	 * follow the spec to the letter. we should only have mode bits, strip
924	 * off all other crud we may be passed.
925	 */
926	arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) &
927	    0xfff);
928#ifdef LONG_OFF_T
929	arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT);
930#else
931	arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT);
932#endif
933	arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT);
934	arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime;
935
936	/*
937	 * If we can find the ascii names for gname and uname in the password
938	 * and group files we will use the uid's and gid they bind. Otherwise
939	 * we use the uid and gid values stored in the header. (This is what
940	 * the posix spec wants).
941	 */
942	hd->gname[sizeof(hd->gname) - 1] = '\0';
943	if (gid_name(hd->gname, &(arcn->sb.st_gid)) < 0)
944		arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT);
945	hd->uname[sizeof(hd->uname) - 1] = '\0';
946	if (uid_name(hd->uname, &(arcn->sb.st_uid)) < 0)
947		arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT);
948
949	/*
950	 * set the defaults, these may be changed depending on the file type
951	 */
952	arcn->pad = 0;
953	arcn->skip = 0;
954	arcn->sb.st_rdev = (dev_t)0;
955
956	/*
957	 * set the mode and PAX type according to the typeflag in the header
958	 */
959	switch (hd->typeflag) {
960	case FIFOTYPE:
961		arcn->type = PAX_FIF;
962		arcn->sb.st_mode |= S_IFIFO;
963		break;
964	case DIRTYPE:
965		arcn->type = PAX_DIR;
966		arcn->sb.st_mode |= S_IFDIR;
967		arcn->sb.st_nlink = 2;
968
969		/*
970		 * Some programs that create pax archives append a '/'
971		 * to the pathname for directories. This clearly violates
972		 * pax specs, but we will silently strip it off anyway.
973		 */
974		if (arcn->name[arcn->nlen - 1] == '/')
975			arcn->name[--arcn->nlen] = '\0';
976		break;
977	case BLKTYPE:
978	case CHRTYPE:
979		/*
980		 * this type requires the rdev field to be set.
981		 */
982		if (hd->typeflag == BLKTYPE) {
983			arcn->type = PAX_BLK;
984			arcn->sb.st_mode |= S_IFBLK;
985		} else {
986			arcn->type = PAX_CHR;
987			arcn->sb.st_mode |= S_IFCHR;
988		}
989		devmajor = (dev_t)asc_ul(hd->devmajor,sizeof(hd->devmajor),OCT);
990		devminor = (dev_t)asc_ul(hd->devminor,sizeof(hd->devminor),OCT);
991		arcn->sb.st_rdev = TODEV(devmajor, devminor);
992		break;
993	case SYMTYPE:
994	case LNKTYPE:
995		if (hd->typeflag == SYMTYPE) {
996			arcn->type = PAX_SLK;
997			arcn->sb.st_mode |= S_IFLNK;
998		} else {
999			arcn->type = PAX_HLK;
1000			/*
1001			 * so printing looks better
1002			 */
1003			arcn->sb.st_mode |= S_IFREG;
1004			arcn->sb.st_nlink = 2;
1005		}
1006		break;
1007	case LONGLINKTYPE:
1008	case LONGNAMETYPE:
1009		/*
1010		 * GNU long link/file; we tag these here and let the
1011		 * pax internals deal with it -- too ugly otherwise.
1012		 */
1013		arcn->type =
1014		    hd->typeflag == LONGLINKTYPE ? PAX_GLL : PAX_GLF;
1015		arcn->pad = TAR_PAD(arcn->sb.st_size);
1016		arcn->skip = arcn->sb.st_size;
1017		break;
1018	case CONTTYPE:
1019	case AREGTYPE:
1020	case REGTYPE:
1021	default:
1022		/*
1023		 * these types have file data that follows. Set the skip and
1024		 * pad fields.
1025		 */
1026		arcn->type = PAX_REG;
1027		arcn->pad = TAR_PAD(arcn->sb.st_size);
1028		arcn->skip = arcn->sb.st_size;
1029		arcn->sb.st_mode |= S_IFREG;
1030		break;
1031	}
1032	return(0);
1033}
1034
1035void
1036adjust_copy_for_pax_options(ARCHD * arcn)
1037{
1038	/* Because ext_header options take precedence over global_header options, apply
1039	   global options first, then override with any extended header options 	*/
1040	int i;
1041	if (global_ext_header_inx) {
1042		for (i=0; i < global_ext_header_inx; i++) {
1043			if (!o_option_table[global_ext_header_entry[i]].active) continue; /* deleted keywords */
1044			if (strcmp(o_option_table[global_ext_header_entry[i]].name, "path")==0) {
1045				strlcpy(arcn->name,*(o_option_table[global_ext_header_entry[i]].g_value),
1046						sizeof(arcn->name));
1047				arcn->nlen = strlen(*(o_option_table[global_ext_header_entry[i]].g_value));
1048			} else {	/* only handle path for now: others TBD */
1049				paxwarn(1, "adjust arcn for global extended header options not implemented:%d", i);
1050			}
1051		}
1052	}
1053	if (ext_header_inx) {
1054		for (i=0; i < ext_header_inx; i++) {
1055			if (!o_option_table[ext_header_entry[i]].active) continue; /* deleted keywords */
1056			if (strcmp(o_option_table[ext_header_entry[i]].name, "path")==0) {
1057				strlcpy(arcn->name,*(o_option_table[ext_header_entry[i]].x_value),
1058						sizeof(arcn->name));
1059				arcn->nlen = strlen(*(o_option_table[ext_header_entry[i]].x_value));
1060			} else {	/* only handle path for now: others TBD */
1061				paxwarn(1, "adjust arcn for extended header options not implemented:%d", i);
1062			}
1063		}
1064	}
1065	if (want_a_m_time_headers) {
1066		/* TBD */
1067	}
1068}
1069
1070static int
1071emit_extended_header_record(int len, int total_len, int head_type,
1072				char * name, char * value)
1073{
1074	if (total_len + len > sizeof(pax_eh_datablk)) {
1075		paxwarn(1,"extended header buffer overflow for header type '%c': %d",
1076				head_type, total_len+len);
1077	} else {
1078		sprintf(&pax_eh_datablk[total_len],"%d %s=%s\n", len, name, value);
1079		total_len += len;
1080	}
1081	return (total_len);
1082}
1083
1084__attribute__((__malloc__))
1085static char *
1086substitute_percent(char * header, char * filename)
1087{
1088	char *nextpercent, *nextchar;
1089	char buf[4*1024];
1090	int pos, cpylen;
1091	char *dname, *fname;
1092
1093	nextpercent = strchr(header,'%');
1094	if (nextpercent==NULL) return strdup(header);
1095	pos = nextpercent-header;
1096	memcpy(buf,header, pos);
1097	while (nextpercent++) {
1098		switch (*nextpercent) {
1099		case '%':
1100			buf[pos++]='%';	/* just skip it */
1101			break;
1102		case 'd':
1103			dname = strrchr(filename,'/');
1104			if (dname==NULL) {
1105				cpylen = 1;
1106				dname = ".";
1107			} else {
1108				cpylen = dname-filename;
1109				dname = filename;
1110			}
1111			memcpy(&buf[pos],dname,cpylen);
1112			pos+= cpylen;
1113			break;
1114		case 'f':
1115			fname = strrchr(filename,'/');
1116			if (fname==NULL) {
1117				fname = filename;
1118			} else {
1119				fname++;
1120			}
1121			cpylen = strlen(fname);
1122			memcpy(&buf[pos],fname,cpylen);
1123			pos+= cpylen;
1124			break;
1125		case 'n':
1126			pos += sprintf (&buf[pos],"%d",nglobal_headers);
1127			break;
1128		case 'p':
1129			pos += sprintf (&buf[pos],"%d",getpid());
1130			break;
1131		default:
1132			paxwarn(1,"header format substitution failed: '%c'", *nextpercent);
1133			return strdup(header);
1134		}
1135		nextpercent++;
1136		if (*nextpercent=='\0') {
1137			break;
1138		}
1139		nextchar = nextpercent;
1140		nextpercent = strchr(nextpercent,'%');
1141		if (nextpercent==NULL) {
1142			cpylen = strlen(nextchar);
1143		} else {
1144			cpylen = nextpercent - nextchar;
1145		}
1146		memcpy(&buf[pos],nextchar, cpylen);
1147		pos += cpylen;
1148	}
1149	buf[pos]='\0';
1150	return (strdup(&buf[0]));
1151}
1152
1153static int
1154generate_pax_ext_header_and_data(ARCHD *arcn, int nfields, int *table,
1155				char header_type, char * header_name, char * header_name_requested)
1156{
1157	HD_USTAR *hd;
1158	char hdblk[sizeof(HD_USTAR)];
1159	u_long	records_size;
1160	int term_char, i, len, total_len;
1161	char * str, *name;
1162
1163	if (nfields == 0 && (header_name_requested == NULL)) {
1164		if (header_type==PAXXTYPE) {
1165			if (!want_a_m_time_headers) return (0);
1166		} else
1167			return (0);
1168	}
1169
1170	/* There might be no fields but a header with a specific name or
1171	   times might be wanted */
1172
1173	term_char = 1;
1174	memset(hdblk, 0, sizeof(hdblk));
1175	hd = (HD_USTAR *)hdblk;
1176	memset(pax_eh_datablk, 0, sizeof(pax_eh_datablk));
1177
1178	/* generate header */
1179	hd->typeflag = header_type;
1180
1181	/* These fields appear to be necessary to be able to treat extended headers
1182	   like files in older versions of pax */
1183	ul_oct((u_long)0444, hd->mode, sizeof(hd->mode), term_char);
1184	strncpy(hd->magic, TMAGIC, TMAGLEN);
1185	strncpy(hd->version, TVERSION, TVERSLEN);
1186	ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),term_char);
1187
1188	/* compute size of data */
1189	total_len = 0;
1190	for (i=0; i < nfields; i++) {
1191		if (!o_option_table[table[i]].active) continue; /* deleted keywords */
1192		name = o_option_table[table[i]].name;
1193		if (header_type == PAXXTYPE) {
1194			str = *(o_option_table[table[i]].x_value);
1195		} else {
1196			str = *(o_option_table[table[i]].g_value);
1197		}
1198		if (str==NULL) {
1199			paxwarn(1,"Missing option value for %s", name);
1200			continue;
1201		}
1202		len = strlen(str) + o_option_table[table[i]].len + 3;
1203		if (len < 9) len++;
1204		else if (len < 98)	len = len + 2;
1205		else if (len < 997)	len = len + 3;
1206		else if (len < 9996)	len = len + 4;
1207		else {
1208			paxwarn(1,"extended header data too long for header type '%c': %d",
1209					header_type, len);
1210		}
1211		total_len = emit_extended_header_record(len, total_len,
1212					header_type, name, str);
1213	}
1214
1215	if ((header_type == PAXXTYPE) && want_a_m_time_headers) {
1216		char time_buffer[12];
1217		memset(time_buffer,0,sizeof(time_buffer));
1218		sprintf(&time_buffer[0],"%d",(int)arcn->sb.st_atime);
1219		/* 3 chars + strlen("atime") + time + # chars in len */
1220		len = 3 + 5 + strlen(&time_buffer[0]) + 2;
1221		total_len = emit_extended_header_record(len, total_len,
1222				header_type, "atime", &time_buffer[0]);
1223		memset(time_buffer,0,sizeof(time_buffer));
1224		sprintf(&time_buffer[0],"%d",(int)arcn->sb.st_mtime);
1225		/* 3 chars + strlen("mtime") + time + # chars in len */
1226		len = 3 + 5 + strlen(&time_buffer[0]) + 2;
1227		total_len = emit_extended_header_record(len, total_len,
1228				header_type, "mtime", &time_buffer[0]);
1229	}
1230
1231	/* Check if all fields were deleted: might not need to generate anything */
1232	if ((total_len==0) && (header_name_requested == NULL)) return (0);
1233
1234	if (header_type == PAXGTYPE) nglobal_headers++;
1235	/* substitution of fields in header_name */
1236	header_name = substitute_percent(header_name, arcn->name);
1237	if (strlen(header_name) == sizeof(hd->name)) {	/* must account for name just fits in buffer */
1238		strncpy(hd->name, header_name, sizeof(hd->name));
1239	} else {
1240		strlcpy(hd->name, header_name, sizeof(hd->name));
1241	}
1242
1243	free(header_name);
1244	header_name = NULL;
1245	records_size = (u_long)total_len;
1246	if (ul_oct(records_size, hd->size, sizeof(hd->size), term_char)) {
1247		paxwarn(1,"extended header data too long for header type '%c'", header_type);
1248		return(1);
1249	}
1250
1251	if (ul_oct(pax_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum, sizeof(hd->chksum), term_char)) {
1252		paxwarn(1,"extended header data checksum failed: header type '%c'", header_type);
1253		return(1);
1254	}
1255
1256	/* write out header */
1257	if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0)
1258		return(-1);
1259	if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0)
1260		return(-1);
1261	/* write out header data */
1262	if (total_len > 0) {
1263		if (wr_rdbuf(pax_eh_datablk, total_len) < 0)
1264			return(-1);
1265		if (wr_skip((off_t)(BLKMULT - total_len)) < 0)
1266			return(-1);
1267		/*
1268		printf("data written:\n%s",&pax_eh_datablk[0]);
1269		*/
1270	}
1271
1272	/*
1273	paxwarn(0,"extended header and data written: header type '%c', #items: %d, %d characters",
1274				header_type, nfields, records_size);
1275	*/
1276	return (0);
1277}
1278
1279/*
1280 * pax_wr()
1281 *	write a pax header for the file specified in the ARCHD to the archive
1282 *	Have to check for file types that cannot be stored and file names that
1283 *	are too long. Be careful of the term (last arg) to ul_oct, we only use
1284 *	'\0' for the termination character (this is different than picky tar)
1285 *	ASSUMED: space after header in header block is zero filled
1286 * Return:
1287 *	0 if file has data to be written after the header, 1 if file has NO
1288 *	data to write after the header, -1 if archive write failed
1289 */
1290
1291int
1292pax_wr(ARCHD *arcn)
1293{
1294	HD_USTAR *hd;
1295	char *pt;
1296	char hdblk[sizeof(HD_USTAR)];
1297	mode_t mode12only;
1298	int term_char=3;	/* orignal setting */
1299	term_char=1;		/* To pass conformance tests 274, 301 */
1300
1301	/*
1302	 * check for those file system types pax cannot store
1303	 */
1304	if (arcn->type == PAX_SCK) {
1305		paxwarn(1, "Pax cannot archive a socket %s", arcn->org_name);
1306		return(1);
1307	}
1308
1309	/*
1310	 * check the length of the linkname
1311	 */
1312	if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) ||
1313	    (arcn->type == PAX_HRG)) && (arcn->ln_nlen > sizeof(hd->linkname))){
1314		paxwarn(1, "Link name too long for pax %s", arcn->ln_name);
1315		/*
1316		 * Conformance: test pax:285 wants error code to be non-zero, and
1317		 * test tar:12 wants error code from pax to be 0
1318		 */
1319		return(1);
1320	}
1321
1322	/*
1323	 * split the path name into prefix and name fields (if needed). if
1324	 * pt != arcn->name, the name has to be split
1325	 */
1326	if ((pt = name_split(arcn->name, arcn->nlen)) == NULL) {
1327		paxwarn(1, "File name too long for pax %s", arcn->name);
1328		return(1);
1329	}
1330
1331	generate_pax_ext_header_and_data(arcn, global_ext_header_inx, &global_ext_header_entry[0],
1332					PAXGTYPE, header_name_g, header_name_g_requested);
1333	generate_pax_ext_header_and_data(arcn, ext_header_inx, &ext_header_entry[0],
1334					PAXXTYPE, header_name_x, header_name_x_requested);
1335
1336	/*
1337	 * zero out the header so we don't have to worry about zero fill below
1338	 */
1339	memset(hdblk, 0, sizeof(hdblk));
1340	hd = (HD_USTAR *)hdblk;
1341	arcn->pad = 0L;
1342	/* To pass conformance tests 274/301, always set these fields to "zero" */
1343	ul_oct(0, hd->devmajor, sizeof(hd->devmajor), term_char);
1344	ul_oct(0, hd->devminor, sizeof(hd->devminor), term_char);
1345
1346	/*
1347	 * split the name, or zero out the prefix
1348	 */
1349	if (pt != arcn->name) {
1350		/*
1351		 * name was split, pt points at the / where the split is to
1352		 * occur, we remove the / and copy the first part to the prefix
1353		 */
1354		*pt = '\0';
1355		strlcpy(hd->prefix, arcn->name, sizeof(hd->prefix));
1356		*pt++ = '/';
1357	}
1358
1359	/*
1360	 * copy the name part. this may be the whole path or the part after
1361	 * the prefix
1362	 */
1363	if (strlen(pt) == sizeof(hd->name)) {	/* must account for name just fits in buffer */
1364		strncpy(hd->name, pt, sizeof(hd->name));
1365	} else {
1366		strlcpy(hd->name, pt, sizeof(hd->name));
1367	}
1368
1369	/*
1370	 * set the fields in the header that are type dependent
1371	 */
1372	switch (arcn->type) {
1373	case PAX_DIR:
1374		hd->typeflag = DIRTYPE;
1375		if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), term_char))
1376			goto out;
1377		break;
1378	case PAX_CHR:
1379	case PAX_BLK:
1380		if (arcn->type == PAX_CHR)
1381			hd->typeflag = CHRTYPE;
1382		else
1383			hd->typeflag = BLKTYPE;
1384		if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor,
1385		   sizeof(hd->devmajor), term_char) ||
1386		   ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor,
1387		   sizeof(hd->devminor), term_char) ||
1388		   ul_oct((u_long)0L, hd->size, sizeof(hd->size), term_char))
1389			goto out;
1390		break;
1391	case PAX_FIF:
1392		hd->typeflag = FIFOTYPE;
1393		if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), term_char))
1394			goto out;
1395		break;
1396	case PAX_SLK:
1397	case PAX_HLK:
1398	case PAX_HRG:
1399		if (arcn->type == PAX_SLK)
1400			hd->typeflag = SYMTYPE;
1401		else
1402			hd->typeflag = LNKTYPE;
1403		if (strlen(arcn->ln_name) == sizeof(hd->linkname)) {	/* must account for name just fits in buffer */
1404			strncpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname));
1405		} else {
1406			strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname));
1407		}
1408		if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), term_char))
1409			goto out;
1410		break;
1411	case PAX_REG:
1412	case PAX_CTG:
1413	default:
1414		/*
1415		 * file data with this type, set the padding
1416		 */
1417		if (arcn->type == PAX_CTG)
1418			hd->typeflag = CONTTYPE;
1419		else
1420			hd->typeflag = REGTYPE;
1421		arcn->pad = TAR_PAD(arcn->sb.st_size);
1422#		ifdef LONG_OFF_T
1423		if (ul_oct((u_long)arcn->sb.st_size, hd->size,
1424		    sizeof(hd->size), term_char)) {
1425#		else
1426		if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size,
1427		    sizeof(hd->size), term_char)) {
1428#		endif
1429			paxwarn(1,"File is too long for pax %s",arcn->org_name);
1430			return(1);
1431		}
1432		break;
1433	}
1434
1435	strncpy(hd->magic, TMAGIC, TMAGLEN);
1436	strncpy(hd->version, TVERSION, TVERSLEN);
1437
1438	/*
1439	 * set the remaining fields. Some versions want all 16 bits of mode
1440	 * we better humor them (they really do not meet spec though)....
1441	 */
1442	if (ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), term_char)) {
1443		if (uid_nobody == 0) {
1444			if (uid_name("nobody", &uid_nobody) == -1)
1445				goto out;
1446		}
1447		if (uid_warn != arcn->sb.st_uid) {
1448			uid_warn = arcn->sb.st_uid;
1449			paxwarn(1,
1450			    "Pax header field is too small for uid %lu, "
1451			    "using nobody", (u_long)arcn->sb.st_uid);
1452		}
1453		if (ul_oct((u_long)uid_nobody, hd->uid, sizeof(hd->uid), term_char))
1454			goto out;
1455	}
1456	if (ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), term_char)) {
1457		if (gid_nobody == 0) {
1458			if (gid_name("nobody", &gid_nobody) == -1)
1459				goto out;
1460		}
1461		if (gid_warn != arcn->sb.st_gid) {
1462			gid_warn = arcn->sb.st_gid;
1463			paxwarn(1,
1464			    "Pax header field is too small for gid %lu, "
1465			    "using nobody", (u_long)arcn->sb.st_gid);
1466		}
1467		if (ul_oct((u_long)gid_nobody, hd->gid, sizeof(hd->gid), term_char))
1468			goto out;
1469	}
1470	/* However, Unix conformance tests do not like MORE than 12 mode bits:
1471	   remove all beyond (see definition of stat.st_mode structure)		*/
1472	mode12only = ((u_long)arcn->sb.st_mode) & 0x00000fff;
1473	if (ul_oct((u_long)mode12only, hd->mode, sizeof(hd->mode), term_char) ||
1474	    ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),term_char))
1475		goto out;
1476	strncpy(hd->uname, name_uid(arcn->sb.st_uid, 0), sizeof(hd->uname));
1477	strncpy(hd->gname, name_gid(arcn->sb.st_gid, 0), sizeof(hd->gname));
1478
1479	/*
1480	 * calculate and store the checksum write the header to the archive
1481	 * return 0 tells the caller to now write the file data, 1 says no data
1482	 * needs to be written
1483	 */
1484	if (ul_oct(pax_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum,
1485	   sizeof(hd->chksum), term_char))
1486		goto out;
1487	if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0)
1488		return(-1);
1489	if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0)
1490		return(-1);
1491	if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG))
1492		return(0);
1493	return(1);
1494
1495    out:
1496	/*
1497	 * header field is out of range
1498	 */
1499	paxwarn(1, "Pax header field is too small for %s", arcn->org_name);
1500	return(1);
1501}
1502
1503/*
1504 * name_split()
1505 *	see if the name has to be split for storage in a ustar header. We try
1506 *	to fit the entire name in the name field without splitting if we can.
1507 *	The split point is always at a /
1508 * Return
1509 *	character pointer to split point (always the / that is to be removed
1510 *	if the split is not needed, the points is set to the start of the file
1511 *	name (it would violate the spec to split there). A NULL is returned if
1512 *	the file name is too long
1513 */
1514
1515static char *
1516name_split(char *name, int len)
1517{
1518	char *start;
1519
1520	/*
1521	 * check to see if the file name is small enough to fit in the name
1522	 * field. if so just return a pointer to the name.
1523	 */
1524	if (len <= TNMSZ)
1525		return(name);
1526	if (len > (TPFSZ + TNMSZ))
1527		return(NULL);
1528
1529	/*
1530	 * we start looking at the biggest sized piece that fits in the name
1531	 * field. We walk forward looking for a slash to split at. The idea is
1532	 * to find the biggest piece to fit in the name field (or the smallest
1533	 * prefix we can find)
1534	 */
1535	start = name + len - TNMSZ -1;
1536	if ((*start == '/') && (start == name))
1537		++start;	/* 101 byte paths with leading '/' are dinged otherwise */
1538	while ((*start != '\0') && (*start != '/'))
1539		++start;
1540
1541	/*
1542	 * if we hit the end of the string, this name cannot be split, so we
1543	 * cannot store this file.
1544	 */
1545	if (*start == '\0')
1546		return(NULL);
1547	len = start - name;
1548
1549	/*
1550	 * NOTE: /str where the length of str == TNMSZ can not be stored under
1551	 * the p1003.1-1990 spec for ustar. We could force a prefix of / and
1552	 * the file would then expand on extract to //str. The len == 0 below
1553	 * makes this special case follow the spec to the letter.
1554	 */
1555	if ((len >= TPFSZ) || (len == 0))
1556		return(NULL);
1557
1558	/*
1559	 * ok have a split point, return it to the caller
1560	 */
1561	return(start);
1562}
1563
1564static size_t
1565expandname(char *buf, size_t len, char **gnu_name, const char *name, size_t name_len)
1566{
1567	size_t nlen;
1568
1569	if (*gnu_name) {
1570		if ((nlen = strlcpy(buf, *gnu_name, len)) >= len)
1571			nlen = len - 1;
1572		free(*gnu_name);
1573		*gnu_name = NULL;
1574	} else {
1575		if (name_len < len) {
1576			/* name may not be null terminated: it might be as big as the
1577			   field,  so copy is limited to the max size of the header field */
1578			if ((nlen = strlcpy(buf, name, name_len+1)) >= name_len+1)
1579				nlen = name_len;
1580		} else {
1581			if ((nlen = strlcpy(buf, name, len)) >= len)
1582				nlen = len - 1;
1583		}
1584	}
1585	return(nlen);
1586}
1587