pkgfs.c revision 329145
1/*- 2 * Copyright (c) 2007-2014, Juniper Networks, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/11/stand/libsa/pkgfs.c 329132 2018-02-11 19:51:29Z kevans $"); 29 30#include "stand.h" 31 32#include <sys/stat.h> 33#include <sys/stdint.h> 34#include <string.h> 35#include <zlib.h> 36 37#ifdef PKGFS_DEBUG 38#define DBG(x) printf x 39#else 40#define DBG(x) 41#endif 42 43static int pkg_open(const char *, struct open_file *); 44static int pkg_close(struct open_file *); 45static int pkg_read(struct open_file *, void *, size_t, size_t *); 46static off_t pkg_seek(struct open_file *, off_t, int); 47static int pkg_stat(struct open_file *, struct stat *); 48static int pkg_readdir(struct open_file *, struct dirent *); 49 50struct fs_ops pkgfs_fsops = { 51 "pkg", 52 pkg_open, 53 pkg_close, 54 pkg_read, 55 null_write, 56 pkg_seek, 57 pkg_stat, 58 pkg_readdir 59}; 60 61#define PKG_BUFSIZE 512 62#define PKG_MAXCACHESZ 4096 63 64#define PKG_FILEEXT ".tgz" 65 66/* 67 * Layout of POSIX 'ustar' header. 68 */ 69struct ustar_hdr { 70 char ut_name[100]; 71 char ut_mode[8]; 72 char ut_uid[8]; 73 char ut_gid[8]; 74 char ut_size[12]; 75 char ut_mtime[12]; 76 char ut_checksum[8]; 77 char ut_typeflag[1]; 78 char ut_linkname[100]; 79 char ut_magic[6]; /* For POSIX: "ustar\0" */ 80 char ut_version[2]; /* For POSIX: "00" */ 81 char ut_uname[32]; 82 char ut_gname[32]; 83 char ut_rdevmajor[8]; 84 char ut_rdevminor[8]; 85 union { 86 struct { 87 char prefix[155]; 88 } posix; 89 struct { 90 char atime[12]; 91 char ctime[12]; 92 char offset[12]; 93 char longnames[4]; 94 char unused[1]; 95 struct gnu_sparse { 96 char offset[12]; 97 char numbytes[12]; 98 } sparse[4]; 99 char isextended[1]; 100 char realsize[12]; 101 } gnu; 102 } u; 103 u_char __padding[12]; 104}; 105 106struct package; 107 108struct tarfile 109{ 110 struct package *tf_pkg; 111 struct tarfile *tf_next; 112 struct ustar_hdr tf_hdr; 113 off_t tf_ofs; 114 off_t tf_size; 115 off_t tf_fp; 116 size_t tf_cachesz; 117 void *tf_cache; 118}; 119 120struct package 121{ 122 struct package *pkg_chain; 123 int pkg_fd; 124 off_t pkg_ofs; 125 z_stream pkg_zs; 126 struct tarfile *pkg_first; 127 struct tarfile *pkg_last; 128 u_char pkg_buf[PKG_BUFSIZE]; 129}; 130 131static struct package *package = NULL; 132 133static int new_package(int, struct package **); 134 135void 136pkgfs_cleanup(void) 137{ 138 struct package *chain; 139 struct tarfile *tf, *tfn; 140 141 while (package != NULL) { 142 inflateEnd(&package->pkg_zs); 143 close(package->pkg_fd); 144 145 tf = package->pkg_first; 146 while (tf != NULL) { 147 tfn = tf->tf_next; 148 if (tf->tf_cachesz > 0) 149 free(tf->tf_cache); 150 free(tf); 151 tf = tfn; 152 } 153 154 chain = package->pkg_chain; 155 free(package); 156 package = chain; 157 } 158} 159 160int 161pkgfs_init(const char *pkgname, struct fs_ops *proto) 162{ 163 struct package *pkg; 164 int error, fd; 165 166 if (proto != &pkgfs_fsops) 167 pkgfs_cleanup(); 168 169 exclusive_file_system = proto; 170 171 fd = open(pkgname, O_RDONLY); 172 173 exclusive_file_system = NULL; 174 175 if (fd == -1) 176 return (errno); 177 178 error = new_package(fd, &pkg); 179 if (error) { 180 close(fd); 181 return (error); 182 } 183 184 if (pkg == NULL) 185 return (EDOOFUS); 186 187 pkg->pkg_chain = package; 188 package = pkg; 189 exclusive_file_system = &pkgfs_fsops; 190 return (0); 191} 192 193static int get_mode(struct tarfile *); 194static int get_zipped(struct package *, void *, size_t); 195static int new_package(int, struct package **); 196static struct tarfile *scan_tarfile(struct package *, struct tarfile *); 197 198static int 199pkg_open(const char *fn, struct open_file *f) 200{ 201 struct tarfile *tf; 202 203 if (fn == NULL || f == NULL) 204 return (EINVAL); 205 206 if (package == NULL) 207 return (ENXIO); 208 209 /* 210 * We can only read from a package, so reject request to open 211 * for write-only or read-write. 212 */ 213 if (f->f_flags != F_READ) 214 return (EPERM); 215 216 /* 217 * Scan the file headers for the named file. We stop scanning 218 * at the first filename that has the .pkg extension. This is 219 * a package within a package. We assume we have all the files 220 * we need up-front and without having to dig within nested 221 * packages. 222 * 223 * Note that we preserve streaming properties as much as possible. 224 */ 225 while (*fn == '/') 226 fn++; 227 228 /* 229 * Allow opening of the root directory for use by readdir() 230 * to support listing files in the package. 231 */ 232 if (*fn == '\0') { 233 f->f_fsdata = NULL; 234 return (0); 235 } 236 237 tf = scan_tarfile(package, NULL); 238 while (tf != NULL) { 239 if (strcmp(fn, tf->tf_hdr.ut_name) == 0) { 240 f->f_fsdata = tf; 241 tf->tf_fp = 0; /* Reset the file pointer. */ 242 return (0); 243 } 244 tf = scan_tarfile(package, tf); 245 } 246 return (errno); 247} 248 249static int 250pkg_close(struct open_file *f) 251{ 252 struct tarfile *tf; 253 254 tf = (struct tarfile *)f->f_fsdata; 255 if (tf == NULL) 256 return (0); 257 258 /* 259 * Free up the cache if we read all of the file. 260 */ 261 if (tf->tf_fp == tf->tf_size && tf->tf_cachesz > 0) { 262 free(tf->tf_cache); 263 tf->tf_cachesz = 0; 264 } 265 return (0); 266} 267 268static int 269pkg_read(struct open_file *f, void *buf, size_t size, size_t *res) 270{ 271 struct tarfile *tf; 272 char *p; 273 off_t fp; 274 size_t sz; 275 276 tf = (struct tarfile *)f->f_fsdata; 277 if (tf == NULL) { 278 if (res != NULL) 279 *res = size; 280 return (EBADF); 281 } 282 283 fp = tf->tf_fp; 284 p = buf; 285 sz = 0; 286 while (size > 0) { 287 sz = tf->tf_size - fp; 288 if (fp < tf->tf_cachesz && tf->tf_cachesz < tf->tf_size) 289 sz = tf->tf_cachesz - fp; 290 if (size < sz) 291 sz = size; 292 if (sz == 0) 293 break; 294 295 if (fp < tf->tf_cachesz) { 296 /* Satisfy the request from cache. */ 297 memcpy(p, tf->tf_cache + fp, sz); 298 fp += sz; 299 p += sz; 300 size -= sz; 301 continue; 302 } 303 304 if (get_zipped(tf->tf_pkg, p, sz) == -1) { 305 sz = -1; 306 break; 307 } 308 309 fp += sz; 310 p += sz; 311 size -= sz; 312 313 if (tf->tf_cachesz != 0) 314 continue; 315 316 tf->tf_cachesz = (sz <= PKG_MAXCACHESZ) ? sz : PKG_MAXCACHESZ; 317 tf->tf_cache = malloc(tf->tf_cachesz); 318 if (tf->tf_cache != NULL) 319 memcpy(tf->tf_cache, buf, tf->tf_cachesz); 320 else 321 tf->tf_cachesz = 0; 322 } 323 324 tf->tf_fp = fp; 325 if (res != NULL) 326 *res = size; 327 return ((sz == -1) ? errno : 0); 328} 329 330static off_t 331pkg_seek(struct open_file *f, off_t ofs, int whence) 332{ 333 char buf[512]; 334 struct tarfile *tf; 335 off_t delta; 336 size_t sz, res; 337 int error; 338 339 tf = (struct tarfile *)f->f_fsdata; 340 if (tf == NULL) { 341 errno = EBADF; 342 return (-1); 343 } 344 345 switch (whence) { 346 case SEEK_SET: 347 delta = ofs - tf->tf_fp; 348 break; 349 case SEEK_CUR: 350 delta = ofs; 351 break; 352 case SEEK_END: 353 delta = tf->tf_size - tf->tf_fp + ofs; 354 break; 355 default: 356 errno = EINVAL; 357 return (-1); 358 } 359 360 if (delta < 0) { 361 DBG(("%s: negative file seek (%jd)\n", __func__, 362 (intmax_t)delta)); 363 errno = ESPIPE; 364 return (-1); 365 } 366 367 while (delta > 0 && tf->tf_fp < tf->tf_size) { 368 sz = (delta > sizeof(buf)) ? sizeof(buf) : delta; 369 error = pkg_read(f, buf, sz, &res); 370 if (error != 0) { 371 errno = error; 372 return (-1); 373 } 374 delta -= sz - res; 375 } 376 377 return (tf->tf_fp); 378} 379 380static int 381pkg_stat(struct open_file *f, struct stat *sb) 382{ 383 struct tarfile *tf; 384 385 tf = (struct tarfile *)f->f_fsdata; 386 if (tf == NULL) 387 return (EBADF); 388 memset(sb, 0, sizeof(*sb)); 389 sb->st_mode = get_mode(tf); 390 sb->st_size = tf->tf_size; 391 sb->st_blocks = (tf->tf_size + 511) / 512; 392 return (0); 393} 394 395static int 396pkg_readdir(struct open_file *f, struct dirent *d) 397{ 398 struct tarfile *tf; 399 400 tf = (struct tarfile *)f->f_fsdata; 401 if (tf != NULL) 402 return (EBADF); 403 404 tf = scan_tarfile(package, NULL); 405 if (tf == NULL) 406 return (ENOENT); 407 408 d->d_fileno = 0; 409 d->d_reclen = sizeof(*d); 410 d->d_type = DT_REG; 411 memcpy(d->d_name, tf->tf_hdr.ut_name, sizeof(d->d_name)); 412 return (0); 413} 414 415/* 416 * Low-level support functions. 417 */ 418 419static int 420get_byte(struct package *pkg, off_t *op) 421{ 422 int c; 423 424 if (pkg->pkg_zs.avail_in == 0) { 425 c = read(pkg->pkg_fd, pkg->pkg_buf, PKG_BUFSIZE); 426 if (c <= 0) 427 return (-1); 428 pkg->pkg_zs.avail_in = c; 429 pkg->pkg_zs.next_in = pkg->pkg_buf; 430 } 431 432 c = *pkg->pkg_zs.next_in; 433 pkg->pkg_zs.next_in++; 434 pkg->pkg_zs.avail_in--; 435 (*op)++; 436 return (c); 437} 438 439static int 440get_zipped(struct package *pkg, void *buf, size_t bufsz) 441{ 442 int c; 443 444 pkg->pkg_zs.next_out = buf; 445 pkg->pkg_zs.avail_out = bufsz; 446 447 while (pkg->pkg_zs.avail_out) { 448 if (pkg->pkg_zs.avail_in == 0) { 449 c = read(pkg->pkg_fd, pkg->pkg_buf, PKG_BUFSIZE); 450 if (c <= 0) { 451 errno = EIO; 452 return (-1); 453 } 454 pkg->pkg_zs.avail_in = c; 455 pkg->pkg_zs.next_in = pkg->pkg_buf; 456 } 457 458 c = inflate(&pkg->pkg_zs, Z_SYNC_FLUSH); 459 if (c != Z_OK && c != Z_STREAM_END) { 460 errno = EIO; 461 return (-1); 462 } 463 } 464 465 pkg->pkg_ofs += bufsz; 466 return (0); 467} 468 469static int 470cache_data(struct tarfile *tf) 471{ 472 struct package *pkg; 473 size_t sz; 474 475 if (tf == NULL) { 476 DBG(("%s: no file to cache data for?\n", __func__)); 477 errno = EINVAL; 478 return (-1); 479 } 480 481 pkg = tf->tf_pkg; 482 if (pkg == NULL) { 483 DBG(("%s: no package associated with file?\n", __func__)); 484 errno = EINVAL; 485 return (-1); 486 } 487 488 if (tf->tf_ofs != pkg->pkg_ofs) { 489 DBG(("%s: caching after partial read of file %s?\n", 490 __func__, tf->tf_hdr.ut_name)); 491 errno = EINVAL; 492 return (-1); 493 } 494 495 /* We don't cache everything... */ 496 if (tf->tf_size > PKG_MAXCACHESZ) { 497 errno = ENOMEM; 498 return (-1); 499 } 500 501 /* All files are padded to a multiple of 512 bytes. */ 502 sz = (tf->tf_size + 0x1ff) & ~0x1ff; 503 504 tf->tf_cache = malloc(sz); 505 if (tf->tf_cache == NULL) { 506 DBG(("%s: could not allocate %d bytes\n", __func__, (int)sz)); 507 errno = ENOMEM; 508 return (-1); 509 } 510 511 tf->tf_cachesz = sz; 512 return (get_zipped(pkg, tf->tf_cache, sz)); 513} 514 515/* 516 * Note that this implementation does not (and should not!) obey 517 * locale settings; you cannot simply substitute strtol here, since 518 * it does obey locale. 519 */ 520static off_t 521pkg_atol8(const char *p, unsigned char_cnt) 522{ 523 int64_t l, limit, last_digit_limit; 524 int digit, sign, base; 525 526 base = 8; 527 limit = INT64_MAX / base; 528 last_digit_limit = INT64_MAX % base; 529 530 while (*p == ' ' || *p == '\t') 531 p++; 532 if (*p == '-') { 533 sign = -1; 534 p++; 535 } else 536 sign = 1; 537 538 l = 0; 539 digit = *p - '0'; 540 while (digit >= 0 && digit < base && char_cnt-- > 0) { 541 if (l>limit || (l == limit && digit > last_digit_limit)) { 542 l = UINT64_MAX; /* Truncate on overflow. */ 543 break; 544 } 545 l = (l * base) + digit; 546 digit = *++p - '0'; 547 } 548 return (sign < 0) ? -l : l; 549} 550 551/* 552 * Parse a base-256 integer. This is just a straight signed binary 553 * value in big-endian order, except that the high-order bit is 554 * ignored. Remember that "int64_t" may or may not be exactly 64 555 * bits; the implementation here tries to avoid making any assumptions 556 * about the actual size of an int64_t. It does assume we're using 557 * twos-complement arithmetic, though. 558 */ 559static int64_t 560pkg_atol256(const char *_p, unsigned char_cnt) 561{ 562 int64_t l, upper_limit, lower_limit; 563 const unsigned char *p = (const unsigned char *)_p; 564 565 upper_limit = INT64_MAX / 256; 566 lower_limit = INT64_MIN / 256; 567 568 /* Pad with 1 or 0 bits, depending on sign. */ 569 if ((0x40 & *p) == 0x40) 570 l = (int64_t)-1; 571 else 572 l = 0; 573 l = (l << 6) | (0x3f & *p++); 574 while (--char_cnt > 0) { 575 if (l > upper_limit) { 576 l = INT64_MAX; /* Truncate on overflow */ 577 break; 578 } else if (l < lower_limit) { 579 l = INT64_MIN; 580 break; 581 } 582 l = (l << 8) | (0xff & (int64_t)*p++); 583 } 584 return (l); 585} 586 587static off_t 588pkg_atol(const char *p, unsigned char_cnt) 589{ 590 /* 591 * Technically, GNU pkg considers a field to be in base-256 592 * only if the first byte is 0xff or 0x80. 593 */ 594 if (*p & 0x80) 595 return (pkg_atol256(p, char_cnt)); 596 return (pkg_atol8(p, char_cnt)); 597} 598 599static int 600get_mode(struct tarfile *tf) 601{ 602 return (pkg_atol(tf->tf_hdr.ut_mode, sizeof(tf->tf_hdr.ut_mode))); 603} 604 605/* GZip flag byte */ 606#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ 607#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ 608#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ 609#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ 610#define COMMENT 0x10 /* bit 4 set: file comment present */ 611#define RESERVED 0xE0 /* bits 5..7: reserved */ 612 613static int 614new_package(int fd, struct package **pp) 615{ 616 struct package *pkg; 617 off_t ofs; 618 int flags, i, error; 619 620 pkg = malloc(sizeof(*pkg)); 621 if (pkg == NULL) 622 return (ENOMEM); 623 624 bzero(pkg, sizeof(*pkg)); 625 pkg->pkg_fd = fd; 626 627 /* 628 * Parse the header. 629 */ 630 error = EFTYPE; 631 ofs = 0; 632 633 /* Check megic. */ 634 if (get_byte(pkg, &ofs) != 0x1f || get_byte(pkg, &ofs) != 0x8b) 635 goto fail; 636 /* Check method. */ 637 if (get_byte(pkg, &ofs) != Z_DEFLATED) 638 goto fail; 639 /* Check flags. */ 640 flags = get_byte(pkg, &ofs); 641 if (flags & RESERVED) 642 goto fail; 643 644 /* Skip time, xflags and OS code. */ 645 for (i = 0; i < 6; i++) { 646 if (get_byte(pkg, &ofs) == -1) 647 goto fail; 648 } 649 650 /* Skip extra field. */ 651 if (flags & EXTRA_FIELD) { 652 i = (get_byte(pkg, &ofs) & 0xff) | 653 ((get_byte(pkg, &ofs) << 8) & 0xff); 654 while (i-- > 0) { 655 if (get_byte(pkg, &ofs) == -1) 656 goto fail; 657 } 658 } 659 660 /* Skip original file name. */ 661 if (flags & ORIG_NAME) { 662 do { 663 i = get_byte(pkg, &ofs); 664 } while (i != 0 && i != -1); 665 if (i == -1) 666 goto fail; 667 } 668 669 /* Print the comment if it's there. */ 670 if (flags & COMMENT) { 671 while (1) { 672 i = get_byte(pkg, &ofs); 673 if (i == -1) 674 goto fail; 675 if (i == 0) 676 break; 677 putchar(i); 678 } 679 } 680 681 /* Skip the CRC. */ 682 if (flags & HEAD_CRC) { 683 if (get_byte(pkg, &ofs) == -1) 684 goto fail; 685 if (get_byte(pkg, &ofs) == -1) 686 goto fail; 687 } 688 689 /* 690 * Done parsing the ZIP header. Spkgt the inflation engine. 691 */ 692 error = inflateInit2(&pkg->pkg_zs, -15); 693 if (error != Z_OK) 694 goto fail; 695 696 *pp = pkg; 697 return (0); 698 699 fail: 700 free(pkg); 701 return (error); 702} 703 704static struct tarfile * 705scan_tarfile(struct package *pkg, struct tarfile *last) 706{ 707 char buf[512]; 708 struct tarfile *cur; 709 off_t ofs; 710 size_t sz; 711 712 cur = (last != NULL) ? last->tf_next : pkg->pkg_first; 713 if (cur == NULL) { 714 ofs = (last != NULL) ? last->tf_ofs + last->tf_size : 715 pkg->pkg_ofs; 716 ofs = (ofs + 0x1ff) & ~0x1ff; 717 718 /* Check if we've reached EOF. */ 719 if (ofs < pkg->pkg_ofs) { 720 errno = ENOSPC; 721 return (NULL); 722 } 723 724 if (ofs != pkg->pkg_ofs) { 725 if (last != NULL && pkg->pkg_ofs == last->tf_ofs) { 726 if (cache_data(last) == -1) 727 return (NULL); 728 } else { 729 sz = ofs - pkg->pkg_ofs; 730 while (sz != 0) { 731 if (sz > sizeof(buf)) 732 sz = sizeof(buf); 733 if (get_zipped(pkg, buf, sz) == -1) 734 return (NULL); 735 sz = ofs - pkg->pkg_ofs; 736 } 737 } 738 } 739 740 cur = malloc(sizeof(*cur)); 741 if (cur == NULL) 742 return (NULL); 743 memset(cur, 0, sizeof(*cur)); 744 cur->tf_pkg = pkg; 745 746 while (1) { 747 if (get_zipped(pkg, &cur->tf_hdr, 748 sizeof(cur->tf_hdr)) == -1) { 749 free(cur); 750 return (NULL); 751 } 752 753 /* 754 * There are always 2 empty blocks appended to 755 * a PKG. It marks the end of the archive. 756 */ 757 if (strncmp(cur->tf_hdr.ut_magic, "ustar", 5) != 0) { 758 free(cur); 759 errno = ENOSPC; 760 return (NULL); 761 } 762 763 cur->tf_ofs = pkg->pkg_ofs; 764 cur->tf_size = pkg_atol(cur->tf_hdr.ut_size, 765 sizeof(cur->tf_hdr.ut_size)); 766 767 if (cur->tf_hdr.ut_name[0] != '+') 768 break; 769 770 /* 771 * Skip package meta-files. 772 */ 773 ofs = cur->tf_ofs + cur->tf_size; 774 ofs = (ofs + 0x1ff) & ~0x1ff; 775 while (pkg->pkg_ofs < ofs) { 776 if (get_zipped(pkg, buf, sizeof(buf)) == -1) { 777 free(cur); 778 return (NULL); 779 } 780 } 781 } 782 783 if (last != NULL) 784 last->tf_next = cur; 785 else 786 pkg->pkg_first = cur; 787 pkg->pkg_last = cur; 788 } 789 790 return (cur); 791} 792