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