1/*- 2 * Copyright (c) 1992 Keith Muller. 3 * Copyright (c) 1992, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * Keith Muller of the University of California, San Diego. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#ifndef lint 35#if 0 36static const char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94"; 37#else 38static const char rcsid[] __attribute__((__unused__)) = "$OpenBSD: tar.c,v 1.34 2004/10/23 19:34:14 otto Exp $"; 39#endif 40#endif /* not lint */ 41 42#include <sys/types.h> 43#include <sys/time.h> 44#include <sys/stat.h> 45#include <sys/param.h> 46#include <string.h> 47#include <stdio.h> 48#include <unistd.h> 49#include <stdlib.h> 50#include "pax.h" 51#include "extern.h" 52#include "tar.h" 53#include <fnmatch.h> 54#include <regex.h> 55#include "pat_rep.h" 56#include <errno.h> 57 58/* 59 * This file implements the -x pax format support; it is incomplete. 60 * Known missing features include: 61 * many -o options for "copy" mode are not implemented (only path=) 62 * many format specifiers for -o listopt are not implemented 63 * -o listopt option should work for all archive formats, not just -x pax 64 * This file was originally derived from the file tar.c. You should 65 * 'diff' it to that file to see how much of the -x pax format has been implemented. 66 */ 67 68char pax_eh_datablk[4*1024]; 69int pax_read_or_list_mode = 0; 70int want_a_m_time_headers = 0; 71int want_linkdata = 0; 72 73int pax_invalid_action = 0; 74char * pax_invalid_action_write_path = NULL; 75char * pax_invalid_action_write_cwd = NULL; 76 77char 78 *path_g, *path_x, *path_g_current, *path_x_current, 79 *uname_g, *uname_x, *uname_g_current, *uname_x_current, 80 *gname_g, *gname_x, *gname_g_current, *gname_x_current, 81 *comment_g, *comment_x, *comment_g_current, *comment_x_current, 82 *charset_g, *charset_x, *charset_g_current, *charset_x_current, 83 *atime_g, *atime_x, *atime_g_current, *atime_x_current, 84 *gid_g, *gid_x, *gid_g_current, *gid_x_current, 85 *linkpath_g, *linkpath_x, *linkpath_g_current, *linkpath_x_current, 86 *mtime_g, *mtime_x, *mtime_g_current, *mtime_x_current, 87 *size_g, *size_x, *size_g_current, *size_x_current, 88 *uid_g, *uid_x, *uid_g_current, *uid_x_current; 89 90char *header_name_g_requested = NULL, 91 *header_name_x_requested = NULL; 92 93char *header_name_g = "/tmp/GlobalHead.%p.%n", 94 *header_name_x = "%d/PaxHeaders.%p/%f"; 95 96int nglobal_headers = 0; 97char *pax_list_opt_format; 98 99#define O_OPTION_ACTION_NOTIMPL 0 100#define O_OPTION_ACTION_INVALID 1 101#define O_OPTION_ACTION_DELETE 2 102#define O_OPTION_ACTION_STORE_HEADER 3 103#define O_OPTION_ACTION_TIMES 4 104#define O_OPTION_ACTION_HEADER_NAME 5 105#define O_OPTION_ACTION_LISTOPT 6 106#define O_OPTION_ACTION_LINKDATA 7 107 108#define O_OPTION_ACTION_IGNORE 8 109#define O_OPTION_ACTION_ERROR 9 110#define O_OPTION_ACTION_STORE_HEADER2 10 111 112#define ATTRSRC_FROM_NOWHERE 0 113#define ATTRSRC_FROM_X_O_OPTION 1 114#define ATTRSRC_FROM_G_O_OPTION 2 115#define ATTRSRC_FROM_X_HEADER 3 116#define ATTRSRC_FROM_G_HEADER 4 117 118#define KW_PATH_CASE 0 119#define KW_SKIP_CASE -1 120 121typedef struct { 122 char * name; 123 int len; 124 int active; /* 1 means active, 0 means deleted via -o delete= */ 125 int cmdline_action; 126 int header_action; 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= */ 135} O_OPTION_TYPE; 136 137O_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 }, 160 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 }, 165 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 }, 177}; 178 179int ext_header_inx, 180 global_ext_header_inx; 181 182/* Make these tables big enough to handle lots of -o options, not just one per table entry */ 183int 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)]; 185 186/* 187 * Routines for reading, writing and header identify of various versions of pax 188 */ 189 190static size_t expandname(char *, size_t, char **, const char *, size_t); 191static u_long pax_chksm(char *, int); 192static char *name_split(char *, int); 193static int ul_oct(u_long, char *, int, int); 194#ifndef LONG_OFF_T 195static int uqd_oct(u_quad_t, char *, int, int); 196#endif 197 198static uid_t uid_nobody; 199static uid_t uid_warn; 200static gid_t gid_nobody; 201static gid_t gid_warn; 202 203/* 204 * Routines common to all versions of pax 205 */ 206 207/* 208 * ul_oct() 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. 214 * Return: 215 * 0 if the number fit into the string, -1 otherwise 216 */ 217 218static int 219ul_oct(u_long val, char *str, int len, int term) 220{ 221 char *pt; 222 223 /* 224 * term selects the appropriate character(s) for the end of the string 225 */ 226 pt = str + len - 1; 227 switch (term) { 228 case 3: 229 *pt-- = '\0'; 230 break; 231 case 2: 232 *pt-- = ' '; 233 *pt-- = '\0'; 234 break; 235 case 1: 236 *pt-- = ' '; 237 break; 238 case 0: 239 default: 240 *pt-- = '\0'; 241 *pt-- = ' '; 242 break; 243 } 244 245 /* 246 * convert and blank pad if there is space 247 */ 248 while (pt >= str) { 249 *pt-- = '0' + (char)(val & 0x7); 250 if ((val = val >> 3) == (u_long)0) 251 break; 252 } 253 254 while (pt >= str) 255 *pt-- = '0'; 256 if (val != (u_long)0) 257 return(-1); 258 return(0); 259} 260 261#ifndef LONG_OFF_T 262/* 263 * uqd_oct() 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. 269 * Return: 270 * 0 if the number fit into the string, -1 otherwise 271 */ 272 273static int 274uqd_oct(u_quad_t val, char *str, int len, int term) 275{ 276 char *pt; 277 278 /* 279 * term selects the appropriate character(s) for the end of the string 280 */ 281 pt = str + len - 1; 282 switch (term) { 283 case 3: 284 *pt-- = '\0'; 285 break; 286 case 2: 287 *pt-- = ' '; 288 *pt-- = '\0'; 289 break; 290 case 1: 291 *pt-- = ' '; 292 break; 293 case 0: 294 default: 295 *pt-- = '\0'; 296 *pt-- = ' '; 297 break; 298 } 299 300 /* 301 * convert and blank pad if there is space 302 */ 303 while (pt >= str) { 304 *pt-- = '0' + (char)(val & 0x7); 305 if ((val = val >> 3) == 0) 306 break; 307 } 308 309 while (pt >= str) 310 *pt-- = '0'; 311 if (val != (u_quad_t)0) 312 return(-1); 313 return(0); 314} 315#endif 316 317/* 318 * pax_chksm() 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. 323 * Return: 324 * unsigned long checksum 325 */ 326 327static u_long 328pax_chksm(char *blk, int len) 329{ 330 char *stop; 331 char *pt; 332 u_long chksm = BLNKSUM; /* initial value is checksum field sum */ 333 334 /* 335 * add the part of the block before the checksum field 336 */ 337 pt = blk; 338 stop = blk + CHK_OFFSET; 339 while (pt < stop) 340 chksm += (u_long)(*pt++ & 0xff); 341 /* 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 344 * BLNKSUM). 345 * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding 346 * starts, no point in summing zero's) 347 */ 348 pt += CHK_LEN; 349 stop = blk + len; 350 while (pt < stop) 351 chksm += (u_long)(*pt++ & 0xff); 352 return(chksm); 353} 354 355void 356pax_format_list_output(ARCHD *arcn, time_t now, FILE *fp, int term) 357{ 358 /* parse specified listopt format */ 359 char *nextpercent, *nextchar; 360 char buf[4*1024]; 361 int pos, cpylen; 362 char *fname; 363 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); 369 (void)fflush(fp); 370 return; 371 } 372 pos = nextpercent-pax_list_opt_format; 373 memcpy(buf,pax_list_opt_format, pos); 374 while (nextpercent++) { 375 switch (*nextpercent) { 376 case 'F': 377 fname = arcn->name; 378 cpylen = strlen(fname); 379 memcpy(&buf[pos],fname,cpylen); 380 pos+= cpylen; 381 break; 382 case 'D': 383 case 'T': 384 case 'M': 385 case 'L': 386 default: 387 paxwarn(1, "Unimplemented listopt format: %c",*nextpercent); 388 break; 389 } 390 nextpercent++; 391 if (*nextpercent=='\0') { 392 break; 393 } 394 nextchar = nextpercent; 395 nextpercent = strchr(nextpercent,'%'); 396 if (nextpercent==NULL) { 397 cpylen = strlen(nextchar); 398 } else { 399 cpylen = nextpercent - nextchar; 400 } 401 memcpy(&buf[pos],nextchar, cpylen); 402 pos += cpylen; 403 } 404 buf[pos]='\0'; 405 safe_print(&buf[0], fp); 406 (void)putc(term, fp); 407 (void)fflush(fp); 408 return; 409} 410 411void 412cleanup_pax_invalid_action() 413{ 414 switch (pax_invalid_action) { 415 case PAX_INVALID_ACTION_BYPASS: 416 case PAX_INVALID_ACTION_RENAME: 417 break; 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; 423 } 424 break; 425 case PAX_INVALID_ACTION_UTF8: 426 default: 427 paxwarn(1, "pax_invalid_action not implemented:%d", pax_invalid_action); 428 } 429} 430 431void 432record_pax_invalid_action_results(ARCHD * arcn, char * fixed_path) 433{ 434 switch (pax_invalid_action) { 435 case PAX_INVALID_ACTION_BYPASS: 436 case PAX_INVALID_ACTION_RENAME: 437 break; 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'; 442 break; 443 case PAX_INVALID_ACTION_UTF8: 444 default: 445 paxwarn(1, "pax_invalid_action not implemented:%d", pax_invalid_action); 446 } 447} 448 449int 450perform_pax_invalid_action(ARCHD * arcn, int err) 451{ 452 int rc = 0; 453 switch (pax_invalid_action) { 454 case PAX_INVALID_ACTION_BYPASS: 455 rc = -1; 456 break; 457 case PAX_INVALID_ACTION_RENAME: 458 rc = tty_rename(arcn); 459 break; 460 case PAX_INVALID_ACTION_WRITE: 461 pax_invalid_action_write_path = NULL; 462 pax_invalid_action_write_cwd = NULL; 463 rc = 2; 464 break; 465 case PAX_INVALID_ACTION_UTF8: 466 default: 467 paxwarn(1, "pax_invalid_action not implemented:%d", pax_invalid_action); 468 rc = -1; /* do nothing? */ 469 } 470 return rc; 471} 472 473static void 474delete_keywords(char * pattern) 475{ 476 int i; 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; 482 } 483 } 484} 485 486/* 487 * pax_opt() 488 * handle pax format specific -o options 489 * Return: 490 * 0 if ok -1 otherwise 491 */ 492 493int 494pax_opt(void) 495{ 496 OPLIST *opt; 497 int got_option = 0; 498 499 while ((opt = opt_next()) != NULL) { 500 int i; 501 got_option = -1; 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 */ 507 /* Save it away */ 508 got_option = 1; 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", 513 opt->name); 514 break; 515 } 516 if (opt->value) { 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; 525 } else { 526 paxwarn(1,"Invalid action %s not recognized: option ignored", 527 opt->value); 528 } 529 } else { 530 paxwarn(1,"Invalid action RHS not specified: option ignored"); 531 } 532 break; 533 case O_OPTION_ACTION_DELETE: 534 if (opt->separator != SEP_EQ) { 535 paxwarn(1,"-o %s= option requires '=' separator: option ignored", 536 opt->name); 537 break; 538 } 539 /* Mark all matches as deleted */ 540 /* can have multiple -o delete= patterns */ 541 delete_keywords(opt->value); 542 break; 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); 550 } else { 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); 559 } 560 } 561 break; 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); 565 break; 566 } 567 want_a_m_time_headers = 1; 568 break; 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); 572 break; 573 } 574 want_linkdata = 1; 575 break; 576 case O_OPTION_ACTION_HEADER_NAME: 577 if (opt->separator != SEP_EQ) { 578 paxwarn(1,"-o %s= option requires '=' separator: option ignored", 579 opt->name); 580 break; 581 } 582 *(o_option_table[i].g_value) = opt->value; 583 *(o_option_table[i].x_value) = "YES"; 584 break; 585 case O_OPTION_ACTION_LISTOPT: 586 if (opt->separator != SEP_EQ) { 587 paxwarn(1,"-o %s= option requires '=' separator: option ignored", 588 opt->name); 589 break; 590 } 591 *(o_option_table[i].g_value) = opt->value; 592 break; 593 case O_OPTION_ACTION_NOTIMPL: 594 default: 595 paxwarn(1,"pax format -o option not yet implemented: %s=%s", 596 opt->name, opt->value); 597 break; 598 } 599 break; 600 } 601 } 602 if (got_option == -1) { 603 paxwarn(1,"pax format -o option not recognized: %s=%s", 604 opt->name, opt->value); 605 } 606 } 607 return(0); 608} 609 610static int 611expand_extended_headers(ARCHD *arcn, HD_USTAR *hd) 612{ 613 char mybuf[BLKMULT]; 614 HD_USTAR *myhd; 615 char * current_value; 616 int path_replaced = 0; 617 int i, len; 618 619 myhd = hd; 620 while (myhd->typeflag == PAXGTYPE || myhd->typeflag == PAXXTYPE) { 621 char *name, *str; 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"); 626 exit(1); 627 } 628 nbytes = rd_wrbuf(mybuf, size); 629 if (nbytes != size) { 630 paxwarn(1,"extended header data read failure: nbytes=%d, size=%d\n", 631 nbytes, size); 632 exit(1); 633 } 634 /* 635 printf("Read 1 extended header: type=%c, size=%d\n", 636 myhd->typeflag, size); 637 */ 638 inx=0; 639 /* loop over buffer collecting attributes */ 640 while (nbytes > 0) { 641 int got_option = -1; 642 int nentries = sscanf(&mybuf[inx],"%d ", &len); 643 if (nentries != 1) { 644 paxwarn(1,"Extended header failure: length"); 645 exit(1); 646 } 647 if (len < 0 || (inx+len-1 >= sizeof(mybuf))) { 648 paxwarn(1, "Extended header failure: invalid length (%d)", len); 649 exit(1); 650 } 651 if (mybuf[inx+len-1] != '\n') { 652 paxwarn(1,"Extended header failure: missed newline"); 653 exit(1); 654 } else 655 mybuf[inx+len-1] = '\0'; 656 name = strchr(&mybuf[inx],' '); 657 if (name) name++; 658 else { 659 paxwarn(1,"Extended header failure: missing space"); 660 exit(1); 661 } 662 str = strchr(name,'='); 663 if (str) { 664 *str++='\0'; /* end of name */ 665 } else { 666 paxwarn(1,"Extended header failure: missing RHS string"); 667 exit(1); 668 } 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 */ 672 /* Save it away */ 673 got_option = i; 674 break; 675 } 676 } 677 if (got_option == -1) { 678 paxwarn(1,"Unrecognized header keyword: %s",name); 679 } else { 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; 687 } else { 688 current_value = str; 689 found_value = ATTRSRC_FROM_X_HEADER; 690 } 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; 695 } else { 696 current_value = str; 697 found_value = ATTRSRC_FROM_G_HEADER; 698 } 699 } else { 700 paxwarn(1,"Unsupported header type:%c",myhd->typeflag); 701 } 702 if (current_value) { 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); 707 break; 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"); 713 break; 714 case ATTRSRC_FROM_X_O_OPTION: 715 case ATTRSRC_FROM_G_O_OPTION: 716 break; 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; 722 break; 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; 728 break; 729 } 730 break; 731 case O_OPTION_ACTION_ERROR: 732 default: 733 paxwarn(1,"Unsupported extended header attribute: %s=%s", 734 name, str); 735 } 736 } 737 } 738 inx+=len; 739 nbytes -= len; 740 } 741 742 /* position file at next header */ 743 (void)rd_skip(TAR_PAD(size)); 744 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", 749 nbytes, frmt->hsz); 750 } 751 myhd = ((HD_USTAR *)mybuf); 752 /* repeat until no more extended headers */ 753 } 754 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. */ 759 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; 765 free_it = 0; 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; 770 if (current_value) { 771 /* Must remove it: x header values not valid beyond this header */ 772 *o_option_table[i].x_value_current = NULL; 773 free_it = 1; 774 } else { /* No x values, try globals */ 775 current_value = *o_option_table[i].g_value; 776 if (!current_value) 777 current_value = *o_option_table[i].g_value_current; 778 } 779 } 780 if (current_value) { 781 /* Update current header with this value */ 782 /* 783 printf ("Found current_value:%s for %s, pids=%d\n", 784 current_value, o_option_table[i].name, pids); 785 */ 786 len = strlen(current_value); 787 if (header_len == KW_PATH_CASE) { /* Special case for path keyword */ 788 path_replaced = 1; 789 arcn->nlen = len; 790 strlcpy(arcn->name,current_value,sizeof(arcn->name)); 791 } else { 792 if (len > header_len) { 793 paxwarn(1," length of string from extended header bigger than header field:" 794 " THAT won't work!\n"); 795 } else { 796 char * p = (char *) myhd; 797 memcpy(&p[o_option_table[i].header_inx], 798 current_value, len); 799 if (len != header_len) { 800 /* pad with ? */ 801 p[o_option_table[i].header_inx+len] = '\0'; 802 } 803 } 804 } 805 } 806 if (free_it) free(current_value); 807 } 808 } 809 810 if (myhd==hd) return(path_replaced); 811 812 /* must put new header into memory of original */ 813 memcpy(hd, myhd, sizeof(HD_USTAR)); 814 815 return(path_replaced); 816} 817 818/* 819 * pax_id() 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 822 * Return: 823 * 0 if a ustar header, -1 otherwise 824 */ 825 826int 827pax_id(char *blk, int size) 828{ 829 HD_USTAR *hd; 830 831 if (size < BLKMULT) 832 return(-1); 833 hd = (HD_USTAR *)blk; 834 835 /* 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. 840 */ 841 if (hd->name[0] == '\0') 842 return(-1); 843 if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0) 844 return(-1); 845 if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != pax_chksm(blk,BLKMULT)) 846 return(-1); 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 */ 851 return(0); 852 } 853 return(-1); 854 } 855 pax_invalid_action = PAX_INVALID_ACTION_BYPASS; /* Default for pax format */ 856 return(0); 857} 858 859/* 860 * pax_rd() 861 * extract the values out of block already determined to be a pax header. 862 * store the values in the ARCHD parameter. 863 * Return: 864 * 0 865 */ 866 867int 868pax_rd(ARCHD *arcn, char *buf) 869{ 870 HD_USTAR *hd; 871 int cnt = 0; 872 int check_path; 873 dev_t devmajor; 874 dev_t devminor; 875 876 /* 877 * we only get proper sized buffers 878 */ 879 if (pax_id(buf, BLKMULT) < 0) 880 return(-1); 881 882 memset(arcn, 0, sizeof(*arcn)); 883 arcn->org_name = arcn->name; 884 arcn->sb.st_nlink = 1; 885 hd = (HD_USTAR *)buf; 886 887 check_path = expand_extended_headers(arcn, hd); 888 889 if (check_path) { 890 /* 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. 894 */ 895 if (arcn->nlen > sizeof(arcn->name)) { 896 paxwarn(1,"pathname from extended header info doesn't fit! (len=%d)\n", 897 arcn->nlen); 898 } 899 } else { 900 /* 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. 903 */ 904 char *dest = arcn->name; 905 if (*(hd->prefix) != '\0') { 906 cnt = strlcpy(dest, hd->prefix, sizeof(arcn->name) - 1); 907 dest += cnt; 908 *dest++ = '/'; 909 cnt++; 910 } else { 911 cnt = 0; 912 } 913 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)); 919 } 920 } 921 922 /* 923 * follow the spec to the letter. we should only have mode bits, strip 924 * off all other crud we may be passed. 925 */ 926 arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) & 927 0xfff); 928#ifdef LONG_OFF_T 929 arcn->sb.st_size = (off_t)asc_ul(hd->size, sizeof(hd->size), OCT); 930#else 931 arcn->sb.st_size = (off_t)asc_uqd(hd->size, sizeof(hd->size), OCT); 932#endif 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; 935 936 /* 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). 941 */ 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); 948 949 /* 950 * set the defaults, these may be changed depending on the file type 951 */ 952 arcn->pad = 0; 953 arcn->skip = 0; 954 arcn->sb.st_rdev = (dev_t)0; 955 956 /* 957 * set the mode and PAX type according to the typeflag in the header 958 */ 959 switch (hd->typeflag) { 960 case FIFOTYPE: 961 arcn->type = PAX_FIF; 962 arcn->sb.st_mode |= S_IFIFO; 963 break; 964 case DIRTYPE: 965 arcn->type = PAX_DIR; 966 arcn->sb.st_mode |= S_IFDIR; 967 arcn->sb.st_nlink = 2; 968 969 /* 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. 973 */ 974 if (arcn->name[arcn->nlen - 1] == '/') 975 arcn->name[--arcn->nlen] = '\0'; 976 break; 977 case BLKTYPE: 978 case CHRTYPE: 979 /* 980 * this type requires the rdev field to be set. 981 */ 982 if (hd->typeflag == BLKTYPE) { 983 arcn->type = PAX_BLK; 984 arcn->sb.st_mode |= S_IFBLK; 985 } else { 986 arcn->type = PAX_CHR; 987 arcn->sb.st_mode |= S_IFCHR; 988 } 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); 992 break; 993 case SYMTYPE: 994 case LNKTYPE: 995 if (hd->typeflag == SYMTYPE) { 996 arcn->type = PAX_SLK; 997 arcn->sb.st_mode |= S_IFLNK; 998 } else { 999 arcn->type = PAX_HLK; 1000 /* 1001 * so printing looks better 1002 */ 1003 arcn->sb.st_mode |= S_IFREG; 1004 arcn->sb.st_nlink = 2; 1005 } 1006 break; 1007 case LONGLINKTYPE: 1008 case LONGNAMETYPE: 1009 /* 1010 * GNU long link/file; we tag these here and let the 1011 * pax internals deal with it -- too ugly otherwise. 1012 */ 1013 arcn->type = 1014 hd->typeflag == LONGLINKTYPE ? PAX_GLL : PAX_GLF; 1015 arcn->pad = TAR_PAD(arcn->sb.st_size); 1016 arcn->skip = arcn->sb.st_size; 1017 break; 1018 case CONTTYPE: 1019 case AREGTYPE: 1020 case REGTYPE: 1021 default: 1022 /* 1023 * these types have file data that follows. Set the skip and 1024 * pad fields. 1025 */ 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; 1030 break; 1031 } 1032 return(0); 1033} 1034 1035void 1036adjust_copy_for_pax_options(ARCHD * arcn) 1037{ 1038 /* Because ext_header options take precedence over global_header options, apply 1039 global options first, then override with any extended header options */ 1040 int i; 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); 1050 } 1051 } 1052 } 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); 1062 } 1063 } 1064 } 1065 if (want_a_m_time_headers) { 1066 /* TBD */ 1067 } 1068} 1069 1070static int 1071emit_extended_header_record(int len, int total_len, int head_type, 1072 char * name, char * value) 1073{ 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); 1077 } else { 1078 sprintf(&pax_eh_datablk[total_len],"%d %s=%s\n", len, name, value); 1079 total_len += len; 1080 } 1081 return (total_len); 1082} 1083 1084__attribute__((__malloc__)) 1085static char * 1086substitute_percent(char * header, char * filename) 1087{ 1088 char *nextpercent, *nextchar; 1089 char buf[4*1024]; 1090 int pos, cpylen; 1091 char *dname, *fname; 1092 1093 nextpercent = strchr(header,'%'); 1094 if (nextpercent==NULL) return strdup(header); 1095 pos = nextpercent-header; 1096 memcpy(buf,header, pos); 1097 while (nextpercent++) { 1098 switch (*nextpercent) { 1099 case '%': 1100 buf[pos++]='%'; /* just skip it */ 1101 break; 1102 case 'd': 1103 dname = strrchr(filename,'/'); 1104 if (dname==NULL) { 1105 cpylen = 1; 1106 dname = "."; 1107 } else { 1108 cpylen = dname-filename; 1109 dname = filename; 1110 } 1111 memcpy(&buf[pos],dname,cpylen); 1112 pos+= cpylen; 1113 break; 1114 case 'f': 1115 fname = strrchr(filename,'/'); 1116 if (fname==NULL) { 1117 fname = filename; 1118 } else { 1119 fname++; 1120 } 1121 cpylen = strlen(fname); 1122 memcpy(&buf[pos],fname,cpylen); 1123 pos+= cpylen; 1124 break; 1125 case 'n': 1126 pos += sprintf (&buf[pos],"%d",nglobal_headers); 1127 break; 1128 case 'p': 1129 pos += sprintf (&buf[pos],"%d",getpid()); 1130 break; 1131 default: 1132 paxwarn(1,"header format substitution failed: '%c'", *nextpercent); 1133 return strdup(header); 1134 } 1135 nextpercent++; 1136 if (*nextpercent=='\0') { 1137 break; 1138 } 1139 nextchar = nextpercent; 1140 nextpercent = strchr(nextpercent,'%'); 1141 if (nextpercent==NULL) { 1142 cpylen = strlen(nextchar); 1143 } else { 1144 cpylen = nextpercent - nextchar; 1145 } 1146 memcpy(&buf[pos],nextchar, cpylen); 1147 pos += cpylen; 1148 } 1149 buf[pos]='\0'; 1150 return (strdup(&buf[0])); 1151} 1152 1153static int 1154generate_pax_ext_header_and_data(ARCHD *arcn, int nfields, int *table, 1155 char header_type, char * header_name, char * header_name_requested) 1156{ 1157 HD_USTAR *hd; 1158 char hdblk[sizeof(HD_USTAR)]; 1159 u_long records_size; 1160 int term_char, i, len, total_len; 1161 char * str, *name; 1162 1163 if (nfields == 0 && (header_name_requested == NULL)) { 1164 if (header_type==PAXXTYPE) { 1165 if (!want_a_m_time_headers) return (0); 1166 } else 1167 return (0); 1168 } 1169 1170 /* There might be no fields but a header with a specific name or 1171 times might be wanted */ 1172 1173 term_char = 1; 1174 memset(hdblk, 0, sizeof(hdblk)); 1175 hd = (HD_USTAR *)hdblk; 1176 memset(pax_eh_datablk, 0, sizeof(pax_eh_datablk)); 1177 1178 /* generate header */ 1179 hd->typeflag = header_type; 1180 1181 /* These fields appear to be necessary to be able to treat extended headers 1182 like files in older versions of pax */ 1183 ul_oct((u_long)0444, hd->mode, sizeof(hd->mode), term_char); 1184 strncpy(hd->magic, TMAGIC, TMAGLEN); 1185 strncpy(hd->version, TVERSION, TVERSLEN); 1186 ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),term_char); 1187 1188 /* compute size of data */ 1189 total_len = 0; 1190 for (i=0; i < nfields; i++) { 1191 if (!o_option_table[table[i]].active) continue; /* deleted keywords */ 1192 name = o_option_table[table[i]].name; 1193 if (header_type == PAXXTYPE) { 1194 str = *(o_option_table[table[i]].x_value); 1195 } else { 1196 str = *(o_option_table[table[i]].g_value); 1197 } 1198 if (str==NULL) { 1199 paxwarn(1,"Missing option value for %s", name); 1200 continue; 1201 } 1202 len = strlen(str) + o_option_table[table[i]].len + 3; 1203 if (len < 9) len++; 1204 else if (len < 98) len = len + 2; 1205 else if (len < 997) len = len + 3; 1206 else if (len < 9996) len = len + 4; 1207 else { 1208 paxwarn(1,"extended header data too long for header type '%c': %d", 1209 header_type, len); 1210 } 1211 total_len = emit_extended_header_record(len, total_len, 1212 header_type, name, str); 1213 } 1214 1215 if ((header_type == PAXXTYPE) && want_a_m_time_headers) { 1216 char time_buffer[12]; 1217 memset(time_buffer,0,sizeof(time_buffer)); 1218 sprintf(&time_buffer[0],"%d",(int)arcn->sb.st_atime); 1219 /* 3 chars + strlen("atime") + time + # chars in len */ 1220 len = 3 + 5 + strlen(&time_buffer[0]) + 2; 1221 total_len = emit_extended_header_record(len, total_len, 1222 header_type, "atime", &time_buffer[0]); 1223 memset(time_buffer,0,sizeof(time_buffer)); 1224 sprintf(&time_buffer[0],"%d",(int)arcn->sb.st_mtime); 1225 /* 3 chars + strlen("mtime") + time + # chars in len */ 1226 len = 3 + 5 + strlen(&time_buffer[0]) + 2; 1227 total_len = emit_extended_header_record(len, total_len, 1228 header_type, "mtime", &time_buffer[0]); 1229 } 1230 1231 /* Check if all fields were deleted: might not need to generate anything */ 1232 if ((total_len==0) && (header_name_requested == NULL)) return (0); 1233 1234 if (header_type == PAXGTYPE) nglobal_headers++; 1235 /* substitution of fields in header_name */ 1236 header_name = substitute_percent(header_name, arcn->name); 1237 if (strlen(header_name) == sizeof(hd->name)) { /* must account for name just fits in buffer */ 1238 strncpy(hd->name, header_name, sizeof(hd->name)); 1239 } else { 1240 strlcpy(hd->name, header_name, sizeof(hd->name)); 1241 } 1242 1243 free(header_name); 1244 header_name = NULL; 1245 records_size = (u_long)total_len; 1246 if (ul_oct(records_size, hd->size, sizeof(hd->size), term_char)) { 1247 paxwarn(1,"extended header data too long for header type '%c'", header_type); 1248 return(1); 1249 } 1250 1251 if (ul_oct(pax_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum, sizeof(hd->chksum), term_char)) { 1252 paxwarn(1,"extended header data checksum failed: header type '%c'", header_type); 1253 return(1); 1254 } 1255 1256 /* write out header */ 1257 if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0) 1258 return(-1); 1259 if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0) 1260 return(-1); 1261 /* write out header data */ 1262 if (total_len > 0) { 1263 if (wr_rdbuf(pax_eh_datablk, total_len) < 0) 1264 return(-1); 1265 if (wr_skip((off_t)(BLKMULT - total_len)) < 0) 1266 return(-1); 1267 /* 1268 printf("data written:\n%s",&pax_eh_datablk[0]); 1269 */ 1270 } 1271 1272 /* 1273 paxwarn(0,"extended header and data written: header type '%c', #items: %d, %d characters", 1274 header_type, nfields, records_size); 1275 */ 1276 return (0); 1277} 1278 1279/* 1280 * pax_wr() 1281 * write a pax header for the file specified in the ARCHD to the archive 1282 * Have to check for file types that cannot be stored and file names that 1283 * are too long. Be careful of the term (last arg) to ul_oct, we only use 1284 * '\0' for the termination character (this is different than picky tar) 1285 * ASSUMED: space after header in header block is zero filled 1286 * Return: 1287 * 0 if file has data to be written after the header, 1 if file has NO 1288 * data to write after the header, -1 if archive write failed 1289 */ 1290 1291int 1292pax_wr(ARCHD *arcn) 1293{ 1294 HD_USTAR *hd; 1295 char *pt; 1296 char hdblk[sizeof(HD_USTAR)]; 1297 mode_t mode12only; 1298 int term_char=3; /* orignal setting */ 1299 term_char=1; /* To pass conformance tests 274, 301 */ 1300 1301 /* 1302 * check for those file system types pax cannot store 1303 */ 1304 if (arcn->type == PAX_SCK) { 1305 paxwarn(1, "Pax cannot archive a socket %s", arcn->org_name); 1306 return(1); 1307 } 1308 1309 /* 1310 * check the length of the linkname 1311 */ 1312 if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) || 1313 (arcn->type == PAX_HRG)) && (arcn->ln_nlen > sizeof(hd->linkname))){ 1314 paxwarn(1, "Link name too long for pax %s", arcn->ln_name); 1315 /* 1316 * Conformance: test pax:285 wants error code to be non-zero, and 1317 * test tar:12 wants error code from pax to be 0 1318 */ 1319 return(1); 1320 } 1321 1322 /* 1323 * split the path name into prefix and name fields (if needed). if 1324 * pt != arcn->name, the name has to be split 1325 */ 1326 if ((pt = name_split(arcn->name, arcn->nlen)) == NULL) { 1327 paxwarn(1, "File name too long for pax %s", arcn->name); 1328 return(1); 1329 } 1330 1331 generate_pax_ext_header_and_data(arcn, global_ext_header_inx, &global_ext_header_entry[0], 1332 PAXGTYPE, header_name_g, header_name_g_requested); 1333 generate_pax_ext_header_and_data(arcn, ext_header_inx, &ext_header_entry[0], 1334 PAXXTYPE, header_name_x, header_name_x_requested); 1335 1336 /* 1337 * zero out the header so we don't have to worry about zero fill below 1338 */ 1339 memset(hdblk, 0, sizeof(hdblk)); 1340 hd = (HD_USTAR *)hdblk; 1341 arcn->pad = 0L; 1342 /* To pass conformance tests 274/301, always set these fields to "zero" */ 1343 ul_oct(0, hd->devmajor, sizeof(hd->devmajor), term_char); 1344 ul_oct(0, hd->devminor, sizeof(hd->devminor), term_char); 1345 1346 /* 1347 * split the name, or zero out the prefix 1348 */ 1349 if (pt != arcn->name) { 1350 /* 1351 * name was split, pt points at the / where the split is to 1352 * occur, we remove the / and copy the first part to the prefix 1353 */ 1354 *pt = '\0'; 1355 strlcpy(hd->prefix, arcn->name, sizeof(hd->prefix)); 1356 *pt++ = '/'; 1357 } 1358 1359 /* 1360 * copy the name part. this may be the whole path or the part after 1361 * the prefix 1362 */ 1363 if (strlen(pt) == sizeof(hd->name)) { /* must account for name just fits in buffer */ 1364 strncpy(hd->name, pt, sizeof(hd->name)); 1365 } else { 1366 strlcpy(hd->name, pt, sizeof(hd->name)); 1367 } 1368 1369 /* 1370 * set the fields in the header that are type dependent 1371 */ 1372 switch (arcn->type) { 1373 case PAX_DIR: 1374 hd->typeflag = DIRTYPE; 1375 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), term_char)) 1376 goto out; 1377 break; 1378 case PAX_CHR: 1379 case PAX_BLK: 1380 if (arcn->type == PAX_CHR) 1381 hd->typeflag = CHRTYPE; 1382 else 1383 hd->typeflag = BLKTYPE; 1384 if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor, 1385 sizeof(hd->devmajor), term_char) || 1386 ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor, 1387 sizeof(hd->devminor), term_char) || 1388 ul_oct((u_long)0L, hd->size, sizeof(hd->size), term_char)) 1389 goto out; 1390 break; 1391 case PAX_FIF: 1392 hd->typeflag = FIFOTYPE; 1393 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), term_char)) 1394 goto out; 1395 break; 1396 case PAX_SLK: 1397 case PAX_HLK: 1398 case PAX_HRG: 1399 if (arcn->type == PAX_SLK) 1400 hd->typeflag = SYMTYPE; 1401 else 1402 hd->typeflag = LNKTYPE; 1403 if (strlen(arcn->ln_name) == sizeof(hd->linkname)) { /* must account for name just fits in buffer */ 1404 strncpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname)); 1405 } else { 1406 strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname)); 1407 } 1408 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), term_char)) 1409 goto out; 1410 break; 1411 case PAX_REG: 1412 case PAX_CTG: 1413 default: 1414 /* 1415 * file data with this type, set the padding 1416 */ 1417 if (arcn->type == PAX_CTG) 1418 hd->typeflag = CONTTYPE; 1419 else 1420 hd->typeflag = REGTYPE; 1421 arcn->pad = TAR_PAD(arcn->sb.st_size); 1422# ifdef LONG_OFF_T 1423 if (ul_oct((u_long)arcn->sb.st_size, hd->size, 1424 sizeof(hd->size), term_char)) { 1425# else 1426 if (uqd_oct((u_quad_t)arcn->sb.st_size, hd->size, 1427 sizeof(hd->size), term_char)) { 1428# endif 1429 paxwarn(1,"File is too long for pax %s",arcn->org_name); 1430 return(1); 1431 } 1432 break; 1433 } 1434 1435 strncpy(hd->magic, TMAGIC, TMAGLEN); 1436 strncpy(hd->version, TVERSION, TVERSLEN); 1437 1438 /* 1439 * set the remaining fields. Some versions want all 16 bits of mode 1440 * we better humor them (they really do not meet spec though).... 1441 */ 1442 if (ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), term_char)) { 1443 if (uid_nobody == 0) { 1444 if (uid_name("nobody", &uid_nobody) == -1) 1445 goto out; 1446 } 1447 if (uid_warn != arcn->sb.st_uid) { 1448 uid_warn = arcn->sb.st_uid; 1449 paxwarn(1, 1450 "Pax header field is too small for uid %lu, " 1451 "using nobody", (u_long)arcn->sb.st_uid); 1452 } 1453 if (ul_oct((u_long)uid_nobody, hd->uid, sizeof(hd->uid), term_char)) 1454 goto out; 1455 } 1456 if (ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), term_char)) { 1457 if (gid_nobody == 0) { 1458 if (gid_name("nobody", &gid_nobody) == -1) 1459 goto out; 1460 } 1461 if (gid_warn != arcn->sb.st_gid) { 1462 gid_warn = arcn->sb.st_gid; 1463 paxwarn(1, 1464 "Pax header field is too small for gid %lu, " 1465 "using nobody", (u_long)arcn->sb.st_gid); 1466 } 1467 if (ul_oct((u_long)gid_nobody, hd->gid, sizeof(hd->gid), term_char)) 1468 goto out; 1469 } 1470 /* However, Unix conformance tests do not like MORE than 12 mode bits: 1471 remove all beyond (see definition of stat.st_mode structure) */ 1472 mode12only = ((u_long)arcn->sb.st_mode) & 0x00000fff; 1473 if (ul_oct((u_long)mode12only, hd->mode, sizeof(hd->mode), term_char) || 1474 ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),term_char)) 1475 goto out; 1476 strncpy(hd->uname, name_uid(arcn->sb.st_uid, 0), sizeof(hd->uname)); 1477 strncpy(hd->gname, name_gid(arcn->sb.st_gid, 0), sizeof(hd->gname)); 1478 1479 /* 1480 * calculate and store the checksum write the header to the archive 1481 * return 0 tells the caller to now write the file data, 1 says no data 1482 * needs to be written 1483 */ 1484 if (ul_oct(pax_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum, 1485 sizeof(hd->chksum), term_char)) 1486 goto out; 1487 if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0) 1488 return(-1); 1489 if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0) 1490 return(-1); 1491 if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG)) 1492 return(0); 1493 return(1); 1494 1495 out: 1496 /* 1497 * header field is out of range 1498 */ 1499 paxwarn(1, "Pax header field is too small for %s", arcn->org_name); 1500 return(1); 1501} 1502 1503/* 1504 * name_split() 1505 * see if the name has to be split for storage in a ustar header. We try 1506 * to fit the entire name in the name field without splitting if we can. 1507 * The split point is always at a / 1508 * Return 1509 * character pointer to split point (always the / that is to be removed 1510 * if the split is not needed, the points is set to the start of the file 1511 * name (it would violate the spec to split there). A NULL is returned if 1512 * the file name is too long 1513 */ 1514 1515static char * 1516name_split(char *name, int len) 1517{ 1518 char *start; 1519 1520 /* 1521 * check to see if the file name is small enough to fit in the name 1522 * field. if so just return a pointer to the name. 1523 */ 1524 if (len <= TNMSZ) 1525 return(name); 1526 if (len > (TPFSZ + TNMSZ)) 1527 return(NULL); 1528 1529 /* 1530 * we start looking at the biggest sized piece that fits in the name 1531 * field. We walk forward looking for a slash to split at. The idea is 1532 * to find the biggest piece to fit in the name field (or the smallest 1533 * prefix we can find) 1534 */ 1535 start = name + len - TNMSZ -1; 1536 if ((*start == '/') && (start == name)) 1537 ++start; /* 101 byte paths with leading '/' are dinged otherwise */ 1538 while ((*start != '\0') && (*start != '/')) 1539 ++start; 1540 1541 /* 1542 * if we hit the end of the string, this name cannot be split, so we 1543 * cannot store this file. 1544 */ 1545 if (*start == '\0') 1546 return(NULL); 1547 len = start - name; 1548 1549 /* 1550 * NOTE: /str where the length of str == TNMSZ can not be stored under 1551 * the p1003.1-1990 spec for ustar. We could force a prefix of / and 1552 * the file would then expand on extract to //str. The len == 0 below 1553 * makes this special case follow the spec to the letter. 1554 */ 1555 if ((len >= TPFSZ) || (len == 0)) 1556 return(NULL); 1557 1558 /* 1559 * ok have a split point, return it to the caller 1560 */ 1561 return(start); 1562} 1563 1564static size_t 1565expandname(char *buf, size_t len, char **gnu_name, const char *name, size_t name_len) 1566{ 1567 size_t nlen; 1568 1569 if (*gnu_name) { 1570 if ((nlen = strlcpy(buf, *gnu_name, len)) >= len) 1571 nlen = len - 1; 1572 free(*gnu_name); 1573 *gnu_name = NULL; 1574 } else { 1575 if (name_len < len) { 1576 /* name may not be null terminated: it might be as big as the 1577 field, so copy is limited to the max size of the header field */ 1578 if ((nlen = strlcpy(buf, name, name_len+1)) >= name_len+1) 1579 nlen = name_len; 1580 } else { 1581 if ((nlen = strlcpy(buf, name, len)) >= len) 1582 nlen = len - 1; 1583 } 1584 } 1585 return(nlen); 1586} 1587