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