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
__archive_clean(struct archive * a)74 __archive_clean(struct archive *a)
75 {
76 archive_string_conversion_free(a);
77 return (ARCHIVE_OK);
78 }
79
80 int
archive_version_number(void)81 archive_version_number(void)
82 {
83 return (ARCHIVE_VERSION_NUMBER);
84 }
85
86 const char *
archive_version_string(void)87 archive_version_string(void)
88 {
89 return (ARCHIVE_VERSION_STRING);
90 }
91
92 int
archive_errno(struct archive * a)93 archive_errno(struct archive *a)
94 {
95 return (a->archive_error_number);
96 }
97
98 const char *
archive_error_string(struct archive * a)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
archive_file_count(struct archive * a)109 archive_file_count(struct archive *a)
110 {
111 return (a->file_count);
112 }
113
114 int
archive_format(struct archive * a)115 archive_format(struct archive *a)
116 {
117 return (a->archive_format);
118 }
119
120 const char *
archive_format_name(struct archive * a)121 archive_format_name(struct archive *a)
122 {
123 return (a->archive_format_name);
124 }
125
126
127 int
archive_compression(struct archive * a)128 archive_compression(struct archive *a)
129 {
130 return archive_filter_code(a, 0);
131 }
132
133 const char *
archive_compression_name(struct archive * a)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
archive_position_compressed(struct archive * a)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
archive_position_uncompressed(struct archive * a)153 archive_position_uncompressed(struct archive *a)
154 {
155 return archive_filter_bytes(a, 0);
156 }
157
158 void
archive_clear_error(struct archive * a)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
archive_set_error(struct archive * a,int error_number,const char * fmt,...)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
archive_copy_error(struct archive * dest,struct archive * src)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
__archive_errx(int retvalue,const char * msg)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 int
__archive_mktemp(const char * tmpdir)222 __archive_mktemp(const char *tmpdir)
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 archive_string_init(&temp_name);
247
248 /* Get a temporary directory. */
249 if (tmpdir == NULL) {
250 size_t l;
251 wchar_t *tmp;
252
253 l = GetTempPathW(0, NULL);
254 if (l == 0) {
255 la_dosmaperr(GetLastError());
256 goto exit_tmpfile;
257 }
258 tmp = malloc(l*sizeof(wchar_t));
259 if (tmp == NULL) {
260 errno = ENOMEM;
261 goto exit_tmpfile;
262 }
263 GetTempPathW((DWORD)l, tmp);
264 archive_wstrcpy(&temp_name, tmp);
265 free(tmp);
266 } else {
267 if (archive_wstring_append_from_mbs(&temp_name, tmpdir,
268 strlen(tmpdir)) < 0)
269 goto exit_tmpfile;
270 if (temp_name.s[temp_name.length-1] != L'/')
271 archive_wstrappend_wchar(&temp_name, L'/');
272 }
273
274 /* Check if temp_name is a directory. */
275 attr = GetFileAttributesW(temp_name.s);
276 if (attr == (DWORD)-1) {
277 if (GetLastError() != ERROR_FILE_NOT_FOUND) {
278 la_dosmaperr(GetLastError());
279 goto exit_tmpfile;
280 }
281 ws = __la_win_permissive_name_w(temp_name.s);
282 if (ws == NULL) {
283 errno = EINVAL;
284 goto exit_tmpfile;
285 }
286 attr = GetFileAttributesW(ws);
287 if (attr == (DWORD)-1) {
288 la_dosmaperr(GetLastError());
289 goto exit_tmpfile;
290 }
291 }
292 if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
293 errno = ENOTDIR;
294 goto exit_tmpfile;
295 }
296
297 /*
298 * Create a temporary file.
299 */
300 archive_wstrcat(&temp_name, prefix);
301 archive_wstrcat(&temp_name, suffix);
302 ep = temp_name.s + archive_strlen(&temp_name);
303 xp = ep - wcslen(suffix);
304
305 if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL,
306 CRYPT_VERIFYCONTEXT)) {
307 la_dosmaperr(GetLastError());
308 goto exit_tmpfile;
309 }
310
311 for (;;) {
312 wchar_t *p;
313 HANDLE h;
314
315 /* Generate a random file name through CryptGenRandom(). */
316 p = xp;
317 if (!CryptGenRandom(hProv, (DWORD)(ep - p)*sizeof(wchar_t),
318 (BYTE*)p)) {
319 la_dosmaperr(GetLastError());
320 goto exit_tmpfile;
321 }
322 for (; p < ep; p++)
323 *p = num[((DWORD)*p) % (sizeof(num)/sizeof(num[0]))];
324
325 free(ws);
326 ws = __la_win_permissive_name_w(temp_name.s);
327 if (ws == NULL) {
328 errno = EINVAL;
329 goto exit_tmpfile;
330 }
331 /* Specifies FILE_FLAG_DELETE_ON_CLOSE flag is to
332 * delete this temporary file immediately when this
333 * file closed. */
334 h = CreateFileW(ws,
335 GENERIC_READ | GENERIC_WRITE | DELETE,
336 0,/* Not share */
337 NULL,
338 CREATE_NEW,/* Create a new file only */
339 FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
340 NULL);
341 if (h == INVALID_HANDLE_VALUE) {
342 /* The same file already exists. retry with
343 * a new filename. */
344 if (GetLastError() == ERROR_FILE_EXISTS)
345 continue;
346 /* Otherwise, fail creation temporary file. */
347 la_dosmaperr(GetLastError());
348 goto exit_tmpfile;
349 }
350 fd = _open_osfhandle((intptr_t)h, _O_BINARY | _O_RDWR);
351 if (fd == -1) {
352 CloseHandle(h);
353 goto exit_tmpfile;
354 } else
355 break;/* success! */
356 }
357 exit_tmpfile:
358 if (hProv != (HCRYPTPROV)NULL)
359 CryptReleaseContext(hProv, 0);
360 free(ws);
361 archive_wstring_free(&temp_name);
362 return (fd);
363 }
364
365 #else
366
367 static int
get_tempdir(struct archive_string * temppath)368 get_tempdir(struct archive_string *temppath)
369 {
370 const char *tmp;
371
372 tmp = getenv("TMPDIR");
373 if (tmp == NULL)
374 #ifdef _PATH_TMP
375 tmp = _PATH_TMP;
376 #else
377 tmp = "/tmp";
378 #endif
379 archive_strcpy(temppath, tmp);
380 if (temppath->s[temppath->length-1] != '/')
381 archive_strappend_char(temppath, '/');
382 return (ARCHIVE_OK);
383 }
384
385 #if defined(HAVE_MKSTEMP)
386
387 /*
388 * We can use mkstemp().
389 */
390
391 int
__archive_mktemp(const char * tmpdir)392 __archive_mktemp(const char *tmpdir)
393 {
394 struct archive_string temp_name;
395 int fd = -1;
396
397 archive_string_init(&temp_name);
398 if (tmpdir == NULL) {
399 if (get_tempdir(&temp_name) != ARCHIVE_OK)
400 goto exit_tmpfile;
401 } else {
402 archive_strcpy(&temp_name, tmpdir);
403 if (temp_name.s[temp_name.length-1] != '/')
404 archive_strappend_char(&temp_name, '/');
405 }
406 archive_strcat(&temp_name, "libarchive_XXXXXX");
407 fd = mkstemp(temp_name.s);
408 if (fd < 0)
409 goto exit_tmpfile;
410 __archive_ensure_cloexec_flag(fd);
411 unlink(temp_name.s);
412 exit_tmpfile:
413 archive_string_free(&temp_name);
414 return (fd);
415 }
416
417 #else
418
419 /*
420 * We use a private routine.
421 */
422
423 int
__archive_mktemp(const char * tmpdir)424 __archive_mktemp(const char *tmpdir)
425 {
426 static const char num[] = {
427 '0', '1', '2', '3', '4', '5', '6', '7',
428 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
429 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
430 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
431 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
432 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
433 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
434 'u', 'v', 'w', 'x', 'y', 'z'
435 };
436 struct archive_string temp_name;
437 struct stat st;
438 int fd;
439 char *tp, *ep;
440
441 fd = -1;
442 archive_string_init(&temp_name);
443 if (tmpdir == NULL) {
444 if (get_tempdir(&temp_name) != ARCHIVE_OK)
445 goto exit_tmpfile;
446 } else
447 archive_strcpy(&temp_name, tmpdir);
448 if (temp_name.s[temp_name.length-1] == '/') {
449 temp_name.s[temp_name.length-1] = '\0';
450 temp_name.length --;
451 }
452 if (la_stat(temp_name.s, &st) < 0)
453 goto exit_tmpfile;
454 if (!S_ISDIR(st.st_mode)) {
455 errno = ENOTDIR;
456 goto exit_tmpfile;
457 }
458 archive_strcat(&temp_name, "/libarchive_");
459 tp = temp_name.s + archive_strlen(&temp_name);
460 archive_strcat(&temp_name, "XXXXXXXXXX");
461 ep = temp_name.s + archive_strlen(&temp_name);
462
463 do {
464 char *p;
465
466 p = tp;
467 archive_random(p, ep - p);
468 while (p < ep) {
469 int d = *((unsigned char *)p) % sizeof(num);
470 *p++ = num[d];
471 }
472 fd = open(temp_name.s, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC,
473 0600);
474 } while (fd < 0 && errno == EEXIST);
475 if (fd < 0)
476 goto exit_tmpfile;
477 __archive_ensure_cloexec_flag(fd);
478 unlink(temp_name.s);
479 exit_tmpfile:
480 archive_string_free(&temp_name);
481 return (fd);
482 }
483
484 #endif /* HAVE_MKSTEMP */
485 #endif /* !_WIN32 || __CYGWIN__ */
486
487 /*
488 * Set FD_CLOEXEC flag to a file descriptor if it is not set.
489 * We have to set the flag if the platform does not provide O_CLOEXEC
490 * or F_DUPFD_CLOEXEC flags.
491 *
492 * Note: This function is absolutely called after creating a new file
493 * descriptor even if the platform seemingly provides O_CLOEXEC or
494 * F_DUPFD_CLOEXEC macros because it is possible that the platform
495 * merely declares those macros, especially Linux 2.6.18 - 2.6.24 do it.
496 */
497 void
__archive_ensure_cloexec_flag(int fd)498 __archive_ensure_cloexec_flag(int fd)
499 {
500 #if defined(_WIN32) && !defined(__CYGWIN__)
501 (void)fd; /* UNUSED */
502 #else
503 int flags;
504
505 if (fd >= 0) {
506 flags = fcntl(fd, F_GETFD);
507 if (flags != -1 && (flags & FD_CLOEXEC) == 0)
508 fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
509 }
510 #endif
511 }
512
513 /*
514 * Utility function to sort a group of strings using quicksort.
515 */
516 static int
archive_utility_string_sort_helper(char ** strings,unsigned int n)517 archive_utility_string_sort_helper(char **strings, unsigned int n)
518 {
519 unsigned int i, lesser_count, greater_count;
520 char **lesser, **greater, **tmp, *pivot;
521 int retval1, retval2;
522
523 /* A list of 0 or 1 elements is already sorted */
524 if (n <= 1)
525 return (ARCHIVE_OK);
526
527 lesser_count = greater_count = 0;
528 lesser = greater = NULL;
529 pivot = strings[0];
530 for (i = 1; i < n; i++)
531 {
532 if (strcmp(strings[i], pivot) < 0)
533 {
534 lesser_count++;
535 tmp = (char **)realloc(lesser,
536 lesser_count * sizeof(char *));
537 if (!tmp) {
538 free(greater);
539 free(lesser);
540 return (ARCHIVE_FATAL);
541 }
542 lesser = tmp;
543 lesser[lesser_count - 1] = strings[i];
544 }
545 else
546 {
547 greater_count++;
548 tmp = (char **)realloc(greater,
549 greater_count * sizeof(char *));
550 if (!tmp) {
551 free(greater);
552 free(lesser);
553 return (ARCHIVE_FATAL);
554 }
555 greater = tmp;
556 greater[greater_count - 1] = strings[i];
557 }
558 }
559
560 /* quicksort(lesser) */
561 retval1 = archive_utility_string_sort_helper(lesser, lesser_count);
562 for (i = 0; i < lesser_count; i++)
563 strings[i] = lesser[i];
564 free(lesser);
565
566 /* pivot */
567 strings[lesser_count] = pivot;
568
569 /* quicksort(greater) */
570 retval2 = archive_utility_string_sort_helper(greater, greater_count);
571 for (i = 0; i < greater_count; i++)
572 strings[lesser_count + 1 + i] = greater[i];
573 free(greater);
574
575 return (retval1 < retval2) ? retval1 : retval2;
576 }
577
578 int
archive_utility_string_sort(char ** strings)579 archive_utility_string_sort(char **strings)
580 {
581 unsigned int size = 0;
582 while (strings[size] != NULL)
583 size++;
584 return archive_utility_string_sort_helper(strings, size);
585 }
586