1 /*- 2 * Copyright (c) 2009-2012 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 49 #include "archive.h" 50 #include "archive_private.h" 51 #include "archive_string.h" 52 53 #ifndef O_CLOEXEC 54 #define O_CLOEXEC 0 55 #endif 56 57 /* Generic initialization of 'struct archive' objects. */ 58 int 59 __archive_clean(struct archive *a) 60 { 61 archive_string_conversion_free(a); 62 return (ARCHIVE_OK); 63 } 64 65 int 66 archive_version_number(void) 67 { 68 return (ARCHIVE_VERSION_NUMBER); 69 } 70 71 const char * 72 archive_version_string(void) 73 { 74 return (ARCHIVE_VERSION_STRING); 75 } 76 77 int 78 archive_errno(struct archive *a) 79 { 80 return (a->archive_error_number); 81 } 82 83 const char * 84 archive_error_string(struct archive *a) 85 { 86 87 if (a->error != NULL && *a->error != '\0') 88 return (a->error); 89 else 90 return (NULL); 91 } 92 93 int 94 archive_file_count(struct archive *a) 95 { 96 return (a->file_count); 97 } 98 99 int 100 archive_format(struct archive *a) 101 { 102 return (a->archive_format); 103 } 104 105 const char * 106 archive_format_name(struct archive *a) 107 { 108 return (a->archive_format_name); 109 } 110 111 112 int 113 archive_compression(struct archive *a) 114 { 115 return archive_filter_code(a, 0); 116 } 117 118 const char * 119 archive_compression_name(struct archive *a) 120 { 121 return archive_filter_name(a, 0); 122 } 123 124 125 /* 126 * Return a count of the number of compressed bytes processed. 127 */ 128 int64_t 129 archive_position_compressed(struct archive *a) 130 { 131 return archive_filter_bytes(a, -1); 132 } 133 134 /* 135 * Return a count of the number of uncompressed bytes processed. 136 */ 137 int64_t 138 archive_position_uncompressed(struct archive *a) 139 { 140 return archive_filter_bytes(a, 0); 141 } 142 143 void 144 archive_clear_error(struct archive *a) 145 { 146 archive_string_empty(&a->error_string); 147 a->error = NULL; 148 a->archive_error_number = 0; 149 } 150 151 void 152 archive_set_error(struct archive *a, int error_number, const char *fmt, ...) 153 { 154 va_list ap; 155 156 a->archive_error_number = error_number; 157 if (fmt == NULL) { 158 a->error = NULL; 159 return; 160 } 161 162 archive_string_empty(&(a->error_string)); 163 va_start(ap, fmt); 164 archive_string_vsprintf(&(a->error_string), fmt, ap); 165 va_end(ap); 166 a->error = a->error_string.s; 167 } 168 169 void 170 archive_copy_error(struct archive *dest, struct archive *src) 171 { 172 dest->archive_error_number = src->archive_error_number; 173 174 archive_string_copy(&dest->error_string, &src->error_string); 175 dest->error = dest->error_string.s; 176 } 177 178 void 179 __archive_errx(int retvalue, const char *msg) 180 { 181 static const char *msg1 = "Fatal Internal Error in libarchive: "; 182 size_t s; 183 184 s = write(2, msg1, strlen(msg1)); 185 (void)s; /* UNUSED */ 186 s = write(2, msg, strlen(msg)); 187 (void)s; /* UNUSED */ 188 s = write(2, "\n", 1); 189 (void)s; /* UNUSED */ 190 exit(retvalue); 191 } 192 193 /* 194 * Create a temporary file 195 */ 196 #if defined(_WIN32) && !defined(__CYGWIN__) 197 198 /* 199 * Do not use Windows tmpfile() function. 200 * It will make a temporary file under the root directory 201 * and it'll cause permission error if a user who is 202 * non-Administrator creates temporary files. 203 * Also Windows version of mktemp family including _mktemp_s 204 * are not secure. 205 */ 206 int 207 __archive_mktemp(const char *tmpdir) 208 { 209 static const wchar_t num[] = { 210 L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', 211 L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F', 212 L'G', L'H', L'I', L'J', L'K', L'L', L'M', L'N', 213 L'O', L'P', L'Q', L'R', L'S', L'T', L'U', L'V', 214 L'W', L'X', L'Y', L'Z', L'a', L'b', L'c', L'd', 215 L'e', L'f', L'g', L'h', L'i', L'j', L'k', L'l', 216 L'm', L'n', L'o', L'p', L'q', L'r', L's', L't', 217 L'u', L'v', L'w', L'x', L'y', L'z' 218 }; 219 HCRYPTPROV hProv; 220 struct archive_wstring temp_name; 221 wchar_t *ws; 222 DWORD attr; 223 wchar_t *xp, *ep; 224 int fd; 225 226 hProv = (HCRYPTPROV)NULL; 227 fd = -1; 228 ws = NULL; 229 archive_string_init(&temp_name); 230 231 /* Get a temporary directory. */ 232 if (tmpdir == NULL) { 233 size_t l; 234 wchar_t *tmp; 235 236 l = GetTempPathW(0, NULL); 237 if (l == 0) { 238 la_dosmaperr(GetLastError()); 239 goto exit_tmpfile; 240 } 241 tmp = malloc(l*sizeof(wchar_t)); 242 if (tmp == NULL) { 243 errno = ENOMEM; 244 goto exit_tmpfile; 245 } 246 GetTempPathW((DWORD)l, tmp); 247 archive_wstrcpy(&temp_name, tmp); 248 free(tmp); 249 } else { 250 if (archive_wstring_append_from_mbs(&temp_name, tmpdir, 251 strlen(tmpdir)) < 0) 252 goto exit_tmpfile; 253 if (temp_name.s[temp_name.length-1] != L'/') 254 archive_wstrappend_wchar(&temp_name, L'/'); 255 } 256 257 /* Check if temp_name is a directory. */ 258 attr = GetFileAttributesW(temp_name.s); 259 if (attr == (DWORD)-1) { 260 if (GetLastError() != ERROR_FILE_NOT_FOUND) { 261 la_dosmaperr(GetLastError()); 262 goto exit_tmpfile; 263 } 264 ws = __la_win_permissive_name_w(temp_name.s); 265 if (ws == NULL) { 266 errno = EINVAL; 267 goto exit_tmpfile; 268 } 269 attr = GetFileAttributesW(ws); 270 if (attr == (DWORD)-1) { 271 la_dosmaperr(GetLastError()); 272 goto exit_tmpfile; 273 } 274 } 275 if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { 276 errno = ENOTDIR; 277 goto exit_tmpfile; 278 } 279 280 /* 281 * Create a temporary file. 282 */ 283 archive_wstrcat(&temp_name, L"libarchive_"); 284 xp = temp_name.s + archive_strlen(&temp_name); 285 archive_wstrcat(&temp_name, L"XXXXXXXXXX"); 286 ep = temp_name.s + archive_strlen(&temp_name); 287 288 if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 289 CRYPT_VERIFYCONTEXT)) { 290 la_dosmaperr(GetLastError()); 291 goto exit_tmpfile; 292 } 293 294 for (;;) { 295 wchar_t *p; 296 HANDLE h; 297 298 /* Generate a random file name through CryptGenRandom(). */ 299 p = xp; 300 if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t), 301 (BYTE*)p)) { 302 la_dosmaperr(GetLastError()); 303 goto exit_tmpfile; 304 } 305 for (; p < ep; p++) 306 *p = num[((DWORD)*p) % (sizeof(num)/sizeof(num[0]))]; 307 308 free(ws); 309 ws = __la_win_permissive_name_w(temp_name.s); 310 if (ws == NULL) { 311 errno = EINVAL; 312 goto exit_tmpfile; 313 } 314 /* Specifies FILE_FLAG_DELETE_ON_CLOSE flag is to 315 * delete this temporary file immediately when this 316 * file closed. */ 317 h = CreateFileW(ws, 318 GENERIC_READ | GENERIC_WRITE | DELETE, 319 0,/* Not share */ 320 NULL, 321 CREATE_NEW,/* Create a new file only */ 322 FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, 323 NULL); 324 if (h == INVALID_HANDLE_VALUE) { 325 /* The same file already exists. retry with 326 * a new filename. */ 327 if (GetLastError() == ERROR_FILE_EXISTS) 328 continue; 329 /* Otherwise, fail creation temporary file. */ 330 la_dosmaperr(GetLastError()); 331 goto exit_tmpfile; 332 } 333 fd = _open_osfhandle((intptr_t)h, _O_BINARY | _O_RDWR); 334 if (fd == -1) { 335 CloseHandle(h); 336 goto exit_tmpfile; 337 } else 338 break;/* success! */ 339 } 340 exit_tmpfile: 341 if (hProv != (HCRYPTPROV)NULL) 342 CryptReleaseContext(hProv, 0); 343 free(ws); 344 archive_wstring_free(&temp_name); 345 return (fd); 346 } 347 348 #else 349 350 static int 351 get_tempdir(struct archive_string *temppath) 352 { 353 const char *tmp; 354 355 tmp = getenv("TMPDIR"); 356 if (tmp == NULL) 357 #ifdef _PATH_TMP 358 tmp = _PATH_TMP; 359 #else 360 tmp = "/tmp"; 361 #endif 362 archive_strcpy(temppath, tmp); 363 if (temppath->s[temppath->length-1] != '/') 364 archive_strappend_char(temppath, '/'); 365 return (ARCHIVE_OK); 366 } 367 368 #if defined(HAVE_MKSTEMP) 369 370 /* 371 * We can use mkstemp(). 372 */ 373 374 int 375 __archive_mktemp(const char *tmpdir) 376 { 377 struct archive_string temp_name; 378 int fd = -1; 379 380 archive_string_init(&temp_name); 381 if (tmpdir == NULL) { 382 if (get_tempdir(&temp_name) != ARCHIVE_OK) 383 goto exit_tmpfile; 384 } else { 385 archive_strcpy(&temp_name, tmpdir); 386 if (temp_name.s[temp_name.length-1] != '/') 387 archive_strappend_char(&temp_name, '/'); 388 } 389 archive_strcat(&temp_name, "libarchive_XXXXXX"); 390 fd = mkstemp(temp_name.s); 391 if (fd < 0) 392 goto exit_tmpfile; 393 __archive_ensure_cloexec_flag(fd); 394 unlink(temp_name.s); 395 exit_tmpfile: 396 archive_string_free(&temp_name); 397 return (fd); 398 } 399 400 #else 401 402 /* 403 * We use a private routine. 404 */ 405 406 int 407 __archive_mktemp(const char *tmpdir) 408 { 409 static const char num[] = { 410 '0', '1', '2', '3', '4', '5', '6', '7', 411 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 412 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 413 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 414 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 415 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 416 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 417 'u', 'v', 'w', 'x', 'y', 'z' 418 }; 419 struct archive_string temp_name; 420 struct stat st; 421 int fd; 422 char *tp, *ep; 423 unsigned seed; 424 425 fd = -1; 426 archive_string_init(&temp_name); 427 if (tmpdir == NULL) { 428 if (get_tempdir(&temp_name) != ARCHIVE_OK) 429 goto exit_tmpfile; 430 } else 431 archive_strcpy(&temp_name, tmpdir); 432 if (temp_name.s[temp_name.length-1] == '/') { 433 temp_name.s[temp_name.length-1] = '\0'; 434 temp_name.length --; 435 } 436 if (stat(temp_name.s, &st) < 0) 437 goto exit_tmpfile; 438 if (!S_ISDIR(st.st_mode)) { 439 errno = ENOTDIR; 440 goto exit_tmpfile; 441 } 442 archive_strcat(&temp_name, "/libarchive_"); 443 tp = temp_name.s + archive_strlen(&temp_name); 444 archive_strcat(&temp_name, "XXXXXXXXXX"); 445 ep = temp_name.s + archive_strlen(&temp_name); 446 447 fd = open("/dev/random", O_RDONLY | O_CLOEXEC); 448 __archive_ensure_cloexec_flag(fd); 449 if (fd < 0) 450 seed = time(NULL); 451 else { 452 if (read(fd, &seed, sizeof(seed)) < 0) 453 seed = time(NULL); 454 close(fd); 455 } 456 do { 457 char *p; 458 459 p = tp; 460 while (p < ep) 461 *p++ = num[((unsigned)rand_r(&seed)) % sizeof(num)]; 462 fd = open(temp_name.s, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 463 0600); 464 } while (fd < 0 && errno == EEXIST); 465 if (fd < 0) 466 goto exit_tmpfile; 467 __archive_ensure_cloexec_flag(fd); 468 unlink(temp_name.s); 469 exit_tmpfile: 470 archive_string_free(&temp_name); 471 return (fd); 472 } 473 474 #endif /* HAVE_MKSTEMP */ 475 #endif /* !_WIN32 || __CYGWIN__ */ 476 477 /* 478 * Set FD_CLOEXEC flag to a file descriptor if it is not set. 479 * We have to set the flag if the platform does not provide O_CLOEXEC 480 * or F_DUPFD_CLOEXEC flags. 481 * 482 * Note: This function is absolutely called after creating a new file 483 * descriptor even if the platform seemingly provides O_CLOEXEC or 484 * F_DUPFD_CLOEXEC macros because it is possible that the platform 485 * merely declares those macros, especially Linux 2.6.18 - 2.6.24 do it. 486 */ 487 void 488 __archive_ensure_cloexec_flag(int fd) 489 { 490 #if defined(_WIN32) && !defined(__CYGWIN__) 491 (void)fd; /* UNSED */ 492 #else 493 int flags; 494 495 if (fd >= 0) { 496 flags = fcntl(fd, F_GETFD); 497 if (flags != -1 && (flags & FD_CLOEXEC) == 0) 498 fcntl(fd, F_SETFD, flags | FD_CLOEXEC); 499 } 500 #endif 501 } 502