archive_util.c 14 KB

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