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