4
0

xheader.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056
  1. /* POSIX extended headers for tar.
  2. Copyright (C) 2003, 2004 Free Software Foundation, Inc.
  3. This program is free software; you can redistribute it and/or modify it
  4. under the terms of the GNU General Public License as published by the
  5. Free Software Foundation; either version 2, or (at your option) any later
  6. version.
  7. This program is distributed in the hope that it will be useful, but
  8. WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
  10. Public License for more details.
  11. You should have received a copy of the GNU General Public License along
  12. with this program; if not, write to the Free Software Foundation, Inc.,
  13. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  14. #include <system.h>
  15. #include <fnmatch.h>
  16. #include <hash.h>
  17. #include <quotearg.h>
  18. #include <stpcpy.h>
  19. #include <xstrtol.h>
  20. #include "common.h"
  21. #include <fnmatch.h>
  22. static bool xheader_protected_pattern_p (char const *pattern);
  23. static bool xheader_protected_keyword_p (char const *keyword);
  24. static void xheader_set_single_keyword (char *) __attribute__ ((noreturn));
  25. /* Used by xheader_finish() */
  26. static void code_string (char const *string, char const *keyword,
  27. struct xheader *xhdr);
  28. static void extended_header_init (void);
  29. /* Number of global headers written so far. */
  30. static size_t global_header_count;
  31. /* FIXME: Possibly it should be reset after changing the volume.
  32. POSIX %n specification says that it is expanded to the sequence
  33. number of current global header in *the* archive. However, for
  34. multi-volume archives this will yield duplicate header names
  35. in different volumes, which I'd like to avoid. The best way
  36. to solve this would be to use per-archive header count as required
  37. by POSIX *and* set globexthdr.name to, say,
  38. $TMPDIR/GlobalHead.%p.$NUMVOLUME.%n.
  39. However it should wait until buffer.c is finally rewritten */
  40. /* Keyword options */
  41. struct keyword_list
  42. {
  43. struct keyword_list *next;
  44. char *pattern;
  45. char *value;
  46. };
  47. /* List of keyword patterns set by delete= option */
  48. static struct keyword_list *keyword_pattern_list;
  49. /* List of keyword/value pairs set by `keyword=value' option */
  50. static struct keyword_list *keyword_global_override_list;
  51. /* List of keyword/value pairs set by `keyword:=value' option */
  52. static struct keyword_list *keyword_override_list;
  53. /* List of keyword/value pairs decoded from the last 'g' type header */
  54. static struct keyword_list *global_header_override_list;
  55. /* Template for the name field of an 'x' type header */
  56. static char *exthdr_name;
  57. /* Template for the name field of a 'g' type header */
  58. static char *globexthdr_name;
  59. static bool
  60. xheader_keyword_deleted_p (const char *kw)
  61. {
  62. struct keyword_list *kp;
  63. for (kp = keyword_pattern_list; kp; kp = kp->next)
  64. if (fnmatch (kp->pattern, kw, 0) == 0)
  65. return true;
  66. return false;
  67. }
  68. static bool
  69. xheader_keyword_override_p (const char *keyword)
  70. {
  71. struct keyword_list *kp;
  72. for (kp = keyword_override_list; kp; kp = kp->next)
  73. if (strcmp (kp->pattern, keyword) == 0)
  74. return true;
  75. return false;
  76. }
  77. static void
  78. xheader_list_append (struct keyword_list **root, char const *kw,
  79. char const *value)
  80. {
  81. struct keyword_list *kp = xmalloc (sizeof *kp);
  82. kp->pattern = xstrdup (kw);
  83. kp->value = value ? xstrdup (value) : NULL;
  84. kp->next = *root;
  85. *root = kp;
  86. }
  87. static void
  88. xheader_list_destroy (struct keyword_list **root)
  89. {
  90. if (root)
  91. {
  92. struct keyword_list *kw = *root;
  93. while (kw)
  94. {
  95. struct keyword_list *next = kw->next;
  96. free (kw->pattern);
  97. free (kw->value);
  98. free (kw);
  99. kw = next;
  100. }
  101. *root = NULL;
  102. }
  103. }
  104. static void
  105. xheader_set_single_keyword (char *kw)
  106. {
  107. USAGE_ERROR ((0, 0, _("Keyword %s is unknown or not yet imlemented"), kw));
  108. }
  109. static void
  110. xheader_set_keyword_equal (char *kw, char *eq)
  111. {
  112. bool global = true;
  113. char *p = eq;
  114. if (eq[-1] == ':')
  115. {
  116. p--;
  117. global = false;
  118. }
  119. while (p > kw && isspace (*p))
  120. p--;
  121. *p = 0;
  122. for (p = eq + 1; *p && isspace (*p); p++)
  123. ;
  124. if (strcmp (kw, "delete") == 0)
  125. {
  126. if (xheader_protected_pattern_p (p))
  127. USAGE_ERROR ((0, 0, _("Pattern %s cannot be used"), quote (p)));
  128. xheader_list_append (&keyword_pattern_list, p, NULL);
  129. }
  130. else if (strcmp (kw, "exthdr.name") == 0)
  131. assign_string (&exthdr_name, p);
  132. else if (strcmp (kw, "globexthdr.name") == 0)
  133. assign_string (&globexthdr_name, p);
  134. else
  135. {
  136. if (xheader_protected_keyword_p (kw))
  137. USAGE_ERROR ((0, 0, _("Keyword %s cannot be overridden"), kw));
  138. if (global)
  139. xheader_list_append (&keyword_global_override_list, kw, p);
  140. else
  141. xheader_list_append (&keyword_override_list, kw, p);
  142. }
  143. }
  144. void
  145. xheader_set_option (char *string)
  146. {
  147. char *token;
  148. for (token = strtok (string, ","); token; token = strtok (NULL, ","))
  149. {
  150. char *p = strchr (token, '=');
  151. if (!p)
  152. xheader_set_single_keyword (token);
  153. else
  154. xheader_set_keyword_equal (token, p);
  155. }
  156. }
  157. static void
  158. to_decimal (uintmax_t value, char *where, size_t size)
  159. {
  160. size_t i = 0, j;
  161. where[i++] = 0;
  162. do
  163. {
  164. where[i++] = '0' + value % 10;
  165. value /= 10;
  166. }
  167. while (i < size && value);
  168. for (j = 0, i--; j < i; j++, i--)
  169. {
  170. char c = where[j];
  171. where[j] = where[i];
  172. where[i] = c;
  173. }
  174. }
  175. /*
  176. string Includes: Replaced By:
  177. %d The directory name of the file,
  178. equivalent to the result of the
  179. dirname utility on the translated
  180. file name.
  181. %f The filename of the file, equivalent
  182. to the result of the basename
  183. utility on the translated file name.
  184. %p The process ID of the pax process.
  185. %% A '%' character. */
  186. static char *
  187. xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
  188. {
  189. char *buf;
  190. size_t len = strlen (fmt);
  191. char *q;
  192. const char *p;
  193. char *dir = NULL;
  194. char *base = NULL;
  195. char pidbuf[64];
  196. char nbuf[64];
  197. for (p = fmt; *p && (p = strchr (p, '%')); )
  198. {
  199. switch (p[1])
  200. {
  201. case '%':
  202. len--;
  203. break;
  204. case 'd':
  205. if (st)
  206. {
  207. dir = safer_name_suffix (dir_name (st->orig_file_name), false);
  208. len += strlen (dir) - 1;
  209. }
  210. break;
  211. case 'f':
  212. if (st)
  213. {
  214. base = base_name (st->orig_file_name);
  215. len += strlen (base) - 1;
  216. }
  217. break;
  218. case 'p':
  219. to_decimal (getpid (), pidbuf, sizeof pidbuf);
  220. len += strlen (pidbuf) - 1;
  221. break;
  222. case 'n':
  223. if (allow_n)
  224. {
  225. to_decimal (global_header_count + 1, pidbuf, sizeof pidbuf);
  226. len += strlen (nbuf) - 1;
  227. }
  228. break;
  229. }
  230. p++;
  231. }
  232. buf = xmalloc (len + 1);
  233. for (q = buf, p = fmt; *p; )
  234. {
  235. if (*p == '%')
  236. {
  237. switch (p[1])
  238. {
  239. case '%':
  240. *q++ = *p++;
  241. p++;
  242. break;
  243. case 'd':
  244. if (dir)
  245. q = stpcpy (q, dir);
  246. p += 2;
  247. break;
  248. case 'f':
  249. if (base)
  250. q = stpcpy (q, base);
  251. p += 2;
  252. break;
  253. case 'p':
  254. q = stpcpy (q, pidbuf);
  255. p += 2;
  256. break;
  257. case 'n':
  258. if (allow_n)
  259. {
  260. q = stpcpy (q, nbuf);
  261. p += 2;
  262. }
  263. /* else fall through */
  264. default:
  265. *q++ = *p++;
  266. if (*p)
  267. *q++ = *p++;
  268. }
  269. }
  270. else
  271. *q++ = *p++;
  272. }
  273. /* Do not allow it to end in a slash */
  274. while (q > buf && ISSLASH (q[-1]))
  275. q--;
  276. *q = 0;
  277. return buf;
  278. }
  279. char *
  280. xheader_xhdr_name (struct tar_stat_info *st)
  281. {
  282. if (!exthdr_name)
  283. assign_string (&exthdr_name, "%d/PaxHeaders.%p/%f");
  284. return xheader_format_name (st, exthdr_name, false);
  285. }
  286. #define GLOBAL_HEADER_TEMPLATE "/GlobalHead.%p.%n"
  287. char *
  288. xheader_ghdr_name (void)
  289. {
  290. if (!globexthdr_name)
  291. {
  292. size_t len;
  293. const char *tmp = getenv ("TMPDIR");
  294. if (!tmp)
  295. tmp = "/tmp";
  296. len = strlen (tmp) + sizeof (GLOBAL_HEADER_TEMPLATE); /* Includes nul */
  297. globexthdr_name = xmalloc (len);
  298. strcpy(globexthdr_name, tmp);
  299. strcat(globexthdr_name, GLOBAL_HEADER_TEMPLATE);
  300. }
  301. return xheader_format_name (NULL, globexthdr_name, true);
  302. }
  303. void
  304. xheader_write (char type, char *name, struct xheader *xhdr)
  305. {
  306. union block *header;
  307. size_t size;
  308. char *p;
  309. size = xhdr->size;
  310. header = start_private_header (name, size);
  311. header->header.typeflag = type;
  312. simple_finish_header (header);
  313. p = xhdr->buffer;
  314. do
  315. {
  316. size_t len;
  317. header = find_next_block ();
  318. len = BLOCKSIZE;
  319. if (len > size)
  320. len = size;
  321. memcpy (header->buffer, p, len);
  322. if (len < BLOCKSIZE)
  323. memset (header->buffer + len, 0, BLOCKSIZE - len);
  324. p += len;
  325. size -= len;
  326. set_next_block_after (header);
  327. }
  328. while (size > 0);
  329. xheader_destroy (xhdr);
  330. }
  331. void
  332. xheader_write_global (void)
  333. {
  334. char *name;
  335. struct keyword_list *kp;
  336. if (!keyword_global_override_list)
  337. return;
  338. extended_header_init ();
  339. for (kp = keyword_global_override_list; kp; kp = kp->next)
  340. code_string (kp->value, kp->pattern, &extended_header);
  341. xheader_finish (&extended_header);
  342. xheader_write (XGLTYPE, name = xheader_ghdr_name (),
  343. &extended_header);
  344. free (name);
  345. global_header_count++;
  346. }
  347. /* General Interface */
  348. struct xhdr_tab
  349. {
  350. char const *keyword;
  351. void (*coder) (struct tar_stat_info const *, char const *,
  352. struct xheader *, void *data);
  353. void (*decoder) (struct tar_stat_info *, char const *);
  354. bool protect;
  355. };
  356. /* This declaration must be extern, because ISO C99 section 6.9.2
  357. prohibits a tentative definition that has both internal linkage and
  358. incomplete type. If we made it static, we'd have to declare its
  359. size which would be a maintenance pain; if we put its initializer
  360. here, we'd need a boatload of forward declarations, which would be
  361. even more of a pain. */
  362. extern struct xhdr_tab const xhdr_tab[];
  363. static struct xhdr_tab const *
  364. locate_handler (char const *keyword)
  365. {
  366. struct xhdr_tab const *p;
  367. for (p = xhdr_tab; p->keyword; p++)
  368. if (strcmp (p->keyword, keyword) == 0)
  369. return p;
  370. return NULL;
  371. }
  372. static bool
  373. xheader_protected_pattern_p (const char *pattern)
  374. {
  375. struct xhdr_tab const *p;
  376. for (p = xhdr_tab; p->keyword; p++)
  377. if (p->protect && fnmatch (pattern, p->keyword, 0) == 0)
  378. return true;
  379. return false;
  380. }
  381. static bool
  382. xheader_protected_keyword_p (const char *keyword)
  383. {
  384. struct xhdr_tab const *p;
  385. for (p = xhdr_tab; p->keyword; p++)
  386. if (p->protect && strcmp (p->keyword, keyword) == 0)
  387. return true;
  388. return false;
  389. }
  390. /* Decodes a single extended header record. Advances P to the next
  391. record.
  392. Returns true on success, false otherwise. */
  393. static bool
  394. decode_record (char **p,
  395. void (*handler) (void *, char const *, char const *),
  396. void *data)
  397. {
  398. size_t len;
  399. char const *keyword;
  400. char *start = *p;
  401. char endc;
  402. if (**p == 0)
  403. return false;
  404. len = strtoul (*p, p, 10);
  405. if (**p != ' ')
  406. {
  407. ERROR ((0, 0,
  408. _("Malformed extended header: missing whitespace after the length")));
  409. return false;
  410. }
  411. keyword = ++*p;
  412. for (;*p < start + len; ++*p)
  413. if (**p == '=')
  414. break;
  415. if (**p != '=')
  416. {
  417. ERROR ((0, 0, _("Malformed extended header: missing equal sign")));
  418. return false;
  419. }
  420. **p = 0;
  421. endc = start[len-1];
  422. start[len-1] = 0;
  423. handler (data, keyword, *p + 1);
  424. start[len-1] = endc;
  425. **p = '=';
  426. *p = &start[len];
  427. return true;
  428. }
  429. static void
  430. run_override_list (struct keyword_list *kp, struct tar_stat_info *st)
  431. {
  432. for (; kp; kp = kp->next)
  433. {
  434. struct xhdr_tab const *t = locate_handler (kp->pattern);
  435. if (t)
  436. t->decoder (st, kp->value);
  437. }
  438. }
  439. static void
  440. decx (void *data, char const *keyword, char const *value)
  441. {
  442. struct xhdr_tab const *t;
  443. struct tar_stat_info *st = data;
  444. if (xheader_keyword_deleted_p (keyword)
  445. || xheader_keyword_override_p (keyword))
  446. return;
  447. t = locate_handler (keyword);
  448. if (t)
  449. t->decoder (st, value);
  450. }
  451. void
  452. xheader_decode (struct tar_stat_info *st)
  453. {
  454. run_override_list (keyword_global_override_list, st);
  455. run_override_list (global_header_override_list, st);
  456. if (extended_header.size)
  457. {
  458. char *p = extended_header.buffer + BLOCKSIZE;
  459. char *endp = &extended_header.buffer[extended_header.size-1];
  460. while (p < endp)
  461. if (!decode_record (&p, decx, st))
  462. break;
  463. }
  464. run_override_list (keyword_override_list, st);
  465. }
  466. static void
  467. decg (void *data, char const *keyword, char const *value)
  468. {
  469. struct keyword_list **kwl = data;
  470. xheader_list_append (kwl, keyword, value);
  471. }
  472. void
  473. xheader_decode_global (void)
  474. {
  475. if (extended_header.size)
  476. {
  477. char *p = extended_header.buffer + BLOCKSIZE;
  478. char *endp = &extended_header.buffer[extended_header.size-1];
  479. xheader_list_destroy (&global_header_override_list);
  480. while (p < endp)
  481. if (!decode_record (&p, decg, &global_header_override_list))
  482. break;
  483. }
  484. }
  485. static void
  486. extended_header_init (void)
  487. {
  488. if (!extended_header.stk)
  489. {
  490. extended_header.stk = xmalloc (sizeof *extended_header.stk);
  491. obstack_init (extended_header.stk);
  492. }
  493. }
  494. void
  495. xheader_store (char const *keyword, struct tar_stat_info const *st, void *data)
  496. {
  497. struct xhdr_tab const *t;
  498. if (extended_header.buffer)
  499. return;
  500. t = locate_handler (keyword);
  501. if (!t)
  502. return;
  503. if (xheader_keyword_deleted_p (keyword)
  504. || xheader_keyword_override_p (keyword))
  505. return;
  506. extended_header_init ();
  507. t->coder (st, keyword, &extended_header, data);
  508. }
  509. void
  510. xheader_read (union block *p, size_t size)
  511. {
  512. size_t j = 0;
  513. size_t nblocks;
  514. free (extended_header.buffer);
  515. size += BLOCKSIZE;
  516. extended_header.size = size;
  517. nblocks = (size + BLOCKSIZE - 1) / BLOCKSIZE;
  518. extended_header.buffer = xmalloc (size + 1);
  519. do
  520. {
  521. size_t len = size;
  522. if (len > BLOCKSIZE)
  523. len = BLOCKSIZE;
  524. memcpy (&extended_header.buffer[j], p->buffer, len);
  525. set_next_block_after (p);
  526. p = find_next_block ();
  527. j += len;
  528. size -= len;
  529. }
  530. while (size > 0);
  531. }
  532. static size_t
  533. format_uintmax (uintmax_t val, char *buf, size_t s)
  534. {
  535. if (!buf)
  536. {
  537. s = 0;
  538. do
  539. s++;
  540. while ((val /= 10) != 0);
  541. }
  542. else
  543. {
  544. char *p = buf + s - 1;
  545. do
  546. {
  547. *p-- = val % 10 + '0';
  548. }
  549. while ((val /= 10) != 0);
  550. while (p >= buf)
  551. *p-- = '0';
  552. }
  553. return s;
  554. }
  555. static void
  556. xheader_print (struct xheader *xhdr, char const *keyword, char const *value)
  557. {
  558. size_t len = strlen (keyword) + strlen (value) + 3; /* ' ' + '=' + '\n' */
  559. size_t p, n = 0;
  560. char nbuf[100];
  561. do
  562. {
  563. p = n;
  564. n = format_uintmax (len + p, NULL, 0);
  565. }
  566. while (n != p);
  567. format_uintmax (len + n, nbuf, n);
  568. obstack_grow (xhdr->stk, nbuf, n);
  569. obstack_1grow (xhdr->stk, ' ');
  570. obstack_grow (xhdr->stk, keyword, strlen (keyword));
  571. obstack_1grow (xhdr->stk, '=');
  572. obstack_grow (xhdr->stk, value, strlen (value));
  573. obstack_1grow (xhdr->stk, '\n');
  574. }
  575. void
  576. xheader_finish (struct xheader *xhdr)
  577. {
  578. struct keyword_list *kp;
  579. for (kp = keyword_override_list; kp; kp = kp->next)
  580. code_string (kp->value, kp->pattern, xhdr);
  581. obstack_1grow (xhdr->stk, 0);
  582. xhdr->buffer = obstack_finish (xhdr->stk);
  583. xhdr->size = strlen (xhdr->buffer);
  584. }
  585. void
  586. xheader_destroy (struct xheader *xhdr)
  587. {
  588. if (xhdr->stk)
  589. {
  590. obstack_free (xhdr->stk, NULL);
  591. free (xhdr->stk);
  592. xhdr->stk = NULL;
  593. }
  594. else
  595. free (xhdr->buffer);
  596. xhdr->buffer = 0;
  597. xhdr->size = 0;
  598. }
  599. /* Implementations */
  600. static void
  601. code_string (char const *string, char const *keyword, struct xheader *xhdr)
  602. {
  603. char *outstr;
  604. if (!utf8_convert (true, string, &outstr))
  605. {
  606. /* FIXME: report error */
  607. outstr = xstrdup (string);
  608. }
  609. xheader_print (xhdr, keyword, outstr);
  610. free (outstr);
  611. }
  612. static void
  613. decode_string (char **string, char const *arg)
  614. {
  615. if (*string)
  616. {
  617. free (*string);
  618. *string = NULL;
  619. }
  620. if (!utf8_convert (false, arg, string))
  621. {
  622. /* FIXME: report error and act accordingly to --pax invalid=UTF-8 */
  623. assign_string (string, arg);
  624. }
  625. }
  626. static void
  627. code_time (time_t t, unsigned long nano,
  628. char const *keyword, struct xheader *xhdr)
  629. {
  630. char sbuf[200];
  631. size_t s = format_uintmax (t, NULL, 0);
  632. if (s + 11 >= sizeof sbuf)
  633. return;
  634. format_uintmax (t, sbuf, s);
  635. sbuf[s++] = '.';
  636. s += format_uintmax (nano, sbuf + s, 9);
  637. sbuf[s] = 0;
  638. xheader_print (xhdr, keyword, sbuf);
  639. }
  640. static void
  641. decode_time (char const *arg, time_t *secs, unsigned long *nsecs)
  642. {
  643. uintmax_t u;
  644. char *p;
  645. if (xstrtoumax (arg, &p, 10, &u, "") == LONGINT_OK)
  646. {
  647. *secs = u;
  648. if (*p == '.' && xstrtoumax (p+1, NULL, 10, &u, "") == LONGINT_OK)
  649. *nsecs = u;
  650. }
  651. }
  652. static void
  653. code_num (uintmax_t value, char const *keyword, struct xheader *xhdr)
  654. {
  655. char sbuf[100];
  656. size_t s = format_uintmax (value, NULL, 0);
  657. format_uintmax (value, sbuf, s);
  658. sbuf[s] = 0;
  659. xheader_print (xhdr, keyword, sbuf);
  660. }
  661. static void
  662. dummy_coder (struct tar_stat_info const *st __attribute__ ((unused)),
  663. char const *keyword __attribute__ ((unused)),
  664. struct xheader *xhdr __attribute__ ((unused)),
  665. void *data __attribute__ ((unused)))
  666. {
  667. }
  668. static void
  669. dummy_decoder (struct tar_stat_info *st __attribute__ ((unused)),
  670. char const *arg __attribute__ ((unused)))
  671. {
  672. }
  673. static void
  674. atime_coder (struct tar_stat_info const *st, char const *keyword,
  675. struct xheader *xhdr, void *data __attribute__ ((unused)))
  676. {
  677. code_time (st->stat.st_atime, st->atime_nsec, keyword, xhdr);
  678. }
  679. static void
  680. atime_decoder (struct tar_stat_info *st, char const *arg)
  681. {
  682. decode_time (arg, &st->stat.st_atime, &st->atime_nsec);
  683. }
  684. static void
  685. gid_coder (struct tar_stat_info const *st, char const *keyword,
  686. struct xheader *xhdr, void *data __attribute__ ((unused)))
  687. {
  688. code_num (st->stat.st_gid, keyword, xhdr);
  689. }
  690. static void
  691. gid_decoder (struct tar_stat_info *st, char const *arg)
  692. {
  693. uintmax_t u;
  694. if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
  695. st->stat.st_gid = u;
  696. }
  697. static void
  698. gname_coder (struct tar_stat_info const *st, char const *keyword,
  699. struct xheader *xhdr, void *data __attribute__ ((unused)))
  700. {
  701. code_string (st->gname, keyword, xhdr);
  702. }
  703. static void
  704. gname_decoder (struct tar_stat_info *st, char const *arg)
  705. {
  706. decode_string (&st->gname, arg);
  707. }
  708. static void
  709. linkpath_coder (struct tar_stat_info const *st, char const *keyword,
  710. struct xheader *xhdr, void *data __attribute__ ((unused)))
  711. {
  712. code_string (st->link_name, keyword, xhdr);
  713. }
  714. static void
  715. linkpath_decoder (struct tar_stat_info *st, char const *arg)
  716. {
  717. decode_string (&st->link_name, arg);
  718. }
  719. static void
  720. ctime_coder (struct tar_stat_info const *st, char const *keyword,
  721. struct xheader *xhdr, void *data __attribute__ ((unused)))
  722. {
  723. code_time (st->stat.st_ctime, st->ctime_nsec, keyword, xhdr);
  724. }
  725. static void
  726. ctime_decoder (struct tar_stat_info *st, char const *arg)
  727. {
  728. decode_time (arg, &st->stat.st_ctime, &st->ctime_nsec);
  729. }
  730. static void
  731. mtime_coder (struct tar_stat_info const *st, char const *keyword,
  732. struct xheader *xhdr, void *data __attribute__ ((unused)))
  733. {
  734. code_time (st->stat.st_mtime, st->mtime_nsec, keyword, xhdr);
  735. }
  736. static void
  737. mtime_decoder (struct tar_stat_info *st, char const *arg)
  738. {
  739. decode_time (arg, &st->stat.st_mtime, &st->mtime_nsec);
  740. }
  741. static void
  742. path_coder (struct tar_stat_info const *st, char const *keyword,
  743. struct xheader *xhdr, void *data __attribute__ ((unused)))
  744. {
  745. code_string (st->file_name, keyword, xhdr);
  746. }
  747. static void
  748. path_decoder (struct tar_stat_info *st, char const *arg)
  749. {
  750. decode_string (&st->orig_file_name, arg);
  751. decode_string (&st->file_name, arg);
  752. st->had_trailing_slash = strip_trailing_slashes (st->file_name);
  753. }
  754. static void
  755. size_coder (struct tar_stat_info const *st, char const *keyword,
  756. struct xheader *xhdr, void *data __attribute__ ((unused)))
  757. {
  758. code_num (st->stat.st_size, keyword, xhdr);
  759. }
  760. static void
  761. size_decoder (struct tar_stat_info *st, char const *arg)
  762. {
  763. uintmax_t u;
  764. if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
  765. st->archive_file_size = st->stat.st_size = u;
  766. }
  767. static void
  768. uid_coder (struct tar_stat_info const *st, char const *keyword,
  769. struct xheader *xhdr, void *data __attribute__ ((unused)))
  770. {
  771. code_num (st->stat.st_uid, keyword, xhdr);
  772. }
  773. static void
  774. uid_decoder (struct tar_stat_info *st, char const *arg)
  775. {
  776. uintmax_t u;
  777. if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
  778. st->stat.st_uid = u;
  779. }
  780. static void
  781. uname_coder (struct tar_stat_info const *st, char const *keyword,
  782. struct xheader *xhdr, void *data __attribute__ ((unused)))
  783. {
  784. code_string (st->uname, keyword, xhdr);
  785. }
  786. static void
  787. uname_decoder (struct tar_stat_info *st, char const *arg)
  788. {
  789. decode_string (&st->uname, arg);
  790. }
  791. static void
  792. sparse_size_coder (struct tar_stat_info const *st, char const *keyword,
  793. struct xheader *xhdr, void *data)
  794. {
  795. size_coder (st, keyword, xhdr, data);
  796. }
  797. static void
  798. sparse_size_decoder (struct tar_stat_info *st, char const *arg)
  799. {
  800. uintmax_t u;
  801. if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
  802. st->stat.st_size = u;
  803. }
  804. static void
  805. sparse_numblocks_coder (struct tar_stat_info const *st, char const *keyword,
  806. struct xheader *xhdr,
  807. void *data __attribute__ ((unused)))
  808. {
  809. code_num (st->sparse_map_avail, keyword, xhdr);
  810. }
  811. static void
  812. sparse_numblocks_decoder (struct tar_stat_info *st, char const *arg)
  813. {
  814. uintmax_t u;
  815. if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
  816. {
  817. st->sparse_map_size = u;
  818. st->sparse_map = calloc(st->sparse_map_size, sizeof(st->sparse_map[0]));
  819. st->sparse_map_avail = 0;
  820. }
  821. }
  822. static void
  823. sparse_offset_coder (struct tar_stat_info const *st, char const *keyword,
  824. struct xheader *xhdr, void *data)
  825. {
  826. size_t i = *(size_t*)data;
  827. code_num (st->sparse_map[i].offset, keyword, xhdr);
  828. }
  829. static void
  830. sparse_offset_decoder (struct tar_stat_info *st, char const *arg)
  831. {
  832. uintmax_t u;
  833. if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
  834. st->sparse_map[st->sparse_map_avail].offset = u;
  835. }
  836. static void
  837. sparse_numbytes_coder (struct tar_stat_info const *st, char const *keyword,
  838. struct xheader *xhdr, void *data)
  839. {
  840. size_t i = *(size_t*)data;
  841. code_num (st->sparse_map[i].numbytes, keyword, xhdr);
  842. }
  843. static void
  844. sparse_numbytes_decoder (struct tar_stat_info *st, char const *arg)
  845. {
  846. uintmax_t u;
  847. if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
  848. {
  849. if (st->sparse_map_avail == st->sparse_map_size)
  850. {
  851. st->sparse_map_size *= 2;
  852. st->sparse_map = xrealloc (st->sparse_map,
  853. st->sparse_map_size
  854. * sizeof st->sparse_map[0]);
  855. }
  856. st->sparse_map[st->sparse_map_avail++].numbytes = u;
  857. }
  858. }
  859. struct xhdr_tab const xhdr_tab[] = {
  860. { "atime", atime_coder, atime_decoder, false },
  861. { "comment", dummy_coder, dummy_decoder, false },
  862. { "charset", dummy_coder, dummy_decoder, false },
  863. { "ctime", ctime_coder, ctime_decoder, false },
  864. { "gid", gid_coder, gid_decoder, false },
  865. { "gname", gname_coder, gname_decoder, false },
  866. { "linkpath", linkpath_coder, linkpath_decoder, false },
  867. { "mtime", mtime_coder, mtime_decoder, false },
  868. { "path", path_coder, path_decoder, false },
  869. { "size", size_coder, size_decoder, false },
  870. { "uid", uid_coder, uid_decoder, false },
  871. { "uname", uname_coder, uname_decoder, false },
  872. /* Sparse file handling */
  873. { "GNU.sparse.size", sparse_size_coder, sparse_size_decoder, true },
  874. { "GNU.sparse.numblocks", sparse_numblocks_coder, sparse_numblocks_decoder,
  875. true },
  876. { "GNU.sparse.offset", sparse_offset_coder, sparse_offset_decoder,
  877. true },
  878. { "GNU.sparse.numbytes", sparse_numbytes_coder, sparse_numbytes_decoder,
  879. true },
  880. #if 0 /* GNU private keywords (not yet implemented) */
  881. /* The next directory entry actually contains the names of files
  882. that were in the directory at the time the dump was made.
  883. Supersedes GNUTYPE_DUMPDIR header type. */
  884. { "GNU.dump.name", dump_name_coder, dump_name_decoder, false },
  885. { "GNU.dump.status", dump_status_coder, dump_status_decoder, false },
  886. /* Keeps the tape/volume header. May be present only in the global headers.
  887. Equivalent to GNUTYPE_VOLHDR. */
  888. { "GNU.volume.header", volume_header_coder, volume_header_decoder, false },
  889. /* These may be present in a first global header of the archive.
  890. They provide the same functionality as GNUTYPE_MULTIVOL header.
  891. The GNU.volume.size keeps the real_s_sizeleft value, which is
  892. otherwise kept in the size field of a multivolume header. The
  893. GNU.volume.offset keeps the offset of the start of this volume,
  894. otherwise kept in oldgnu_header.offset. */
  895. { "GNU.volume.size", volume_size_coder, volume_size_decoder, false },
  896. { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder, false },
  897. #endif
  898. { NULL, NULL, NULL, false }
  899. };