2 * Copyright (c) 2009-2012,2014 Michihiro NAKAJIMA
3 * Copyright (c) 2003-2007 Tim Kientzle
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
27 #include "archive_platform.h"
28 __FBSDID("$FreeBSD$");
30 #ifdef HAVE_SYS_TYPES_H
31 #include <sys/types.h>
45 #if defined(HAVE_WINCRYPT_H) && !defined(__CYGWIN__)
62 #include "archive_private.h"
63 #include "archive_random_private.h"
64 #include "archive_string.h"
70 static int archive_utility_string_sort_helper(char **, unsigned int);
72 /* Generic initialization of 'struct archive' objects. */
74 __archive_clean(struct archive *a)
76 archive_string_conversion_free(a);
81 archive_version_number(void)
83 return (ARCHIVE_VERSION_NUMBER);
87 archive_version_string(void)
89 return (ARCHIVE_VERSION_STRING);
93 archive_version_details(void)
95 static struct archive_string str;
97 const char *zlib = archive_zlib_version();
98 const char *liblzma = archive_liblzma_version();
99 const char *bzlib = archive_bzlib_version();
100 const char *liblz4 = archive_liblz4_version();
103 archive_string_init(&str);
105 archive_strcat(&str, ARCHIVE_VERSION_STRING);
107 archive_strcat(&str, " zlib/");
108 archive_strcat(&str, zlib);
111 archive_strcat(&str, " liblzma/");
112 archive_strcat(&str, liblzma);
115 const char *p = bzlib;
116 const char *sep = strchr(p, ',');
119 archive_strcat(&str, " bz2lib/");
120 archive_strncat(&str, p, sep - p);
123 archive_strcat(&str, " liblz4/");
124 archive_strcat(&str, liblz4);
131 archive_zlib_version(void)
141 archive_liblzma_version(void)
144 return LZMA_VERSION_STRING;
151 archive_bzlib_version(void)
154 return BZ2_bzlibVersion();
161 archive_liblz4_version(void)
163 #if defined(HAVE_LZ4_H) && defined(HAVE_LIBLZ4)
165 #define NUMBER(x) str(x)
166 return NUMBER(LZ4_VERSION_MAJOR) "." NUMBER(LZ4_VERSION_MINOR) "." NUMBER(LZ4_VERSION_RELEASE);
175 archive_errno(struct archive *a)
177 return (a->archive_error_number);
181 archive_error_string(struct archive *a)
184 if (a->error != NULL && *a->error != '\0')
191 archive_file_count(struct archive *a)
193 return (a->file_count);
197 archive_format(struct archive *a)
199 return (a->archive_format);
203 archive_format_name(struct archive *a)
205 return (a->archive_format_name);
210 archive_compression(struct archive *a)
212 return archive_filter_code(a, 0);
216 archive_compression_name(struct archive *a)
218 return archive_filter_name(a, 0);
223 * Return a count of the number of compressed bytes processed.
226 archive_position_compressed(struct archive *a)
228 return archive_filter_bytes(a, -1);
232 * Return a count of the number of uncompressed bytes processed.
235 archive_position_uncompressed(struct archive *a)
237 return archive_filter_bytes(a, 0);
241 archive_clear_error(struct archive *a)
243 archive_string_empty(&a->error_string);
245 a->archive_error_number = 0;
249 archive_set_error(struct archive *a, int error_number, const char *fmt, ...)
253 a->archive_error_number = error_number;
259 archive_string_empty(&(a->error_string));
261 archive_string_vsprintf(&(a->error_string), fmt, ap);
263 a->error = a->error_string.s;
267 archive_copy_error(struct archive *dest, struct archive *src)
269 dest->archive_error_number = src->archive_error_number;
271 archive_string_copy(&dest->error_string, &src->error_string);
272 dest->error = dest->error_string.s;
276 __archive_errx(int retvalue, const char *msg)
278 static const char *msg1 = "Fatal Internal Error in libarchive: ";
281 s = write(2, msg1, strlen(msg1));
282 (void)s; /* UNUSED */
283 s = write(2, msg, strlen(msg));
284 (void)s; /* UNUSED */
285 s = write(2, "\n", 1);
286 (void)s; /* UNUSED */
291 * Create a temporary file
293 #if defined(_WIN32) && !defined(__CYGWIN__)
296 * Do not use Windows tmpfile() function.
297 * It will make a temporary file under the root directory
298 * and it'll cause permission error if a user who is
299 * non-Administrator creates temporary files.
300 * Also Windows version of mktemp family including _mktemp_s
304 __archive_mktemp(const char *tmpdir)
306 static const wchar_t *prefix = L"libarchive_";
307 static const wchar_t *suffix = L"XXXXXXXXXX";
308 static const wchar_t num[] = {
309 L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7',
310 L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F',
311 L'G', L'H', L'I', L'J', L'K', L'L', L'M', L'N',
312 L'O', L'P', L'Q', L'R', L'S', L'T', L'U', L'V',
313 L'W', L'X', L'Y', L'Z', L'a', L'b', L'c', L'd',
314 L'e', L'f', L'g', L'h', L'i', L'j', L'k', L'l',
315 L'm', L'n', L'o', L'p', L'q', L'r', L's', L't',
316 L'u', L'v', L'w', L'x', L'y', L'z'
319 struct archive_wstring temp_name;
325 hProv = (HCRYPTPROV)NULL;
328 archive_string_init(&temp_name);
330 /* Get a temporary directory. */
331 if (tmpdir == NULL) {
335 l = GetTempPathW(0, NULL);
337 la_dosmaperr(GetLastError());
340 tmp = malloc(l*sizeof(wchar_t));
345 GetTempPathW((DWORD)l, tmp);
346 archive_wstrcpy(&temp_name, tmp);
349 if (archive_wstring_append_from_mbs(&temp_name, tmpdir,
352 if (temp_name.s[temp_name.length-1] != L'/')
353 archive_wstrappend_wchar(&temp_name, L'/');
356 /* Check if temp_name is a directory. */
357 attr = GetFileAttributesW(temp_name.s);
358 if (attr == (DWORD)-1) {
359 if (GetLastError() != ERROR_FILE_NOT_FOUND) {
360 la_dosmaperr(GetLastError());
363 ws = __la_win_permissive_name_w(temp_name.s);
368 attr = GetFileAttributesW(ws);
369 if (attr == (DWORD)-1) {
370 la_dosmaperr(GetLastError());
374 if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
380 * Create a temporary file.
382 archive_wstrcat(&temp_name, prefix);
383 archive_wstrcat(&temp_name, suffix);
384 ep = temp_name.s + archive_strlen(&temp_name);
385 xp = ep - wcslen(suffix);
387 if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
388 CRYPT_VERIFYCONTEXT)) {
389 la_dosmaperr(GetLastError());
397 /* Generate a random file name through CryptGenRandom(). */
399 if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t),
401 la_dosmaperr(GetLastError());
405 *p = num[((DWORD)*p) % (sizeof(num)/sizeof(num[0]))];
408 ws = __la_win_permissive_name_w(temp_name.s);
413 /* Specifies FILE_FLAG_DELETE_ON_CLOSE flag is to
414 * delete this temporary file immediately when this
417 GENERIC_READ | GENERIC_WRITE | DELETE,
420 CREATE_NEW,/* Create a new file only */
421 FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
423 if (h == INVALID_HANDLE_VALUE) {
424 /* The same file already exists. retry with
426 if (GetLastError() == ERROR_FILE_EXISTS)
428 /* Otherwise, fail creation temporary file. */
429 la_dosmaperr(GetLastError());
432 fd = _open_osfhandle((intptr_t)h, _O_BINARY | _O_RDWR);
440 if (hProv != (HCRYPTPROV)NULL)
441 CryptReleaseContext(hProv, 0);
443 archive_wstring_free(&temp_name);
450 get_tempdir(struct archive_string *temppath)
454 tmp = getenv("TMPDIR");
461 archive_strcpy(temppath, tmp);
462 if (temppath->s[temppath->length-1] != '/')
463 archive_strappend_char(temppath, '/');
467 #if defined(HAVE_MKSTEMP)
470 * We can use mkstemp().
474 __archive_mktemp(const char *tmpdir)
476 struct archive_string temp_name;
479 archive_string_init(&temp_name);
480 if (tmpdir == NULL) {
481 if (get_tempdir(&temp_name) != ARCHIVE_OK)
484 archive_strcpy(&temp_name, tmpdir);
485 if (temp_name.s[temp_name.length-1] != '/')
486 archive_strappend_char(&temp_name, '/');
488 archive_strcat(&temp_name, "libarchive_XXXXXX");
489 fd = mkstemp(temp_name.s);
492 __archive_ensure_cloexec_flag(fd);
495 archive_string_free(&temp_name);
502 * We use a private routine.
506 __archive_mktemp(const char *tmpdir)
508 static const char num[] = {
509 '0', '1', '2', '3', '4', '5', '6', '7',
510 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
511 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
512 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
513 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
514 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
515 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
516 'u', 'v', 'w', 'x', 'y', 'z'
518 struct archive_string temp_name;
524 archive_string_init(&temp_name);
525 if (tmpdir == NULL) {
526 if (get_tempdir(&temp_name) != ARCHIVE_OK)
529 archive_strcpy(&temp_name, tmpdir);
530 if (temp_name.s[temp_name.length-1] == '/') {
531 temp_name.s[temp_name.length-1] = '\0';
534 if (stat(temp_name.s, &st) < 0)
536 if (!S_ISDIR(st.st_mode)) {
540 archive_strcat(&temp_name, "/libarchive_");
541 tp = temp_name.s + archive_strlen(&temp_name);
542 archive_strcat(&temp_name, "XXXXXXXXXX");
543 ep = temp_name.s + archive_strlen(&temp_name);
549 archive_random(p, ep - p);
551 int d = *((unsigned char *)p) % sizeof(num);
554 fd = open(temp_name.s, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC,
556 } while (fd < 0 && errno == EEXIST);
559 __archive_ensure_cloexec_flag(fd);
562 archive_string_free(&temp_name);
566 #endif /* HAVE_MKSTEMP */
567 #endif /* !_WIN32 || __CYGWIN__ */
570 * Set FD_CLOEXEC flag to a file descriptor if it is not set.
571 * We have to set the flag if the platform does not provide O_CLOEXEC
572 * or F_DUPFD_CLOEXEC flags.
574 * Note: This function is absolutely called after creating a new file
575 * descriptor even if the platform seemingly provides O_CLOEXEC or
576 * F_DUPFD_CLOEXEC macros because it is possible that the platform
577 * merely declares those macros, especially Linux 2.6.18 - 2.6.24 do it.
580 __archive_ensure_cloexec_flag(int fd)
582 #if defined(_WIN32) && !defined(__CYGWIN__)
583 (void)fd; /* UNSED */
588 flags = fcntl(fd, F_GETFD);
589 if (flags != -1 && (flags & FD_CLOEXEC) == 0)
590 fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
596 * Utility function to sort a group of strings using quicksort.
599 archive_utility_string_sort_helper(char **strings, unsigned int n)
601 unsigned int i, lesser_count, greater_count;
602 char **lesser, **greater, **tmp, *pivot;
603 int retval1, retval2;
605 /* A list of 0 or 1 elements is already sorted */
609 lesser_count = greater_count = 0;
610 lesser = greater = NULL;
612 for (i = 1; i < n; i++)
614 if (strcmp(strings[i], pivot) < 0)
617 tmp = (char **)realloc(lesser,
618 lesser_count * sizeof(char *));
622 return (ARCHIVE_FATAL);
625 lesser[lesser_count - 1] = strings[i];
630 tmp = (char **)realloc(greater,
631 greater_count * sizeof(char *));
635 return (ARCHIVE_FATAL);
638 greater[greater_count - 1] = strings[i];
642 /* quicksort(lesser) */
643 retval1 = archive_utility_string_sort_helper(lesser, lesser_count);
644 for (i = 0; i < lesser_count; i++)
645 strings[i] = lesser[i];
649 strings[lesser_count] = pivot;
651 /* quicksort(greater) */
652 retval2 = archive_utility_string_sort_helper(greater, greater_count);
653 for (i = 0; i < greater_count; i++)
654 strings[lesser_count + 1 + i] = greater[i];
657 return (retval1 < retval2) ? retval1 : retval2;
661 archive_utility_string_sort(char **strings)
663 unsigned int size = 0;
664 while (strings[size] != NULL)
666 return archive_utility_string_sort_helper(strings, size);