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

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

DEFINITIONS

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

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