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