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
);
1085 substitute_percent(char * header
, char * filename
)
1087 char *nextpercent
, *nextchar
;
1090 char *dname
, *fname
;
1092 nextpercent
= strchr(header
,'%');
1093 if (nextpercent
==NULL
) return header
;
1094 pos
= nextpercent
-header
;
1095 memcpy(buf
,header
, pos
);
1096 while (nextpercent
++) {
1097 switch (*nextpercent
) {
1099 buf
[pos
++]='%'; /* just skip it */
1102 dname
= strrchr(filename
,'/');
1107 cpylen
= dname
-filename
;
1110 memcpy(&buf
[pos
],dname
,cpylen
);
1114 fname
= strrchr(filename
,'/');
1120 cpylen
= strlen(fname
);
1121 memcpy(&buf
[pos
],fname
,cpylen
);
1125 pos
+= sprintf (&buf
[pos
],"%d",nglobal_headers
);
1128 pos
+= sprintf (&buf
[pos
],"%d",getpid());
1131 paxwarn(1,"header format substitution failed: '%c'", *nextpercent
);
1135 if (*nextpercent
=='\0') {
1138 nextchar
= nextpercent
;
1139 nextpercent
= strchr(nextpercent
,'%');
1140 if (nextpercent
==NULL
) {
1141 cpylen
= strlen(nextchar
);
1143 cpylen
= nextpercent
- nextchar
;
1145 memcpy(&buf
[pos
],nextchar
, cpylen
);
1149 return (strdup(&buf
[0]));
1153 generate_pax_ext_header_and_data(ARCHD
*arcn
, int nfields
, int *table
,
1154 char header_type
, char * header_name
, char * header_name_requested
)
1157 char hdblk
[sizeof(HD_USTAR
)];
1158 u_long records_size
;
1159 int term_char
, i
, len
, total_len
;
1162 if (nfields
== 0 && (header_name_requested
== NULL
)) {
1163 if (header_type
==PAXXTYPE
) {
1164 if (!want_a_m_time_headers
) return (0);
1169 /* There might be no fields but a header with a specific name or
1170 times might be wanted */
1173 memset(hdblk
, 0, sizeof(hdblk
));
1174 hd
= (HD_USTAR
*)hdblk
;
1175 memset(pax_eh_datablk
, 0, sizeof(pax_eh_datablk
));
1177 /* generate header */
1178 hd
->typeflag
= header_type
;
1180 /* These fields appear to be necessary to be able to treat extended headers
1181 like files in older versions of pax */
1182 ul_oct((u_long
)0444, hd
->mode
, sizeof(hd
->mode
), term_char
);
1183 strncpy(hd
->magic
, TMAGIC
, TMAGLEN
);
1184 strncpy(hd
->version
, TVERSION
, TVERSLEN
);
1185 ul_oct((u_long
)arcn
->sb
.st_mtime
,hd
->mtime
,sizeof(hd
->mtime
),term_char
);
1187 /* compute size of data */
1189 for (i
=0; i
< nfields
; i
++) {
1190 if (!o_option_table
[table
[i
]].active
) continue; /* deleted keywords */
1191 name
= o_option_table
[table
[i
]].name
;
1192 if (header_type
== PAXXTYPE
) {
1193 str
= *(o_option_table
[table
[i
]].x_value
);
1195 str
= *(o_option_table
[table
[i
]].g_value
);
1198 paxwarn(1,"Missing option value for %s", name
);
1201 len
= strlen(str
) + o_option_table
[table
[i
]].len
+ 3;
1203 else if (len
< 98) len
= len
+ 2;
1204 else if (len
< 997) len
= len
+ 3;
1205 else if (len
< 9996) len
= len
+ 4;
1207 paxwarn(1,"extended header data too long for header type '%c': %d",
1210 total_len
= emit_extended_header_record(len
, total_len
,
1211 header_type
, name
, str
);
1214 if ((header_type
== PAXXTYPE
) && want_a_m_time_headers
) {
1215 char time_buffer
[12];
1216 memset(time_buffer
,0,sizeof(time_buffer
));
1217 sprintf(&time_buffer
[0],"%d",(int)arcn
->sb
.st_atime
);
1218 /* 3 chars + strlen("atime") + time + # chars in len */
1219 len
= 3 + 5 + strlen(&time_buffer
[0]) + 2;
1220 total_len
= emit_extended_header_record(len
, total_len
,
1221 header_type
, "atime", &time_buffer
[0]);
1222 memset(time_buffer
,0,sizeof(time_buffer
));
1223 sprintf(&time_buffer
[0],"%d",(int)arcn
->sb
.st_mtime
);
1224 /* 3 chars + strlen("mtime") + time + # chars in len */
1225 len
= 3 + 5 + strlen(&time_buffer
[0]) + 2;
1226 total_len
= emit_extended_header_record(len
, total_len
,
1227 header_type
, "mtime", &time_buffer
[0]);
1230 /* Check if all fields were deleted: might not need to generate anything */
1231 if ((total_len
==0) && (header_name_requested
== NULL
)) return (0);
1233 if (header_type
== PAXGTYPE
) nglobal_headers
++;
1234 /* substitution of fields in header_name */
1235 header_name
= substitute_percent(header_name
, arcn
->name
);
1236 if (strlen(header_name
) == sizeof(hd
->name
)) { /* must account for name just fits in buffer */
1237 strncpy(hd
->name
, header_name
, sizeof(hd
->name
));
1239 strlcpy(hd
->name
, header_name
, sizeof(hd
->name
));
1242 records_size
= (u_long
)total_len
;
1243 if (ul_oct(records_size
, hd
->size
, sizeof(hd
->size
), term_char
)) {
1244 paxwarn(1,"extended header data too long for header type '%c'", header_type
);
1248 if (ul_oct(pax_chksm(hdblk
, sizeof(HD_USTAR
)), hd
->chksum
, sizeof(hd
->chksum
), term_char
)) {
1249 paxwarn(1,"extended header data checksum failed: header type '%c'", header_type
);
1253 /* write out header */
1254 if (wr_rdbuf(hdblk
, sizeof(HD_USTAR
)) < 0)
1256 if (wr_skip((off_t
)(BLKMULT
- sizeof(HD_USTAR
))) < 0)
1258 /* write out header data */
1259 if (total_len
> 0) {
1260 if (wr_rdbuf(pax_eh_datablk
, total_len
) < 0)
1262 if (wr_skip((off_t
)(BLKMULT
- total_len
)) < 0)
1265 printf("data written:\n%s",&pax_eh_datablk[0]);
1270 paxwarn(0,"extended header and data written: header type '%c', #items: %d, %d characters",
1271 header_type, nfields, records_size);
1278 * write a pax header for the file specified in the ARCHD to the archive
1279 * Have to check for file types that cannot be stored and file names that
1280 * are too long. Be careful of the term (last arg) to ul_oct, we only use
1281 * '\0' for the termination character (this is different than picky tar)
1282 * ASSUMED: space after header in header block is zero filled
1284 * 0 if file has data to be written after the header, 1 if file has NO
1285 * data to write after the header, -1 if archive write failed
1293 char hdblk
[sizeof(HD_USTAR
)];
1295 int term_char
=3; /* orignal setting */
1296 term_char
=1; /* To pass conformance tests 274, 301 */
1299 * check for those file system types pax cannot store
1301 if (arcn
->type
== PAX_SCK
) {
1302 paxwarn(1, "Pax cannot archive a socket %s", arcn
->org_name
);
1307 * check the length of the linkname
1309 if (((arcn
->type
== PAX_SLK
) || (arcn
->type
== PAX_HLK
) ||
1310 (arcn
->type
== PAX_HRG
)) && (arcn
->ln_nlen
> sizeof(hd
->linkname
))){
1311 paxwarn(1, "Link name too long for pax %s", arcn
->ln_name
);
1313 * Conformance: test pax:285 wants error code to be non-zero, and
1314 * test tar:12 wants error code from pax to be 0
1320 * split the path name into prefix and name fields (if needed). if
1321 * pt != arcn->name, the name has to be split
1323 if ((pt
= name_split(arcn
->name
, arcn
->nlen
)) == NULL
) {
1324 paxwarn(1, "File name too long for pax %s", arcn
->name
);
1328 generate_pax_ext_header_and_data(arcn
, global_ext_header_inx
, &global_ext_header_entry
[0],
1329 PAXGTYPE
, header_name_g
, header_name_g_requested
);
1330 generate_pax_ext_header_and_data(arcn
, ext_header_inx
, &ext_header_entry
[0],
1331 PAXXTYPE
, header_name_x
, header_name_x_requested
);
1334 * zero out the header so we don't have to worry about zero fill below
1336 memset(hdblk
, 0, sizeof(hdblk
));
1337 hd
= (HD_USTAR
*)hdblk
;
1339 /* To pass conformance tests 274/301, always set these fields to "zero" */
1340 ul_oct(0, hd
->devmajor
, sizeof(hd
->devmajor
), term_char
);
1341 ul_oct(0, hd
->devminor
, sizeof(hd
->devminor
), term_char
);
1344 * split the name, or zero out the prefix
1346 if (pt
!= arcn
->name
) {
1348 * name was split, pt points at the / where the split is to
1349 * occur, we remove the / and copy the first part to the prefix
1352 strlcpy(hd
->prefix
, arcn
->name
, sizeof(hd
->prefix
));
1357 * copy the name part. this may be the whole path or the part after
1360 if (strlen(pt
) == sizeof(hd
->name
)) { /* must account for name just fits in buffer */
1361 strncpy(hd
->name
, pt
, sizeof(hd
->name
));
1363 strlcpy(hd
->name
, pt
, sizeof(hd
->name
));
1367 * set the fields in the header that are type dependent
1369 switch (arcn
->type
) {
1371 hd
->typeflag
= DIRTYPE
;
1372 if (ul_oct((u_long
)0L, hd
->size
, sizeof(hd
->size
), term_char
))
1377 if (arcn
->type
== PAX_CHR
)
1378 hd
->typeflag
= CHRTYPE
;
1380 hd
->typeflag
= BLKTYPE
;
1381 if (ul_oct((u_long
)MAJOR(arcn
->sb
.st_rdev
), hd
->devmajor
,
1382 sizeof(hd
->devmajor
), term_char
) ||
1383 ul_oct((u_long
)MINOR(arcn
->sb
.st_rdev
), hd
->devminor
,
1384 sizeof(hd
->devminor
), term_char
) ||
1385 ul_oct((u_long
)0L, hd
->size
, sizeof(hd
->size
), term_char
))
1389 hd
->typeflag
= FIFOTYPE
;
1390 if (ul_oct((u_long
)0L, hd
->size
, sizeof(hd
->size
), term_char
))
1396 if (arcn
->type
== PAX_SLK
)
1397 hd
->typeflag
= SYMTYPE
;
1399 hd
->typeflag
= LNKTYPE
;
1400 if (strlen(arcn
->ln_name
) == sizeof(hd
->linkname
)) { /* must account for name just fits in buffer */
1401 strncpy(hd
->linkname
, arcn
->ln_name
, sizeof(hd
->linkname
));
1403 strlcpy(hd
->linkname
, arcn
->ln_name
, sizeof(hd
->linkname
));
1405 if (ul_oct((u_long
)0L, hd
->size
, sizeof(hd
->size
), term_char
))
1412 * file data with this type, set the padding
1414 if (arcn
->type
== PAX_CTG
)
1415 hd
->typeflag
= CONTTYPE
;
1417 hd
->typeflag
= REGTYPE
;
1418 arcn
->pad
= TAR_PAD(arcn
->sb
.st_size
);
1420 if (ul_oct((u_long
)arcn
->sb
.st_size
, hd
->size
,
1421 sizeof(hd
->size
), term_char
)) {
1423 if (uqd_oct((u_quad_t
)arcn
->sb
.st_size
, hd
->size
,
1424 sizeof(hd
->size
), term_char
)) {
1426 paxwarn(1,"File is too long for pax %s",arcn
->org_name
);
1432 strncpy(hd
->magic
, TMAGIC
, TMAGLEN
);
1433 strncpy(hd
->version
, TVERSION
, TVERSLEN
);
1436 * set the remaining fields. Some versions want all 16 bits of mode
1437 * we better humor them (they really do not meet spec though)....
1439 if (ul_oct((u_long
)arcn
->sb
.st_uid
, hd
->uid
, sizeof(hd
->uid
), term_char
)) {
1440 if (uid_nobody
== 0) {
1441 if (uid_name("nobody", &uid_nobody
) == -1)
1444 if (uid_warn
!= arcn
->sb
.st_uid
) {
1445 uid_warn
= arcn
->sb
.st_uid
;
1447 "Pax header field is too small for uid %lu, "
1448 "using nobody", (u_long
)arcn
->sb
.st_uid
);
1450 if (ul_oct((u_long
)uid_nobody
, hd
->uid
, sizeof(hd
->uid
), term_char
))
1453 if (ul_oct((u_long
)arcn
->sb
.st_gid
, hd
->gid
, sizeof(hd
->gid
), term_char
)) {
1454 if (gid_nobody
== 0) {
1455 if (gid_name("nobody", &gid_nobody
) == -1)
1458 if (gid_warn
!= arcn
->sb
.st_gid
) {
1459 gid_warn
= arcn
->sb
.st_gid
;
1461 "Pax header field is too small for gid %lu, "
1462 "using nobody", (u_long
)arcn
->sb
.st_gid
);
1464 if (ul_oct((u_long
)gid_nobody
, hd
->gid
, sizeof(hd
->gid
), term_char
))
1467 /* However, Unix conformance tests do not like MORE than 12 mode bits:
1468 remove all beyond (see definition of stat.st_mode structure) */
1469 mode12only
= ((u_long
)arcn
->sb
.st_mode
) & 0x00000fff;
1470 if (ul_oct((u_long
)mode12only
, hd
->mode
, sizeof(hd
->mode
), term_char
) ||
1471 ul_oct((u_long
)arcn
->sb
.st_mtime
,hd
->mtime
,sizeof(hd
->mtime
),term_char
))
1473 strncpy(hd
->uname
, name_uid(arcn
->sb
.st_uid
, 0), sizeof(hd
->uname
));
1474 strncpy(hd
->gname
, name_gid(arcn
->sb
.st_gid
, 0), sizeof(hd
->gname
));
1477 * calculate and store the checksum write the header to the archive
1478 * return 0 tells the caller to now write the file data, 1 says no data
1479 * needs to be written
1481 if (ul_oct(pax_chksm(hdblk
, sizeof(HD_USTAR
)), hd
->chksum
,
1482 sizeof(hd
->chksum
), term_char
))
1484 if (wr_rdbuf(hdblk
, sizeof(HD_USTAR
)) < 0)
1486 if (wr_skip((off_t
)(BLKMULT
- sizeof(HD_USTAR
))) < 0)
1488 if ((arcn
->type
== PAX_CTG
) || (arcn
->type
== PAX_REG
))
1494 * header field is out of range
1496 paxwarn(1, "Pax header field is too small for %s", arcn
->org_name
);
1502 * see if the name has to be split for storage in a ustar header. We try
1503 * to fit the entire name in the name field without splitting if we can.
1504 * The split point is always at a /
1506 * character pointer to split point (always the / that is to be removed
1507 * if the split is not needed, the points is set to the start of the file
1508 * name (it would violate the spec to split there). A NULL is returned if
1509 * the file name is too long
1513 name_split(char *name
, int len
)
1518 * check to see if the file name is small enough to fit in the name
1519 * field. if so just return a pointer to the name.
1523 if (len
> (TPFSZ
+ TNMSZ
))
1527 * we start looking at the biggest sized piece that fits in the name
1528 * field. We walk forward looking for a slash to split at. The idea is
1529 * to find the biggest piece to fit in the name field (or the smallest
1530 * prefix we can find)
1532 start
= name
+ len
- TNMSZ
-1;
1533 if ((*start
== '/') && (start
== name
))
1534 ++start
; /* 101 byte paths with leading '/' are dinged otherwise */
1535 while ((*start
!= '\0') && (*start
!= '/'))
1539 * if we hit the end of the string, this name cannot be split, so we
1540 * cannot store this file.
1547 * NOTE: /str where the length of str == TNMSZ can not be stored under
1548 * the p1003.1-1990 spec for ustar. We could force a prefix of / and
1549 * the file would then expand on extract to //str. The len == 0 below
1550 * makes this special case follow the spec to the letter.
1552 if ((len
>= TPFSZ
) || (len
== 0))
1556 * ok have a split point, return it to the caller
1562 expandname(char *buf
, size_t len
, char **gnu_name
, const char *name
, size_t name_len
)
1567 if ((nlen
= strlcpy(buf
, *gnu_name
, len
)) >= len
)
1572 if (name_len
< len
) {
1573 /* name may not be null terminated: it might be as big as the
1574 field, so copy is limited to the max size of the header field */
1575 if ((nlen
= strlcpy(buf
, name
, name_len
+1)) >= name_len
+1)
1578 if ((nlen
= strlcpy(buf
, name
, len
)) >= len
)