tar.c revision 1.28
1/* $NetBSD: tar.c,v 1.28 2002/10/16 18:53:40 christos Exp $ */ 2 3/*- 4 * Copyright (c) 1992 Keith Muller. 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Keith Muller of the University of California, San Diego. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 */ 39 40#include <sys/cdefs.h> 41#if defined(__RCSID) && !defined(lint) 42#if 0 43static char sccsid[] = "@(#)tar.c 8.2 (Berkeley) 4/18/94"; 44#else 45__RCSID("$NetBSD: tar.c,v 1.28 2002/10/16 18:53:40 christos Exp $"); 46#endif 47#endif /* not lint */ 48 49#include <sys/types.h> 50#include <sys/time.h> 51#include <sys/stat.h> 52#include <sys/param.h> 53 54#include <ctype.h> 55#include <errno.h> 56#include <grp.h> 57#include <pwd.h> 58#include <stdio.h> 59#include <stdlib.h> 60#include <string.h> 61#include <unistd.h> 62 63#include "pax.h" 64#include "extern.h" 65#include "tar.h" 66 67/* 68 * Routines for reading, writing and header identify of various versions of tar 69 */ 70 71static void longlink(ARCHD *); 72static u_long tar_chksm(char *, int); 73static char *name_split(char *, int); 74static int ul_oct(u_long, char *, int, int); 75#if !defined(NET2_STAT) && !defined(_LP64) 76static int ull_oct(unsigned long long, char *, int, int); 77#endif 78 79/* 80 * Routines common to all versions of tar 81 */ 82 83static int tar_nodir; /* do not write dirs under old tar */ 84int is_gnutar; /* behave like gnu tar; enable gnu 85 * extensions and skip end-ofvolume 86 * checks 87 */ 88char *gnu_hack_string; /* ././@LongLink hackery */ 89int gnu_hack_len; /* len of gnu_hack_string */ 90 91/* 92 * tar_endwr() 93 * add the tar trailer of two null blocks 94 * Return: 95 * 0 if ok, -1 otherwise (what wr_skip returns) 96 */ 97 98int 99tar_endwr(void) 100{ 101 return(wr_skip((off_t)(NULLCNT*BLKMULT))); 102} 103 104/* 105 * tar_endrd() 106 * no cleanup needed here, just return size of trailer (for append) 107 * Return: 108 * size of trailer (2 * BLKMULT) 109 */ 110 111off_t 112tar_endrd(void) 113{ 114 return((off_t)(NULLCNT*BLKMULT)); 115} 116 117/* 118 * tar_trail() 119 * Called to determine if a header block is a valid trailer. We are passed 120 * the block, the in_sync flag (which tells us we are in resync mode; 121 * looking for a valid header), and cnt (which starts at zero) which is 122 * used to count the number of empty blocks we have seen so far. 123 * Return: 124 * 0 if a valid trailer, -1 if not a valid trailer, or 1 if the block 125 * could never contain a header. 126 */ 127 128int 129tar_trail(char *buf, int in_resync, int *cnt) 130{ 131 int i; 132 133 /* 134 * look for all zero, trailer is two consecutive blocks of zero 135 */ 136 for (i = 0; i < BLKMULT; ++i) { 137 if (buf[i] != '\0') 138 break; 139 } 140 141 /* 142 * if not all zero it is not a trailer, but MIGHT be a header. 143 */ 144 if (i != BLKMULT) 145 return(-1); 146 147 /* 148 * When given a zero block, we must be careful! 149 * If we are not in resync mode, check for the trailer. Have to watch 150 * out that we do not mis-identify file data as the trailer, so we do 151 * NOT try to id a trailer during resync mode. During resync mode we 152 * might as well throw this block out since a valid header can NEVER be 153 * a block of all 0 (we must have a valid file name). 154 */ 155 if (!in_resync && (++*cnt >= NULLCNT)) 156 return(0); 157 return(1); 158} 159 160/* 161 * ul_oct() 162 * convert an unsigned long to an octal string. many oddball field 163 * termination characters are used by the various versions of tar in the 164 * different fields. term selects which kind to use. str is '0' padded 165 * at the front to len. we are unable to use only one format as many old 166 * tar readers are very cranky about this. 167 * Return: 168 * 0 if the number fit into the string, -1 otherwise 169 */ 170 171static int 172ul_oct(u_long val, char *str, int len, int term) 173{ 174 char *pt; 175 176 /* 177 * term selects the appropriate character(s) for the end of the string 178 */ 179 pt = str + len - 1; 180 switch(term) { 181 case 3: 182 *pt-- = '\0'; 183 break; 184 case 2: 185 *pt-- = ' '; 186 *pt-- = '\0'; 187 break; 188 case 1: 189 *pt-- = ' '; 190 break; 191 case 0: 192 default: 193 *pt-- = '\0'; 194 *pt-- = ' '; 195 break; 196 } 197 198 /* 199 * convert and blank pad if there is space 200 */ 201 while (pt >= str) { 202 *pt-- = '0' + (char)(val & 0x7); 203 if ((val = val >> 3) == (u_long)0) 204 break; 205 } 206 207 while (pt >= str) 208 *pt-- = '0'; 209 if (val != (u_long)0) 210 return(-1); 211 return(0); 212} 213 214#if !defined(NET2_STAT) && !defined(_LP64) 215/* 216 * ull_oct() 217 * convert an unsigned long long to an octal string. one of many oddball 218 * field termination characters are used by the various versions of tar 219 * in the different fields. term selects which kind to use. str is '0' 220 * padded at the front to len. we are unable to use only one format as 221 * many old tar readers are very cranky about this. 222 * Return: 223 * 0 if the number fit into the string, -1 otherwise 224 */ 225 226static int 227ull_oct(unsigned long long val, char *str, int len, int term) 228{ 229 char *pt; 230 231 /* 232 * term selects the appropriate character(s) for the end of the string 233 */ 234 pt = str + len - 1; 235 switch(term) { 236 case 3: 237 *pt-- = '\0'; 238 break; 239 case 2: 240 *pt-- = ' '; 241 *pt-- = '\0'; 242 break; 243 case 1: 244 *pt-- = ' '; 245 break; 246 case 0: 247 default: 248 *pt-- = '\0'; 249 *pt-- = ' '; 250 break; 251 } 252 253 /* 254 * convert and blank pad if there is space 255 */ 256 while (pt >= str) { 257 *pt-- = '0' + (char)(val & 0x7); 258 if ((val = val >> 3) == 0) 259 break; 260 } 261 262 while (pt >= str) 263 *pt-- = '0'; 264 if (val != (unsigned long long)0) 265 return(-1); 266 return(0); 267} 268#endif 269 270/* 271 * tar_chksm() 272 * calculate the checksum for a tar block counting the checksum field as 273 * all blanks (BLNKSUM is that value pre-calculated, the sum of 8 blanks). 274 * NOTE: we use len to short circuit summing 0's on write since we ALWAYS 275 * pad headers with 0. 276 * Return: 277 * unsigned long checksum 278 */ 279 280static u_long 281tar_chksm(char *blk, int len) 282{ 283 char *stop; 284 char *pt; 285 u_long chksm = BLNKSUM; /* initial value is checksum field sum */ 286 287 /* 288 * add the part of the block before the checksum field 289 */ 290 pt = blk; 291 stop = blk + CHK_OFFSET; 292 while (pt < stop) 293 chksm += (u_long)(*pt++ & 0xff); 294 /* 295 * move past the checksum field and keep going, spec counts the 296 * checksum field as the sum of 8 blanks (which is pre-computed as 297 * BLNKSUM). 298 * ASSUMED: len is greater than CHK_OFFSET. (len is where our 0 padding 299 * starts, no point in summing zero's) 300 */ 301 pt += CHK_LEN; 302 stop = blk + len; 303 while (pt < stop) 304 chksm += (u_long)(*pt++ & 0xff); 305 return(chksm); 306} 307 308/* 309 * Routines for old BSD style tar (also made portable to sysV tar) 310 */ 311 312/* 313 * tar_id() 314 * determine if a block given to us is a valid tar header (and not a USTAR 315 * header). We have to be on the lookout for those pesky blocks of all 316 * zero's. 317 * Return: 318 * 0 if a tar header, -1 otherwise 319 */ 320 321int 322tar_id(char *blk, int size) 323{ 324 HD_TAR *hd; 325 HD_USTAR *uhd; 326 327 if (size < BLKMULT) 328 return(-1); 329 hd = (HD_TAR *)blk; 330 uhd = (HD_USTAR *)blk; 331 332 /* 333 * check for block of zero's first, a simple and fast test, then make 334 * sure this is not a ustar header by looking for the ustar magic 335 * cookie. We should use TMAGLEN, but some USTAR archive programs are 336 * wrong and create archives missing the \0. Last we check the 337 * checksum. If this is ok we have to assume it is a valid header. 338 */ 339 if (hd->name[0] == '\0') 340 return(-1); 341 if (strncmp(uhd->magic, TMAGIC, TMAGLEN - 1) == 0) 342 return(-1); 343 if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT)) 344 return(-1); 345 return(0); 346} 347 348/* 349 * tar_opt() 350 * handle tar format specific -o options 351 * Return: 352 * 0 if ok -1 otherwise 353 */ 354 355int 356tar_opt(void) 357{ 358 OPLIST *opt; 359 360 while ((opt = opt_next()) != NULL) { 361 if (strcmp(opt->name, TAR_OPTION) || 362 strcmp(opt->value, TAR_NODIR)) { 363 tty_warn(1, 364 "Unknown tar format -o option/value pair %s=%s", 365 opt->name, opt->value); 366 tty_warn(1, 367 "%s=%s is the only supported tar format option", 368 TAR_OPTION, TAR_NODIR); 369 return(-1); 370 } 371 372 /* 373 * we only support one option, and only when writing 374 */ 375 if ((act != APPND) && (act != ARCHIVE)) { 376 tty_warn(1, "%s=%s is only supported when writing.", 377 opt->name, opt->value); 378 return(-1); 379 } 380 tar_nodir = 1; 381 } 382 return(0); 383} 384 385 386/* 387 * tar_rd() 388 * extract the values out of block already determined to be a tar header. 389 * store the values in the ARCHD parameter. 390 * Return: 391 * 0 392 */ 393 394int 395tar_rd(ARCHD *arcn, char *buf) 396{ 397 HD_TAR *hd; 398 char *pt; 399 400 /* 401 * we only get proper sized buffers passed to us 402 */ 403 if (tar_id(buf, BLKMULT) < 0) 404 return(-1); 405 arcn->org_name = arcn->name; 406 arcn->sb.st_nlink = 1; 407 arcn->pat = NULL; 408 409 /* 410 * copy out the name and values in the stat buffer 411 */ 412 hd = (HD_TAR *)buf; 413 if (gnu_hack_string) { 414 arcn->nlen = strlcpy(arcn->name, gnu_hack_string, 415 sizeof(arcn->name)); 416 free(gnu_hack_string); 417 gnu_hack_string = NULL; 418 } else { 419 arcn->nlen = strlcpy(arcn->name, hd->name, sizeof(arcn->name)); 420 } 421 arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode,sizeof(hd->mode),OCT) & 422 0xfff); 423 arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT); 424 arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT); 425 arcn->sb.st_size = (off_t)ASC_OFFT(hd->size, sizeof(hd->size), OCT); 426 arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT); 427 arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 428 429 /* 430 * have to look at the last character, it may be a '/' and that is used 431 * to encode this as a directory 432 */ 433 pt = &(arcn->name[arcn->nlen - 1]); 434 arcn->pad = 0; 435 arcn->skip = 0; 436 switch(hd->linkflag) { 437 case SYMTYPE: 438 /* 439 * symbolic link, need to get the link name and set the type in 440 * the st_mode so -v printing will look correct. 441 */ 442 arcn->type = PAX_SLK; 443 arcn->ln_nlen = strlcpy(arcn->ln_name, hd->linkname, 444 sizeof(arcn->ln_name)); 445 arcn->sb.st_mode |= S_IFLNK; 446 break; 447 case LNKTYPE: 448 /* 449 * hard link, need to get the link name, set the type in the 450 * st_mode and st_nlink so -v printing will look better. 451 */ 452 arcn->type = PAX_HLK; 453 arcn->sb.st_nlink = 2; 454 arcn->ln_nlen = strlcpy(arcn->ln_name, hd->linkname, 455 sizeof(arcn->ln_name)); 456 457 /* 458 * no idea of what type this thing really points at, but 459 * we set something for printing only. 460 */ 461 arcn->sb.st_mode |= S_IFREG; 462 break; 463 case LONGLINKTYPE: 464 arcn->type = PAX_GLL; 465 /* FALLTHROUGH */ 466 case LONGNAMETYPE: 467 /* 468 * GNU long link/file; we tag these here and let the 469 * pax internals deal with it -- too ugly otherwise. 470 */ 471 if (hd->linkflag != LONGLINKTYPE) 472 arcn->type = PAX_GLF; 473 arcn->pad = TAR_PAD(arcn->sb.st_size); 474 arcn->skip = arcn->sb.st_size; 475 arcn->ln_name[0] = '\0'; 476 arcn->ln_nlen = 0; 477 break; 478 case AREGTYPE: 479 case REGTYPE: 480 case DIRTYPE: /* see below */ 481 default: 482 /* 483 * If we have a trailing / this is a directory and NOT a file. 484 * Note: V7 tar doesn't actually have DIRTYPE, but it was 485 * reported that V7 archives using USTAR directories do exist. 486 */ 487 arcn->ln_name[0] = '\0'; 488 arcn->ln_nlen = 0; 489 if (*pt == '/' || hd->linkflag == DIRTYPE) { 490 /* 491 * it is a directory, set the mode for -v printing 492 */ 493 arcn->type = PAX_DIR; 494 arcn->sb.st_mode |= S_IFDIR; 495 arcn->sb.st_nlink = 2; 496 } else { 497 /* 498 * have a file that will be followed by data. Set the 499 * skip value to the size field and calculate the size 500 * of the padding. 501 */ 502 arcn->type = PAX_REG; 503 arcn->sb.st_mode |= S_IFREG; 504 arcn->pad = TAR_PAD(arcn->sb.st_size); 505 arcn->skip = arcn->sb.st_size; 506 } 507 break; 508 } 509 510 /* 511 * strip off any trailing slash. 512 */ 513 if (*pt == '/') { 514 *pt = '\0'; 515 --arcn->nlen; 516 } 517 return(0); 518} 519 520/* 521 * tar_wr() 522 * write a tar header for the file specified in the ARCHD to the archive. 523 * Have to check for file types that cannot be stored and file names that 524 * are too long. Be careful of the term (last arg) to ul_oct, each field 525 * of tar has it own spec for the termination character(s). 526 * ASSUMED: space after header in header block is zero filled 527 * Return: 528 * 0 if file has data to be written after the header, 1 if file has NO 529 * data to write after the header, -1 if archive write failed 530 */ 531 532int 533tar_wr(ARCHD *arcn) 534{ 535 HD_TAR *hd; 536 int len; 537 char hdblk[sizeof(HD_TAR)]; 538 539 /* 540 * check for those file system types which tar cannot store 541 */ 542 switch(arcn->type) { 543 case PAX_DIR: 544 /* 545 * user asked that dirs not be written to the archive 546 */ 547 if (tar_nodir) 548 return(1); 549 break; 550 case PAX_CHR: 551 tty_warn(1, "Tar cannot archive a character device %s", 552 arcn->org_name); 553 return(1); 554 case PAX_BLK: 555 tty_warn(1, 556 "Tar cannot archive a block device %s", arcn->org_name); 557 return(1); 558 case PAX_SCK: 559 tty_warn(1, "Tar cannot archive a socket %s", arcn->org_name); 560 return(1); 561 case PAX_FIF: 562 tty_warn(1, "Tar cannot archive a fifo %s", arcn->org_name); 563 return(1); 564 case PAX_SLK: 565 case PAX_HLK: 566 case PAX_HRG: 567 if (arcn->ln_nlen > sizeof(hd->linkname)) { 568 tty_warn(1,"Link name too long for tar %s", 569 arcn->ln_name); 570 return(1); 571 } 572 break; 573 case PAX_REG: 574 case PAX_CTG: 575 default: 576 break; 577 } 578 579 /* 580 * check file name len, remember extra char for dirs (the / at the end) 581 */ 582 len = arcn->nlen; 583 if (arcn->type == PAX_DIR) 584 ++len; 585 if (len >= sizeof(hd->name)) { 586 tty_warn(1, "File name too long for tar %s", arcn->name); 587 return(1); 588 } 589 590 /* 591 * copy the data out of the ARCHD into the tar header based on the type 592 * of the file. Remember many tar readers want the unused fields to be 593 * padded with zero. We set the linkflag field (type), the linkname 594 * (or zero if not used),the size, and set the padding (if any) to be 595 * added after the file data (0 for all other types, as they only have 596 * a header) 597 */ 598 memset(hdblk, 0, sizeof(hdblk)); 599 hd = (HD_TAR *)hdblk; 600 strlcpy(hd->name, arcn->name, sizeof(hd->name)); 601 arcn->pad = 0; 602 603 if (arcn->type == PAX_DIR) { 604 /* 605 * directories are the same as files, except have a filename 606 * that ends with a /, we add the slash here. No data follows, 607 * dirs, so no pad. 608 */ 609 hd->linkflag = AREGTYPE; 610 hd->name[len-1] = '/'; 611 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) 612 goto out; 613 } else if (arcn->type == PAX_SLK) { 614 /* 615 * no data follows this file, so no pad 616 */ 617 hd->linkflag = SYMTYPE; 618 strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname)); 619 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) 620 goto out; 621 } else if ((arcn->type == PAX_HLK) || (arcn->type == PAX_HRG)) { 622 /* 623 * no data follows this file, so no pad 624 */ 625 hd->linkflag = LNKTYPE; 626 strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname)); 627 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 1)) 628 goto out; 629 } else { 630 /* 631 * data follows this file, so set the pad 632 */ 633 hd->linkflag = AREGTYPE; 634 if (OFFT_OCT(arcn->sb.st_size, hd->size, sizeof(hd->size), 1)) { 635 tty_warn(1,"File is too large for tar %s", 636 arcn->org_name); 637 return(1); 638 } 639 arcn->pad = TAR_PAD(arcn->sb.st_size); 640 } 641 642 /* 643 * copy those fields that are independent of the type 644 */ 645 if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 0) || 646 ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 0) || 647 ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 0) || 648 ul_oct((u_long)arcn->sb.st_mtime, hd->mtime, sizeof(hd->mtime), 1)) 649 goto out; 650 651 /* 652 * calculate and add the checksum, then write the header. A return of 653 * 0 tells the caller to now write the file data, 1 says no data needs 654 * to be written 655 */ 656 if (ul_oct(tar_chksm(hdblk, sizeof(HD_TAR)), hd->chksum, 657 sizeof(hd->chksum), 3)) 658 goto out; /* XXX Something's wrong here 659 * because a zero-byte file can 660 * cause this to be done and 661 * yet the resulting warning 662 * seems incorrect */ 663 664 if (wr_rdbuf(hdblk, sizeof(HD_TAR)) < 0) 665 return(-1); 666 if (wr_skip((off_t)(BLKMULT - sizeof(HD_TAR))) < 0) 667 return(-1); 668 if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG)) 669 return(0); 670 return(1); 671 672 out: 673 /* 674 * header field is out of range 675 */ 676 tty_warn(1, "Tar header field is too small for %s", arcn->org_name); 677 return(1); 678} 679 680/* 681 * Routines for POSIX ustar 682 */ 683 684/* 685 * ustar_strd() 686 * initialization for ustar read 687 * Return: 688 * 0 if ok, -1 otherwise 689 */ 690 691int 692ustar_strd(void) 693{ 694 return(0); 695} 696 697/* 698 * ustar_stwr() 699 * initialization for ustar write 700 * Return: 701 * 0 if ok, -1 otherwise 702 */ 703 704int 705ustar_stwr(void) 706{ 707 return(0); 708} 709 710/* 711 * ustar_id() 712 * determine if a block given to us is a valid ustar header. We have to 713 * be on the lookout for those pesky blocks of all zero's 714 * Return: 715 * 0 if a ustar header, -1 otherwise 716 */ 717 718int 719ustar_id(char *blk, int size) 720{ 721 HD_USTAR *hd; 722 723 if (size < BLKMULT) 724 return(-1); 725 hd = (HD_USTAR *)blk; 726 727 /* 728 * check for block of zero's first, a simple and fast test then check 729 * ustar magic cookie. We should use TMAGLEN, but some USTAR archive 730 * programs are fouled up and create archives missing the \0. Last we 731 * check the checksum. If ok we have to assume it is a valid header. 732 */ 733 if (hd->name[0] == '\0') 734 return(-1); 735 if (strncmp(hd->magic, TMAGIC, TMAGLEN - 1) != 0) 736 return(-1); 737 /* This is GNU tar */ 738 if (strncmp(hd->magic, "ustar ", 8) == 0 && !is_gnutar) 739 tty_warn(1, 740 "Trying to read GNU tar archive with extensions off"); 741 if (asc_ul(hd->chksum,sizeof(hd->chksum),OCT) != tar_chksm(blk,BLKMULT)) 742 return(-1); 743 return(0); 744} 745 746/* 747 * ustar_rd() 748 * extract the values out of block already determined to be a ustar header. 749 * store the values in the ARCHD parameter. 750 * Return: 751 * 0 752 */ 753 754int 755ustar_rd(ARCHD *arcn, char *buf) 756{ 757 HD_USTAR *hd; 758 char *dest; 759 int cnt; 760 dev_t devmajor; 761 dev_t devminor; 762 763 /* 764 * we only get proper sized buffers 765 */ 766 if (ustar_id(buf, BLKMULT) < 0) 767 return(-1); 768 arcn->org_name = arcn->name; 769 arcn->sb.st_nlink = 1; 770 arcn->pat = NULL; 771 arcn->nlen = 0; 772 hd = (HD_USTAR *)buf; 773 774 /* 775 * see if the filename is split into two parts. if, so joint the parts. 776 * we copy the prefix first and add a / between the prefix and name. 777 */ 778 dest = arcn->name; 779 if (*(hd->prefix) != '\0') { 780 cnt = strlcpy(arcn->name, hd->prefix, sizeof(arcn->name)); 781 dest += cnt; 782 *dest++ = '/'; 783 cnt++; 784 } 785 if (gnu_hack_string) { 786 arcn->nlen = strlcpy(dest, gnu_hack_string, 787 sizeof(arcn->name) - cnt); 788 free(gnu_hack_string); 789 gnu_hack_string = NULL; 790 } else { 791 arcn->nlen = strlcpy(dest, hd->name, sizeof(arcn->name) - cnt); 792 } 793 794 /* 795 * follow the spec to the letter. we should only have mode bits, strip 796 * off all other crud we may be passed. 797 */ 798 arcn->sb.st_mode = (mode_t)(asc_ul(hd->mode, sizeof(hd->mode), OCT) & 799 0xfff); 800 arcn->sb.st_size = (off_t)ASC_OFFT(hd->size, sizeof(hd->size), OCT); 801 arcn->sb.st_mtime = (time_t)asc_ul(hd->mtime, sizeof(hd->mtime), OCT); 802 arcn->sb.st_ctime = arcn->sb.st_atime = arcn->sb.st_mtime; 803 804 /* 805 * If we can find the ascii names for gname and uname in the password 806 * and group files we will use the uid's and gid they bind. Otherwise 807 * we use the uid and gid values stored in the header. (This is what 808 * the posix spec wants). 809 */ 810 hd->gname[sizeof(hd->gname) - 1] = '\0'; 811 if (gid_from_group(hd->gname, &(arcn->sb.st_gid)) < 0) 812 arcn->sb.st_gid = (gid_t)asc_ul(hd->gid, sizeof(hd->gid), OCT); 813 hd->uname[sizeof(hd->uname) - 1] = '\0'; 814 if (uid_from_user(hd->uname, &(arcn->sb.st_uid)) < 0) 815 arcn->sb.st_uid = (uid_t)asc_ul(hd->uid, sizeof(hd->uid), OCT); 816 817 /* 818 * set the defaults, these may be changed depending on the file type 819 */ 820 arcn->ln_name[0] = '\0'; 821 arcn->ln_nlen = 0; 822 arcn->pad = 0; 823 arcn->skip = 0; 824 arcn->sb.st_rdev = (dev_t)0; 825 826 /* 827 * set the mode and PAX type according to the typeflag in the header 828 */ 829 switch(hd->typeflag) { 830 case FIFOTYPE: 831 arcn->type = PAX_FIF; 832 arcn->sb.st_mode |= S_IFIFO; 833 break; 834 case DIRTYPE: 835 arcn->type = PAX_DIR; 836 arcn->sb.st_mode |= S_IFDIR; 837 arcn->sb.st_nlink = 2; 838 839 /* 840 * Some programs that create ustar archives append a '/' 841 * to the pathname for directories. This clearly violates 842 * ustar specs, but we will silently strip it off anyway. 843 */ 844 if (arcn->name[arcn->nlen - 1] == '/') 845 arcn->name[--arcn->nlen] = '\0'; 846 break; 847 case BLKTYPE: 848 case CHRTYPE: 849 /* 850 * this type requires the rdev field to be set. 851 */ 852 if (hd->typeflag == BLKTYPE) { 853 arcn->type = PAX_BLK; 854 arcn->sb.st_mode |= S_IFBLK; 855 } else { 856 arcn->type = PAX_CHR; 857 arcn->sb.st_mode |= S_IFCHR; 858 } 859 devmajor = (dev_t)asc_ul(hd->devmajor,sizeof(hd->devmajor),OCT); 860 devminor = (dev_t)asc_ul(hd->devminor,sizeof(hd->devminor),OCT); 861 arcn->sb.st_rdev = TODEV(devmajor, devminor); 862 break; 863 case SYMTYPE: 864 case LNKTYPE: 865 if (hd->typeflag == SYMTYPE) { 866 arcn->type = PAX_SLK; 867 arcn->sb.st_mode |= S_IFLNK; 868 } else { 869 arcn->type = PAX_HLK; 870 /* 871 * so printing looks better 872 */ 873 arcn->sb.st_mode |= S_IFREG; 874 arcn->sb.st_nlink = 2; 875 } 876 /* 877 * copy the link name 878 */ 879 arcn->ln_nlen = strlcpy(arcn->ln_name, hd->linkname, 880 sizeof(arcn->ln_name)); 881 break; 882 case LONGLINKTYPE: 883 if (is_gnutar) 884 arcn->type = PAX_GLL; 885 /* FALLTHROUGH */ 886 case LONGNAMETYPE: 887 if (is_gnutar) { 888 /* 889 * GNU long link/file; we tag these here and let the 890 * pax internals deal with it -- too ugly otherwise. 891 */ 892 if (hd->typeflag != LONGLINKTYPE) 893 arcn->type = PAX_GLF; 894 arcn->pad = TAR_PAD(arcn->sb.st_size); 895 arcn->skip = arcn->sb.st_size; 896 arcn->ln_name[0] = '\0'; 897 arcn->ln_nlen = 0; 898 } else { 899 tty_warn(1, "GNU Long %s found in posix ustar archive.", 900 hd->typeflag == LONGLINKTYPE ? "Link" : "File"); 901 } 902 break; 903 case CONTTYPE: 904 case AREGTYPE: 905 case REGTYPE: 906 default: 907 /* 908 * these types have file data that follows. Set the skip and 909 * pad fields. 910 */ 911 arcn->type = PAX_REG; 912 arcn->pad = TAR_PAD(arcn->sb.st_size); 913 arcn->skip = arcn->sb.st_size; 914 arcn->sb.st_mode |= S_IFREG; 915 break; 916 } 917 return(0); 918} 919 920 921static void 922longlink(ARCHD *arcn) 923{ 924 ARCHD larc; 925 926 memset(&larc, 0, sizeof(larc)); 927 928 switch (arcn->type) { 929 case PAX_SLK: 930 case PAX_HRG: 931 case PAX_HLK: 932 larc.type = PAX_GLL; 933 larc.ln_nlen = strlcpy(larc.ln_name, "././@LongLink", 934 sizeof(larc.ln_name)); 935 gnu_hack_string = arcn->ln_name; 936 gnu_hack_len = arcn->ln_nlen + 1; 937 break; 938 default: 939 larc.nlen = strlcpy(larc.name, "././@LongLink", 940 sizeof(larc.name)); 941 gnu_hack_string = arcn->name; 942 gnu_hack_len = arcn->nlen + 1; 943 larc.type = PAX_GLF; 944 } 945 /* 946 * We need a longlink now. 947 */ 948 ustar_wr(&larc); 949} 950 951/* 952 * ustar_wr() 953 * write a ustar header for the file specified in the ARCHD to the archive 954 * Have to check for file types that cannot be stored and file names that 955 * are too long. Be careful of the term (last arg) to ul_oct, we only use 956 * '\0' for the termination character (this is different than picky tar) 957 * ASSUMED: space after header in header block is zero filled 958 * Return: 959 * 0 if file has data to be written after the header, 1 if file has NO 960 * data to write after the header, -1 if archive write failed 961 */ 962 963int 964ustar_wr(ARCHD *arcn) 965{ 966 HD_USTAR *hd; 967 char *pt; 968 char hdblk[sizeof(HD_USTAR)]; 969 const char *user, *group; 970 971 /* 972 * check for those file system types ustar cannot store 973 */ 974 if (arcn->type == PAX_SCK) { 975 tty_warn(1, "Ustar cannot archive a socket %s", arcn->org_name); 976 return(1); 977 } 978 979 /* 980 * check the length of the linkname 981 */ 982 if (((arcn->type == PAX_SLK) || (arcn->type == PAX_HLK) || 983 (arcn->type == PAX_HRG)) && 984 (arcn->ln_nlen >= sizeof(hd->linkname))){ 985 if (is_gnutar) { 986 longlink(arcn); 987 } else { 988 tty_warn(1, "Link name too long for ustar %s", 989 arcn->ln_name); 990 return(1); 991 } 992 } 993 994 /* 995 * split the path name into prefix and name fields (if needed). if 996 * pt != arcn->name, the name has to be split 997 */ 998 if ((pt = name_split(arcn->name, arcn->nlen)) == NULL) { 999 if (is_gnutar) { 1000 longlink(arcn); 1001 pt = arcn->name; 1002 } else { 1003 tty_warn(1, "File name too long for ustar %s", 1004 arcn->name); 1005 return(1); 1006 } 1007 } 1008 1009 /* 1010 * zero out the header so we don't have to worry about zero fill below 1011 */ 1012 memset(hdblk, 0, sizeof(hdblk)); 1013 hd = (HD_USTAR *)hdblk; 1014 arcn->pad = 0L; 1015 1016 /* 1017 * split the name, or zero out the prefix 1018 */ 1019 if (pt != arcn->name) { 1020 /* 1021 * name was split, pt points at the / where the split is to 1022 * occur, we remove the / and copy the first part to the prefix 1023 */ 1024 *pt = '\0'; 1025 strlcpy(hd->prefix, arcn->name, sizeof(hd->prefix)); 1026 *pt++ = '/'; 1027 } 1028 1029 /* 1030 * copy the name part. this may be the whole path or the part after 1031 * the prefix 1032 */ 1033 strlcpy(hd->name, pt, sizeof(hd->name)); 1034 1035 /* 1036 * set the fields in the header that are type dependent 1037 */ 1038 switch(arcn->type) { 1039 case PAX_DIR: 1040 hd->typeflag = DIRTYPE; 1041 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 1042 goto out; 1043 break; 1044 case PAX_CHR: 1045 case PAX_BLK: 1046 if (arcn->type == PAX_CHR) 1047 hd->typeflag = CHRTYPE; 1048 else 1049 hd->typeflag = BLKTYPE; 1050 if (ul_oct((u_long)MAJOR(arcn->sb.st_rdev), hd->devmajor, 1051 sizeof(hd->devmajor), 3) || 1052 ul_oct((u_long)MINOR(arcn->sb.st_rdev), hd->devminor, 1053 sizeof(hd->devminor), 3) || 1054 ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 1055 goto out; 1056 break; 1057 case PAX_FIF: 1058 hd->typeflag = FIFOTYPE; 1059 if (ul_oct((u_long)0L, hd->size, sizeof(hd->size), 3)) 1060 goto out; 1061 break; 1062 case PAX_GLL: 1063 case PAX_SLK: 1064 case PAX_HLK: 1065 case PAX_HRG: 1066 if (arcn->type == PAX_SLK) 1067 hd->typeflag = SYMTYPE; 1068 else if (arcn->type == PAX_GLL) 1069 hd->typeflag = LONGLINKTYPE; 1070 else 1071 hd->typeflag = LNKTYPE; 1072 strlcpy(hd->linkname, arcn->ln_name, sizeof(hd->linkname)); 1073 if (ul_oct((u_long)gnu_hack_len, hd->size, 1074 sizeof(hd->size), 3)) 1075 goto out; 1076 break; 1077 case PAX_GLF: 1078 case PAX_REG: 1079 case PAX_CTG: 1080 default: 1081 /* 1082 * file data with this type, set the padding 1083 */ 1084 if (arcn->type == PAX_GLF) { 1085 hd->typeflag = LONGNAMETYPE; 1086 arcn->pad = TAR_PAD(gnu_hack_len); 1087 if (OFFT_OCT((u_long)gnu_hack_len, hd->size, 1088 sizeof(hd->size), 3)) { 1089 tty_warn(1,"File is too long for ustar %s", 1090 arcn->org_name); 1091 return(1); 1092 } 1093 } else { 1094 if (arcn->type == PAX_CTG) 1095 hd->typeflag = CONTTYPE; 1096 else 1097 hd->typeflag = REGTYPE; 1098 arcn->pad = TAR_PAD(arcn->sb.st_size); 1099 if (OFFT_OCT(arcn->sb.st_size, hd->size, 1100 sizeof(hd->size), 3)) { 1101 tty_warn(1,"File is too long for ustar %s", 1102 arcn->org_name); 1103 return(1); 1104 } 1105 } 1106 break; 1107 } 1108 1109 strncpy(hd->magic, TMAGIC, TMAGLEN); 1110 if (is_gnutar) 1111 hd->magic[TMAGLEN - 1] = hd->magic[TMAGLEN] = ' '; 1112 else 1113 strncpy(hd->version, TVERSION, TVERSLEN); 1114 1115 /* 1116 * set the remaining fields. Some versions want all 16 bits of mode 1117 * we better humor them (they really do not meet spec though).... 1118 */ 1119 if (ul_oct((u_long)arcn->sb.st_mode, hd->mode, sizeof(hd->mode), 3) || 1120 ul_oct((u_long)arcn->sb.st_uid, hd->uid, sizeof(hd->uid), 3) || 1121 ul_oct((u_long)arcn->sb.st_gid, hd->gid, sizeof(hd->gid), 3) || 1122 ul_oct((u_long)arcn->sb.st_mtime,hd->mtime,sizeof(hd->mtime),3)) 1123 goto out; 1124 user = user_from_uid(arcn->sb.st_uid, 1); 1125 group = group_from_gid(arcn->sb.st_gid, 1); 1126 strncpy(hd->uname, user ? user : "", sizeof(hd->uname)); 1127 strncpy(hd->gname, group ? group : "", sizeof(hd->gname)); 1128 1129 /* 1130 * calculate and store the checksum write the header to the archive 1131 * return 0 tells the caller to now write the file data, 1 says no data 1132 * needs to be written 1133 */ 1134 if (ul_oct(tar_chksm(hdblk, sizeof(HD_USTAR)), hd->chksum, 1135 sizeof(hd->chksum), 3)) 1136 goto out; 1137 if (wr_rdbuf(hdblk, sizeof(HD_USTAR)) < 0) 1138 return(-1); 1139 if (wr_skip((off_t)(BLKMULT - sizeof(HD_USTAR))) < 0) 1140 return(-1); 1141 if (gnu_hack_string) { 1142 int res = wr_rdbuf(gnu_hack_string, gnu_hack_len); 1143 int pad = gnu_hack_len; 1144 gnu_hack_string = NULL; 1145 gnu_hack_len = 0; 1146 if (res < 0) 1147 return(-1); 1148 if (wr_skip((off_t)(BLKMULT - (pad % BLKMULT))) < 0) 1149 return(-1); 1150 } 1151 if ((arcn->type == PAX_CTG) || (arcn->type == PAX_REG)) 1152 return(0); 1153 return(1); 1154 1155 out: 1156 /* 1157 * header field is out of range 1158 */ 1159 tty_warn(1, "Ustar header field is too small for %s", arcn->org_name); 1160 return(1); 1161} 1162 1163/* 1164 * name_split() 1165 * see if the name has to be split for storage in a ustar header. We try 1166 * to fit the entire name in the name field without splitting if we can. 1167 * The split point is always at a / 1168 * Return 1169 * character pointer to split point (always the / that is to be removed 1170 * if the split is not needed, the points is set to the start of the file 1171 * name (it would violate the spec to split there). A NULL is returned if 1172 * the file name is too long 1173 */ 1174 1175static char * 1176name_split(char *name, int len) 1177{ 1178 char *start; 1179 1180 /* 1181 * check to see if the file name is small enough to fit in the name 1182 * field. if so just return a pointer to the name. 1183 */ 1184 if (len < TNMSZ) 1185 return(name); 1186 if (len > (TPFSZ + TNMSZ)) 1187 return(NULL); 1188 1189 /* 1190 * we start looking at the biggest sized piece that fits in the name 1191 * field. We walk forward looking for a slash to split at. The idea is 1192 * to find the biggest piece to fit in the name field (or the smallest 1193 * prefix we can find) (the -1 is correct the biggest piece would 1194 * include the slash between the two parts that gets thrown away) 1195 */ 1196 start = name + len - TNMSZ; 1197 while ((*start != '\0') && (*start != '/')) 1198 ++start; 1199 1200 /* 1201 * if we hit the end of the string, this name cannot be split, so we 1202 * cannot store this file. 1203 */ 1204 if (*start == '\0') 1205 return(NULL); 1206 len = start - name; 1207 1208 /* 1209 * NOTE: /str where the length of str == TNMSZ can not be stored under 1210 * the p1003.1-1990 spec for ustar. We could force a prefix of / and 1211 * the file would then expand on extract to //str. The len == 0 below 1212 * makes this special case follow the spec to the letter. 1213 */ 1214 if ((len >= TPFSZ) || (len == 0)) 1215 return(NULL); 1216 1217 /* 1218 * ok have a split point, return it to the caller 1219 */ 1220 return(start); 1221} 1222 1223/* 1224 * deal with GNU tar -X switch. basically, we go through each line of 1225 * the file, building a string from the "glob" lines in the file into 1226 * RE lines, of the form `/^RE$//', which we pass to rep_add(), which 1227 * will add a empty replacement (exclusion), for the named files. 1228 */ 1229int 1230tar_gnutar_X_compat(path) 1231 const char *path; 1232{ 1233 char *line, sbuf[MAXPATHLEN * 2 + 1 + 5]; 1234 FILE *fp; 1235 int lineno = 0, i, j; 1236 size_t len; 1237 1238 fp = fopen(path, "r"); 1239 if (fp == NULL) { 1240 tty_warn(1, "can not open %s: %s", path, 1241 strerror(errno)); 1242 return(-1); 1243 } 1244 1245 while ((line = fgetln(fp, &len))) { 1246 lineno++; 1247 if (len > MAXPATHLEN) { 1248 tty_warn(0, "pathname too long, line %d of %s", 1249 lineno, path); 1250 } 1251 if (line[len - 1] == '\n') 1252 len--; 1253 for (i = 0, j = 2; i < len; i++) { 1254 /* 1255 * convert glob to regexp, escaping everything 1256 */ 1257 if (line[i] == '*') 1258 sbuf[j++] = '.'; 1259 else if (line[i] == '?') 1260 line[i] = '.'; 1261 else if (!isalnum(line[i]) && !isblank(line[i])) 1262 sbuf[j++] = '\\'; 1263 sbuf[j++] = line[i]; 1264 } 1265 sbuf[0] = sbuf[j + 1] = sbuf[j + 2] = '/'; 1266 sbuf[1] = '^'; 1267 sbuf[j] = '$'; 1268 sbuf[j + 3] = '\0'; 1269 if (rep_add(sbuf) < 0) 1270 return (-1); 1271 } 1272 return (0); 1273} 1274