2 Virtual File System: GNU Tar file system.
4 Copyright (C) 1995-2024
5 Free Software Foundation, Inc.
8 Andrew Borodin <aborodin@vmail.ru>, 2023
10 This file is part of the Midnight Commander.
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.
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.
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/>.
28 * \brief Source: Virtual File System: GNU Tar file system
33 #include <ctype.h> /* isdigit() */
37 #include "lib/global.h"
38 #include "lib/util.h" /* MC_PTR_FREE */
40 #include "tar-internal.h"
42 /*** global variables ****************************************************************************/
44 /*** file scope macro definitions ****************************************************************/
46 #define XHDR_PROTECTED 0x01
47 #define XHDR_GLOBAL 0x02
49 /*** file scope type declarations ****************************************************************/
51 /* General Interface */
53 /* Since tar VFS is read-only, inplement decodes only */
58 gboolean (*decoder
) (struct tar_stat_info
* st
, const char *keyword
, const char *arg
, size_t size
);
70 enum decode_record_status
77 /*** forward declarations (file scope functions) *************************************************/
79 static gboolean
dummy_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
,
81 static gboolean
atime_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
,
83 static gboolean
gid_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
,
86 static gboolean
gname_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
,
89 static gboolean
linkpath_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
,
91 static gboolean
mtime_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
,
93 static gboolean
ctime_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
,
95 static gboolean
path_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
,
97 static gboolean
size_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
,
99 static gboolean
uid_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
,
102 static gboolean
uname_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
,
105 static gboolean
sparse_path_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
,
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
,
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
,
121 static gboolean
dumpdir_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
,
124 /*** file scope variables ************************************************************************/
128 BILLION
= 1000000000,
133 static struct xhdr_tab xhdr_tab
[] =
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 },
141 { "gname", gname_decoder
, 0 },
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 },
149 { "uname", uname_decoder
, 0 },
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
},
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 },
169 { "GNU.dumpdir", dumpdir_decoder
, XHDR_PROTECTED
},
175 /* List of keyword/value pairs decoded from the last 'g' type header */
176 static GSList
*global_header_override_list
= NULL
;
178 /* --------------------------------------------------------------------------------------------- */
179 /*** file scope functions ************************************************************************/
180 /* --------------------------------------------------------------------------------------------- */
182 static struct xhdr_tab
*
183 locate_handler (const char *keyword
)
187 for (p
= xhdr_tab
; p
->keyword
!= NULL
; p
++)
188 if (strcmp (p
->keyword
, keyword
) == 0)
194 /* --------------------------------------------------------------------------------------------- */
197 keyword_item_run (gpointer data
, gpointer user_data
)
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
;
203 t
= locate_handler (kp
->pattern
);
205 return t
->decoder (st
, t
->keyword
, kp
->value
, strlen (kp
->value
));
207 return TRUE
; /* FIXME */
210 /* --------------------------------------------------------------------------------------------- */
213 keyword_item_free (gpointer data
)
215 struct keyword_item
*kp
= (struct keyword_item
*) data
;
217 g_free (kp
->pattern
);
222 /* --------------------------------------------------------------------------------------------- */
225 xheader_list_append (GSList
**root
, const char *kw
, const char *value
)
227 struct keyword_item
*kp
;
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
);
235 /* --------------------------------------------------------------------------------------------- */
238 xheader_list_destroy (GSList
**root
)
240 g_slist_free_full (*root
, keyword_item_free
);
244 /* --------------------------------------------------------------------------------------------- */
247 run_override_list (GSList
*kp
, struct tar_stat_info
*st
)
249 g_slist_foreach (kp
, (GFunc
) keyword_item_run
, st
);
252 /* --------------------------------------------------------------------------------------------- */
254 static struct timespec
255 decode_timespec (const char *arg
, char **arg_lim
, gboolean parse_fraction
)
260 char const *p
= *arg_lim
;
263 s
= stoint (arg
, arg_lim
, &overflow
, TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t));
269 if (parse_fraction
&& *p
== '.')
272 gboolean trailing_nonzero
= FALSE
;
274 while (isdigit (*++p
))
275 if (digits
< LOG10_BILLION
)
278 ns
= 10 * ns
+ (*p
- '0');
281 trailing_nonzero
= TRUE
;
283 *arg_lim
= (char *) p
;
285 while (digits
< LOG10_BILLION
)
293 /* Convert "-1.10000000000001" to s == -2, ns == 89999999.
294 I.e., truncate time stamps towards minus infinity while
295 converting them to internal form. */
296 if (trailing_nonzero
)
299 ns
= ckd_sub (&s
, s
, 1) ? -1 : BILLION
- ns
;
312 /* --------------------------------------------------------------------------------------------- */
315 decode_time (struct timespec
*ts
, const char *arg
, const char *keyword
)
322 t
= decode_timespec (arg
, &arg_lim
, TRUE
);
325 /* Malformed extended header */
328 if (*arg_lim
!= '\0')
329 /* Malformed extended header */
337 /* --------------------------------------------------------------------------------------------- */
340 decode_signed_num (intmax_t *num
, const char *arg
, intmax_t minval
, uintmax_t maxval
,
349 u
= stoint (arg
, &arg_lim
, &overflow
, minval
, maxval
);
351 if (arg_lim
== arg
|| *arg_lim
!= '\0')
352 return FALSE
; /* malformed extended header */
355 return FALSE
; /* out of range */
361 /* --------------------------------------------------------------------------------------------- */
364 decode_num (uintmax_t *num
, const char *arg
, uintmax_t maxval
, const char *keyword
)
368 if (!decode_signed_num (&i
, arg
, 0, maxval
, keyword
))
375 /* --------------------------------------------------------------------------------------------- */
378 raw_path_decoder (struct tar_stat_info
*st
, const char *arg
)
382 tar_assign_string_dup (&st
->orig_file_name
, arg
);
383 tar_assign_string_dup (&st
->file_name
, arg
);
389 /* --------------------------------------------------------------------------------------------- */
392 dummy_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
402 /* --------------------------------------------------------------------------------------------- */
405 atime_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
411 if (!decode_time (&ts
, arg
, keyword
))
418 /* --------------------------------------------------------------------------------------------- */
421 gid_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
427 if (!decode_signed_num (&u
, arg
, TYPE_MINIMUM (gid_t
), TYPE_MINIMUM (gid_t
), keyword
))
434 /* --------------------------------------------------------------------------------------------- */
438 gname_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
443 tar_assign_string_dup (&st
->gname
, arg
);
448 /* --------------------------------------------------------------------------------------------- */
451 linkpath_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
456 tar_assign_string_dup (&st
->link_name
, arg
);
460 /* --------------------------------------------------------------------------------------------- */
463 ctime_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
469 if (!decode_time (&ts
, arg
, keyword
))
476 /* --------------------------------------------------------------------------------------------- */
479 mtime_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
485 if (!decode_time (&ts
, arg
, keyword
))
492 /* --------------------------------------------------------------------------------------------- */
495 path_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
500 if (!st
->sparse_name_done
)
501 return raw_path_decoder (st
, arg
);
503 return TRUE
; /* FIXME */
506 /* --------------------------------------------------------------------------------------------- */
509 size_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
515 if (!decode_num (&u
, arg
, TYPE_MAXIMUM (off_t
), keyword
))
518 st
->stat
.st_size
= u
;
522 /* --------------------------------------------------------------------------------------------- */
525 uid_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
531 if (!decode_signed_num (&u
, arg
, TYPE_MINIMUM (uid_t
), TYPE_MAXIMUM (uid_t
), keyword
))
538 /* --------------------------------------------------------------------------------------------- */
542 uname_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
547 tar_assign_string_dup (&st
->uname
, arg
);
552 /* --------------------------------------------------------------------------------------------- */
555 dumpdir_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
559 #if GLIB_CHECK_VERSION (2, 68, 0)
560 st
->dumpdir
= g_memdup2 (arg
, size
);
562 st
->dumpdir
= g_memdup (arg
, size
);
567 /* --------------------------------------------------------------------------------------------- */
570 * Decodes a single extended header record, advancing @ptr to the next record.
572 * @param p pointer to extended header record
573 * @param st stat info
575 * @return decode_record_ok or decode_record_finish on success, decode_record_fail otherwize
577 static enum decode_record_status
578 decode_record (struct xheader
*xhdr
, char **ptr
,
579 gboolean (*handler
) (void *data
, const char *keyword
, const char *value
,
580 size_t size
), void *data
)
591 len_max
= xhdr
->buffer
+ xhdr
->size
- start
;
593 while (*p
== ' ' || *p
== '\t')
596 len
= stoint (p
, &len_lim
, NULL
, 0, IDX_MAX
);
599 /* Is the length missing? */
600 return (*p
!= '\0' ? decode_record_fail
: decode_record_finish
);
603 return decode_record_fail
;
607 for (p
= len_lim
; *p
== ' ' || *p
== '\t'; p
++)
611 return decode_record_fail
;
615 if (!(p
!= NULL
&& p
< nextp
))
616 return decode_record_fail
;
618 if (nextp
[-1] != '\n')
619 return decode_record_fail
;
621 *p
= nextp
[-1] = '\0';
622 ret
= handler (data
, keyword
, p
+ 1, nextp
- p
- 2); /* '=' + trailing '\n' */
627 return (ret
? decode_record_ok
: decode_record_fail
);
630 /* --------------------------------------------------------------------------------------------- */
633 decg (void *data
, const char *keyword
, const char *value
, size_t size
)
635 GSList
**kwl
= (GSList
**) data
;
636 struct xhdr_tab
const *tab
;
640 tab
= locate_handler (keyword
);
641 if (tab
!= NULL
&& (tab
->flags
& XHDR_GLOBAL
) != 0)
643 if (!tab
->decoder (data
, keyword
, value
, size
))
647 xheader_list_append (kwl
, keyword
, value
);
652 /* --------------------------------------------------------------------------------------------- */
655 decx (void *data
, const char *keyword
, const char *value
, size_t size
)
657 struct keyword_item kp
= {
658 .pattern
= (char *) keyword
,
659 .value
= (char *) value
664 return keyword_item_run (&kp
, data
);
667 /* --------------------------------------------------------------------------------------------- */
670 sparse_path_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
675 st
->sparse_name_done
= TRUE
;
676 return raw_path_decoder (st
, arg
);
679 /* --------------------------------------------------------------------------------------------- */
682 sparse_major_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
688 if (!decode_num (&u
, arg
, INTMAX_MAX
, keyword
))
691 st
->sparse_major
= u
;
695 /* --------------------------------------------------------------------------------------------- */
698 sparse_minor_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
704 if (!decode_num (&u
, arg
, INTMAX_MAX
, keyword
))
707 st
->sparse_minor
= u
;
711 /* --------------------------------------------------------------------------------------------- */
714 sparse_size_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
720 if (!decode_num (&u
, arg
, TYPE_MAXIMUM (off_t
), keyword
))
723 st
->real_size_set
= TRUE
;
728 /* --------------------------------------------------------------------------------------------- */
731 sparse_numblocks_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
,
738 if (!decode_num (&u
, arg
, SIZE_MAX
, keyword
))
741 if (st
->sparse_map
== NULL
)
742 st
->sparse_map
= g_array_sized_new (FALSE
, FALSE
, sizeof (struct sp_array
), u
);
744 g_array_set_size (st
->sparse_map
, u
);
749 /* --------------------------------------------------------------------------------------------- */
752 sparse_offset_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
759 if (!decode_num (&u
, arg
, TYPE_MAXIMUM (off_t
), keyword
))
762 s
= &g_array_index (st
->sparse_map
, struct sp_array
, st
->sparse_map
->len
- 1);
767 /* --------------------------------------------------------------------------------------------- */
770 sparse_numbytes_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
,
778 if (!decode_num (&u
, arg
, SIZE_MAX
, keyword
))
783 g_array_append_val (st
->sparse_map
, s
);
787 /* --------------------------------------------------------------------------------------------- */
790 sparse_map_decoder (struct tar_stat_info
*st
, const char *keyword
, const char *arg
, size_t size
)
792 gboolean offset
= TRUE
;
798 if (st
->sparse_map
!= NULL
)
799 g_array_set_size (st
->sparse_map
, 0);
807 u
= stoint (arg
, &delim
, &overflow
, 0, TYPE_MAXIMUM (off_t
));
811 /* malformed extended header */
833 g_array_append_val (st
->sparse_map
, e
);
842 /* malformed extended header */
851 /* malformed extended header */
858 /* --------------------------------------------------------------------------------------------- */
859 /*** public functions ****************************************************************************/
860 /* --------------------------------------------------------------------------------------------- */
863 * Decodes an extended header.
865 * @param st stat info
867 * @return TRUE on success, FALSE otherwize
870 tar_xheader_decode (struct tar_stat_info
*st
)
873 enum decode_record_status status
;
875 run_override_list (global_header_override_list
, st
);
877 p
= st
->xhdr
.buffer
+ BLOCKSIZE
;
879 while ((status
= decode_record (&st
->xhdr
, &p
, decx
, st
)) == decode_record_ok
)
882 if (status
== decode_record_fail
)
885 /* The archived (effective) file size is always set directly in tar header
886 field, possibly overridden by "size" extended header - in both cases,
887 result is now decoded in st->stat.st_size */
888 st
->archive_file_size
= st
->stat
.st_size
;
890 /* The real file size (given by stat()) may be redefined for sparse
891 files in "GNU.sparse.realsize" extended header */
892 if (st
->real_size_set
)
893 st
->stat
.st_size
= st
->real_size
;
898 /* --------------------------------------------------------------------------------------------- */
901 tar_xheader_read (tar_super_t
*archive
, struct xheader
*xhdr
, union block
*p
, off_t size
)
906 size
= MAX (0, size
);
907 if (ckd_add (&size_plus_1
, size
, BLOCKSIZE
+ 1))
909 size
= size_plus_1
- 1;
911 xhdr
->buffer
= g_malloc (size_plus_1
);
912 xhdr
->buffer
[size
] = '\0';
919 return FALSE
; /* Unexpected EOF in archive */
921 len
= MIN (size
, BLOCKSIZE
);
923 memcpy (xhdr
->buffer
+ j
, p
->buffer
, len
);
924 tar_set_next_block_after (p
);
925 p
= tar_find_next_block (archive
);
935 /* --------------------------------------------------------------------------------------------- */
938 tar_xheader_decode_global (struct xheader
*xhdr
)
943 p
= xhdr
->buffer
+ BLOCKSIZE
;
945 xheader_list_destroy (&global_header_override_list
);
947 while ((ret
= decode_record (xhdr
, &p
, decg
, &global_header_override_list
)) == decode_record_ok
)
950 return (ret
== decode_record_finish
);
953 /* --------------------------------------------------------------------------------------------- */
956 tar_xheader_destroy (struct xheader
*xhdr
)
958 MC_PTR_FREE (xhdr
->buffer
);
962 /* --------------------------------------------------------------------------------------------- */