4
0

xheader.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  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 <hash.h>
  16. #include <quotearg.h>
  17. #include <xstrtol.h>
  18. #include "common.h"
  19. #define obstack_chunk_alloc xmalloc
  20. #define obstack_chunk_free free
  21. #include <obstack.h>
  22. bool xheader_protected_pattern_p (const char *pattern);
  23. bool xheader_protected_keyword_p (const char *keyword);
  24. /* Number of the global headers written so far. Not used yet */
  25. static size_t global_header_count;
  26. /* Keyword options */
  27. struct keyword_list
  28. {
  29. struct keyword_list *next;
  30. char *pattern;
  31. char *value;
  32. };
  33. /* List of keyword patterns set by delete= option */
  34. static struct keyword_list *keyword_pattern_list;
  35. /* List of keyword/value pairs set by `keyword=value' option */
  36. static struct keyword_list *keyword_global_override_list;
  37. /* List of keyword/value pairs set by `keyword:=value' option */
  38. static struct keyword_list *keyword_override_list;
  39. /* Template for the name field of an 'x' type header */
  40. static char *exthdr_name;
  41. /* Template for the name field of a 'g' type header */
  42. static char *globexthdr_name;
  43. bool
  44. xheader_keyword_deleted_p (const char *kw)
  45. {
  46. struct keyword_list *kp;
  47. for (kp = keyword_pattern_list; kp; kp = kp->next)
  48. if (fnmatch (kp->pattern, kw, 0) == 0)
  49. return true;
  50. return false;
  51. }
  52. bool
  53. xheader_keyword_override_p (const char *keyword)
  54. {
  55. struct keyword_list *kp;
  56. for (kp = keyword_override_list; kp; kp = kp->next)
  57. if (strcmp (kp->pattern, keyword) == 0)
  58. return true;
  59. return false;
  60. }
  61. void
  62. xheader_list_append (struct keyword_list **root, char *kw, char *value)
  63. {
  64. struct keyword_list *kp = xmalloc (sizeof *kp);
  65. kp->pattern = xstrdup (kw);
  66. kp->value = value ? xstrdup (value) : NULL;
  67. kp->next = *root;
  68. *root = kp;
  69. }
  70. void
  71. xheader_set_single_keyword (char *kw)
  72. {
  73. USAGE_ERROR ((0, 0, "Keyword %s is unknown or not yet imlemented", kw));
  74. }
  75. void
  76. xheader_set_keyword_equal (char *kw, char *eq)
  77. {
  78. bool global = true;
  79. char *p = eq;
  80. if (eq[-1] == ':')
  81. {
  82. p--;
  83. global = false;
  84. }
  85. while (p > kw && isspace (*p))
  86. p--;
  87. *p = 0;
  88. for (p = eq + 1; *p && isspace (*p); p++)
  89. ;
  90. if (strcmp (kw, "delete") == 0)
  91. {
  92. if (xheader_protected_pattern_p (p))
  93. USAGE_ERROR ((0, 0, "Pattern %s cannot be used", p));
  94. xheader_list_append (&keyword_pattern_list, p, NULL);
  95. }
  96. else if (strcmp (kw, "exthdr.name") == 0)
  97. assign_string (&exthdr_name, p);
  98. else if (strcmp (kw, "globexthdr.name") == 0)
  99. assign_string (&globexthdr_name, p);
  100. else
  101. {
  102. if (xheader_protected_keyword_p (kw))
  103. USAGE_ERROR ((0, 0, "Keyword %s cannot be overridden", kw));
  104. if (global)
  105. xheader_list_append (&keyword_global_override_list, kw, p);
  106. else
  107. xheader_list_append (&keyword_override_list, kw, p);
  108. }
  109. }
  110. void
  111. xheader_set_option (char *string)
  112. {
  113. char *token;
  114. for (token = strtok (string, ","); token; token = strtok (NULL, ","))
  115. {
  116. char *p = strchr (token, '=');
  117. if (!p)
  118. xheader_set_single_keyword (token);
  119. else
  120. xheader_set_keyword_equal (token, p);
  121. }
  122. }
  123. /*
  124. string Includes: Replaced By:
  125. %d The directory name of the file,
  126. equivalent to the result of the
  127. dirname utility on the translated
  128. pathname.
  129. %f The filename of the file, equivalent
  130. to the result of the basename
  131. utility on the translated pathname.
  132. %p The process ID of the pax process.
  133. %% A '%' character. */
  134. static char *
  135. xheader_format_name (struct tar_stat_info *st, const char *fmt, bool allow_n)
  136. {
  137. char *buf;
  138. size_t len = strlen (fmt);
  139. char *q;
  140. const char *p;
  141. char *dirname = NULL;
  142. char *basename = NULL;
  143. char pidbuf[64];
  144. char nbuf[64];
  145. for (p = exthdr_name; *p && (p = strchr (p, '%')); )
  146. {
  147. switch (p[1])
  148. {
  149. case '%':
  150. len--;
  151. break;
  152. case 'd':
  153. dirname = safer_name_suffix (dir_name (st->orig_file_name), false);
  154. len += strlen (dirname) - 1;
  155. break;
  156. case 'f':
  157. basename = base_name (st->orig_file_name);
  158. len += strlen (basename) - 1;
  159. break;
  160. case 'p':
  161. snprintf (pidbuf, sizeof pidbuf, "%lu",
  162. (unsigned long) getpid ());
  163. len += strlen (pidbuf) - 1;
  164. break;
  165. case 'n':
  166. if (allow_n)
  167. {
  168. snprintf (nbuf, sizeof nbuf, "%lu",
  169. (unsigned long) global_header_count + 1);
  170. len += strlen (nbuf) - 1;
  171. }
  172. break;
  173. }
  174. p++;
  175. }
  176. buf = xmalloc (len + 1);
  177. for (q = buf, p = fmt; *p; )
  178. {
  179. if (*p == '%')
  180. {
  181. switch (p[1])
  182. {
  183. case '%':
  184. *q++ = *p++;
  185. p++;
  186. break;
  187. case 'd':
  188. q = stpcpy (q, dirname);
  189. p += 2;
  190. break;
  191. case 'f':
  192. q = stpcpy (q, basename);
  193. p += 2;
  194. break;
  195. case 'p':
  196. q = stpcpy (q, pidbuf);
  197. p += 2;
  198. break;
  199. case 'n':
  200. if (allow_n)
  201. {
  202. q = stpcpy (q, nbuf);
  203. p += 2;
  204. }
  205. /* else fall through */
  206. default:
  207. *q++ = *p++;
  208. if (*p)
  209. *q++ = *p++;
  210. }
  211. }
  212. else
  213. *q++ = *p++;
  214. }
  215. /* Do not allow it to end in a slash */
  216. while (q > buf && ISSLASH (q[-1]))
  217. q--;
  218. *q = 0;
  219. return buf;
  220. }
  221. char *
  222. xheader_xhdr_name (struct tar_stat_info *st)
  223. {
  224. /* FIXME: POSIX requires the default name to be '%d/PaxHeaders.%p/%f' */
  225. if (!exthdr_name)
  226. return xstrdup ("././@PaxHeader");
  227. return xheader_format_name (st, exthdr_name, false);
  228. }
  229. #define GLOBAL_HEADER_TEMPLATE "/GlobalHead.%p.%n"
  230. char *
  231. xheader_ghdr_name (struct tar_stat_info *st)
  232. {
  233. if (!globexthdr_name)
  234. {
  235. size_t len;
  236. const char *tmp = getenv ("TMPDIR");
  237. if (!tmp)
  238. tmp = "/tmp";
  239. len = strlen (tmp) + sizeof (GLOBAL_HEADER_TEMPLATE); /* Includes nul */
  240. globexthdr_name = xmalloc (len);
  241. strcpy(globexthdr_name, tmp);
  242. strcat(globexthdr_name, GLOBAL_HEADER_TEMPLATE);
  243. }
  244. return xheader_format_name (st, globexthdr_name, true);
  245. }
  246. /* General Interface */
  247. /* Used by xheader_finish() */
  248. static void code_string (char const *string, char const *keyword,
  249. struct xheader *xhdr);
  250. struct xhdr_tab
  251. {
  252. char const *keyword;
  253. void (*coder) (struct tar_stat_info const *, char const *,
  254. struct xheader *, void *data);
  255. void (*decoder) (struct tar_stat_info *, char const *);
  256. bool protect;
  257. };
  258. /* This declaration must be extern, because ISO C99 section 6.9.2
  259. prohibits a tentative definition that has both internal linkage and
  260. incomplete type. If we made it static, we'd have to declare its
  261. size which would be a maintenance pain; if we put its initializer
  262. here, we'd need a boatload of forward declarations, which would be
  263. even more of a pain. */
  264. extern struct xhdr_tab const xhdr_tab[];
  265. static struct xhdr_tab const *
  266. locate_handler (char const *keyword)
  267. {
  268. struct xhdr_tab const *p;
  269. for (p = xhdr_tab; p->keyword; p++)
  270. if (strcmp (p->keyword, keyword) == 0)
  271. return p;
  272. return NULL;
  273. }
  274. bool
  275. xheader_protected_pattern_p (const char *pattern)
  276. {
  277. struct xhdr_tab const *p;
  278. for (p = xhdr_tab; p->keyword; p++)
  279. if (p->protect && fnmatch (pattern, p->keyword, 0) == 0)
  280. return true;
  281. return false;
  282. }
  283. bool
  284. xheader_protected_keyword_p (const char *keyword)
  285. {
  286. struct xhdr_tab const *p;
  287. for (p = xhdr_tab; p->keyword; p++)
  288. if (p->protect && strcmp (p->keyword, keyword) == 0)
  289. return true;
  290. return false;
  291. }
  292. /* Decodes a single extended header record. Advances P to the next
  293. record.
  294. Returns true on success, false otherwise. */
  295. static bool
  296. decode_record (char **p, struct tar_stat_info *st)
  297. {
  298. size_t len;
  299. char const *keyword;
  300. char *eqp;
  301. char *start = *p;
  302. struct xhdr_tab const *t;
  303. if (**p == 0)
  304. return false;
  305. len = strtoul (*p, p, 10);
  306. if (**p != ' ')
  307. {
  308. ERROR ((0, 0,
  309. _("Malformed extended header: missing whitespace after the length")));
  310. return false;
  311. }
  312. keyword = ++*p;
  313. for (;*p < start + len; ++*p)
  314. if (**p == '=')
  315. break;
  316. if (**p != '=')
  317. {
  318. ERROR ((0, 0, _("Malformed extended header: missing equal sign")));
  319. return false;
  320. }
  321. eqp = *p;
  322. **p = 0;
  323. if (xheader_keyword_deleted_p (keyword)
  324. || xheader_keyword_override_p (keyword))
  325. return true;
  326. t = locate_handler (keyword);
  327. if (t)
  328. {
  329. char endc;
  330. char *value;
  331. value = ++*p;
  332. endc = start[len-1];
  333. start[len-1] = 0;
  334. t->decoder (st, value);
  335. start[len-1] = endc;
  336. }
  337. *eqp = '=';
  338. *p = &start[len];
  339. return true;
  340. }
  341. static void
  342. run_override_list (struct keyword_list *kp, struct tar_stat_info *st)
  343. {
  344. for (; kp; kp = kp->next)
  345. {
  346. struct xhdr_tab const *t = locate_handler (kp->pattern);
  347. if (t)
  348. t->decoder (st, kp->value);
  349. }
  350. }
  351. void
  352. xheader_decode (struct tar_stat_info *st)
  353. {
  354. char *p = extended_header.buffer + BLOCKSIZE;
  355. char *endp = &extended_header.buffer[extended_header.size-1];
  356. run_override_list (keyword_global_override_list, st);
  357. while (p < endp)
  358. if (!decode_record (&p, st))
  359. break;
  360. run_override_list (keyword_override_list, st);
  361. }
  362. void
  363. xheader_store (char const *keyword, struct tar_stat_info const *st, void *data)
  364. {
  365. struct xhdr_tab const *t;
  366. char *value;
  367. if (extended_header.buffer)
  368. return;
  369. t = locate_handler (keyword);
  370. if (!t)
  371. return;
  372. if (xheader_keyword_deleted_p (keyword)
  373. || xheader_keyword_override_p (keyword))
  374. return;
  375. if (!extended_header.stk)
  376. {
  377. extended_header.stk = xmalloc (sizeof *extended_header.stk);
  378. obstack_init (extended_header.stk);
  379. }
  380. t->coder (st, keyword, &extended_header, data);
  381. }
  382. void
  383. xheader_read (union block *p, size_t size)
  384. {
  385. size_t j = 0;
  386. size_t nblocks;
  387. free (extended_header.buffer);
  388. size += BLOCKSIZE;
  389. extended_header.size = size;
  390. nblocks = (size + BLOCKSIZE - 1) / BLOCKSIZE;
  391. extended_header.buffer = xmalloc (size + 1);
  392. do
  393. {
  394. size_t len = size;
  395. if (len > BLOCKSIZE)
  396. len = BLOCKSIZE;
  397. memcpy (&extended_header.buffer[j], p->buffer, len);
  398. set_next_block_after (p);
  399. p = find_next_block ();
  400. j += len;
  401. size -= len;
  402. }
  403. while (size > 0);
  404. }
  405. static size_t
  406. format_uintmax (uintmax_t val, char *buf, size_t s)
  407. {
  408. if (!buf)
  409. {
  410. s = 0;
  411. do
  412. s++;
  413. while ((val /= 10) != 0);
  414. }
  415. else
  416. {
  417. char *p = buf + s - 1;
  418. do
  419. {
  420. *p-- = val % 10 + '0';
  421. }
  422. while ((val /= 10) != 0);
  423. while (p >= buf)
  424. *p-- = '0';
  425. }
  426. return s;
  427. }
  428. static void
  429. xheader_print (struct xheader *xhdr, char const *keyword, char const *value)
  430. {
  431. size_t len = strlen (keyword) + strlen (value) + 3; /* ' ' + '=' + '\n' */
  432. size_t p, n = 0;
  433. char nbuf[100];
  434. do
  435. {
  436. p = n;
  437. n = format_uintmax (len + p, NULL, 0);
  438. }
  439. while (n != p);
  440. format_uintmax (len + n, nbuf, n);
  441. obstack_grow (xhdr->stk, nbuf, n);
  442. obstack_1grow (xhdr->stk, ' ');
  443. obstack_grow (xhdr->stk, keyword, strlen (keyword));
  444. obstack_1grow (xhdr->stk, '=');
  445. obstack_grow (xhdr->stk, value, strlen (value));
  446. obstack_1grow (xhdr->stk, '\n');
  447. }
  448. void
  449. xheader_finish (struct xheader *xhdr)
  450. {
  451. struct keyword_list *kp;
  452. for (kp = keyword_override_list; kp; kp = kp->next)
  453. code_string (kp->value, kp->pattern, xhdr);
  454. obstack_1grow (xhdr->stk, 0);
  455. xhdr->buffer = obstack_finish (xhdr->stk);
  456. xhdr->size = strlen (xhdr->buffer);
  457. }
  458. void
  459. xheader_destroy (struct xheader *xhdr)
  460. {
  461. if (xhdr->stk)
  462. {
  463. obstack_free (xhdr->stk, NULL);
  464. free (xhdr->stk);
  465. xhdr->stk = NULL;
  466. }
  467. else
  468. free (xhdr->buffer);
  469. xhdr->buffer = 0;
  470. xhdr->size = 0;
  471. }
  472. /* Implementations */
  473. static void
  474. code_string (char const *string, char const *keyword, struct xheader *xhdr)
  475. {
  476. xheader_print (xhdr, keyword, string);
  477. }
  478. static void
  479. code_time (time_t t, unsigned long nano,
  480. char const *keyword, struct xheader *xhdr)
  481. {
  482. char sbuf[200];
  483. size_t s = format_uintmax (t, NULL, 0);
  484. if (s + 11 >= sizeof sbuf)
  485. return;
  486. format_uintmax (t, sbuf, s);
  487. sbuf[s++] = '.';
  488. s += format_uintmax (nano, sbuf + s, 9);
  489. sbuf[s] = 0;
  490. xheader_print (xhdr, keyword, sbuf);
  491. }
  492. static void
  493. decode_time (char const *arg, time_t *secs, unsigned long *nsecs)
  494. {
  495. uintmax_t u;
  496. char *p;
  497. if (xstrtoumax (arg, &p, 10, &u, "") == LONGINT_OK)
  498. {
  499. *secs = u;
  500. if (*p == '.' && xstrtoumax (p+1, NULL, 10, &u, "") == LONGINT_OK)
  501. *nsecs = u;
  502. }
  503. }
  504. static void
  505. code_num (uintmax_t value, char const *keyword, struct xheader *xhdr)
  506. {
  507. char sbuf[100];
  508. size_t s = format_uintmax (value, NULL, 0);
  509. format_uintmax (value, sbuf, s);
  510. sbuf[s] = 0;
  511. xheader_print (xhdr, keyword, sbuf);
  512. }
  513. static void
  514. dummy_coder (struct tar_stat_info const *st, char const *keyword,
  515. struct xheader *xhdr, void *data)
  516. {
  517. }
  518. static void
  519. dummy_decoder (struct tar_stat_info *st, char const *arg)
  520. {
  521. }
  522. static void
  523. atime_coder (struct tar_stat_info const *st, char const *keyword,
  524. struct xheader *xhdr, void *data)
  525. {
  526. code_time (st->stat.st_atime, st->atime_nsec, keyword, xhdr);
  527. }
  528. static void
  529. atime_decoder (struct tar_stat_info *st, char const *arg)
  530. {
  531. decode_time (arg, &st->stat.st_atime, &st->atime_nsec);
  532. }
  533. static void
  534. gid_coder (struct tar_stat_info const *st, char const *keyword,
  535. struct xheader *xhdr, void *data)
  536. {
  537. code_num (st->stat.st_gid, keyword, xhdr);
  538. }
  539. static void
  540. gid_decoder (struct tar_stat_info *st, char const *arg)
  541. {
  542. uintmax_t u;
  543. if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
  544. st->stat.st_gid = u;
  545. }
  546. static void
  547. gname_coder (struct tar_stat_info const *st, char const *keyword,
  548. struct xheader *xhdr, void *data)
  549. {
  550. code_string (st->gname, keyword, xhdr);
  551. }
  552. static void
  553. gname_decoder (struct tar_stat_info *st, char const *arg)
  554. {
  555. assign_string (&st->gname, arg);
  556. }
  557. static void
  558. linkpath_coder (struct tar_stat_info const *st, char const *keyword,
  559. struct xheader *xhdr, void *data)
  560. {
  561. code_string (st->link_name, keyword, xhdr);
  562. }
  563. static void
  564. linkpath_decoder (struct tar_stat_info *st, char const *arg)
  565. {
  566. assign_string (&st->link_name, arg);
  567. }
  568. static void
  569. ctime_coder (struct tar_stat_info const *st, char const *keyword,
  570. struct xheader *xhdr, void *data)
  571. {
  572. code_time (st->stat.st_ctime, st->ctime_nsec, keyword, xhdr);
  573. }
  574. static void
  575. ctime_decoder (struct tar_stat_info *st, char const *arg)
  576. {
  577. decode_time (arg, &st->stat.st_ctime, &st->ctime_nsec);
  578. }
  579. static void
  580. mtime_coder (struct tar_stat_info const *st, char const *keyword,
  581. struct xheader *xhdr, void *data)
  582. {
  583. code_time (st->stat.st_mtime, st->mtime_nsec, keyword, xhdr);
  584. }
  585. static void
  586. mtime_decoder (struct tar_stat_info *st, char const *arg)
  587. {
  588. decode_time (arg, &st->stat.st_mtime, &st->mtime_nsec);
  589. }
  590. static void
  591. path_coder (struct tar_stat_info const *st, char const *keyword,
  592. struct xheader *xhdr, void *data)
  593. {
  594. code_string (st->file_name, keyword, xhdr);
  595. }
  596. static void
  597. path_decoder (struct tar_stat_info *st, char const *arg)
  598. {
  599. assign_string (&st->orig_file_name, arg);
  600. assign_string (&st->file_name, arg);
  601. st->had_trailing_slash = strip_trailing_slashes (st->file_name);
  602. }
  603. static void
  604. size_coder (struct tar_stat_info const *st, char const *keyword,
  605. struct xheader *xhdr, void *data)
  606. {
  607. code_num (st->stat.st_size, keyword, xhdr);
  608. }
  609. static void
  610. size_decoder (struct tar_stat_info *st, char const *arg)
  611. {
  612. uintmax_t u;
  613. if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
  614. st->stat.st_size = u;
  615. }
  616. static void
  617. uid_coder (struct tar_stat_info const *st, char const *keyword,
  618. struct xheader *xhdr, void *data)
  619. {
  620. code_num (st->stat.st_uid, keyword, xhdr);
  621. }
  622. static void
  623. uid_decoder (struct tar_stat_info *st, char const *arg)
  624. {
  625. uintmax_t u;
  626. if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
  627. st->stat.st_uid = u;
  628. }
  629. static void
  630. uname_coder (struct tar_stat_info const *st, char const *keyword,
  631. struct xheader *xhdr, void *data)
  632. {
  633. code_string (st->uname, keyword, xhdr);
  634. }
  635. static void
  636. uname_decoder (struct tar_stat_info *st, char const *arg)
  637. {
  638. assign_string (&st->uname, arg);
  639. }
  640. static void
  641. sparse_size_coder (struct tar_stat_info const *st, char const *keyword,
  642. struct xheader *xhdr, void *data)
  643. {
  644. size_coder (st, keyword, xhdr, data);
  645. }
  646. static void
  647. sparse_size_decoder (struct tar_stat_info *st, char const *arg)
  648. {
  649. uintmax_t u;
  650. if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
  651. st->archive_file_size = u;
  652. }
  653. static void
  654. sparse_numblocks_coder (struct tar_stat_info const *st, char const *keyword,
  655. struct xheader *xhdr, void *data)
  656. {
  657. code_num (st->sparse_map_avail, keyword, xhdr);
  658. }
  659. static void
  660. sparse_numblocks_decoder (struct tar_stat_info *st, char const *arg)
  661. {
  662. uintmax_t u;
  663. if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
  664. {
  665. st->sparse_map_size = u;
  666. st->sparse_map = calloc(st->sparse_map_size, sizeof(st->sparse_map[0]));
  667. st->sparse_map_avail = 0;
  668. }
  669. }
  670. static void
  671. sparse_offset_coder (struct tar_stat_info const *st, char const *keyword,
  672. struct xheader *xhdr, void *data)
  673. {
  674. size_t i = *(size_t*)data;
  675. code_num (st->sparse_map[i].offset, keyword, xhdr);
  676. }
  677. static void
  678. sparse_offset_decoder (struct tar_stat_info *st, char const *arg)
  679. {
  680. uintmax_t u;
  681. if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
  682. st->sparse_map[st->sparse_map_avail].offset = u;
  683. }
  684. static void
  685. sparse_numbytes_coder (struct tar_stat_info const *st, char const *keyword,
  686. struct xheader *xhdr, void *data)
  687. {
  688. size_t i = *(size_t*)data;
  689. code_num (st->sparse_map[i].numbytes, keyword, xhdr);
  690. }
  691. static void
  692. sparse_numbytes_decoder (struct tar_stat_info *st, char const *arg)
  693. {
  694. uintmax_t u;
  695. if (xstrtoumax (arg, NULL, 10, &u, "") == LONGINT_OK)
  696. {
  697. if (st->sparse_map_avail == st->sparse_map_size)
  698. {
  699. size_t newsize = st->sparse_map_size *= 2;
  700. st->sparse_map = xrealloc (st->sparse_map,
  701. st->sparse_map_size
  702. * sizeof st->sparse_map[0]);
  703. }
  704. st->sparse_map[st->sparse_map_avail++].numbytes = u;
  705. }
  706. }
  707. struct xhdr_tab const xhdr_tab[] = {
  708. { "atime", atime_coder, atime_decoder },
  709. { "comment", dummy_coder, dummy_decoder },
  710. { "charset", dummy_coder, dummy_decoder },
  711. { "ctime", ctime_coder, ctime_decoder },
  712. { "gid", gid_coder, gid_decoder },
  713. { "gname", gname_coder, gname_decoder },
  714. { "linkpath", linkpath_coder, linkpath_decoder},
  715. { "mtime", mtime_coder, mtime_decoder },
  716. { "path", path_coder, path_decoder },
  717. { "size", size_coder, size_decoder },
  718. { "uid", uid_coder, uid_decoder },
  719. { "uname", uname_coder, uname_decoder },
  720. /* Sparse file handling */
  721. { "GNU.sparse.size", sparse_size_coder, sparse_size_decoder, true },
  722. { "GNU.sparse.numblocks", sparse_numblocks_coder, sparse_numblocks_decoder,
  723. true },
  724. { "GNU.sparse.offset", sparse_offset_coder, sparse_offset_decoder,
  725. true },
  726. { "GNU.sparse.numbytes", sparse_numbytes_coder, sparse_numbytes_decoder,
  727. true },
  728. #if 0 /* GNU private keywords (not yet implemented) */
  729. /* The next directory entry actually contains the names of files
  730. that were in the directory at the time the dump was made.
  731. Supersedes GNUTYPE_DUMPDIR header type. */
  732. { "GNU.dumpdir", dumpdir_coder, dumpdir_decoder },
  733. /* Keeps the tape/volume header. May be present only in the global headers.
  734. Equivalent to GNUTYPE_VOLHDR. */
  735. { "GNU.volume.header", volume_header_coder, volume_header_decoder },
  736. /* These may be present in a first global header of the archive.
  737. They provide the same functionality as GNUTYPE_MULTIVOL header.
  738. The GNU.volume.size keeps the real_s_sizeleft value, which is
  739. otherwise kept in the size field of a multivolume header. The
  740. GNU.volume.offset keeps the offset of the start of this volume,
  741. otherwise kept in oldgnu_header.offset. */
  742. { "GNU.volume.size", volume_size_coder, volume_size_decoder },
  743. { "GNU.volume.offset", volume_offset_coder, volume_offset_decoder },
  744. #endif
  745. { NULL, NULL, NULL }
  746. };