xheader.c 27 KB

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