util.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. /*-
  2. * Copyright 2006-2008 Colin Percival
  3. * All rights reserved.
  4. *
  5. * Portions of the file below are covered by the following license:
  6. *
  7. * Copyright (c) 2003-2007 Tim Kientzle
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in the
  17. * documentation and/or other materials provided with the distribution.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
  20. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  21. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  22. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
  23. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  24. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  28. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. #include "bsdtar_platform.h"
  31. __FBSDID("$FreeBSD: src/usr.bin/tar/util.c,v 1.23 2008/12/15 06:00:25 kientzle Exp $");
  32. #ifdef HAVE_SYS_STAT_H
  33. #include <sys/stat.h>
  34. #endif
  35. #ifdef HAVE_SYS_TYPES_H
  36. #include <sys/types.h> /* Linux doesn't define mode_t, etc. in sys/stat.h. */
  37. #endif
  38. #ifdef MAJOR_IN_MKDEV
  39. #include <sys/mkdev.h>
  40. #elif defined(MAJOR_IN_SYSMACROS)
  41. #include <sys/sysmacros.h>
  42. #endif
  43. #include <ctype.h>
  44. #ifdef HAVE_ERRNO_H
  45. #include <errno.h>
  46. #endif
  47. #ifdef HAVE_STDARG_H
  48. #include <stdarg.h>
  49. #endif
  50. #include <stdio.h>
  51. #ifdef HAVE_STDLIB_H
  52. #include <stdlib.h>
  53. #endif
  54. #ifdef HAVE_STRING_H
  55. #include <string.h>
  56. #endif
  57. #ifdef HAVE_WCTYPE_H
  58. #include <wctype.h>
  59. #else
  60. /* If we don't have wctype, we need to hack up some version of iswprint(). */
  61. #define iswprint isprint
  62. #endif
  63. #include <assert.h>
  64. #include "bsdtar.h"
  65. static void bsdtar_vwarnc(struct bsdtar *, int code,
  66. const char *fmt, va_list ap);
  67. static size_t bsdtar_expand_char(char *, size_t, char);
  68. static const char *strip_components(const char *path, int elements);
  69. /* TODO: Hack up a version of mbtowc for platforms with no wide
  70. * character support at all. I think the following might suffice,
  71. * but it needs careful testing.
  72. * #if !HAVE_MBTOWC
  73. * #define mbtowc(wcp, p, n) ((*wcp = *p), 1)
  74. * #endif
  75. */
  76. /*
  77. * Print a string, taking care with any non-printable characters.
  78. *
  79. * Note that we use a stack-allocated buffer to receive the formatted
  80. * string if we can. This is partly performance (avoiding a call to
  81. * malloc()), partly out of expedience (we have to call vsnprintf()
  82. * before malloc() anyway to find out how big a buffer we need; we may
  83. * as well point that first call at a small local buffer in case it
  84. * works), but mostly for safety (so we can use this to print messages
  85. * about out-of-memory conditions).
  86. */
  87. void
  88. safe_fprintf(FILE *f, const char *fmt, ...)
  89. {
  90. char fmtbuff_stack[256]; /* Place to format the printf() string. */
  91. char outbuff[256]; /* Buffer for outgoing characters. */
  92. char *fmtbuff_heap; /* If fmtbuff_stack is too small, we use malloc */
  93. char *fmtbuff; /* Pointer to fmtbuff_stack or fmtbuff_heap. */
  94. int fmtbuff_length;
  95. int length;
  96. va_list ap;
  97. const char *p;
  98. unsigned i;
  99. wchar_t wc;
  100. char try_wc;
  101. /* Use a stack-allocated buffer if we can, for speed and safety. */
  102. fmtbuff_heap = NULL;
  103. fmtbuff_length = sizeof(fmtbuff_stack);
  104. fmtbuff = fmtbuff_stack;
  105. /* Try formatting into the stack buffer. */
  106. va_start(ap, fmt);
  107. length = vsnprintf(fmtbuff, fmtbuff_length, fmt, ap);
  108. va_end(ap);
  109. /* If the result was too large, allocate a buffer on the heap. */
  110. if (length >= fmtbuff_length) {
  111. fmtbuff_length = length+1;
  112. fmtbuff_heap = malloc(fmtbuff_length);
  113. /* Reformat the result into the heap buffer if we can. */
  114. if (fmtbuff_heap != NULL) {
  115. fmtbuff = fmtbuff_heap;
  116. va_start(ap, fmt);
  117. length = vsnprintf(fmtbuff, fmtbuff_length, fmt, ap);
  118. va_end(ap);
  119. } else {
  120. /* Leave fmtbuff pointing to the truncated
  121. * string in fmtbuff_stack. */
  122. length = sizeof(fmtbuff_stack) - 1;
  123. }
  124. }
  125. /* Note: mbrtowc() has a cleaner API, but mbtowc() seems a bit
  126. * more portable, so we use that here instead. */
  127. mbtowc(NULL, NULL, 0); /* Reset the shift state. */
  128. /* Write data, expanding unprintable characters. */
  129. p = fmtbuff;
  130. i = 0;
  131. try_wc = 1;
  132. while (*p != '\0') {
  133. int n;
  134. /* Convert to wide char, test if the wide
  135. * char is printable in the current locale. */
  136. if (try_wc && (n = mbtowc(&wc, p, length)) != -1) {
  137. length -= n;
  138. if (iswprint(wc) && wc != L'\\') {
  139. /* Printable, copy the bytes through. */
  140. while (n-- > 0)
  141. outbuff[i++] = *p++;
  142. } else {
  143. /* Not printable, format the bytes. */
  144. while (n-- > 0)
  145. i += bsdtar_expand_char(
  146. outbuff, i, *p++);
  147. }
  148. } else {
  149. /* After any conversion failure, don't bother
  150. * trying to convert the rest. */
  151. i += bsdtar_expand_char(outbuff, i, *p++);
  152. try_wc = 0;
  153. }
  154. /* If our output buffer is full, dump it and keep going. */
  155. if (i > (sizeof(outbuff) - 20)) {
  156. outbuff[i++] = '\0';
  157. fprintf(f, "%s", outbuff);
  158. i = 0;
  159. }
  160. }
  161. outbuff[i++] = '\0';
  162. fprintf(f, "%s", outbuff);
  163. /* If we allocated a heap-based formatting buffer, free it now. */
  164. if (fmtbuff_heap != NULL)
  165. free(fmtbuff_heap);
  166. }
  167. /*
  168. * Render an arbitrary sequence of bytes into printable ASCII characters.
  169. */
  170. static size_t
  171. bsdtar_expand_char(char *buff, size_t offset, char c)
  172. {
  173. size_t i = offset;
  174. if (isprint((unsigned char)c) && c != '\\')
  175. buff[i++] = c;
  176. else {
  177. buff[i++] = '\\';
  178. switch (c) {
  179. case '\a': buff[i++] = 'a'; break;
  180. case '\b': buff[i++] = 'b'; break;
  181. case '\f': buff[i++] = 'f'; break;
  182. case '\n': buff[i++] = 'n'; break;
  183. #if '\r' != '\n'
  184. /* On some platforms, \n and \r are the same. */
  185. case '\r': buff[i++] = 'r'; break;
  186. #endif
  187. case '\t': buff[i++] = 't'; break;
  188. case '\v': buff[i++] = 'v'; break;
  189. case '\\': buff[i++] = '\\'; break;
  190. default:
  191. sprintf(buff + i, "%03o", 0xFF & (int)c);
  192. i += 3;
  193. }
  194. }
  195. return (i - offset);
  196. }
  197. static void
  198. bsdtar_vwarnc(struct bsdtar *bsdtar, int code, const char *fmt, va_list ap)
  199. {
  200. fprintf(stderr, "%s: ", bsdtar->progname);
  201. vfprintf(stderr, fmt, ap);
  202. if (code != 0)
  203. fprintf(stderr, ": %s", strerror(code));
  204. fprintf(stderr, "\n");
  205. }
  206. void
  207. bsdtar_warnc(struct bsdtar *bsdtar, int code, const char *fmt, ...)
  208. {
  209. va_list ap;
  210. va_start(ap, fmt);
  211. bsdtar_vwarnc(bsdtar, code, fmt, ap);
  212. va_end(ap);
  213. }
  214. void
  215. bsdtar_errc(struct bsdtar *bsdtar, int eval, int code, const char *fmt, ...)
  216. {
  217. va_list ap;
  218. va_start(ap, fmt);
  219. bsdtar_vwarnc(bsdtar, code, fmt, ap);
  220. va_end(ap);
  221. exit(eval);
  222. }
  223. int
  224. yes(const char *fmt, ...)
  225. {
  226. char buff[32];
  227. char *p;
  228. ssize_t l;
  229. va_list ap;
  230. va_start(ap, fmt);
  231. vfprintf(stderr, fmt, ap);
  232. va_end(ap);
  233. fprintf(stderr, " (y/N)? ");
  234. fflush(stderr);
  235. l = read(2, buff, sizeof(buff) - 1);
  236. if (l <= 0)
  237. return (0);
  238. buff[l] = 0;
  239. for (p = buff; *p != '\0'; p++) {
  240. if (isspace((unsigned char)*p))
  241. continue;
  242. switch(*p) {
  243. case 'y': case 'Y':
  244. return (1);
  245. case 'n': case 'N':
  246. return (0);
  247. default:
  248. return (0);
  249. }
  250. }
  251. return (0);
  252. }
  253. /*
  254. * Read lines from file and do something with each one. If null
  255. * is set, lines are terminated with zero bytes; otherwise, they're
  256. * terminated with newlines.
  257. *
  258. * This uses a self-sizing buffer to handle arbitrarily-long lines.
  259. * If the "process" function returns non-zero for any line, this
  260. * function will return non-zero after attempting to process all
  261. * remaining lines.
  262. */
  263. int
  264. process_lines(struct bsdtar *bsdtar, const char *pathname,
  265. int (*process)(struct bsdtar *, const char *), int null)
  266. {
  267. FILE *f;
  268. char *buff, *buff_end, *line_start, *line_end, *p;
  269. size_t buff_length, new_buff_length, bytes_read, bytes_wanted;
  270. size_t buff_end_pos;
  271. size_t line_end_pos;
  272. const char * separator;
  273. size_t seplen;
  274. int lastcharwasr = 0;
  275. int ret;
  276. int fread_errno;
  277. if (null) {
  278. separator = "";
  279. seplen = 1;
  280. } else {
  281. separator = "\012\015";
  282. seplen = 2;
  283. }
  284. ret = 0;
  285. if (strcmp(pathname, "-") == 0)
  286. f = stdin;
  287. else
  288. f = fopen(pathname, "r");
  289. if (f == NULL)
  290. bsdtar_errc(bsdtar, 1, errno, "Couldn't open %s", pathname);
  291. /* Record pointer for freeing upon error. */
  292. bsdtar->conffile_actual = f;
  293. buff_length = 8192;
  294. buff = malloc(buff_length);
  295. if (buff == NULL)
  296. bsdtar_errc(bsdtar, 1, ENOMEM, "Can't read %s", pathname);
  297. /* Record pointer for freeing upon error. */
  298. bsdtar->conffile_buffer = buff;
  299. line_start = line_end = buff_end = buff;
  300. for (;;) {
  301. /* Get some more data into the buffer. */
  302. bytes_wanted = buff + buff_length - buff_end;
  303. bytes_read = fread(buff_end, 1, bytes_wanted, f);
  304. fread_errno = errno;
  305. buff_end += bytes_read;
  306. /* Process all complete lines in the buffer. */
  307. while (line_end < buff_end) {
  308. if ((lastcharwasr != 0) && (*line_end == '\012')) {
  309. /*
  310. * Skip this \n character -- it belongs to
  311. * a \r\n pair.
  312. */
  313. line_start++;
  314. line_end++;
  315. lastcharwasr = 0;
  316. continue;
  317. }
  318. lastcharwasr = 0;
  319. if (memchr(separator, *line_end, seplen) != NULL) {
  320. if (*line_end == '\015')
  321. lastcharwasr = 1;
  322. *line_end = '\0';
  323. if ((*process)(bsdtar, line_start) != 0)
  324. ret = -1;
  325. line_start = line_end + 1;
  326. line_end = line_start;
  327. } else
  328. line_end++;
  329. }
  330. if (feof(f)) {
  331. /* fread() should not set EOF unless this is true. */
  332. assert(bytes_read < bytes_wanted);
  333. break;
  334. }
  335. if (ferror(f))
  336. bsdtar_errc(bsdtar, 1, fread_errno,
  337. "Can't read %s", pathname);
  338. if (line_start > buff) {
  339. /* Move a leftover fractional line to the beginning. */
  340. memmove(buff, line_start, buff_end - line_start);
  341. buff_end -= line_start - buff;
  342. line_end -= line_start - buff;
  343. line_start = buff;
  344. } else {
  345. /* Line is too big; enlarge the buffer. */
  346. new_buff_length = buff_length * 2;
  347. if (new_buff_length <= buff_length)
  348. bsdtar_errc(bsdtar, 1, ENOMEM,
  349. "Line too long in %s", pathname);
  350. buff_length = new_buff_length;
  351. buff_end_pos = buff_end - buff;
  352. line_end_pos = line_end - buff;
  353. p = realloc(buff, buff_length);
  354. if (p == NULL)
  355. bsdtar_errc(bsdtar, 1, ENOMEM,
  356. "Line too long in %s", pathname);
  357. buff_end = p + buff_end_pos;
  358. line_end = p + line_end_pos;
  359. line_start = buff = p;
  360. bsdtar->conffile_buffer = buff;
  361. }
  362. }
  363. /* At end-of-file, handle the final line. */
  364. if (line_end > line_start) {
  365. *line_end = '\0';
  366. if ((*process)(bsdtar, line_start) != 0)
  367. ret = -1;
  368. }
  369. free(buff);
  370. if (f != stdin)
  371. fclose(f);
  372. /* Memory has been freed. */
  373. bsdtar->conffile_actual = NULL;
  374. bsdtar->conffile_buffer = NULL;
  375. return (ret);
  376. }
  377. /*-
  378. * The logic here for -C <dir> attempts to avoid
  379. * chdir() as long as possible. For example:
  380. * "-C /foo -C /bar file" needs chdir("/bar") but not chdir("/foo")
  381. * "-C /foo -C bar file" needs chdir("/foo/bar")
  382. * "-C /foo -C bar /file1" does not need chdir()
  383. * "-C /foo -C bar /file1 file2" needs chdir("/foo/bar") before file2
  384. *
  385. * The only correct way to handle this is to record a "pending" chdir
  386. * request and combine multiple requests intelligently until we
  387. * need to process a non-absolute file. set_chdir() adds the new dir
  388. * to the pending list; do_chdir() actually executes any pending chdir.
  389. *
  390. * This way, programs that build tar command lines don't have to worry
  391. * about -C with non-existent directories; such requests will only
  392. * fail if the directory must be accessed.
  393. */
  394. void
  395. set_chdir(struct bsdtar *bsdtar, const char *newdir)
  396. {
  397. if (newdir[0] == '/') {
  398. /* The -C /foo -C /bar case; dump first one. */
  399. free(bsdtar->pending_chdir);
  400. bsdtar->pending_chdir = NULL;
  401. }
  402. if (bsdtar->pending_chdir == NULL)
  403. /* Easy case: no previously-saved dir. */
  404. bsdtar->pending_chdir = strdup(newdir);
  405. else {
  406. /* The -C /foo -C bar case; concatenate */
  407. char *old_pending = bsdtar->pending_chdir;
  408. size_t old_len = strlen(old_pending);
  409. bsdtar->pending_chdir = malloc(old_len + strlen(newdir) + 2);
  410. if (old_pending[old_len - 1] == '/')
  411. old_pending[old_len - 1] = '\0';
  412. if (bsdtar->pending_chdir != NULL)
  413. sprintf(bsdtar->pending_chdir, "%s/%s",
  414. old_pending, newdir);
  415. free(old_pending);
  416. }
  417. if (bsdtar->pending_chdir == NULL)
  418. bsdtar_errc(bsdtar, 1, errno, "No memory");
  419. }
  420. void
  421. do_chdir(struct bsdtar *bsdtar)
  422. {
  423. if (bsdtar->pending_chdir == NULL)
  424. return;
  425. if (chdir(bsdtar->pending_chdir) != 0) {
  426. bsdtar_errc(bsdtar, 1, 0, "could not chdir to '%s'\n",
  427. bsdtar->pending_chdir);
  428. }
  429. free(bsdtar->pending_chdir);
  430. bsdtar->pending_chdir = NULL;
  431. }
  432. const char *
  433. strip_components(const char *path, int elements)
  434. {
  435. const char *p = path;
  436. while (elements > 0) {
  437. switch (*p++) {
  438. case '/':
  439. elements--;
  440. path = p;
  441. break;
  442. case '\0':
  443. /* Path is too short, skip it. */
  444. return (NULL);
  445. }
  446. }
  447. while (*path == '/')
  448. ++path;
  449. if (*path == '\0')
  450. return (NULL);
  451. return (path);
  452. }
  453. /*
  454. * Handle --strip-components and any future path-rewriting options.
  455. * Returns non-zero if the pathname should not be extracted.
  456. *
  457. * TODO: Support pax-style regex path rewrites.
  458. */
  459. int
  460. edit_pathname(struct bsdtar *bsdtar, struct archive_entry *entry)
  461. {
  462. const char *name = archive_entry_pathname(entry);
  463. #if HAVE_REGEX_H
  464. char *subst_name;
  465. int r;
  466. #endif
  467. #if HAVE_REGEX_H
  468. r = apply_substitution(bsdtar, name, &subst_name, 0);
  469. if (r == -1) {
  470. bsdtar_warnc(bsdtar, 0, "Invalid substitution, skipping entry");
  471. return 1;
  472. }
  473. if (r == 1) {
  474. archive_entry_copy_pathname(entry, subst_name);
  475. if (*subst_name == '\0') {
  476. free(subst_name);
  477. return -1;
  478. } else
  479. free(subst_name);
  480. name = archive_entry_pathname(entry);
  481. }
  482. if (archive_entry_hardlink(entry)) {
  483. r = apply_substitution(bsdtar, archive_entry_hardlink(entry), &subst_name, 1);
  484. if (r == -1) {
  485. bsdtar_warnc(bsdtar, 0, "Invalid substitution, skipping entry");
  486. return 1;
  487. }
  488. if (r == 1) {
  489. archive_entry_copy_hardlink(entry, subst_name);
  490. free(subst_name);
  491. }
  492. }
  493. if (archive_entry_symlink(entry) != NULL) {
  494. r = apply_substitution(bsdtar, archive_entry_symlink(entry), &subst_name, 1);
  495. if (r == -1) {
  496. bsdtar_warnc(bsdtar, 0, "Invalid substitution, skipping entry");
  497. return 1;
  498. }
  499. if (r == 1) {
  500. archive_entry_copy_symlink(entry, subst_name);
  501. free(subst_name);
  502. }
  503. }
  504. #endif
  505. /* Strip leading dir names as per --strip-components option. */
  506. if (bsdtar->strip_components > 0) {
  507. const char *linkname = archive_entry_hardlink(entry);
  508. name = strip_components(name, bsdtar->strip_components);
  509. if (name == NULL)
  510. return (1);
  511. if (linkname != NULL) {
  512. linkname = strip_components(linkname,
  513. bsdtar->strip_components);
  514. if (linkname == NULL)
  515. return (1);
  516. archive_entry_copy_hardlink(entry, linkname);
  517. }
  518. }
  519. /* By default, don't write or restore absolute pathnames. */
  520. if (!bsdtar->option_absolute_paths) {
  521. const char *rp, *p = name;
  522. int slashonly = 1;
  523. /* Remove leading "//./" or "//?/" or "//?/UNC/"
  524. * (absolute path prefixes used by Windows API) */
  525. if ((p[0] == '/' || p[0] == '\\') &&
  526. (p[1] == '/' || p[1] == '\\') &&
  527. (p[2] == '.' || p[2] == '?') &&
  528. (p[3] == '/' || p[3] == '\\'))
  529. {
  530. if (p[2] == '?' &&
  531. (p[4] == 'U' || p[4] == 'u') &&
  532. (p[5] == 'N' || p[5] == 'n') &&
  533. (p[6] == 'C' || p[6] == 'c') &&
  534. (p[7] == '/' || p[7] == '\\'))
  535. p += 8;
  536. else
  537. p += 4;
  538. slashonly = 0;
  539. }
  540. do {
  541. rp = p;
  542. /* Remove leading drive letter from archives created
  543. * on Windows. */
  544. if (((p[0] >= 'a' && p[0] <= 'z') ||
  545. (p[0] >= 'A' && p[0] <= 'Z')) &&
  546. p[1] == ':') {
  547. p += 2;
  548. slashonly = 0;
  549. }
  550. /* Remove leading "/../", "//", etc. */
  551. while (p[0] == '/' || p[0] == '\\') {
  552. if (p[1] == '.' && p[2] == '.' &&
  553. (p[3] == '/' || p[3] == '\\')) {
  554. p += 3; /* Remove "/..", leave "/"
  555. * for next pass. */
  556. slashonly = 0;
  557. } else
  558. p += 1; /* Remove "/". */
  559. }
  560. } while (rp != p);
  561. if (p != name && !bsdtar->warned_lead_slash &&
  562. !bsdtar->option_quiet) {
  563. /* Generate a warning the first time this happens. */
  564. if (slashonly)
  565. bsdtar_warnc(bsdtar, 0,
  566. "Removing leading '%c' from member names",
  567. name[0]);
  568. else
  569. bsdtar_warnc(bsdtar, 0,
  570. "Removing leading drive letter from "
  571. "member names");
  572. bsdtar->warned_lead_slash = 1;
  573. }
  574. /* Special case: Stripping everything yields ".". */
  575. if (*p == '\0')
  576. name = ".";
  577. else
  578. name = p;
  579. } else {
  580. /* Strip redundant leading '/' characters. */
  581. while (name[0] == '/' && name[1] == '/')
  582. name++;
  583. }
  584. /* Safely replace name in archive_entry. */
  585. if (name != archive_entry_pathname(entry)) {
  586. char *q = strdup(name);
  587. archive_entry_copy_pathname(entry, q);
  588. free(q);
  589. }
  590. return (0);
  591. }
  592. /*
  593. * Like strcmp(), but try to be a little more aware of the fact that
  594. * we're comparing two paths. Right now, it just handles leading
  595. * "./" and trailing '/' specially, so that "a/b/" == "./a/b"
  596. *
  597. * TODO: Make this better, so that "./a//b/./c/" == "a/b/c"
  598. * TODO: After this works, push it down into libarchive.
  599. * TODO: Publish the path normalization routines in libarchive so
  600. * that bsdtar can normalize paths and use fast strcmp() instead
  601. * of this.
  602. */
  603. int
  604. pathcmp(const char *a, const char *b)
  605. {
  606. /* Skip leading './' */
  607. if (a[0] == '.' && a[1] == '/' && a[2] != '\0')
  608. a += 2;
  609. if (b[0] == '.' && b[1] == '/' && b[2] != '\0')
  610. b += 2;
  611. /* Find the first difference, or return (0) if none. */
  612. while (*a == *b) {
  613. if (*a == '\0')
  614. return (0);
  615. a++;
  616. b++;
  617. }
  618. /*
  619. * If one ends in '/' and the other one doesn't,
  620. * they're the same.
  621. */
  622. if (a[0] == '/' && a[1] == '\0' && b[0] == '\0')
  623. return (0);
  624. if (a[0] == '\0' && b[0] == '/' && b[1] == '\0')
  625. return (0);
  626. /* They're really different, return the correct sign. */
  627. return (*(const unsigned char *)a - *(const unsigned char *)b);
  628. }
  629. /*
  630. * Display information about the current file.
  631. *
  632. * The format here roughly duplicates the output of 'ls -l'.
  633. * This is based on SUSv2, where 'tar tv' is documented as
  634. * listing additional information in an "unspecified format,"
  635. * and 'pax -l' is documented as using the same format as 'ls -l'.
  636. */
  637. void
  638. list_item_verbose(struct bsdtar *bsdtar, FILE *out, struct archive_entry *entry)
  639. {
  640. const struct stat *st;
  641. char tmp[100];
  642. size_t w;
  643. const char *p;
  644. const char *fmt;
  645. time_t tim;
  646. static time_t now;
  647. st = archive_entry_stat(entry);
  648. /*
  649. * We avoid collecting the entire list in memory at once by
  650. * listing things as we see them. However, that also means we can't
  651. * just pre-compute the field widths. Instead, we start with guesses
  652. * and just widen them as necessary. These numbers are completely
  653. * arbitrary.
  654. */
  655. if (!bsdtar->u_width) {
  656. bsdtar->u_width = 6;
  657. bsdtar->gs_width = 13;
  658. }
  659. if (!now)
  660. time(&now);
  661. fprintf(out, "%s %d ",
  662. archive_entry_strmode(entry),
  663. (int)(st->st_nlink));
  664. /* Use uname if it's present, else uid. */
  665. p = archive_entry_uname(entry);
  666. if ((p == NULL) || (*p == '\0')) {
  667. sprintf(tmp, "%lu ", (unsigned long)st->st_uid);
  668. p = tmp;
  669. }
  670. w = strlen(p);
  671. if (w > bsdtar->u_width)
  672. bsdtar->u_width = w;
  673. fprintf(out, "%-*s ", (int)bsdtar->u_width, p);
  674. /* Use gname if it's present, else gid. */
  675. p = archive_entry_gname(entry);
  676. if (p != NULL && p[0] != '\0') {
  677. fprintf(out, "%s", p);
  678. w = strlen(p);
  679. } else {
  680. sprintf(tmp, "%lu", (unsigned long)st->st_gid);
  681. w = strlen(tmp);
  682. fprintf(out, "%s", tmp);
  683. }
  684. /*
  685. * Print device number or file size, right-aligned so as to make
  686. * total width of group and devnum/filesize fields be gs_width.
  687. * If gs_width is too small, grow it.
  688. */
  689. if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) {
  690. sprintf(tmp, "%lu,%lu",
  691. (unsigned long)major(st->st_rdev),
  692. (unsigned long)minor(st->st_rdev)); /* ls(1) also casts here. */
  693. } else {
  694. /*
  695. * Note the use of platform-dependent macros to format
  696. * the filesize here. We need the format string and the
  697. * corresponding type for the cast.
  698. */
  699. sprintf(tmp, BSDTAR_FILESIZE_PRINTF,
  700. (BSDTAR_FILESIZE_TYPE)st->st_size);
  701. }
  702. if (w + strlen(tmp) >= bsdtar->gs_width)
  703. bsdtar->gs_width = w+strlen(tmp)+1;
  704. fprintf(out, "%*s", (int)(bsdtar->gs_width - w), tmp);
  705. /* Format the time. */
  706. tim = (time_t)st->st_mtime;
  707. if (bsdtar->option_iso_dates) {
  708. fmt = "%F %T";
  709. } else {
  710. /* Use the 'ls -l' convention. */
  711. #if defined(_WIN32) && !defined(__CYGWIN__)
  712. /* Windows' strftime function does not support %e format. */
  713. if (imaxabs(tim - now) > (365/2)*86400)
  714. fmt = bsdtar->day_first ? "%d %b %Y" : "%b %d %Y";
  715. else
  716. fmt = bsdtar->day_first ? "%d %b %H:%M" : "%b %d %H:%M";
  717. #else
  718. if (imaxabs(tim - now) > (365/2)*86400)
  719. fmt = bsdtar->day_first ? "%e %b %Y" : "%b %e %Y";
  720. else
  721. fmt = bsdtar->day_first ? "%e %b %H:%M" : "%b %e %H:%M";
  722. #endif
  723. }
  724. strftime(tmp, sizeof(tmp), fmt, localtime(&tim));
  725. fprintf(out, " %s ", tmp);
  726. safe_fprintf(out, "%s", archive_entry_pathname(entry));
  727. /* Extra information for links. */
  728. if (archive_entry_hardlink(entry)) /* Hard link */
  729. safe_fprintf(out, " link to %s",
  730. archive_entry_hardlink(entry));
  731. else if (S_ISLNK(st->st_mode)) /* Symbolic link */
  732. safe_fprintf(out, " -> %s", archive_entry_symlink(entry));
  733. }