2 * Copyright (c) 1992 Keith Muller.
3 * Copyright (c) 1992, 1993
4 * The Regents of the University of California. All rights reserved.
6 * This code is derived from software contributed to Berkeley by
7 * Keith Muller of the University of California, San Diego.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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
36 static const char sccsid
[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94";
38 static const char rcsid
[] __attribute__((__unused__
)) = "$OpenBSD: tar.c,v 1.34 2004/10/23 19:34:14 otto Exp $";
42 #include <sys/types.h>
45 #include <sys/param.h>
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.
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;
73 int pax_invalid_action
= 0;
74 char * pax_invalid_action_write_path
= NULL
;
75 char * pax_invalid_action_write_cwd
= NULL
;
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
;
90 char *header_name_g_requested
= NULL
,
91 *header_name_x_requested
= NULL
;
93 char *header_name_g
= "/tmp/GlobalHead.%p.%n",
94 *header_name_x
= "%d/PaxHeaders.%p/%f";
96 int nglobal_headers
= 0;
97 char *pax_list_opt_format
;
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
108 #define O_OPTION_ACTION_IGNORE 8
109 #define O_OPTION_ACTION_ERROR 9
110 #define O_OPTION_ACTION_STORE_HEADER2 10
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
118 #define KW_PATH_CASE 0
119 #define KW_SKIP_CASE -1
124 int active
; /* 1 means active, 0 means deleted via -o delete= */
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= */
137 O_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 },
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
},
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
},
180 global_ext_header_inx
;
182 /* Make these tables big enough to handle lots of -o options, not just one per table entry */
183 int 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
)];
187 * Routines for reading, writing and header identify of various versions of pax
190 static size_t expandname(char *, size_t, char **, const char *, size_t);
191 static u_long
pax_chksm(char *, int);
192 static char *name_split(char *, int);
193 static int ul_oct(u_long
, char *, int, int);
195 static int uqd_oct(u_quad_t
, char *, int, int);
198 static uid_t uid_nobody
;
199 static uid_t uid_warn
;
200 static gid_t gid_nobody
;
201 static gid_t gid_warn
;
204 * Routines common to all versions of pax
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.
215 * 0 if the number fit into the string, -1 otherwise
219 ul_oct(u_long val
, char *str
, int len
, int term
)
224 * term selects the appropriate character(s) for the end of the string
246 * convert and blank pad if there is space
249 *pt
-- = '0' + (char)(val
& 0x7);
250 if ((val
= val
>> 3) == (u_long
)0)
256 if (val
!= (u_long
)0)
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.
270 * 0 if the number fit into the string, -1 otherwise
274 uqd_oct(u_quad_t val
, char *str
, int len
, int term
)
279 * term selects the appropriate character(s) for the end of the string
301 * convert and blank pad if there is space
304 *pt
-- = '0' + (char)(val
& 0x7);
305 if ((val
= val
>> 3) == 0)
311 if (val
!= (u_quad_t
)0)
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.
324 * unsigned long checksum
328 pax_chksm(char *blk
, int len
)
332 u_long chksm
= BLNKSUM
; /* initial value is checksum field sum */
335 * add the part of the block before the checksum field
338 stop
= blk
+ CHK_OFFSET
;
340 chksm
+= (u_long
)(*pt
++ & 0xff);
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
345 * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding
346 * starts, no point in summing zero's)
351 chksm
+= (u_long
)(*pt
++ & 0xff);
356 pax_format_list_output(ARCHD
*arcn
, time_t now
, FILE *fp
, int term
)
358 /* parse specified listopt format */
359 char *nextpercent
, *nextchar
;
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
);
372 pos
= nextpercent
-pax_list_opt_format
;
373 memcpy(buf
,pax_list_opt_format
, pos
);
374 while (nextpercent
++) {
375 switch (*nextpercent
) {
378 cpylen
= strlen(fname
);
379 memcpy(&buf
[pos
],fname
,cpylen
);
387 paxwarn(1, "Unimplemented listopt format: %c",*nextpercent
);
391 if (*nextpercent
=='\0') {
394 nextchar
= nextpercent
;
395 nextpercent
= strchr(nextpercent
,'%');
396 if (nextpercent
==NULL
) {
397 cpylen
= strlen(nextchar
);
399 cpylen
= nextpercent
- nextchar
;
401 memcpy(&buf
[pos
],nextchar
, cpylen
);
405 safe_print(&buf
[0], fp
);
406 (void)putc(term
, fp
);
412 cleanup_pax_invalid_action()
414 switch (pax_invalid_action
) {
415 case PAX_INVALID_ACTION_BYPASS
:
416 case PAX_INVALID_ACTION_RENAME
:
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
;
425 case PAX_INVALID_ACTION_UTF8
:
427 paxwarn(1, "pax_invalid_action not implemented:%d", pax_invalid_action
);
432 record_pax_invalid_action_results(ARCHD
* arcn
, char * fixed_path
)
434 switch (pax_invalid_action
) {
435 case PAX_INVALID_ACTION_BYPASS
:
436 case PAX_INVALID_ACTION_RENAME
:
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';
443 case PAX_INVALID_ACTION_UTF8
:
445 paxwarn(1, "pax_invalid_action not implemented:%d", pax_invalid_action
);
450 perform_pax_invalid_action(ARCHD
* arcn
, int err
)
453 switch (pax_invalid_action
) {
454 case PAX_INVALID_ACTION_BYPASS
:
457 case PAX_INVALID_ACTION_RENAME
:
458 rc
= tty_rename(arcn
);
460 case PAX_INVALID_ACTION_WRITE
:
461 pax_invalid_action_write_path
= NULL
;
462 pax_invalid_action_write_cwd
= NULL
;
465 case PAX_INVALID_ACTION_UTF8
:
467 paxwarn(1, "pax_invalid_action not implemented:%d", pax_invalid_action
);
468 rc
= -1; /* do nothing? */
474 delete_keywords(char * pattern
)
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;
488 * handle pax format specific -o options
490 * 0 if ok -1 otherwise
499 while ((opt
= opt_next()) != NULL
) {
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 */
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",
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
;
526 paxwarn(1,"Invalid action %s not recognized: option ignored",
530 paxwarn(1,"Invalid action RHS not specified: option ignored");
533 case O_OPTION_ACTION_DELETE
:
534 if (opt
->separator
!= SEP_EQ
) {
535 paxwarn(1,"-o %s= option requires '=' separator: option ignored",
539 /* Mark all matches as deleted */
540 /* can have multiple -o delete= patterns */
541 delete_keywords(opt
->value
);
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
);
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
);
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
);
567 want_a_m_time_headers
= 1;
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
);
576 case O_OPTION_ACTION_HEADER_NAME
:
577 if (opt
->separator
!= SEP_EQ
) {
578 paxwarn(1,"-o %s= option requires '=' separator: option ignored",
582 *(o_option_table
[i
].g_value
) = opt
->value
;
583 *(o_option_table
[i
].x_value
) = "YES";
585 case O_OPTION_ACTION_LISTOPT
:
586 if (opt
->separator
!= SEP_EQ
) {
587 paxwarn(1,"-o %s= option requires '=' separator: option ignored",
591 *(o_option_table
[i
].g_value
) = opt
->value
;
593 case O_OPTION_ACTION_NOTIMPL
:
595 paxwarn(1,"pax format -o option not yet implemented: %s=%s",
596 opt
->name
, opt
->value
);
602 if (got_option
== -1) {
603 paxwarn(1,"pax format -o option not recognized: %s=%s",
604 opt
->name
, opt
->value
);
611 expand_extended_headers(ARCHD
*arcn
, HD_USTAR
*hd
)
615 char * current_value
;
616 int path_replaced
= 0;
620 while (myhd
->typeflag
== PAXGTYPE
|| myhd
->typeflag
== PAXXTYPE
) {
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");
628 nbytes
= rd_wrbuf(mybuf
, size
);
629 if (nbytes
!= size
) {
630 paxwarn(1,"extended header data read failure: nbytes=%d, size=%d\n",
635 printf("Read 1 extended header: type=%c, size=%d\n",
636 myhd->typeflag, size);
639 /* loop over buffer collecting attributes */
642 int nentries
= sscanf(&mybuf
[inx
],"%d ", &len
);
644 paxwarn(1,"Extended header failure: length");
647 if (len
< 0 || (inx
+len
-1 >= sizeof(mybuf
))) {
648 paxwarn(1, "Extended header failure: invalid length (%d)", len
);
651 if (mybuf
[inx
+len
-1] != '\n') {
652 paxwarn(1,"Extended header failure: missed newline");
655 mybuf
[inx
+len
-1] = '\0';
656 name
= strchr(&mybuf
[inx
],' ');
659 paxwarn(1,"Extended header failure: missing space");
662 str
= strchr(name
,'=');
664 *str
++='\0'; /* end of name */
666 paxwarn(1,"Extended header failure: missing RHS string");
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 */
677 if (got_option
== -1) {
678 paxwarn(1,"Unrecognized header keyword: %s",name
);
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
;
689 found_value
= ATTRSRC_FROM_X_HEADER
;
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
;
697 found_value
= ATTRSRC_FROM_G_HEADER
;
700 paxwarn(1,"Unsupported header type:%c",myhd
->typeflag
);
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
);
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");
714 case ATTRSRC_FROM_X_O_OPTION
:
715 case ATTRSRC_FROM_G_O_OPTION
:
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
;
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
;
731 case O_OPTION_ACTION_ERROR
:
733 paxwarn(1,"Unsupported extended header attribute: %s=%s",
742 /* position file at next header */
743 (void)rd_skip(TAR_PAD(size
));
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",
751 myhd
= ((HD_USTAR
*)mybuf
);
752 /* repeat until no more extended headers */
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. */
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
;
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
;
771 /* Must remove it: x header values not valid beyond this header */
772 *o_option_table
[i
].x_value_current
= NULL
;
774 } else { /* No x values, try globals */
775 current_value
= *o_option_table
[i
].g_value
;
777 current_value
= *o_option_table
[i
].g_value_current
;
781 /* Update current header with this value */
783 printf ("Found current_value:%s for %s, pids=%d\n",
784 current_value, o_option_table[i].name, pids);
786 len
= strlen(current_value
);
787 if (header_len
== KW_PATH_CASE
) { /* Special case for path keyword */
790 strlcpy(arcn
->name
,current_value
,sizeof(arcn
->name
));
792 if (len
> header_len
) {
793 paxwarn(1," length of string from extended header bigger than header field:"
794 " THAT won't work!\n");
796 char * p
= (char *) myhd
;
797 memcpy(&p
[o_option_table
[i
].header_inx
],
799 if (len
!= header_len
) {
801 p
[o_option_table
[i
].header_inx
+len
] = '\0';
806 if (free_it
) free(current_value
);
810 if (myhd
==hd
) return(path_replaced
);
812 /* must put new header into memory of original */
813 memcpy(hd
, myhd
, sizeof(HD_USTAR
));
815 return(path_replaced
);
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
823 * 0 if a ustar header, -1 otherwise
827 pax_id(char *blk
, int size
)
833 hd
= (HD_USTAR
*)blk
;
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.
841 if (hd
->name
[0] == '\0')
843 if (strncmp(hd
->magic
, TMAGIC
, TMAGLEN
- 1) != 0)
845 if (asc_ul(hd
->chksum
,sizeof(hd
->chksum
),OCT
) != pax_chksm(blk
,BLKMULT
))
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 */
855 pax_invalid_action
= PAX_INVALID_ACTION_BYPASS
; /* Default for pax format */
861 * extract the values out of block already determined to be a pax header.
862 * store the values in the ARCHD parameter.
868 pax_rd(ARCHD
*arcn
, char *buf
)
877 * we only get proper sized buffers
879 if (pax_id(buf
, BLKMULT
) < 0)
882 memset(arcn
, 0, sizeof(*arcn
));
883 arcn
->org_name
= arcn
->name
;
884 arcn
->sb
.st_nlink
= 1;
885 hd
= (HD_USTAR
*)buf
;
887 check_path
= expand_extended_headers(arcn
, hd
);
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.
895 if (arcn
->nlen
> sizeof(arcn
->name
)) {
896 paxwarn(1,"pathname from extended header info doesn't fit! (len=%d)\n",
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.
904 char *dest
= arcn
->name
;
905 if (*(hd
->prefix
) != '\0') {
906 cnt
= strlcpy(dest
, hd
->prefix
, sizeof(arcn
->name
) - 1);
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
));
923 * follow the spec to the letter. we should only have mode bits, strip
924 * off all other crud we may be passed.
926 arcn
->sb
.st_mode
= (mode_t
)(asc_ul(hd
->mode
, sizeof(hd
->mode
), OCT
) &
929 arcn
->sb
.st_size
= (off_t
)asc_ul(hd
->size
, sizeof(hd
->size
), OCT
);
931 arcn
->sb
.st_size
= (off_t
)asc_uqd(hd
->size
, sizeof(hd
->size
), OCT
);
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
;
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).
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
);
950 * set the defaults, these may be changed depending on the file type
954 arcn
->sb
.st_rdev
= (dev_t
)0;
957 * set the mode and PAX type according to the typeflag in the header
959 switch (hd
->typeflag
) {
961 arcn
->type
= PAX_FIF
;
962 arcn
->sb
.st_mode
|= S_IFIFO
;
965 arcn
->type
= PAX_DIR
;
966 arcn
->sb
.st_mode
|= S_IFDIR
;
967 arcn
->sb
.st_nlink
= 2;
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.
974 if (arcn
->name
[arcn
->nlen
- 1] == '/')
975 arcn
->name
[--arcn
->nlen
] = '\0';
980 * this type requires the rdev field to be set.
982 if (hd
->typeflag
== BLKTYPE
) {
983 arcn
->type
= PAX_BLK
;
984 arcn
->sb
.st_mode
|= S_IFBLK
;
986 arcn
->type
= PAX_CHR
;
987 arcn
->sb
.st_mode
|= S_IFCHR
;
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
);
995 if (hd
->typeflag
== SYMTYPE
) {
996 arcn
->type
= PAX_SLK
;
997 arcn
->sb
.st_mode
|= S_IFLNK
;
999 arcn
->type
= PAX_HLK
;
1001 * so printing looks better
1003 arcn
->sb
.st_mode
|= S_IFREG
;
1004 arcn
->sb
.st_nlink
= 2;
1010 * GNU long link/file; we tag these here and let the
1011 * pax internals deal with it -- too ugly otherwise.
1014 hd
->typeflag
== LONGLINKTYPE ? PAX_GLL
: PAX_GLF
;
1015 arcn
->pad
= TAR_PAD(arcn
->sb
.st_size
);
1016 arcn
->skip
= arcn
->sb
.st_size
;
1023 * these types have file data that follows. Set the skip and
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
;
1036 adjust_copy_for_pax_options(ARCHD
* arcn
)
1038 /* Because ext_header options take precedence over global_header options, apply
1039 global options first, then override with any extended header options */
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
);
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
);
1065 if (want_a_m_time_headers
) {
1071 emit_extended_header_record(int len
, int total_len
, int head_type
,
1072 char * name
, char * value
)
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
);
1078 sprintf(&pax_eh_datablk
[total_len
],"%d %s=%s\n", len
, name
, value
);
1084 __attribute__((__malloc__
))
1086 substitute_percent(char * header
, char * filename
)
1088 char *nextpercent
, *nextchar
;
1091 char *dname
, *fname
;
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
) {
1100 buf
[pos
++]='%'; /* just skip it */
1103 dname
= strrchr(filename
,'/');
1108 cpylen
= dname
-filename
;
1111 memcpy(&buf
[pos
],dname
,cpylen
);
1115 fname
= strrchr(filename
,'/');
1121 cpylen
= strlen(fname
);
1122 memcpy(&buf
[pos
],fname
,cpylen
);
1126 pos
+= sprintf (&buf
[pos
],"%d",nglobal_headers
);
1129 pos
+= sprintf (&buf
[pos
],"%d",getpid());
1132 paxwarn(1,"header format substitution failed: '%c'", *nextpercent
);
1133 return strdup(header
);
1136 if (*nextpercent
=='\0') {
1139 nextchar
= nextpercent
;
1140 nextpercent
= strchr(nextpercent
,'%');
1141 if (nextpercent
==NULL
) {
1142 cpylen
= strlen(nextchar
);
1144 cpylen
= nextpercent
- nextchar
;
1146 memcpy(&buf
[pos
],nextchar
, cpylen
);
1150 return (strdup(&buf
[0]));
1154 generate_pax_ext_header_and_data(ARCHD
*arcn
, int nfields
, int *table
,
1155 char header_type
, char * header_name
, char * header_name_requested
)
1158 char hdblk
[sizeof(HD_USTAR
)];
1159 u_long records_size
;
1160 int term_char
, i
, len
, total_len
;
1163 if (nfields
== 0 && (header_name_requested
== NULL
)) {
1164 if (header_type
==PAXXTYPE
) {
1165 if (!want_a_m_time_headers
) return (0);
1170 /* There might be no fields but a header with a specific name or
1171 times might be wanted */
1174 memset(hdblk
, 0, sizeof(hdblk
));
1175 hd
= (HD_USTAR
*)hdblk
;
1176 memset(pax_eh_datablk
, 0, sizeof(pax_eh_datablk
));
1178 /* generate header */
1179 hd
->typeflag
= header_type
;
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
);
1188 /* compute size of data */
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
);
1196 str
= *(o_option_table
[table
[i
]].g_value
);
1199 paxwarn(1,"Missing option value for %s", name
);
1202 len
= strlen(str
) + o_option_table
[table
[i
]].len
+ 3;
1204 else if (len
< 98) len
= len
+ 2;
1205 else if (len
< 997) len
= len
+ 3;
1206 else if (len
< 9996) len
= len
+ 4;
1208 paxwarn(1,"extended header data too long for header type '%c': %d",
1211 total_len
= emit_extended_header_record(len
, total_len
,
1212 header_type
, name
, str
);
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]);
1231 /* Check if all fields were deleted: might not need to generate anything */
1232 if ((total_len
==0) && (header_name_requested
== NULL
)) return (0);
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
));
1240 strlcpy(hd
->name
, header_name
, sizeof(hd
->name
));
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
);
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
);
1256 /* write out header */
1257 if (wr_rdbuf(hdblk
, sizeof(HD_USTAR
)) < 0)
1259 if (wr_skip((off_t
)(BLKMULT
- sizeof(HD_USTAR
))) < 0)
1261 /* write out header data */
1262 if (total_len
> 0) {
1263 if (wr_rdbuf(pax_eh_datablk
, total_len
) < 0)
1265 if (wr_skip((off_t
)(BLKMULT
- total_len
)) < 0)
1268 printf("data written:\n%s",&pax_eh_datablk[0]);
1273 paxwarn(0,"extended header and data written: header type '%c', #items: %d, %d characters",
1274 header_type, nfields, records_size);
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
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
1296 char hdblk
[sizeof(HD_USTAR
)];
1298 int term_char
=3; /* orignal setting */
1299 term_char
=1; /* To pass conformance tests 274, 301 */
1302 * check for those file system types pax cannot store
1304 if (arcn
->type
== PAX_SCK
) {
1305 paxwarn(1, "Pax cannot archive a socket %s", arcn
->org_name
);
1310 * check the length of the linkname
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
);
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
1323 * split the path name into prefix and name fields (if needed). if
1324 * pt != arcn->name, the name has to be split
1326 if ((pt
= name_split(arcn
->name
, arcn
->nlen
)) == NULL
) {
1327 paxwarn(1, "File name too long for pax %s", arcn
->name
);
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
);
1337 * zero out the header so we don't have to worry about zero fill below
1339 memset(hdblk
, 0, sizeof(hdblk
));
1340 hd
= (HD_USTAR
*)hdblk
;
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
);
1347 * split the name, or zero out the prefix
1349 if (pt
!= arcn
->name
) {
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
1355 strlcpy(hd
->prefix
, arcn
->name
, sizeof(hd
->prefix
));
1360 * copy the name part. this may be the whole path or the part after
1363 if (strlen(pt
) == sizeof(hd
->name
)) { /* must account for name just fits in buffer */
1364 strncpy(hd
->name
, pt
, sizeof(hd
->name
));
1366 strlcpy(hd
->name
, pt
, sizeof(hd
->name
));
1370 * set the fields in the header that are type dependent
1372 switch (arcn
->type
) {
1374 hd
->typeflag
= DIRTYPE
;
1375 if (ul_oct((u_long
)0L, hd
->size
, sizeof(hd
->size
), term_char
))
1380 if (arcn
->type
== PAX_CHR
)
1381 hd
->typeflag
= CHRTYPE
;
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
))
1392 hd
->typeflag
= FIFOTYPE
;
1393 if (ul_oct((u_long
)0L, hd
->size
, sizeof(hd
->size
), term_char
))
1399 if (arcn
->type
== PAX_SLK
)
1400 hd
->typeflag
= SYMTYPE
;
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
));
1406 strlcpy(hd
->linkname
, arcn
->ln_name
, sizeof(hd
->linkname
));
1408 if (ul_oct((u_long
)0L, hd
->size
, sizeof(hd
->size
), term_char
))
1415 * file data with this type, set the padding
1417 if (arcn
->type
== PAX_CTG
)
1418 hd
->typeflag
= CONTTYPE
;
1420 hd
->typeflag
= REGTYPE
;
1421 arcn
->pad
= TAR_PAD(arcn
->sb
.st_size
);
1423 if (ul_oct((u_long
)arcn
->sb
.st_size
, hd
->size
,
1424 sizeof(hd
->size
), term_char
)) {
1426 if (uqd_oct((u_quad_t
)arcn
->sb
.st_size
, hd
->size
,
1427 sizeof(hd
->size
), term_char
)) {
1429 paxwarn(1,"File is too long for pax %s",arcn
->org_name
);
1435 strncpy(hd
->magic
, TMAGIC
, TMAGLEN
);
1436 strncpy(hd
->version
, TVERSION
, TVERSLEN
);
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)....
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)
1447 if (uid_warn
!= arcn
->sb
.st_uid
) {
1448 uid_warn
= arcn
->sb
.st_uid
;
1450 "Pax header field is too small for uid %lu, "
1451 "using nobody", (u_long
)arcn
->sb
.st_uid
);
1453 if (ul_oct((u_long
)uid_nobody
, hd
->uid
, sizeof(hd
->uid
), term_char
))
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)
1461 if (gid_warn
!= arcn
->sb
.st_gid
) {
1462 gid_warn
= arcn
->sb
.st_gid
;
1464 "Pax header field is too small for gid %lu, "
1465 "using nobody", (u_long
)arcn
->sb
.st_gid
);
1467 if (ul_oct((u_long
)gid_nobody
, hd
->gid
, sizeof(hd
->gid
), term_char
))
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
))
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
));
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
1484 if (ul_oct(pax_chksm(hdblk
, sizeof(HD_USTAR
)), hd
->chksum
,
1485 sizeof(hd
->chksum
), term_char
))
1487 if (wr_rdbuf(hdblk
, sizeof(HD_USTAR
)) < 0)
1489 if (wr_skip((off_t
)(BLKMULT
- sizeof(HD_USTAR
))) < 0)
1491 if ((arcn
->type
== PAX_CTG
) || (arcn
->type
== PAX_REG
))
1497 * header field is out of range
1499 paxwarn(1, "Pax header field is too small for %s", arcn
->org_name
);
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 /
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
1516 name_split(char *name
, int len
)
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.
1526 if (len
> (TPFSZ
+ TNMSZ
))
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)
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
!= '/'))
1542 * if we hit the end of the string, this name cannot be split, so we
1543 * cannot store this file.
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.
1555 if ((len
>= TPFSZ
) || (len
== 0))
1559 * ok have a split point, return it to the caller
1565 expandname(char *buf
, size_t len
, char **gnu_name
, const char *name
, size_t name_len
)
1570 if ((nlen
= strlcpy(buf
, *gnu_name
, len
)) >= len
)
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)
1581 if ((nlen
= strlcpy(buf
, name
, len
)) >= len
)