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