1 /*- 2 * Copyright (c) 2009-2012,2014 Michihiro NAKAJIMA 3 * Copyright (c) 2003-2007 Tim Kientzle 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "archive_platform.h" 28 __FBSDID("$FreeBSD$"); 29 30 #ifdef HAVE_SYS_TYPES_H 31 #include <sys/types.h> 32 #endif 33 #ifdef HAVE_ERRNO_H 34 #include <errno.h> 35 #endif 36 #ifdef HAVE_FCNTL_H 37 #include <fcntl.h> 38 #endif 39 #ifdef HAVE_STDLIB_H 40 #include <stdlib.h> 41 #endif 42 #ifdef HAVE_STRING_H 43 #include <string.h> 44 #endif 45 #if defined(_WIN32) && !defined(__CYGWIN__) 46 #if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA 47 /* don't use bcrypt when XP needs to be supported */ 48 #include <bcrypt.h> 49 50 /* Common in other bcrypt implementations, but missing from VS2008. */ 51 #ifndef BCRYPT_SUCCESS 52 #define BCRYPT_SUCCESS(r) ((NTSTATUS)(r) == STATUS_SUCCESS) 53 #endif 54 55 #elif defined(HAVE_WINCRYPT_H) 56 #include <wincrypt.h> 57 #endif 58 #endif 59 #ifdef HAVE_ZLIB_H 60 #include <zlib.h> 61 #endif 62 #ifdef HAVE_LZMA_H 63 #include <lzma.h> 64 #endif 65 #ifdef HAVE_BZLIB_H 66 #include <bzlib.h> 67 #endif 68 #ifdef HAVE_LZ4_H 69 #include <lz4.h> 70 #endif 71 72 #include "archive.h" 73 #include "archive_private.h" 74 #include "archive_random_private.h" 75 #include "archive_string.h" 76 77 #ifndef O_CLOEXEC 78 #define O_CLOEXEC 0 79 #endif 80 81 static int archive_utility_string_sort_helper(char **, unsigned int); 82 83 /* Generic initialization of 'struct archive' objects. */ 84 int 85 __archive_clean(struct archive *a) 86 { 87 archive_string_conversion_free(a); 88 return (ARCHIVE_OK); 89 } 90 91 int 92 archive_version_number(void) 93 { 94 return (ARCHIVE_VERSION_NUMBER); 95 } 96 97 const char * 98 archive_version_string(void) 99 { 100 return (ARCHIVE_VERSION_STRING); 101 } 102 103 int 104 archive_errno(struct archive *a) 105 { 106 return (a->archive_error_number); 107 } 108 109 const char * 110 archive_error_string(struct archive *a) 111 { 112 113 if (a->error != NULL && *a->error != '\0') 114 return (a->error); 115 else 116 return (NULL); 117 } 118 119 int 120 archive_file_count(struct archive *a) 121 { 122 return (a->file_count); 123 } 124 125 int 126 archive_format(struct archive *a) 127 { 128 return (a->archive_format); 129 } 130 131 const char * 132 archive_format_name(struct archive *a) 133 { 134 return (a->archive_format_name); 135 } 136 137 138 int 139 archive_compression(struct archive *a) 140 { 141 return archive_filter_code(a, 0); 142 } 143 144 const char * 145 archive_compression_name(struct archive *a) 146 { 147 return archive_filter_name(a, 0); 148 } 149 150 151 /* 152 * Return a count of the number of compressed bytes processed. 153 */ 154 la_int64_t 155 archive_position_compressed(struct archive *a) 156 { 157 return archive_filter_bytes(a, -1); 158 } 159 160 /* 161 * Return a count of the number of uncompressed bytes processed. 162 */ 163 la_int64_t 164 archive_position_uncompressed(struct archive *a) 165 { 166 return archive_filter_bytes(a, 0); 167 } 168 169 void 170 archive_clear_error(struct archive *a) 171 { 172 archive_string_empty(&a->error_string); 173 a->error = NULL; 174 a->archive_error_number = 0; 175 } 176 177 void 178 archive_set_error(struct archive *a, int error_number, const char *fmt, ...) 179 { 180 va_list ap; 181 182 a->archive_error_number = error_number; 183 if (fmt == NULL) { 184 a->error = NULL; 185 return; 186 } 187 188 archive_string_empty(&(a->error_string)); 189 va_start(ap, fmt); 190 archive_string_vsprintf(&(a->error_string), fmt, ap); 191 va_end(ap); 192 a->error = a->error_string.s; 193 } 194 195 void 196 archive_copy_error(struct archive *dest, struct archive *src) 197 { 198 dest->archive_error_number = src->archive_error_number; 199 200 archive_string_copy(&dest->error_string, &src->error_string); 201 dest->error = dest->error_string.s; 202 } 203 204 void 205 __archive_errx(int retvalue, const char *msg) 206 { 207 static const char msg1[] = "Fatal Internal Error in libarchive: "; 208 size_t s; 209 210 s = write(2, msg1, strlen(msg1)); 211 (void)s; /* UNUSED */ 212 s = write(2, msg, strlen(msg)); 213 (void)s; /* UNUSED */ 214 s = write(2, "\n", 1); 215 (void)s; /* UNUSED */ 216 exit(retvalue); 217 } 218 219 /* 220 * Create a temporary file 221 */ 222 #if defined(_WIN32) && !defined(__CYGWIN__) 223 224 /* 225 * Do not use Windows tmpfile() function. 226 * It will make a temporary file under the root directory 227 * and it'll cause permission error if a user who is 228 * non-Administrator creates temporary files. 229 * Also Windows version of mktemp family including _mktemp_s 230 * are not secure. 231 */ 232 static int 233 __archive_mktempx(const char *tmpdir, wchar_t *template) 234 { 235 static const wchar_t prefix[] = L"libarchive_"; 236 static const wchar_t suffix[] = L"XXXXXXXXXX"; 237 static const wchar_t num[] = { 238 L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', 239 L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F', 240 L'G', L'H', L'I', L'J', L'K', L'L', L'M', L'N', 241 L'O', L'P', L'Q', L'R', L'S', L'T', L'U', L'V', 242 L'W', L'X', L'Y', L'Z', L'a', L'b', L'c', L'd', 243 L'e', L'f', L'g', L'h', L'i', L'j', L'k', L'l', 244 L'm', L'n', L'o', L'p', L'q', L'r', L's', L't', 245 L'u', L'v', L'w', L'x', L'y', L'z' 246 }; 247 struct archive_wstring temp_name; 248 wchar_t *ws; 249 DWORD attr; 250 wchar_t *xp, *ep; 251 int fd; 252 #if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA 253 BCRYPT_ALG_HANDLE hAlg = NULL; 254 #else 255 HCRYPTPROV hProv = (HCRYPTPROV)NULL; 256 #endif 257 fd = -1; 258 ws = NULL; 259 260 if (template == NULL) { 261 archive_string_init(&temp_name); 262 263 /* Get a temporary directory. */ 264 if (tmpdir == NULL) { 265 size_t l; 266 wchar_t *tmp; 267 268 l = GetTempPathW(0, NULL); 269 if (l == 0) { 270 la_dosmaperr(GetLastError()); 271 goto exit_tmpfile; 272 } 273 tmp = malloc(l*sizeof(wchar_t)); 274 if (tmp == NULL) { 275 errno = ENOMEM; 276 goto exit_tmpfile; 277 } 278 GetTempPathW((DWORD)l, tmp); 279 archive_wstrcpy(&temp_name, tmp); 280 free(tmp); 281 } else { 282 if (archive_wstring_append_from_mbs(&temp_name, tmpdir, 283 strlen(tmpdir)) < 0) 284 goto exit_tmpfile; 285 if (temp_name.s[temp_name.length-1] != L'/') 286 archive_wstrappend_wchar(&temp_name, L'/'); 287 } 288 289 /* Check if temp_name is a directory. */ 290 attr = GetFileAttributesW(temp_name.s); 291 if (attr == (DWORD)-1) { 292 if (GetLastError() != ERROR_FILE_NOT_FOUND) { 293 la_dosmaperr(GetLastError()); 294 goto exit_tmpfile; 295 } 296 ws = __la_win_permissive_name_w(temp_name.s); 297 if (ws == NULL) { 298 errno = EINVAL; 299 goto exit_tmpfile; 300 } 301 attr = GetFileAttributesW(ws); 302 if (attr == (DWORD)-1) { 303 la_dosmaperr(GetLastError()); 304 goto exit_tmpfile; 305 } 306 } 307 if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { 308 errno = ENOTDIR; 309 goto exit_tmpfile; 310 } 311 312 /* 313 * Create a temporary file. 314 */ 315 archive_wstrcat(&temp_name, prefix); 316 archive_wstrcat(&temp_name, suffix); 317 ep = temp_name.s + archive_strlen(&temp_name); 318 xp = ep - wcslen(suffix); 319 template = temp_name.s; 320 } else { 321 xp = wcschr(template, L'X'); 322 if (xp == NULL) /* No X, programming error */ 323 abort(); 324 for (ep = xp; *ep == L'X'; ep++) 325 continue; 326 if (*ep) /* X followed by non X, programming error */ 327 abort(); 328 } 329 330 #if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA 331 if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM, 332 NULL, 0))) { 333 la_dosmaperr(GetLastError()); 334 goto exit_tmpfile; 335 } 336 #else 337 if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 338 CRYPT_VERIFYCONTEXT)) { 339 la_dosmaperr(GetLastError()); 340 goto exit_tmpfile; 341 } 342 #endif 343 344 for (;;) { 345 wchar_t *p; 346 HANDLE h; 347 # if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */ 348 CREATEFILE2_EXTENDED_PARAMETERS createExParams; 349 #endif 350 351 /* Generate a random file name through CryptGenRandom(). */ 352 p = xp; 353 #if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA 354 if (!BCRYPT_SUCCESS(BCryptGenRandom(hAlg, (PUCHAR)p, 355 (DWORD)(ep - p)*sizeof(wchar_t), 0))) { 356 la_dosmaperr(GetLastError()); 357 goto exit_tmpfile; 358 } 359 #else 360 if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t), 361 (BYTE*)p)) { 362 la_dosmaperr(GetLastError()); 363 goto exit_tmpfile; 364 } 365 #endif 366 for (; p < ep; p++) 367 *p = num[((DWORD)*p) % (sizeof(num)/sizeof(num[0]))]; 368 369 free(ws); 370 ws = __la_win_permissive_name_w(template); 371 if (ws == NULL) { 372 errno = EINVAL; 373 goto exit_tmpfile; 374 } 375 if (template == temp_name.s) { 376 attr = FILE_ATTRIBUTE_TEMPORARY | 377 FILE_FLAG_DELETE_ON_CLOSE; 378 } else { 379 /* mkstemp */ 380 attr = FILE_ATTRIBUTE_NORMAL; 381 } 382 # if _WIN32_WINNT >= 0x0602 /* _WIN32_WINNT_WIN8 */ 383 ZeroMemory(&createExParams, sizeof(createExParams)); 384 createExParams.dwSize = sizeof(createExParams); 385 createExParams.dwFileAttributes = attr & 0xFFFF; 386 createExParams.dwFileFlags = attr & 0xFFF00000; 387 h = CreateFile2(ws, 388 GENERIC_READ | GENERIC_WRITE | DELETE, 389 0,/* Not share */ 390 CREATE_NEW, 391 &createExParams); 392 #else 393 h = CreateFileW(ws, 394 GENERIC_READ | GENERIC_WRITE | DELETE, 395 0,/* Not share */ 396 NULL, 397 CREATE_NEW,/* Create a new file only */ 398 attr, 399 NULL); 400 #endif 401 if (h == INVALID_HANDLE_VALUE) { 402 /* The same file already exists. retry with 403 * a new filename. */ 404 if (GetLastError() == ERROR_FILE_EXISTS) 405 continue; 406 /* Otherwise, fail creation temporary file. */ 407 la_dosmaperr(GetLastError()); 408 goto exit_tmpfile; 409 } 410 fd = _open_osfhandle((intptr_t)h, _O_BINARY | _O_RDWR); 411 if (fd == -1) { 412 la_dosmaperr(GetLastError()); 413 CloseHandle(h); 414 goto exit_tmpfile; 415 } else 416 break;/* success! */ 417 } 418 exit_tmpfile: 419 #if defined(HAVE_BCRYPT_H) && _WIN32_WINNT >= _WIN32_WINNT_VISTA 420 if (hAlg != NULL) 421 BCryptCloseAlgorithmProvider(hAlg, 0); 422 #else 423 if (hProv != (HCRYPTPROV)NULL) 424 CryptReleaseContext(hProv, 0); 425 #endif 426 free(ws); 427 if (template == temp_name.s) 428 archive_wstring_free(&temp_name); 429 return (fd); 430 } 431 432 int 433 __archive_mktemp(const char *tmpdir) 434 { 435 return __archive_mktempx(tmpdir, NULL); 436 } 437 438 int 439 __archive_mkstemp(wchar_t *template) 440 { 441 return __archive_mktempx(NULL, template); 442 } 443 444 #else 445 446 static int 447 get_tempdir(struct archive_string *temppath) 448 { 449 const char *tmp; 450 451 tmp = getenv("TMPDIR"); 452 if (tmp == NULL) 453 #ifdef _PATH_TMP 454 tmp = _PATH_TMP; 455 #else 456 tmp = "/tmp"; 457 #endif 458 archive_strcpy(temppath, tmp); 459 if (temppath->s[temppath->length-1] != '/') 460 archive_strappend_char(temppath, '/'); 461 return (ARCHIVE_OK); 462 } 463 464 #if defined(HAVE_MKSTEMP) 465 466 /* 467 * We can use mkstemp(). 468 */ 469 470 int 471 __archive_mktemp(const char *tmpdir) 472 { 473 struct archive_string temp_name; 474 int fd = -1; 475 476 archive_string_init(&temp_name); 477 if (tmpdir == NULL) { 478 if (get_tempdir(&temp_name) != ARCHIVE_OK) 479 goto exit_tmpfile; 480 } else { 481 archive_strcpy(&temp_name, tmpdir); 482 if (temp_name.s[temp_name.length-1] != '/') 483 archive_strappend_char(&temp_name, '/'); 484 } 485 #ifdef O_TMPFILE 486 fd = open(temp_name.s, O_RDWR|O_CLOEXEC|O_TMPFILE|O_EXCL, 0600); 487 if(fd >= 0) 488 goto exit_tmpfile; 489 #endif 490 archive_strcat(&temp_name, "libarchive_XXXXXX"); 491 fd = mkstemp(temp_name.s); 492 if (fd < 0) 493 goto exit_tmpfile; 494 __archive_ensure_cloexec_flag(fd); 495 unlink(temp_name.s); 496 exit_tmpfile: 497 archive_string_free(&temp_name); 498 return (fd); 499 } 500 501 int 502 __archive_mkstemp(char *template) 503 { 504 int fd = -1; 505 fd = mkstemp(template); 506 if (fd >= 0) 507 __archive_ensure_cloexec_flag(fd); 508 return (fd); 509 } 510 511 #else /* !HAVE_MKSTEMP */ 512 513 /* 514 * We use a private routine. 515 */ 516 517 static int 518 __archive_mktempx(const char *tmpdir, char *template) 519 { 520 static const char num[] = { 521 '0', '1', '2', '3', '4', '5', '6', '7', 522 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 523 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 524 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 525 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 526 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 527 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 528 'u', 'v', 'w', 'x', 'y', 'z' 529 }; 530 struct archive_string temp_name; 531 struct stat st; 532 int fd; 533 char *tp, *ep; 534 535 fd = -1; 536 if (template == NULL) { 537 archive_string_init(&temp_name); 538 if (tmpdir == NULL) { 539 if (get_tempdir(&temp_name) != ARCHIVE_OK) 540 goto exit_tmpfile; 541 } else 542 archive_strcpy(&temp_name, tmpdir); 543 if (temp_name.s[temp_name.length-1] == '/') { 544 temp_name.s[temp_name.length-1] = '\0'; 545 temp_name.length --; 546 } 547 if (la_stat(temp_name.s, &st) < 0) 548 goto exit_tmpfile; 549 if (!S_ISDIR(st.st_mode)) { 550 errno = ENOTDIR; 551 goto exit_tmpfile; 552 } 553 archive_strcat(&temp_name, "/libarchive_"); 554 tp = temp_name.s + archive_strlen(&temp_name); 555 archive_strcat(&temp_name, "XXXXXXXXXX"); 556 ep = temp_name.s + archive_strlen(&temp_name); 557 template = temp_name.s; 558 } else { 559 tp = strchr(template, 'X'); 560 if (tp == NULL) /* No X, programming error */ 561 abort(); 562 for (ep = tp; *ep == 'X'; ep++) 563 continue; 564 if (*ep) /* X followed by non X, programming error */ 565 abort(); 566 } 567 568 do { 569 char *p; 570 571 p = tp; 572 archive_random(p, ep - p); 573 while (p < ep) { 574 int d = *((unsigned char *)p) % sizeof(num); 575 *p++ = num[d]; 576 } 577 fd = open(template, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 578 0600); 579 } while (fd < 0 && errno == EEXIST); 580 if (fd < 0) 581 goto exit_tmpfile; 582 __archive_ensure_cloexec_flag(fd); 583 if (template == temp_name.s) 584 unlink(temp_name.s); 585 exit_tmpfile: 586 if (template == temp_name.s) 587 archive_string_free(&temp_name); 588 return (fd); 589 } 590 591 int 592 __archive_mktemp(const char *tmpdir) 593 { 594 return __archive_mktempx(tmpdir, NULL); 595 } 596 597 int 598 __archive_mkstemp(char *template) 599 { 600 return __archive_mktempx(NULL, template); 601 } 602 603 #endif /* !HAVE_MKSTEMP */ 604 #endif /* !_WIN32 || __CYGWIN__ */ 605 606 /* 607 * Set FD_CLOEXEC flag to a file descriptor if it is not set. 608 * We have to set the flag if the platform does not provide O_CLOEXEC 609 * or F_DUPFD_CLOEXEC flags. 610 * 611 * Note: This function is absolutely called after creating a new file 612 * descriptor even if the platform seemingly provides O_CLOEXEC or 613 * F_DUPFD_CLOEXEC macros because it is possible that the platform 614 * merely declares those macros, especially Linux 2.6.18 - 2.6.24 do it. 615 */ 616 void 617 __archive_ensure_cloexec_flag(int fd) 618 { 619 #if defined(_WIN32) && !defined(__CYGWIN__) 620 (void)fd; /* UNUSED */ 621 #else 622 int flags; 623 624 if (fd >= 0) { 625 flags = fcntl(fd, F_GETFD); 626 if (flags != -1 && (flags & FD_CLOEXEC) == 0) 627 fcntl(fd, F_SETFD, flags | FD_CLOEXEC); 628 } 629 #endif 630 } 631 632 /* 633 * Utility function to sort a group of strings using quicksort. 634 */ 635 static int 636 archive_utility_string_sort_helper(char **strings, unsigned int n) 637 { 638 unsigned int i, lesser_count, greater_count; 639 char **lesser, **greater, **tmp, *pivot; 640 int retval1, retval2; 641 642 /* A list of 0 or 1 elements is already sorted */ 643 if (n <= 1) 644 return (ARCHIVE_OK); 645 646 lesser_count = greater_count = 0; 647 lesser = greater = NULL; 648 pivot = strings[0]; 649 for (i = 1; i < n; i++) 650 { 651 if (strcmp(strings[i], pivot) < 0) 652 { 653 lesser_count++; 654 tmp = (char **)realloc(lesser, 655 lesser_count * sizeof(char *)); 656 if (!tmp) { 657 free(greater); 658 free(lesser); 659 return (ARCHIVE_FATAL); 660 } 661 lesser = tmp; 662 lesser[lesser_count - 1] = strings[i]; 663 } 664 else 665 { 666 greater_count++; 667 tmp = (char **)realloc(greater, 668 greater_count * sizeof(char *)); 669 if (!tmp) { 670 free(greater); 671 free(lesser); 672 return (ARCHIVE_FATAL); 673 } 674 greater = tmp; 675 greater[greater_count - 1] = strings[i]; 676 } 677 } 678 679 /* quicksort(lesser) */ 680 retval1 = archive_utility_string_sort_helper(lesser, lesser_count); 681 for (i = 0; i < lesser_count; i++) 682 strings[i] = lesser[i]; 683 free(lesser); 684 685 /* pivot */ 686 strings[lesser_count] = pivot; 687 688 /* quicksort(greater) */ 689 retval2 = archive_utility_string_sort_helper(greater, greater_count); 690 for (i = 0; i < greater_count; i++) 691 strings[lesser_count + 1 + i] = greater[i]; 692 free(greater); 693 694 return (retval1 < retval2) ? retval1 : retval2; 695 } 696 697 int 698 archive_utility_string_sort(char **strings) 699 { 700 unsigned int size = 0; 701 while (strings[size] != NULL) 702 size++; 703 return archive_utility_string_sort_helper(strings, size); 704 } 705