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
120 #define KW_ATIME_CASE -2
125 int active
; /* 1 means active, 0 means deleted via -o delete= */
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= */
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 },
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
},
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
},
181 global_ext_header_inx
;
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
)];
188 * Routines for reading, writing and header identify of various versions of pax
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);
196 static int uqd_oct(u_quad_t
, char *, int, int);
199 static uid_t uid_nobody
;
200 static uid_t uid_warn
;
201 static gid_t gid_nobody
;
202 static gid_t gid_warn
;
205 * Routines common to all versions of pax
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.
216 * 0 if the number fit into the string, -1 otherwise
220 ul_oct(u_long val
, char *str
, int len
, int term
)
225 * term selects the appropriate character(s) for the end of the string
247 * convert and blank pad if there is space
250 *pt
-- = '0' + (char)(val
& 0x7);
251 if ((val
= val
>> 3) == (u_long
)0)
257 if (val
!= (u_long
)0)
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.
271 * 0 if the number fit into the string, -1 otherwise
275 uqd_oct(u_quad_t val
, char *str
, int len
, int term
)
280 * term selects the appropriate character(s) for the end of the string
302 * convert and blank pad if there is space
305 *pt
-- = '0' + (char)(val
& 0x7);
306 if ((val
= val
>> 3) == 0)
312 if (val
!= (u_quad_t
)0)
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.
325 * unsigned long checksum
329 pax_chksm(char *blk
, int len
)
333 u_long chksm
= BLNKSUM
; /* initial value is checksum field sum */
336 * add the part of the block before the checksum field
339 stop
= blk
+ CHK_OFFSET
;
341 chksm
+= (u_long
)(*pt
++ & 0xff);
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
346 * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding
347 * starts, no point in summing zero's)
352 chksm
+= (u_long
)(*pt
++ & 0xff);
357 pax_format_list_output(ARCHD
*arcn
, time_t now
, FILE *fp
, int term
)
359 /* parse specified listopt format */
360 char *nextpercent
, *nextchar
;
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
);
373 pos
= nextpercent
-pax_list_opt_format
;
374 memcpy(buf
,pax_list_opt_format
, pos
);
375 while (nextpercent
++) {
376 switch (*nextpercent
) {
379 cpylen
= strlen(fname
);
380 memcpy(&buf
[pos
],fname
,cpylen
);
388 paxwarn(1, "Unimplemented listopt format: %c",*nextpercent
);
392 if (*nextpercent
=='\0') {
395 nextchar
= nextpercent
;
396 nextpercent
= strchr(nextpercent
,'%');
397 if (nextpercent
==NULL
) {
398 cpylen
= strlen(nextchar
);
400 cpylen
= nextpercent
- nextchar
;
402 memcpy(&buf
[pos
],nextchar
, cpylen
);
406 safe_print(&buf
[0], fp
);
407 (void)putc(term
, fp
);
413 cleanup_pax_invalid_action()
415 switch (pax_invalid_action
) {
416 case PAX_INVALID_ACTION_BYPASS
:
417 case PAX_INVALID_ACTION_RENAME
:
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
;
426 case PAX_INVALID_ACTION_UTF8
:
428 paxwarn(1, "pax_invalid_action not implemented:%d", pax_invalid_action
);
433 record_pax_invalid_action_results(ARCHD
* arcn
, char * fixed_path
)
435 switch (pax_invalid_action
) {
436 case PAX_INVALID_ACTION_BYPASS
:
437 case PAX_INVALID_ACTION_RENAME
:
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';
444 case PAX_INVALID_ACTION_UTF8
:
446 paxwarn(1, "pax_invalid_action not implemented:%d", pax_invalid_action
);
451 perform_pax_invalid_action(ARCHD
* arcn
, int err
)
454 switch (pax_invalid_action
) {
455 case PAX_INVALID_ACTION_BYPASS
:
458 case PAX_INVALID_ACTION_RENAME
:
459 rc
= tty_rename(arcn
);
461 case PAX_INVALID_ACTION_WRITE
:
462 pax_invalid_action_write_path
= NULL
;
463 pax_invalid_action_write_cwd
= NULL
;
466 case PAX_INVALID_ACTION_UTF8
:
468 paxwarn(1, "pax_invalid_action not implemented:%d", pax_invalid_action
);
469 rc
= -1; /* do nothing? */
475 delete_keywords(char * pattern
)
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;
489 * handle pax format specific -o options
491 * 0 if ok -1 otherwise
500 while ((opt
= opt_next()) != NULL
) {
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 */
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",
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
;
527 paxwarn(1,"Invalid action %s not recognized: option ignored",
531 paxwarn(1,"Invalid action RHS not specified: option ignored");
534 case O_OPTION_ACTION_DELETE
:
535 if (opt
->separator
!= SEP_EQ
) {
536 paxwarn(1,"-o %s= option requires '=' separator: option ignored",
540 /* Mark all matches as deleted */
541 /* can have multiple -o delete= patterns */
542 delete_keywords(opt
->value
);
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
);
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
);
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
);
568 want_a_m_time_headers
= 1;
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
);
577 case O_OPTION_ACTION_HEADER_NAME
:
578 if (opt
->separator
!= SEP_EQ
) {
579 paxwarn(1,"-o %s= option requires '=' separator: option ignored",
583 *(o_option_table
[i
].g_value
) = opt
->value
;
584 *(o_option_table
[i
].x_value
) = "YES";
586 case O_OPTION_ACTION_LISTOPT
:
587 if (opt
->separator
!= SEP_EQ
) {
588 paxwarn(1,"-o %s= option requires '=' separator: option ignored",
592 *(o_option_table
[i
].g_value
) = opt
->value
;
594 case O_OPTION_ACTION_NOTIMPL
:
596 paxwarn(1,"pax format -o option not yet implemented: %s=%s",
597 opt
->name
, opt
->value
);
603 if (got_option
== -1) {
604 paxwarn(1,"pax format -o option not recognized: %s=%s",
605 opt
->name
, opt
->value
);
612 expand_extended_headers(ARCHD
*arcn
, HD_USTAR
*hd
)
616 char * current_value
;
617 int path_replaced
= 0;
621 while (myhd
->typeflag
== PAXGTYPE
|| myhd
->typeflag
== PAXXTYPE
) {
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");
629 nbytes
= rd_wrbuf(mybuf
, size
);
630 if (nbytes
!= size
) {
631 paxwarn(1,"extended header data read failure: nbytes=%d, size=%d\n",
636 printf("Read 1 extended header: type=%c, size=%d\n",
637 myhd->typeflag, size);
640 /* loop over buffer collecting attributes */
643 int nentries
= sscanf(&mybuf
[inx
],"%d ", &len
);
645 paxwarn(1,"Extended header failure: length");
648 if (len
< 0 || (inx
+len
-1 >= sizeof(mybuf
))) {
649 paxwarn(1, "Extended header failure: invalid length (%d)", len
);
652 if (mybuf
[inx
+len
-1] != '\n') {
653 paxwarn(1,"Extended header failure: missed newline");
656 mybuf
[inx
+len
-1] = '\0';
657 name
= strchr(&mybuf
[inx
],' ');
660 paxwarn(1,"Extended header failure: missing space");
663 str
= strchr(name
,'=');
665 *str
++='\0'; /* end of name */
667 paxwarn(1,"Extended header failure: missing RHS string");
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 */
678 if (got_option
== -1) {
679 paxwarn(1,"Unrecognized header keyword: %s",name
);
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
;
690 found_value
= ATTRSRC_FROM_X_HEADER
;
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
;
698 found_value
= ATTRSRC_FROM_G_HEADER
;
701 paxwarn(1,"Unsupported header type:%c",myhd
->typeflag
);
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
);
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");
715 case ATTRSRC_FROM_X_O_OPTION
:
716 case ATTRSRC_FROM_G_O_OPTION
:
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
;
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
;
732 case O_OPTION_ACTION_ERROR
:
734 paxwarn(1,"Unsupported extended header attribute: %s=%s",
743 /* position file at next header */
744 (void)rd_skip(TAR_PAD(size
));
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",
752 myhd
= ((HD_USTAR
*)mybuf
);
753 /* repeat until no more extended headers */
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. */
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 */
766 header_len
= o_option_table
[i
].header_len
;
767 if (header_len
== KW_SKIP_CASE
) {
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
;
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
;
781 /* Must remove it: x header values not valid beyond this header */
782 *o_option_table
[i
].x_value_current
= NULL
;
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
;
792 /* Update current header with this value */
794 printf ("Found current_value:%s for %s, pids=%d\n",
795 current_value, o_option_table[i].name, pids);
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 */
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");
810 char * p
= (char *) myhd
;
811 memcpy(&p
[o_option_table
[i
].header_inx
],
813 if (len
!= header_len
) {
815 p
[o_option_table
[i
].header_inx
+len
] = '\0';
825 if (myhd
==hd
) return(path_replaced
);
827 /* must put new header into memory of original */
828 memcpy(hd
, myhd
, sizeof(HD_USTAR
));
830 return(path_replaced
);
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
838 * 0 if a ustar header, -1 otherwise
842 pax_id(char *blk
, int size
)
848 hd
= (HD_USTAR
*)blk
;
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.
856 if (hd
->name
[0] == '\0')
858 if (strncmp(hd
->magic
, TMAGIC
, TMAGLEN
- 1) != 0)
860 if (asc_ul(hd
->chksum
,sizeof(hd
->chksum
),OCT
) != pax_chksm(blk
,BLKMULT
))
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 */
870 pax_invalid_action
= PAX_INVALID_ACTION_BYPASS
; /* Default for pax format */
876 * extract the values out of block already determined to be a pax header.
877 * store the values in the ARCHD parameter.
883 pax_rd(ARCHD
*arcn
, char *buf
)
892 * we only get proper sized buffers
894 if (pax_id(buf
, BLKMULT
) < 0)
897 memset(arcn
, 0, sizeof(*arcn
));
898 arcn
->org_name
= arcn
->name
;
899 arcn
->sb
.st_nlink
= 1;
900 hd
= (HD_USTAR
*)buf
;
902 check_path
= expand_extended_headers(arcn
, hd
);
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.
910 if (arcn
->nlen
> sizeof(arcn
->name
)) {
911 paxwarn(1,"pathname from extended header info doesn't fit! (len=%d)\n",
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.
919 char *dest
= arcn
->name
;
920 if (*(hd
->prefix
) != '\0') {
921 cnt
= strlcpy(dest
, hd
->prefix
, sizeof(arcn
->name
) - 1);
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
));
938 * follow the spec to the letter. we should only have mode bits, strip
939 * off all other crud we may be passed.
941 arcn
->sb
.st_mode
= (mode_t
)(asc_ul(hd
->mode
, sizeof(hd
->mode
), OCT
) &
944 arcn
->sb
.st_size
= (off_t
)asc_ul(hd
->size
, sizeof(hd
->size
), OCT
);
946 arcn
->sb
.st_size
= (off_t
)asc_uqd(hd
->size
, sizeof(hd
->size
), OCT
);
948 arcn
->sb
.st_mtime
= (time_t)asc_ul(hd
->mtime
, sizeof(hd
->mtime
), OCT
);
949 if (arcn
->sb
.st_atimespec
.tv_sec
== 0) { // Can be set from header
950 arcn
->sb
.st_atime
= arcn
->sb
.st_mtime
;
952 arcn
->sb
.st_ctime
= arcn
->sb
.st_mtime
;
955 * If we can find the ascii names for gname and uname in the password
956 * and group files we will use the uid's and gid they bind. Otherwise
957 * we use the uid and gid values stored in the header. (This is what
958 * the posix spec wants).
960 hd
->gname
[sizeof(hd
->gname
) - 1] = '\0';
961 if (gid_name(hd
->gname
, &(arcn
->sb
.st_gid
)) < 0)
962 arcn
->sb
.st_gid
= (gid_t
)asc_ul(hd
->gid
, sizeof(hd
->gid
), OCT
);
963 hd
->uname
[sizeof(hd
->uname
) - 1] = '\0';
964 if (uid_name(hd
->uname
, &(arcn
->sb
.st_uid
)) < 0)
965 arcn
->sb
.st_uid
= (uid_t
)asc_ul(hd
->uid
, sizeof(hd
->uid
), OCT
);
968 * set the defaults, these may be changed depending on the file type
972 arcn
->sb
.st_rdev
= (dev_t
)0;
975 * set the mode and PAX type according to the typeflag in the header
977 switch (hd
->typeflag
) {
979 arcn
->type
= PAX_FIF
;
980 arcn
->sb
.st_mode
|= S_IFIFO
;
983 arcn
->type
= PAX_DIR
;
984 arcn
->sb
.st_mode
|= S_IFDIR
;
985 arcn
->sb
.st_nlink
= 2;
988 * Some programs that create pax archives append a '/'
989 * to the pathname for directories. This clearly violates
990 * pax specs, but we will silently strip it off anyway.
992 if (arcn
->name
[arcn
->nlen
- 1] == '/')
993 arcn
->name
[--arcn
->nlen
] = '\0';
998 * this type requires the rdev field to be set.
1000 if (hd
->typeflag
== BLKTYPE
) {
1001 arcn
->type
= PAX_BLK
;
1002 arcn
->sb
.st_mode
|= S_IFBLK
;
1004 arcn
->type
= PAX_CHR
;
1005 arcn
->sb
.st_mode
|= S_IFCHR
;
1007 devmajor
= (dev_t
)asc_ul(hd
->devmajor
,sizeof(hd
->devmajor
),OCT
);
1008 devminor
= (dev_t
)asc_ul(hd
->devminor
,sizeof(hd
->devminor
),OCT
);
1009 arcn
->sb
.st_rdev
= TODEV(devmajor
, devminor
);
1013 if (hd
->typeflag
== SYMTYPE
) {
1014 arcn
->type
= PAX_SLK
;
1015 arcn
->sb
.st_mode
|= S_IFLNK
;
1017 arcn
->type
= PAX_HLK
;
1019 * so printing looks better
1021 arcn
->sb
.st_mode
|= S_IFREG
;
1022 arcn
->sb
.st_nlink
= 2;
1028 * GNU long link/file; we tag these here and let the
1029 * pax internals deal with it -- too ugly otherwise.
1032 hd
->typeflag
== LONGLINKTYPE
? PAX_GLL
: PAX_GLF
;
1033 arcn
->pad
= TAR_PAD(arcn
->sb
.st_size
);
1034 arcn
->skip
= arcn
->sb
.st_size
;
1041 * these types have file data that follows. Set the skip and
1044 arcn
->type
= PAX_REG
;
1045 arcn
->pad
= TAR_PAD(arcn
->sb
.st_size
);
1046 arcn
->skip
= arcn
->sb
.st_size
;
1047 arcn
->sb
.st_mode
|= S_IFREG
;
1054 adjust_copy_for_pax_options(ARCHD
* arcn
)
1056 /* Because ext_header options take precedence over global_header options, apply
1057 global options first, then override with any extended header options */
1059 if (global_ext_header_inx
) {
1060 for (i
=0; i
< global_ext_header_inx
; i
++) {
1061 if (!o_option_table
[global_ext_header_entry
[i
]].active
) continue; /* deleted keywords */
1062 if (strcmp(o_option_table
[global_ext_header_entry
[i
]].name
, "path")==0) {
1063 strlcpy(arcn
->name
,*(o_option_table
[global_ext_header_entry
[i
]].g_value
),
1064 sizeof(arcn
->name
));
1065 arcn
->nlen
= strlen(*(o_option_table
[global_ext_header_entry
[i
]].g_value
));
1066 } else { /* only handle path for now: others TBD */
1067 paxwarn(1, "adjust arcn for global extended header options not implemented:%d", i
);
1071 if (ext_header_inx
) {
1072 for (i
=0; i
< ext_header_inx
; i
++) {
1073 if (!o_option_table
[ext_header_entry
[i
]].active
) continue; /* deleted keywords */
1074 if (strcmp(o_option_table
[ext_header_entry
[i
]].name
, "path")==0) {
1075 strlcpy(arcn
->name
,*(o_option_table
[ext_header_entry
[i
]].x_value
),
1076 sizeof(arcn
->name
));
1077 arcn
->nlen
= strlen(*(o_option_table
[ext_header_entry
[i
]].x_value
));
1078 } else { /* only handle path for now: others TBD */
1079 paxwarn(1, "adjust arcn for extended header options not implemented:%d", i
);
1083 if (want_a_m_time_headers
) {
1089 emit_extended_header_record(int len
, int total_len
, int head_type
,
1090 char * name
, char * value
)
1092 if (total_len
+ len
> sizeof(pax_eh_datablk
)) {
1093 paxwarn(1,"extended header buffer overflow for header type '%c': %d",
1094 head_type
, total_len
+len
);
1096 sprintf(&pax_eh_datablk
[total_len
],"%d %s=%s\n", len
, name
, value
);
1102 __attribute__((__malloc__
))
1104 substitute_percent(char * header
, char * filename
)
1106 char *nextpercent
, *nextchar
;
1109 char *dname
, *fname
;
1111 nextpercent
= strchr(header
,'%');
1112 if (nextpercent
==NULL
) return strdup(header
);
1113 pos
= nextpercent
-header
;
1114 memcpy(buf
,header
, pos
);
1115 while (nextpercent
++) {
1116 switch (*nextpercent
) {
1118 buf
[pos
++]='%'; /* just skip it */
1121 dname
= strrchr(filename
,'/');
1126 cpylen
= dname
-filename
;
1129 memcpy(&buf
[pos
],dname
,cpylen
);
1133 fname
= strrchr(filename
,'/');
1139 cpylen
= strlen(fname
);
1140 memcpy(&buf
[pos
],fname
,cpylen
);
1144 pos
+= sprintf (&buf
[pos
],"%d",nglobal_headers
);
1147 pos
+= sprintf (&buf
[pos
],"%d",getpid());
1150 paxwarn(1,"header format substitution failed: '%c'", *nextpercent
);
1151 return strdup(header
);
1154 if (*nextpercent
=='\0') {
1157 nextchar
= nextpercent
;
1158 nextpercent
= strchr(nextpercent
,'%');
1159 if (nextpercent
==NULL
) {
1160 cpylen
= strlen(nextchar
);
1162 cpylen
= nextpercent
- nextchar
;
1164 memcpy(&buf
[pos
],nextchar
, cpylen
);
1168 return (strdup(&buf
[0]));
1172 generate_pax_ext_header_and_data(ARCHD
*arcn
, int nfields
, int *table
,
1173 char header_type
, char * header_name
, char * header_name_requested
)
1176 char hdblk
[sizeof(HD_USTAR
)];
1177 u_long records_size
;
1178 int term_char
, i
, len
, total_len
;
1181 if (nfields
== 0 && (header_name_requested
== NULL
)) {
1182 if (header_type
==PAXXTYPE
) {
1183 if (!want_a_m_time_headers
) return (0);
1188 /* There might be no fields but a header with a specific name or
1189 times might be wanted */
1192 memset(hdblk
, 0, sizeof(hdblk
));
1193 hd
= (HD_USTAR
*)hdblk
;
1194 memset(pax_eh_datablk
, 0, sizeof(pax_eh_datablk
));
1196 /* generate header */
1197 hd
->typeflag
= header_type
;
1199 /* These fields appear to be necessary to be able to treat extended headers
1200 like files in older versions of pax */
1201 ul_oct((u_long
)0444, hd
->mode
, sizeof(hd
->mode
), term_char
);
1202 strncpy(hd
->magic
, TMAGIC
, TMAGLEN
);
1203 strncpy(hd
->version
, TVERSION
, TVERSLEN
);
1204 ul_oct((u_long
)arcn
->sb
.st_mtime
,hd
->mtime
,sizeof(hd
->mtime
),term_char
);
1206 /* compute size of data */
1208 for (i
=0; i
< nfields
; i
++) {
1209 if (!o_option_table
[table
[i
]].active
) continue; /* deleted keywords */
1210 name
= o_option_table
[table
[i
]].name
;
1211 if (header_type
== PAXXTYPE
) {
1212 str
= *(o_option_table
[table
[i
]].x_value
);
1214 str
= *(o_option_table
[table
[i
]].g_value
);
1217 paxwarn(1,"Missing option value for %s", name
);
1220 len
= strlen(str
) + o_option_table
[table
[i
]].len
+ 3;
1222 else if (len
< 98) len
= len
+ 2;
1223 else if (len
< 997) len
= len
+ 3;
1224 else if (len
< 9996) len
= len
+ 4;
1226 paxwarn(1,"extended header data too long for header type '%c': %d",
1229 total_len
= emit_extended_header_record(len
, total_len
,
1230 header_type
, name
, str
);
1233 if ((header_type
== PAXXTYPE
) && want_a_m_time_headers
) {
1234 char time_buffer
[12];
1235 memset(time_buffer
,0,sizeof(time_buffer
));
1236 sprintf(&time_buffer
[0],"%d",(int)arcn
->sb
.st_atime
);
1237 /* 3 chars + strlen("atime") + time + # chars in len */
1238 len
= 3 + 5 + strlen(&time_buffer
[0]) + 2;
1239 total_len
= emit_extended_header_record(len
, total_len
,
1240 header_type
, "atime", &time_buffer
[0]);
1241 memset(time_buffer
,0,sizeof(time_buffer
));
1242 sprintf(&time_buffer
[0],"%d",(int)arcn
->sb
.st_mtime
);
1243 /* 3 chars + strlen("mtime") + time + # chars in len */
1244 len
= 3 + 5 + strlen(&time_buffer
[0]) + 2;
1245 total_len
= emit_extended_header_record(len
, total_len
,
1246 header_type
, "mtime", &time_buffer
[0]);
1249 /* Check if all fields were deleted: might not need to generate anything */
1250 if ((total_len
==0) && (header_name_requested
== NULL
)) return (0);
1252 if (header_type
== PAXGTYPE
) nglobal_headers
++;
1253 /* substitution of fields in header_name */
1254 header_name
= substitute_percent(header_name
, arcn
->name
);
1255 if (strlen(header_name
) == sizeof(hd
->name
)) { /* must account for name just fits in buffer */
1256 strncpy(hd
->name
, header_name
, sizeof(hd
->name
));
1258 strlcpy(hd
->name
, header_name
, sizeof(hd
->name
));
1263 records_size
= (u_long
)total_len
;
1264 if (ul_oct(records_size
, hd
->size
, sizeof(hd
->size
), term_char
)) {
1265 paxwarn(1,"extended header data too long for header type '%c'", header_type
);
1269 if (ul_oct(pax_chksm(hdblk
, sizeof(HD_USTAR
)), hd
->chksum
, sizeof(hd
->chksum
), term_char
)) {
1270 paxwarn(1,"extended header data checksum failed: header type '%c'", header_type
);
1274 /* write out header */
1275 if (wr_rdbuf(hdblk
, sizeof(HD_USTAR
)) < 0)
1277 if (wr_skip((off_t
)(BLKMULT
- sizeof(HD_USTAR
))) < 0)
1279 /* write out header data */
1280 if (total_len
> 0) {
1281 if (wr_rdbuf(pax_eh_datablk
, total_len
) < 0)
1283 if (wr_skip((off_t
)(BLKMULT
- total_len
)) < 0)
1286 printf("data written:\n%s",&pax_eh_datablk[0]);
1291 paxwarn(0,"extended header and data written: header type '%c', #items: %d, %d characters",
1292 header_type, nfields, records_size);
1299 * write a pax header for the file specified in the ARCHD to the archive
1300 * Have to check for file types that cannot be stored and file names that
1301 * are too long. Be careful of the term (last arg) to ul_oct, we only use
1302 * '\0' for the termination character (this is different than picky tar)
1303 * ASSUMED: space after header in header block is zero filled
1305 * 0 if file has data to be written after the header, 1 if file has NO
1306 * data to write after the header, -1 if archive write failed
1314 char hdblk
[sizeof(HD_USTAR
)];
1316 int term_char
=3; /* orignal setting */
1317 term_char
=1; /* To pass conformance tests 274, 301 */
1320 * check for those file system types pax cannot store
1322 if (arcn
->type
== PAX_SCK
) {
1323 paxwarn(1, "Pax cannot archive a socket %s", arcn
->org_name
);
1328 * check the length of the linkname
1330 if (((arcn
->type
== PAX_SLK
) || (arcn
->type
== PAX_HLK
) ||
1331 (arcn
->type
== PAX_HRG
)) && (arcn
->ln_nlen
> sizeof(hd
->linkname
))){
1332 paxwarn(1, "Link name too long for pax %s", arcn
->ln_name
);
1334 * Conformance: test pax:285 wants error code to be non-zero, and
1335 * test tar:12 wants error code from pax to be 0
1341 * split the path name into prefix and name fields (if needed). if
1342 * pt != arcn->name, the name has to be split
1344 if ((pt
= name_split(arcn
->name
, arcn
->nlen
)) == NULL
) {
1345 paxwarn(1, "File name too long for pax %s", arcn
->name
);
1349 generate_pax_ext_header_and_data(arcn
, global_ext_header_inx
, &global_ext_header_entry
[0],
1350 PAXGTYPE
, header_name_g
, header_name_g_requested
);
1351 generate_pax_ext_header_and_data(arcn
, ext_header_inx
, &ext_header_entry
[0],
1352 PAXXTYPE
, header_name_x
, header_name_x_requested
);
1355 * zero out the header so we don't have to worry about zero fill below
1357 memset(hdblk
, 0, sizeof(hdblk
));
1358 hd
= (HD_USTAR
*)hdblk
;
1360 /* To pass conformance tests 274/301, always set these fields to "zero" */
1361 ul_oct(0, hd
->devmajor
, sizeof(hd
->devmajor
), term_char
);
1362 ul_oct(0, hd
->devminor
, sizeof(hd
->devminor
), term_char
);
1365 * split the name, or zero out the prefix
1367 if (pt
!= arcn
->name
) {
1369 * name was split, pt points at the / where the split is to
1370 * occur, we remove the / and copy the first part to the prefix
1373 strlcpy(hd
->prefix
, arcn
->name
, sizeof(hd
->prefix
));
1378 * copy the name part. this may be the whole path or the part after
1381 if (strlen(pt
) == sizeof(hd
->name
)) { /* must account for name just fits in buffer */
1382 strncpy(hd
->name
, pt
, sizeof(hd
->name
));
1384 strlcpy(hd
->name
, pt
, sizeof(hd
->name
));
1388 * set the fields in the header that are type dependent
1390 switch (arcn
->type
) {
1392 hd
->typeflag
= DIRTYPE
;
1393 if (ul_oct((u_long
)0L, hd
->size
, sizeof(hd
->size
), term_char
))
1398 if (arcn
->type
== PAX_CHR
)
1399 hd
->typeflag
= CHRTYPE
;
1401 hd
->typeflag
= BLKTYPE
;
1402 if (ul_oct((u_long
)MAJOR(arcn
->sb
.st_rdev
), hd
->devmajor
,
1403 sizeof(hd
->devmajor
), term_char
) ||
1404 ul_oct((u_long
)MINOR(arcn
->sb
.st_rdev
), hd
->devminor
,
1405 sizeof(hd
->devminor
), term_char
) ||
1406 ul_oct((u_long
)0L, hd
->size
, sizeof(hd
->size
), term_char
))
1410 hd
->typeflag
= FIFOTYPE
;
1411 if (ul_oct((u_long
)0L, hd
->size
, sizeof(hd
->size
), term_char
))
1417 if (arcn
->type
== PAX_SLK
)
1418 hd
->typeflag
= SYMTYPE
;
1420 hd
->typeflag
= LNKTYPE
;
1421 if (strlen(arcn
->ln_name
) == sizeof(hd
->linkname
)) { /* must account for name just fits in buffer */
1422 strncpy(hd
->linkname
, arcn
->ln_name
, sizeof(hd
->linkname
));
1424 strlcpy(hd
->linkname
, arcn
->ln_name
, sizeof(hd
->linkname
));
1426 if (ul_oct((u_long
)0L, hd
->size
, sizeof(hd
->size
), term_char
))
1433 * file data with this type, set the padding
1435 if (arcn
->type
== PAX_CTG
)
1436 hd
->typeflag
= CONTTYPE
;
1438 hd
->typeflag
= REGTYPE
;
1439 arcn
->pad
= TAR_PAD(arcn
->sb
.st_size
);
1441 if (ul_oct((u_long
)arcn
->sb
.st_size
, hd
->size
,
1442 sizeof(hd
->size
), term_char
)) {
1444 if (uqd_oct((u_quad_t
)arcn
->sb
.st_size
, hd
->size
,
1445 sizeof(hd
->size
), term_char
)) {
1447 paxwarn(1,"File is too long for pax %s",arcn
->org_name
);
1453 strncpy(hd
->magic
, TMAGIC
, TMAGLEN
);
1454 strncpy(hd
->version
, TVERSION
, TVERSLEN
);
1457 * set the remaining fields. Some versions want all 16 bits of mode
1458 * we better humor them (they really do not meet spec though)....
1460 if (ul_oct((u_long
)arcn
->sb
.st_uid
, hd
->uid
, sizeof(hd
->uid
), term_char
)) {
1461 if (uid_nobody
== 0) {
1462 if (uid_name("nobody", &uid_nobody
) == -1)
1465 if (uid_warn
!= arcn
->sb
.st_uid
) {
1466 uid_warn
= arcn
->sb
.st_uid
;
1468 "Pax header field is too small for uid %lu, "
1469 "using nobody", (u_long
)arcn
->sb
.st_uid
);
1471 if (ul_oct((u_long
)uid_nobody
, hd
->uid
, sizeof(hd
->uid
), term_char
))
1474 if (ul_oct((u_long
)arcn
->sb
.st_gid
, hd
->gid
, sizeof(hd
->gid
), term_char
)) {
1475 if (gid_nobody
== 0) {
1476 if (gid_name("nobody", &gid_nobody
) == -1)
1479 if (gid_warn
!= arcn
->sb
.st_gid
) {
1480 gid_warn
= arcn
->sb
.st_gid
;
1482 "Pax header field is too small for gid %lu, "
1483 "using nobody", (u_long
)arcn
->sb
.st_gid
);
1485 if (ul_oct((u_long
)gid_nobody
, hd
->gid
, sizeof(hd
->gid
), term_char
))
1488 /* However, Unix conformance tests do not like MORE than 12 mode bits:
1489 remove all beyond (see definition of stat.st_mode structure) */
1490 mode12only
= ((u_long
)arcn
->sb
.st_mode
) & 0x00000fff;
1491 if (ul_oct((u_long
)mode12only
, hd
->mode
, sizeof(hd
->mode
), term_char
) ||
1492 ul_oct((u_long
)arcn
->sb
.st_mtime
,hd
->mtime
,sizeof(hd
->mtime
),term_char
))
1494 strncpy(hd
->uname
, name_uid(arcn
->sb
.st_uid
, 0), sizeof(hd
->uname
));
1495 strncpy(hd
->gname
, name_gid(arcn
->sb
.st_gid
, 0), sizeof(hd
->gname
));
1498 * calculate and store the checksum write the header to the archive
1499 * return 0 tells the caller to now write the file data, 1 says no data
1500 * needs to be written
1502 if (ul_oct(pax_chksm(hdblk
, sizeof(HD_USTAR
)), hd
->chksum
,
1503 sizeof(hd
->chksum
), term_char
))
1505 if (wr_rdbuf(hdblk
, sizeof(HD_USTAR
)) < 0)
1507 if (wr_skip((off_t
)(BLKMULT
- sizeof(HD_USTAR
))) < 0)
1509 if ((arcn
->type
== PAX_CTG
) || (arcn
->type
== PAX_REG
))
1515 * header field is out of range
1517 paxwarn(1, "Pax header field is too small for %s", arcn
->org_name
);
1523 * see if the name has to be split for storage in a ustar header. We try
1524 * to fit the entire name in the name field without splitting if we can.
1525 * The split point is always at a /
1527 * character pointer to split point (always the / that is to be removed
1528 * if the split is not needed, the points is set to the start of the file
1529 * name (it would violate the spec to split there). A NULL is returned if
1530 * the file name is too long
1534 name_split(char *name
, int len
)
1539 * check to see if the file name is small enough to fit in the name
1540 * field. if so just return a pointer to the name.
1544 if (len
> (TPFSZ
+ TNMSZ
))
1548 * we start looking at the biggest sized piece that fits in the name
1549 * field. We walk forward looking for a slash to split at. The idea is
1550 * to find the biggest piece to fit in the name field (or the smallest
1551 * prefix we can find)
1553 start
= name
+ len
- TNMSZ
-1;
1554 if ((*start
== '/') && (start
== name
))
1555 ++start
; /* 101 byte paths with leading '/' are dinged otherwise */
1556 while ((*start
!= '\0') && (*start
!= '/'))
1560 * if we hit the end of the string, this name cannot be split, so we
1561 * cannot store this file.
1568 * NOTE: /str where the length of str == TNMSZ can not be stored under
1569 * the p1003.1-1990 spec for ustar. We could force a prefix of / and
1570 * the file would then expand on extract to //str. The len == 0 below
1571 * makes this special case follow the spec to the letter.
1573 if ((len
>= TPFSZ
) || (len
== 0))
1577 * ok have a split point, return it to the caller
1583 expandname(char *buf
, size_t len
, char **gnu_name
, const char *name
, size_t name_len
)
1588 if ((nlen
= strlcpy(buf
, *gnu_name
, len
)) >= len
)
1593 if (name_len
< len
) {
1594 /* name may not be null terminated: it might be as big as the
1595 field, so copy is limited to the max size of the header field */
1596 if ((nlen
= strlcpy(buf
, name
, name_len
+1)) >= name_len
+1)
1599 if ((nlen
= strlcpy(buf
, name
, len
)) >= len
)