root/src/vfs/tar/tar-xheader.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. strtosysint
  2. locate_handler
  3. keyword_item_run
  4. keyword_item_free
  5. xheader_list_append
  6. xheader_list_destroy
  7. run_override_list
  8. decode_timespec
  9. decode_time
  10. decode_signed_num
  11. decode_num
  12. raw_path_decoder
  13. dummy_decoder
  14. atime_decoder
  15. gid_decoder
  16. gname_decoder
  17. linkpath_decoder
  18. ctime_decoder
  19. mtime_decoder
  20. path_decoder
  21. size_decoder
  22. uid_decoder
  23. uname_decoder
  24. dumpdir_decoder
  25. decode_record
  26. decg
  27. decx
  28. sparse_path_decoder
  29. sparse_major_decoder
  30. sparse_minor_decoder
  31. sparse_size_decoder
  32. sparse_numblocks_decoder
  33. sparse_offset_decoder
  34. sparse_numbytes_decoder
  35. sparse_map_decoder
  36. tar_xheader_decode
  37. tar_xheader_read
  38. tar_xheader_decode_global
  39. tar_xheader_destroy

   1 /*
   2    Virtual File System: GNU Tar file system.
   3 
   4    Copyright (C) 1995-2024
   5    Free Software Foundation, Inc.
   6 
   7    Written by:
   8    Andrew Borodin <aborodin@vmail.ru>, 2023
   9 
  10    This file is part of the Midnight Commander.
  11 
  12    The Midnight Commander is free software: you can redistribute it
  13    and/or modify it under the terms of the GNU General Public License as
  14    published by the Free Software Foundation, either version 3 of the License,
  15    or (at your option) any later version.
  16 
  17    The Midnight Commander is distributed in the hope that it will be useful,
  18    but WITHOUT ANY WARRANTY; without even the implied warranty of
  19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20    GNU General Public License for more details.
  21 
  22    You should have received a copy of the GNU General Public License
  23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  24  */
  25 
  26 /**
  27  * \file
  28  * \brief Source: Virtual File System: GNU Tar file system
  29  */
  30 
  31 #include <config.h>
  32 
  33 #include <ctype.h>              /* isdigit() */
  34 #include <errno.h>
  35 #include <stdlib.h>
  36 #include <string.h>
  37 
  38 #include "lib/global.h"
  39 #include "lib/util.h"           /* MC_PTR_FREE */
  40 
  41 #include "tar-internal.h"
  42 
  43 /*** global variables ****************************************************************************/
  44 
  45 /*** file scope macro definitions ****************************************************************/
  46 
  47 #define XHDR_PROTECTED 0x01
  48 #define XHDR_GLOBAL    0x02
  49 
  50 /*** file scope type declarations ****************************************************************/
  51 
  52 /* General Interface */
  53 
  54 /* Since tar VFS is read-only, inplement decodes only */
  55 /* *INDENT-OFF* */
  56 struct xhdr_tab
  57 {
  58     const char *keyword;
  59     gboolean (*decoder) (struct tar_stat_info * st, const char *keyword, const char *arg, size_t size);
  60     int flags;
  61 };
  62 /* *INDENT-ON* */
  63 
  64 /* Keyword options */
  65 struct keyword_item
  66 {
  67     char *pattern;
  68     char *value;
  69 };
  70 
  71 enum decode_record_status
  72 {
  73     decode_record_ok,
  74     decode_record_finish,
  75     decode_record_fail
  76 };
  77 
  78 /*** forward declarations (file scope functions) *************************************************/
  79 
  80 static gboolean dummy_decoder (struct tar_stat_info *st, const char *keyword, const char *arg,
  81                                size_t size);
  82 static gboolean atime_decoder (struct tar_stat_info *st, const char *keyword, const char *arg,
  83                                size_t size);
  84 static gboolean gid_decoder (struct tar_stat_info *st, const char *keyword, const char *arg,
  85                              size_t size);
  86 #if 0
  87 static gboolean gname_decoder (struct tar_stat_info *st, const char *keyword, const char *arg,
  88                                size_t size);
  89 #endif
  90 static gboolean linkpath_decoder (struct tar_stat_info *st, const char *keyword, const char *arg,
  91                                   size_t size);
  92 static gboolean mtime_decoder (struct tar_stat_info *st, const char *keyword, const char *arg,
  93                                size_t size);
  94 static gboolean ctime_decoder (struct tar_stat_info *st, const char *keyword, const char *arg,
  95                                size_t size);
  96 static gboolean path_decoder (struct tar_stat_info *st, const char *keyword, const char *arg,
  97                               size_t size);
  98 static gboolean size_decoder (struct tar_stat_info *st, const char *keyword, const char *arg,
  99                               size_t size);
 100 static gboolean uid_decoder (struct tar_stat_info *st, const char *keyword, const char *arg,
 101                              size_t size);
 102 #if 0
 103 static gboolean uname_decoder (struct tar_stat_info *st, const char *keyword, const char *arg,
 104                                size_t size);
 105 #endif
 106 static gboolean sparse_path_decoder (struct tar_stat_info *st, const char *keyword, const char *arg,
 107                                      size_t size);
 108 static gboolean sparse_major_decoder (struct tar_stat_info *st, const char *keyword,
 109                                       const char *arg, size_t size);
 110 static gboolean sparse_minor_decoder (struct tar_stat_info *st, const char *keyword,
 111                                       const char *arg, size_t size);
 112 static gboolean sparse_size_decoder (struct tar_stat_info *st, const char *keyword, const char *arg,
 113                                      size_t size);
 114 static gboolean sparse_numblocks_decoder (struct tar_stat_info *st, const char *keyword,
 115                                           const char *arg, size_t size);
 116 static gboolean sparse_offset_decoder (struct tar_stat_info *st, const char *keyword,
 117                                        const char *arg, size_t size);
 118 static gboolean sparse_numbytes_decoder (struct tar_stat_info *st, const char *keyword,
 119                                          const char *arg, size_t size);
 120 static gboolean sparse_map_decoder (struct tar_stat_info *st, const char *keyword, const char *arg,
 121                                     size_t size);
 122 static gboolean dumpdir_decoder (struct tar_stat_info *st, const char *keyword, const char *arg,
 123                                  size_t size);
 124 
 125 /*** file scope variables ************************************************************************/
 126 
 127 enum
 128 {
 129     BILLION = 1000000000,
 130     LOG10_BILLION = 9
 131 };
 132 
 133 /* *INDENT-OFF* */
 134 static struct xhdr_tab xhdr_tab[] =
 135 {
 136     { "atime",                atime_decoder,            0  },
 137     { "comment",              dummy_decoder,            0  },
 138     { "charset",              dummy_decoder,            0  },
 139     { "ctime",                ctime_decoder,            0  },
 140     { "gid",                  gid_decoder,              0  },
 141 #if 0
 142     { "gname",                gname_decoder,            0  },
 143 #endif
 144     { "linkpath",             linkpath_decoder,         0  },
 145     { "mtime",                mtime_decoder,            0  },
 146     { "path",                 path_decoder,             0  },
 147     { "size",                 size_decoder,             0  },
 148     { "uid",                  uid_decoder,              0  },
 149 #if 0
 150     { "uname",                uname_decoder,            0  },
 151 #endif
 152 
 153     /* Sparse file handling */
 154     { "GNU.sparse.name",      sparse_path_decoder,      XHDR_PROTECTED },
 155     { "GNU.sparse.major",     sparse_major_decoder,     XHDR_PROTECTED },
 156     { "GNU.sparse.minor",     sparse_minor_decoder,     XHDR_PROTECTED },
 157     { "GNU.sparse.realsize",  sparse_size_decoder,      XHDR_PROTECTED },
 158     { "GNU.sparse.numblocks", sparse_numblocks_decoder, XHDR_PROTECTED },
 159 
 160     { "GNU.sparse.size",      sparse_size_decoder,      XHDR_PROTECTED },
 161     /* tar 1.14 - 1.15.1 keywords. Multiple instances of these appeared in 'x'
 162        headers, and each of them was meaningful. It confilcted with POSIX specs,
 163        which requires that "when extended header records conflict, the last one
 164        given in the header shall take precedence." */
 165     { "GNU.sparse.offset",    sparse_offset_decoder,    XHDR_PROTECTED },
 166     { "GNU.sparse.numbytes",  sparse_numbytes_decoder,  XHDR_PROTECTED },
 167     /* tar 1.15.90 keyword, introduced to remove the above-mentioned conflict. */
 168     { "GNU.sparse.map",       sparse_map_decoder,       0 },
 169 
 170     { "GNU.dumpdir",          dumpdir_decoder,          XHDR_PROTECTED },
 171 
 172     { NULL,                   NULL,                     0 }
 173 };
 174 /* *INDENT-ON* */
 175 
 176 /* List of keyword/value pairs decoded from the last 'g' type header */
 177 static GSList *global_header_override_list = NULL;
 178 
 179 /* --------------------------------------------------------------------------------------------- */
 180 /*** file scope functions ************************************************************************/
 181 /* --------------------------------------------------------------------------------------------- */
 182 
 183 /* Convert a prefix of the string @arg to a system integer type whose minimum value is @minval
 184    and maximum @maxval. If @minval is negative, negative integers @minval .. -1 are assumed
 185    to be represented using leading '-' in the usual way. If the represented value exceeds INTMAX_MAX,
 186    return a negative integer V such that (uintmax_t) V yields the represented value. If @arglim is
 187    nonnull, store into *@arglim a pointer to the first character after the prefix.
 188 
 189    This is the inverse of sysinttostr.
 190 
 191    On a normal return, set errno = 0.
 192    On conversion error, return 0 and set errno = EINVAL.
 193    On overflow, return an extreme value and set errno = ERANGE.
 194  */
 195 #if ! (INTMAX_MAX <= UINTMAX_MAX)
 196 #error "strtosysint: nonnegative intmax_t does not fit in uintmax_t"
 197 #endif
 198 static intmax_t
 199 strtosysint (const char *arg, char **arglim, intmax_t minval, uintmax_t maxval)
     /* [previous][next][first][last][top][bottom][index][help]  */
 200 {
 201     errno = 0;
 202 
 203     if (maxval <= INTMAX_MAX)
 204     {
 205         if (isdigit (arg[*arg == '-' ? 1 : 0]))
 206         {
 207             gint64 i;
 208 
 209             i = g_ascii_strtoll (arg, arglim, 10);
 210             if ((gint64) minval <= i && i <= (gint64) maxval)
 211                 return (intmax_t) i;
 212 
 213             errno = ERANGE;
 214             return i < (gint64) minval ? minval : (intmax_t) maxval;
 215         }
 216     }
 217     else
 218     {
 219         if (isdigit (*arg))
 220         {
 221             guint64 i;
 222 
 223             i = g_ascii_strtoull (arg, arglim, 10);
 224             if (i <= (guint64) maxval)
 225                 return tar_represent_uintmax ((uintmax_t) i);
 226 
 227             errno = ERANGE;
 228             return maxval;
 229         }
 230     }
 231 
 232     errno = EINVAL;
 233     return 0;
 234 }
 235 
 236 /* --------------------------------------------------------------------------------------------- */
 237 
 238 static struct xhdr_tab *
 239 locate_handler (const char *keyword)
     /* [previous][next][first][last][top][bottom][index][help]  */
 240 {
 241     struct xhdr_tab *p;
 242 
 243     for (p = xhdr_tab; p->keyword != NULL; p++)
 244         if (strcmp (p->keyword, keyword) == 0)
 245             return p;
 246 
 247     return NULL;
 248 }
 249 
 250 /* --------------------------------------------------------------------------------------------- */
 251 
 252 static gboolean
 253 keyword_item_run (gpointer data, gpointer user_data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 254 {
 255     struct keyword_item *kp = (struct keyword_item *) data;
 256     struct tar_stat_info *st = (struct tar_stat_info *) user_data;
 257     struct xhdr_tab const *t;
 258 
 259     t = locate_handler (kp->pattern);
 260     if (t != NULL)
 261         return t->decoder (st, t->keyword, kp->value, strlen (kp->value));
 262 
 263     return TRUE;                /* FIXME */
 264 }
 265 
 266 /* --------------------------------------------------------------------------------------------- */
 267 
 268 static void
 269 keyword_item_free (gpointer data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 270 {
 271     struct keyword_item *kp = (struct keyword_item *) data;
 272 
 273     g_free (kp->pattern);
 274     g_free (kp->value);
 275     g_free (kp);
 276 }
 277 
 278 /* --------------------------------------------------------------------------------------------- */
 279 
 280 static void
 281 xheader_list_append (GSList ** root, const char *kw, const char *value)
     /* [previous][next][first][last][top][bottom][index][help]  */
 282 {
 283     struct keyword_item *kp;
 284 
 285     kp = g_new (struct keyword_item, 1);
 286     kp->pattern = g_strdup (kw);
 287     kp->value = g_strdup (value);
 288     *root = g_slist_prepend (*root, kp);
 289 }
 290 
 291 /* --------------------------------------------------------------------------------------------- */
 292 
 293 static inline void
 294 xheader_list_destroy (GSList ** root)
     /* [previous][next][first][last][top][bottom][index][help]  */
 295 {
 296     g_slist_free_full (*root, keyword_item_free);
 297     *root = NULL;
 298 }
 299 
 300 /* --------------------------------------------------------------------------------------------- */
 301 
 302 static inline void
 303 run_override_list (GSList * kp, struct tar_stat_info *st)
     /* [previous][next][first][last][top][bottom][index][help]  */
 304 {
 305     g_slist_foreach (kp, (GFunc) keyword_item_run, st);
 306 }
 307 
 308 /* --------------------------------------------------------------------------------------------- */
 309 
 310 static struct timespec
 311 decode_timespec (const char *arg, char **arg_lim, gboolean parse_fraction)
     /* [previous][next][first][last][top][bottom][index][help]  */
 312 {
 313     time_t s = TYPE_MINIMUM (time_t);
 314     int ns = -1;
 315     const char *p = arg;
 316     gboolean negative = *arg == '-';
 317     struct timespec r;
 318 
 319     if (!isdigit (arg[negative]))
 320         errno = EINVAL;
 321     else
 322     {
 323         errno = 0;
 324 
 325         if (negative)
 326         {
 327             gint64 i;
 328 
 329             i = g_ascii_strtoll (arg, arg_lim, 10);
 330             if (TYPE_SIGNED (time_t) ? TYPE_MINIMUM (time_t) <= i : 0 <= i)
 331                 s = (intmax_t) i;
 332             else
 333                 errno = ERANGE;
 334         }
 335         else
 336         {
 337             guint64 i;
 338 
 339             i = g_ascii_strtoull (arg, arg_lim, 10);
 340             if (i <= TYPE_MAXIMUM (time_t))
 341                 s = (uintmax_t) i;
 342             else
 343                 errno = ERANGE;
 344         }
 345 
 346         p = *arg_lim;
 347         ns = 0;
 348 
 349         if (parse_fraction && *p == '.')
 350         {
 351             int digits = 0;
 352             gboolean trailing_nonzero = FALSE;
 353 
 354             while (isdigit (*++p))
 355                 if (digits < LOG10_BILLION)
 356                 {
 357                     digits++;
 358                     ns = 10 * ns + (*p - '0');
 359                 }
 360                 else if (*p != '0')
 361                     trailing_nonzero = TRUE;
 362 
 363             while (digits < LOG10_BILLION)
 364             {
 365                 digits++;
 366                 ns *= 10;
 367             }
 368 
 369             if (negative)
 370             {
 371                 /* Convert "-1.10000000000001" to s == -2, ns == 89999999.
 372                    I.e., truncate time stamps towards minus infinity while
 373                    converting them to internal form.  */
 374                 if (trailing_nonzero)
 375                     ns++;
 376                 if (ns != 0)
 377                 {
 378                     if (s == TYPE_MINIMUM (time_t))
 379                         ns = -1;
 380                     else
 381                     {
 382                         s--;
 383                         ns = BILLION - ns;
 384                     }
 385                 }
 386             }
 387         }
 388 
 389         if (errno == ERANGE)
 390             ns = -1;
 391     }
 392 
 393     *arg_lim = (char *) p;
 394     r.tv_sec = s;
 395     r.tv_nsec = ns;
 396     return r;
 397 }
 398 
 399 /* --------------------------------------------------------------------------------------------- */
 400 
 401 static gboolean
 402 decode_time (struct timespec *ts, const char *arg, const char *keyword)
     /* [previous][next][first][last][top][bottom][index][help]  */
 403 {
 404     char *arg_lim;
 405     struct timespec t;
 406 
 407     (void) keyword;
 408 
 409     t = decode_timespec (arg, &arg_lim, TRUE);
 410 
 411     if (t.tv_nsec < 0)
 412         /* Malformed extended header */
 413         return FALSE;
 414 
 415     if (*arg_lim != '\0')
 416         /* Malformed extended header */
 417         return FALSE;
 418 
 419     *ts = t;
 420 
 421     return TRUE;
 422 }
 423 
 424 /* --------------------------------------------------------------------------------------------- */
 425 
 426 static gboolean
 427 decode_signed_num (intmax_t * num, const char *arg, intmax_t minval, uintmax_t maxval,
     /* [previous][next][first][last][top][bottom][index][help]  */
 428                    const char *keyword)
 429 {
 430     char *arg_lim;
 431     intmax_t u;
 432 
 433     (void) keyword;
 434 
 435     if (!isdigit (*arg))
 436         return FALSE;           /* malformed extended header */
 437 
 438     u = strtosysint (arg, &arg_lim, minval, maxval);
 439 
 440     if (errno == EINVAL || *arg_lim != '\0')
 441         return FALSE;           /* malformed extended header */
 442 
 443     if (errno == ERANGE)
 444         return FALSE;           /* out of range */
 445 
 446     *num = u;
 447     return TRUE;
 448 }
 449 
 450 /* --------------------------------------------------------------------------------------------- */
 451 
 452 static gboolean
 453 decode_num (uintmax_t * num, const char *arg, uintmax_t maxval, const char *keyword)
     /* [previous][next][first][last][top][bottom][index][help]  */
 454 {
 455     intmax_t i;
 456 
 457     if (!decode_signed_num (&i, arg, 0, maxval, keyword))
 458         return FALSE;
 459 
 460     *num = i;
 461     return TRUE;
 462 }
 463 
 464 /* --------------------------------------------------------------------------------------------- */
 465 
 466 static gboolean
 467 raw_path_decoder (struct tar_stat_info *st, const char *arg)
     /* [previous][next][first][last][top][bottom][index][help]  */
 468 {
 469     if (*arg != '\0')
 470     {
 471         tar_assign_string_dup (&st->orig_file_name, arg);
 472         tar_assign_string_dup (&st->file_name, arg);
 473     }
 474 
 475     return TRUE;
 476 }
 477 
 478 /* --------------------------------------------------------------------------------------------- */
 479 
 480 static gboolean
 481 dummy_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 482 {
 483     (void) st;
 484     (void) keyword;
 485     (void) arg;
 486     (void) size;
 487 
 488     return TRUE;
 489 }
 490 
 491 /* --------------------------------------------------------------------------------------------- */
 492 
 493 static gboolean
 494 atime_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 495 {
 496     struct timespec ts;
 497 
 498     (void) size;
 499 
 500     if (!decode_time (&ts, arg, keyword))
 501         return FALSE;
 502 
 503     st->atime = ts;
 504     return TRUE;
 505 }
 506 
 507 /* --------------------------------------------------------------------------------------------- */
 508 
 509 static gboolean
 510 gid_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 511 {
 512     intmax_t u;
 513 
 514     (void) size;
 515 
 516     if (!decode_signed_num (&u, arg, TYPE_MINIMUM (gid_t), TYPE_MINIMUM (gid_t), keyword))
 517         return FALSE;
 518 
 519     st->stat.st_gid = u;
 520     return TRUE;
 521 }
 522 
 523 /* --------------------------------------------------------------------------------------------- */
 524 
 525 #if 0
 526 static gboolean
 527 gname_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 528 {
 529     (void) keyword;
 530     (void) size;
 531 
 532     tar_assign_string_dup (&st->gname, arg);
 533     return TRUE;
 534 }
 535 #endif
 536 
 537 /* --------------------------------------------------------------------------------------------- */
 538 
 539 static gboolean
 540 linkpath_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 541 {
 542     (void) keyword;
 543     (void) size;
 544 
 545     tar_assign_string_dup (&st->link_name, arg);
 546     return TRUE;
 547 }
 548 
 549 /* --------------------------------------------------------------------------------------------- */
 550 
 551 static gboolean
 552 ctime_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 553 {
 554     struct timespec ts;
 555 
 556     (void) size;
 557 
 558     if (!decode_time (&ts, arg, keyword))
 559         return FALSE;
 560 
 561     st->ctime = ts;
 562     return TRUE;
 563 }
 564 
 565 /* --------------------------------------------------------------------------------------------- */
 566 
 567 static gboolean
 568 mtime_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 569 {
 570     struct timespec ts;
 571 
 572     (void) size;
 573 
 574     if (!decode_time (&ts, arg, keyword))
 575         return FALSE;
 576 
 577     st->mtime = ts;
 578     return TRUE;
 579 }
 580 
 581 /* --------------------------------------------------------------------------------------------- */
 582 
 583 static gboolean
 584 path_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 585 {
 586     (void) keyword;
 587     (void) size;
 588 
 589     if (!st->sparse_name_done)
 590         return raw_path_decoder (st, arg);
 591 
 592     return TRUE;                /* FIXME */
 593 }
 594 
 595 /* --------------------------------------------------------------------------------------------- */
 596 
 597 static gboolean
 598 size_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 599 {
 600     uintmax_t u;
 601 
 602     (void) size;
 603 
 604     if (!decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
 605         return FALSE;
 606 
 607     st->stat.st_size = u;
 608     return TRUE;
 609 }
 610 
 611 /* --------------------------------------------------------------------------------------------- */
 612 
 613 static gboolean
 614 uid_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 615 {
 616     intmax_t u;
 617 
 618     (void) size;
 619 
 620     if (!decode_signed_num (&u, arg, TYPE_MINIMUM (uid_t), TYPE_MAXIMUM (uid_t), keyword))
 621         return FALSE;
 622 
 623     st->stat.st_uid = u;
 624     return TRUE;
 625 }
 626 
 627 /* --------------------------------------------------------------------------------------------- */
 628 
 629 #if 0
 630 static gboolean
 631 uname_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 632 {
 633     (void) keyword;
 634     (void) size;
 635 
 636     tar_assign_string_dup (&st->uname, arg);
 637     return TRUE;
 638 }
 639 #endif
 640 
 641 /* --------------------------------------------------------------------------------------------- */
 642 
 643 static gboolean
 644 dumpdir_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 645 {
 646     (void) keyword;
 647 
 648 #if GLIB_CHECK_VERSION (2, 68, 0)
 649     st->dumpdir = g_memdup2 (arg, size);
 650 #else
 651     st->dumpdir = g_memdup (arg, size);
 652 #endif
 653     return TRUE;
 654 }
 655 
 656 /* --------------------------------------------------------------------------------------------- */
 657 
 658 /**
 659  * Decodes a single extended header record, advancing @ptr to the next record.
 660  *
 661  * @param p pointer to extended header record
 662  * @param st stat info
 663  *
 664  * @return decode_record_ok or decode_record_finish on success, decode_record_fail otherwize
 665  */
 666 static enum decode_record_status
 667 decode_record (struct xheader *xhdr, char **ptr,
     /* [previous][next][first][last][top][bottom][index][help]  */
 668                gboolean (*handler) (void *data, const char *keyword, const char *value,
 669                                     size_t size), void *data)
 670 {
 671     char *start = *ptr;
 672     char *p = start;
 673     size_t len;
 674     char *len_lim;
 675     const char *keyword;
 676     char *nextp;
 677     size_t len_max;
 678     gboolean ret;
 679 
 680     len_max = xhdr->buffer + xhdr->size - start;
 681 
 682     while (*p == ' ' || *p == '\t')
 683         p++;
 684 
 685     if (!isdigit (*p))
 686         return (*p != '\0' ? decode_record_fail : decode_record_finish);
 687 
 688     len = (uintmax_t) g_ascii_strtoull (p, &len_lim, 10);
 689     if (len_max < len)
 690         return decode_record_fail;
 691 
 692     nextp = start + len;
 693 
 694     for (p = len_lim; *p == ' ' || *p == '\t'; p++)
 695         ;
 696 
 697     if (p == len_lim)
 698         return decode_record_fail;
 699 
 700     keyword = p;
 701     p = strchr (p, '=');
 702     if (!(p != NULL && p < nextp))
 703         return decode_record_fail;
 704 
 705     if (nextp[-1] != '\n')
 706         return decode_record_fail;
 707 
 708     *p = nextp[-1] = '\0';
 709     ret = handler (data, keyword, p + 1, nextp - p - 2);        /* '=' + trailing '\n' */
 710     *p = '=';
 711     nextp[-1] = '\n';
 712     *ptr = nextp;
 713 
 714     return (ret ? decode_record_ok : decode_record_fail);
 715 }
 716 
 717 /* --------------------------------------------------------------------------------------------- */
 718 
 719 static gboolean
 720 decg (void *data, const char *keyword, const char *value, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 721 {
 722     GSList **kwl = (GSList **) data;
 723     struct xhdr_tab const *tab;
 724 
 725     (void) size;
 726 
 727     tab = locate_handler (keyword);
 728     if (tab != NULL && (tab->flags & XHDR_GLOBAL) != 0)
 729     {
 730         if (!tab->decoder (data, keyword, value, size))
 731             return FALSE;
 732     }
 733     else
 734         xheader_list_append (kwl, keyword, value);
 735 
 736     return TRUE;
 737 }
 738 
 739 /* --------------------------------------------------------------------------------------------- */
 740 
 741 static gboolean
 742 decx (void *data, const char *keyword, const char *value, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 743 {
 744     struct keyword_item kp = {
 745         .pattern = (char *) keyword,
 746         .value = (char *) value
 747     };
 748 
 749     (void) size;
 750 
 751     return keyword_item_run (&kp, data);
 752 }
 753 
 754 /* --------------------------------------------------------------------------------------------- */
 755 
 756 static gboolean
 757 sparse_path_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 758 {
 759     (void) keyword;
 760     (void) size;
 761 
 762     st->sparse_name_done = TRUE;
 763     return raw_path_decoder (st, arg);
 764 }
 765 
 766 /* --------------------------------------------------------------------------------------------- */
 767 
 768 static gboolean
 769 sparse_major_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 770 {
 771     uintmax_t u;
 772 
 773     (void) size;
 774 
 775     if (!decode_num (&u, arg, TYPE_MAXIMUM (unsigned), keyword))
 776           return FALSE;
 777 
 778     st->sparse_major = u;
 779     return TRUE;
 780 }
 781 
 782 /* --------------------------------------------------------------------------------------------- */
 783 
 784 static gboolean
 785 sparse_minor_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 786 {
 787     uintmax_t u;
 788 
 789     (void) size;
 790 
 791     if (!decode_num (&u, arg, TYPE_MAXIMUM (unsigned), keyword))
 792           return FALSE;
 793 
 794     st->sparse_minor = u;
 795     return TRUE;
 796 }
 797 
 798 /* --------------------------------------------------------------------------------------------- */
 799 
 800 static gboolean
 801 sparse_size_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 802 {
 803     uintmax_t u;
 804 
 805     (void) size;
 806 
 807     if (!decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
 808         return FALSE;
 809 
 810     st->real_size_set = TRUE;
 811     st->real_size = u;
 812     return TRUE;
 813 }
 814 
 815 /* --------------------------------------------------------------------------------------------- */
 816 
 817 static gboolean
 818 sparse_numblocks_decoder (struct tar_stat_info *st, const char *keyword, const char *arg,
     /* [previous][next][first][last][top][bottom][index][help]  */
 819                           size_t size)
 820 {
 821     uintmax_t u;
 822 
 823     (void) size;
 824 
 825     if (!decode_num (&u, arg, SIZE_MAX, keyword))
 826         return FALSE;
 827 
 828     if (st->sparse_map == NULL)
 829         st->sparse_map = g_array_sized_new (FALSE, FALSE, sizeof (struct sp_array), u);
 830     else
 831         g_array_set_size (st->sparse_map, u);
 832 
 833     return TRUE;
 834 }
 835 
 836 /* --------------------------------------------------------------------------------------------- */
 837 
 838 static gboolean
 839 sparse_offset_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 840 {
 841     uintmax_t u;
 842     struct sp_array *s;
 843 
 844     (void) size;
 845 
 846     if (!decode_num (&u, arg, TYPE_MAXIMUM (off_t), keyword))
 847         return FALSE;
 848 
 849     s = &g_array_index (st->sparse_map, struct sp_array, st->sparse_map->len - 1);
 850     s->offset = u;
 851     return TRUE;
 852 }
 853 
 854 /* --------------------------------------------------------------------------------------------- */
 855 
 856 static gboolean
 857 sparse_numbytes_decoder (struct tar_stat_info *st, const char *keyword, const char *arg,
     /* [previous][next][first][last][top][bottom][index][help]  */
 858                          size_t size)
 859 {
 860     uintmax_t u;
 861     struct sp_array s;
 862 
 863     (void) size;
 864 
 865     if (!decode_num (&u, arg, SIZE_MAX, keyword))
 866         return FALSE;
 867 
 868     s.offset = 0;
 869     s.numbytes = u;
 870     g_array_append_val (st->sparse_map, s);
 871     return TRUE;
 872 }
 873 
 874 /* --------------------------------------------------------------------------------------------- */
 875 
 876 static gboolean
 877 sparse_map_decoder (struct tar_stat_info *st, const char *keyword, const char *arg, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 878 {
 879     gboolean offset = TRUE;
 880     struct sp_array e;
 881 
 882     (void) keyword;
 883     (void) size;
 884 
 885     if (st->sparse_map != NULL)
 886         g_array_set_size (st->sparse_map, 0);
 887 
 888     while (TRUE)
 889     {
 890         gint64 u;
 891         char *delim;
 892 
 893         if (!isdigit (*arg))
 894         {
 895             /* malformed extended header */
 896             return FALSE;
 897         }
 898 
 899         errno = 0;
 900         u = g_ascii_strtoll (arg, &delim, 10);
 901         if (TYPE_MAXIMUM (off_t) < u)
 902         {
 903             u = TYPE_MAXIMUM (off_t);
 904             errno = ERANGE;
 905         }
 906         if (offset)
 907         {
 908             e.offset = u;
 909             if (errno == ERANGE)
 910             {
 911                 /* out of range */
 912                 return FALSE;
 913             }
 914         }
 915         else
 916         {
 917             e.numbytes = u;
 918             if (errno == ERANGE)
 919             {
 920                 /* out of range */
 921                 return FALSE;
 922             }
 923 
 924             g_array_append_val (st->sparse_map, e);
 925         }
 926 
 927         offset = !offset;
 928 
 929         if (*delim == '\0')
 930             break;
 931         if (*delim != ',')
 932         {
 933             /* malformed extended header */
 934             return FALSE;
 935         }
 936 
 937         arg = delim + 1;
 938     }
 939 
 940     if (!offset)
 941     {
 942         /* malformed extended header */
 943         return FALSE;
 944     }
 945 
 946     return TRUE;
 947 }
 948 
 949 /* --------------------------------------------------------------------------------------------- */
 950 /*** public functions ****************************************************************************/
 951 /* --------------------------------------------------------------------------------------------- */
 952 
 953 /**
 954  * Decodes an extended header.
 955  *
 956  * @param st stat info
 957  *
 958  * @return TRUE on success, FALSE otherwize
 959  */
 960 gboolean
 961 tar_xheader_decode (struct tar_stat_info * st)
     /* [previous][next][first][last][top][bottom][index][help]  */
 962 {
 963     char *p;
 964     enum decode_record_status status;
 965 
 966     run_override_list (global_header_override_list, st);
 967 
 968     p = st->xhdr.buffer + BLOCKSIZE;
 969 
 970     while ((status = decode_record (&st->xhdr, &p, decx, st)) == decode_record_ok)
 971         ;
 972 
 973     if (status == decode_record_fail)
 974         return FALSE;
 975 
 976     /* The archived (effective) file size is always set directly in tar header
 977        field, possibly overridden by "size" extended header - in both cases,
 978        result is now decoded in st->stat.st_size */
 979     st->archive_file_size = st->stat.st_size;
 980 
 981     /* The real file size (given by stat()) may be redefined for sparse
 982        files in "GNU.sparse.realsize" extended header */
 983     if (st->real_size_set)
 984         st->stat.st_size = st->real_size;
 985 
 986     return TRUE;
 987 }
 988 
 989 /* --------------------------------------------------------------------------------------------- */
 990 
 991 gboolean
 992 tar_xheader_read (tar_super_t * archive, struct xheader * xhdr, union block * p, off_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 993 {
 994     size_t j = 0;
 995 
 996     size = MAX (0, size);
 997     size += BLOCKSIZE;
 998 
 999     xhdr->size = size;
1000     xhdr->buffer = g_malloc (size + 1);
1001     xhdr->buffer[size] = '\0';
1002 
1003     do
1004     {
1005         size_t len;
1006 
1007         if (p == NULL)
1008             return FALSE;       /* Unexpected EOF in archive */
1009 
1010         len = MIN (size, BLOCKSIZE);
1011 
1012         memcpy (xhdr->buffer + j, p->buffer, len);
1013         tar_set_next_block_after (p);
1014         p = tar_find_next_block (archive);
1015 
1016         j += len;
1017         size -= len;
1018     }
1019     while (size > 0);
1020 
1021     return TRUE;
1022 }
1023 
1024 /* --------------------------------------------------------------------------------------------- */
1025 
1026 gboolean
1027 tar_xheader_decode_global (struct xheader * xhdr)
     /* [previous][next][first][last][top][bottom][index][help]  */
1028 {
1029     char *p;
1030     gboolean ret;
1031 
1032     p = xhdr->buffer + BLOCKSIZE;
1033 
1034     xheader_list_destroy (&global_header_override_list);
1035 
1036     while ((ret = decode_record (xhdr, &p, decg, &global_header_override_list)) == decode_record_ok)
1037         ;
1038 
1039     return (ret == decode_record_finish);
1040 }
1041 
1042 /* --------------------------------------------------------------------------------------------- */
1043 
1044 void
1045 tar_xheader_destroy (struct xheader *xhdr)
     /* [previous][next][first][last][top][bottom][index][help]  */
1046 {
1047     MC_PTR_FREE (xhdr->buffer);
1048     xhdr->size = 0;
1049 }
1050 
1051 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */