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
__archive_clean(struct archive * a)86 __archive_clean(struct archive *a)
87 {
88 archive_string_conversion_free(a);
89 return (ARCHIVE_OK);
90 }
91
92 int
archive_version_number(void)93 archive_version_number(void)
94 {
95 return (ARCHIVE_VERSION_NUMBER);
96 }
97
98 const char *
archive_version_string(void)99 archive_version_string(void)
100 {
101 return (ARCHIVE_VERSION_STRING);
102 }
103
104 int
archive_errno(struct archive * a)105 archive_errno(struct archive *a)
106 {
107 return (a->archive_error_number);
108 }
109
110 const char *
archive_error_string(struct archive * a)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
archive_file_count(struct archive * a)121 archive_file_count(struct archive *a)
122 {
123 return (a->file_count);
124 }
125
126 int
archive_format(struct archive * a)127 archive_format(struct archive *a)
128 {
129 return (a->archive_format);
130 }
131
132 const char *
archive_format_name(struct archive * a)133 archive_format_name(struct archive *a)
134 {
135 return (a->archive_format_name);
136 }
137
138
139 int
archive_compression(struct archive * a)140 archive_compression(struct archive *a)
141 {
142 return archive_filter_code(a, 0);
143 }
144
145 const char *
archive_compression_name(struct archive * a)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
archive_position_compressed(struct archive * a)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
archive_position_uncompressed(struct archive * a)165 archive_position_uncompressed(struct archive *a)
166 {
167 return archive_filter_bytes(a, 0);
168 }
169
170 void
archive_clear_error(struct archive * a)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
archive_set_error(struct archive * a,int error_number,const char * fmt,...)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
archive_copy_error(struct archive * dest,struct archive * src)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
__archive_errx(int retvalue,const char * msg)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
__archive_mktempx(const char * tmpdir,wchar_t * template)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
__archive_mktemp(const char * tmpdir)434 __archive_mktemp(const char *tmpdir)
435 {
436 return __archive_mktempx(tmpdir, NULL);
437 }
438
439 int
__archive_mkstemp(wchar_t * template)440 __archive_mkstemp(wchar_t *template)
441 {
442 return __archive_mktempx(NULL, template);
443 }
444
445 #else
446
447 static int
get_tempdir(struct archive_string * temppath)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
__archive_mktemp(const char * tmpdir)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
__archive_mkstemp(char * template)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
__archive_mktempx(const char * tmpdir,char * template)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
__archive_mktemp(const char * tmpdir)594 __archive_mktemp(const char *tmpdir)
595 {
596 return __archive_mktempx(tmpdir, NULL);
597 }
598
599 int
__archive_mkstemp(char * template)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
__archive_ensure_cloexec_flag(int fd)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
archive_utility_string_sort_helper(const void * p1,const void * p2)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
archive_utility_string_sort(char ** strings)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