1 /*
2    Virtual File System: GNU Tar file system.
3 
4    Copyright (C) 1995-2021
5    Free Software Foundation, Inc.
6 
7    Written by:
8    Jakub Jelinek, 1995
9    Pavel Machek, 1998
10    Slava Zanko <slavazanko@gmail.com>, 2013
11 
12    This file is part of the Midnight Commander.
13 
14    The Midnight Commander is free software: you can redistribute it
15    and/or modify it under the terms of the GNU General Public License as
16    published by the Free Software Foundation, either version 3 of the License,
17    or (at your option) any later version.
18 
19    The Midnight Commander is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22    GNU General Public License for more details.
23 
24    You should have received a copy of the GNU General Public License
25    along with this program.  If not, see <http://www.gnu.org/licenses/>.
26  */
27 
28 /**
29  * \file
30  * \brief Source: Virtual File System: GNU Tar file system
31  * \author Jakub Jelinek
32  * \author Pavel Machek
33  * \date 1995, 1998
34  *
35  * Namespace: init_tarfs
36  */
37 
38 #include <config.h>
39 #include <sys/types.h>
40 #include <errno.h>
41 #include <ctype.h>
42 
43 #ifdef hpux
44 /* major() and minor() macros (among other things) defined here for hpux */
45 #include <sys/mknod.h>
46 #endif
47 
48 #include "lib/global.h"
49 #include "lib/util.h"
50 #include "lib/unixcompat.h"     /* makedev() */
51 #include "lib/widget.h"         /* message() */
52 
53 #include "lib/vfs/vfs.h"
54 #include "lib/vfs/utilvfs.h"
55 #include "lib/vfs/xdirentry.h"
56 #include "lib/vfs/gc.h"         /* vfs_rmstamp */
57 
58 #include "tar.h"
59 
60 /*** global variables ****************************************************************************/
61 
62 /*** file scope macro definitions ****************************************************************/
63 
64 #define TAR_SUPER(super) ((tar_super_t *) (super))
65 
66 
67 /* tar Header Block, from POSIX 1003.1-1990.  */
68 
69 /* The magic field is filled with this if uname and gname are valid. */
70 #define TMAGIC "ustar"          /* ustar and a null */
71 
72 #define XHDTYPE 'x'             /* Extended header referring to the next file in the archive */
73 #define XGLTYPE 'g'             /* Global extended header */
74 
75 /* Values used in typeflag field.  */
76 #define LNKTYPE  '1'            /* link */
77 #define SYMTYPE  '2'            /* symbolic link */
78 #define CHRTYPE  '3'            /* character special */
79 #define BLKTYPE  '4'            /* block special */
80 #define DIRTYPE  '5'            /* directory */
81 #define FIFOTYPE '6'            /* FIFO special */
82 
83 
84 /* tar Header Block, GNU extensions.  */
85 
86 /* *BEWARE* *BEWARE* *BEWARE* that the following information is still
87    boiling, and may change.  Even if the OLDGNU format description should be
88    accurate, the so-called GNU format is not yet fully decided.  It is
89    surely meant to use only extensions allowed by POSIX, but the sketch
90    below repeats some ugliness from the OLDGNU format, which should rather
91    go away.  Sparse files should be saved in such a way that they do *not*
92    require two passes at archive creation time.  Huge files get some POSIX
93    fields to overflow, alternate solutions have to be sought for this.  */
94 
95 
96 /* Sparse files are not supported in POSIX ustar format.  For sparse files
97    with a POSIX header, a GNU extra header is provided which holds overall
98    sparse information and a few sparse descriptors.  When an old GNU header
99    replaces both the POSIX header and the GNU extra header, it holds some
100    sparse descriptors too.  Whether POSIX or not, if more sparse descriptors
101    are still needed, they are put into as many successive sparse headers as
102    necessary.  The following constants tell how many sparse descriptors fit
103    in each kind of header able to hold them.  */
104 
105 #define SPARSES_IN_EXTRA_HEADER  16
106 #define SPARSES_IN_OLDGNU_HEADER 4
107 #define SPARSES_IN_SPARSE_HEADER 21
108 
109 /* OLDGNU_MAGIC uses both magic and version fields, which are contiguous.
110    Found in an archive, it indicates an old GNU header format, which will be
111    hopefully become obsolescent.  With OLDGNU_MAGIC, uname and gname are
112    valid, though the header is not truly POSIX conforming.  */
113 #define OLDGNU_MAGIC "ustar  "  /* 7 chars and a null */
114 
115 /* The standards committee allows only capital A through capital Z for user-defined expansion.  */
116 
117 /* This is a dir entry that contains the names of files that were in the
118    dir at the time the dump was made.  */
119 #define GNUTYPE_DUMPDIR 'D'
120 
121 /* Identifies the *next* file on the tape as having a long linkname.  */
122 #define GNUTYPE_LONGLINK 'K'
123 
124 /* Identifies the *next* file on the tape as having a long name.  */
125 #define GNUTYPE_LONGNAME 'L'
126 
127 
128 /* tar Header Block, overall structure.  */
129 
130 /* tar files are made in basic blocks of this size.  */
131 #define BLOCKSIZE 512
132 
133 
134 #define isodigit(c) ( ((c) >= '0') && ((c) <= '7') )
135 
136 /*** file scope type declarations ****************************************************************/
137 
138 /* *INDENT-OFF* */
139 
140 /* POSIX header */
141 struct posix_header
142 {                               /* byte offset */
143     char name[100];             /*   0 */
144     char mode[8];               /* 100 */
145     char uid[8];                /* 108 */
146     char gid[8];                /* 116 */
147     char size[12];              /* 124 */
148     char mtime[12];             /* 136 */
149     char chksum[8];             /* 148 */
150     char typeflag;              /* 156 */
151     char linkname[100];         /* 157 */
152     char magic[6];              /* 257 */
153     char version[2];            /* 263 */
154     char uname[32];             /* 265 */
155     char gname[32];             /* 297 */
156     char devmajor[8];           /* 329 */
157     char devminor[8];           /* 337 */
158     char prefix[155];           /* 345 */
159                                 /* 500 */
160 };
161 
162 /* Descriptor for a single file hole */
163 struct sparse
164 {                               /* byte offset */
165     /* cppcheck-suppress unusedStructMember */
166     char offset[12];            /*   0 */
167     /* cppcheck-suppress unusedStructMember */
168     char numbytes[12];          /*  12 */
169                                 /*  24 */
170 };
171 
172 /* The GNU extra header contains some information GNU tar needs, but not
173    foreseen in POSIX header format.  It is only used after a POSIX header
174    (and never with old GNU headers), and immediately follows this POSIX
175    header, when typeflag is a letter rather than a digit, so signaling a GNU
176    extension.  */
177 struct extra_header
178 {                               /* byte offset */
179     char atime[12];             /*   0 */
180     char ctime[12];             /*  12 */
181     char offset[12];            /*  24 */
182     char realsize[12];          /*  36 */
183     char longnames[4];          /*  48 */
184     char unused_pad1[68];       /*  52 */
185     struct sparse sp[SPARSES_IN_EXTRA_HEADER];
186                                 /* 120 */
187     char isextended;            /* 504 */
188                                 /* 505 */
189 };
190 
191 /* Extension header for sparse files, used immediately after the GNU extra
192    header, and used only if all sparse information cannot fit into that
193    extra header.  There might even be many such extension headers, one after
194    the other, until all sparse information has been recorded.  */
195 struct sparse_header
196 {                               /* byte offset */
197     struct sparse sp[SPARSES_IN_SPARSE_HEADER];
198                                 /*   0 */
199     char isextended;            /* 504 */
200                                 /* 505 */
201 };
202 
203 /* The old GNU format header conflicts with POSIX format in such a way that
204    POSIX archives may fool old GNU tar's, and POSIX tar's might well be
205    fooled by old GNU tar archives.  An old GNU format header uses the space
206    used by the prefix field in a POSIX header, and cumulates information
207    normally found in a GNU extra header.  With an old GNU tar header, we
208    never see any POSIX header nor GNU extra header.  Supplementary sparse
209    headers are allowed, however.  */
210 struct oldgnu_header
211 {                               /* byte offset */
212     char unused_pad1[345];      /*   0 */
213     char atime[12];             /* 345 */
214     char ctime[12];             /* 357 */
215     char offset[12];            /* 369 */
216     char longnames[4];          /* 381 */
217     char unused_pad2;           /* 385 */
218     struct sparse sp[SPARSES_IN_OLDGNU_HEADER];
219                                 /* 386 */
220     char isextended;            /* 482 */
221     char realsize[12];          /* 483 */
222                                 /* 495 */
223 };
224 
225 /* *INDENT-ON* */
226 
227 /* tar Header Block, overall structure */
228 union block
229 {
230     char buffer[BLOCKSIZE];
231     struct posix_header header;
232     struct extra_header extra_header;
233     struct oldgnu_header oldgnu_header;
234     struct sparse_header sparse_header;
235 };
236 
237 enum archive_format
238 {
239     TAR_UNKNOWN = 0,
240     TAR_V7,
241     TAR_USTAR,
242     TAR_POSIX,
243     TAR_GNU
244 };
245 
246 typedef enum
247 {
248     STATUS_BADCHECKSUM,
249     STATUS_SUCCESS,
250     STATUS_EOFMARK,
251     STATUS_EOF
252 } ReadStatus;
253 
254 typedef struct
255 {
256     struct vfs_s_super base;    /* base class */
257 
258     int fd;
259     struct stat st;
260     enum archive_format type;   /* Type of the archive */
261 } tar_super_t;
262 
263 /*** file scope variables ************************************************************************/
264 
265 static struct vfs_s_subclass tarfs_subclass;
266 static struct vfs_class *vfs_tarfs_ops = VFS_CLASS (&tarfs_subclass);
267 
268 /* As we open one archive at a time, it is safe to have this static */
269 static off_t current_tar_position = 0;
270 
271 static union block block_buf;
272 
273 /* --------------------------------------------------------------------------------------------- */
274 /*** file scope functions ************************************************************************/
275 /* --------------------------------------------------------------------------------------------- */
276 /**
277  * Quick and dirty octal conversion.
278  *
279  * Result is -1 if the field is invalid (all blank, or nonoctal).
280  */
281 static long
tar_from_oct(int digs,const char * where)282 tar_from_oct (int digs, const char *where)
283 {
284     long value;
285 
286     while (isspace ((unsigned char) *where))
287     {                           /* Skip spaces */
288         where++;
289         if (--digs <= 0)
290             return -1;          /* All blank field */
291     }
292     value = 0;
293     while (digs > 0 && isodigit (*where))
294     {                           /* Scan till nonoctal */
295         value = (value << 3) | (*where++ - '0');
296         --digs;
297     }
298 
299     if (digs > 0 && *where && !isspace ((unsigned char) *where))
300         return -1;              /* Ended on non-space/nul */
301 
302     return value;
303 }
304 
305 /* --------------------------------------------------------------------------------------------- */
306 
307 static struct vfs_s_super *
tar_new_archive(struct vfs_class * me)308 tar_new_archive (struct vfs_class *me)
309 {
310     tar_super_t *arch;
311 
312     arch = g_new0 (tar_super_t, 1);
313     arch->base.me = me;
314     arch->fd = -1;
315     arch->type = TAR_UNKNOWN;
316 
317     return VFS_SUPER (arch);
318 }
319 
320 /* --------------------------------------------------------------------------------------------- */
321 
322 static void
tar_free_archive(struct vfs_class * me,struct vfs_s_super * archive)323 tar_free_archive (struct vfs_class *me, struct vfs_s_super *archive)
324 {
325     tar_super_t *arch = TAR_SUPER (archive);
326 
327     (void) me;
328 
329     if (arch->fd != -1)
330     {
331         mc_close (arch->fd);
332         arch->fd = -1;
333     }
334 }
335 
336 /* --------------------------------------------------------------------------------------------- */
337 
338 /* Returns fd of the open tar file */
339 static int
tar_open_archive_int(struct vfs_class * me,const vfs_path_t * vpath,struct vfs_s_super * archive)340 tar_open_archive_int (struct vfs_class *me, const vfs_path_t * vpath, struct vfs_s_super *archive)
341 {
342     int result, type;
343     tar_super_t *arch;
344     mode_t mode;
345     struct vfs_s_inode *root;
346 
347     result = mc_open (vpath, O_RDONLY);
348     if (result == -1)
349     {
350         message (D_ERROR, MSG_ERROR, _("Cannot open tar archive\n%s"), vfs_path_as_str (vpath));
351         ERRNOR (ENOENT, -1);
352     }
353 
354     archive->name = g_strdup (vfs_path_as_str (vpath));
355     arch = TAR_SUPER (archive);
356     mc_stat (vpath, &arch->st);
357 
358     /* Find out the method to handle this tar file */
359     type = get_compression_type (result, archive->name);
360     if (type == COMPRESSION_NONE)
361         mc_lseek (result, 0, SEEK_SET);
362     else
363     {
364         char *s;
365         vfs_path_t *tmp_vpath;
366 
367         mc_close (result);
368         s = g_strconcat (archive->name, decompress_extension (type), (char *) NULL);
369         tmp_vpath = vfs_path_from_str_flags (s, VPF_NO_CANON);
370         result = mc_open (tmp_vpath, O_RDONLY);
371         vfs_path_free (tmp_vpath, TRUE);
372         if (result == -1)
373             message (D_ERROR, MSG_ERROR, _("Cannot open tar archive\n%s"), s);
374         g_free (s);
375         if (result == -1)
376         {
377             MC_PTR_FREE (archive->name);
378             ERRNOR (ENOENT, -1);
379         }
380     }
381 
382     arch->fd = result;
383     mode = arch->st.st_mode & 07777;
384     if (mode & 0400)
385         mode |= 0100;
386     if (mode & 0040)
387         mode |= 0010;
388     if (mode & 0004)
389         mode |= 0001;
390     mode |= S_IFDIR;
391 
392     root = vfs_s_new_inode (me, archive, &arch->st);
393     root->st.st_mode = mode;
394     root->data_offset = -1;
395     root->st.st_nlink++;
396     root->st.st_dev = VFS_SUBCLASS (me)->rdev++;
397 
398     archive->root = root;
399 
400     return result;
401 }
402 
403 /* --------------------------------------------------------------------------------------------- */
404 
405 static union block *
tar_get_next_block(struct vfs_s_super * archive,int tard)406 tar_get_next_block (struct vfs_s_super *archive, int tard)
407 {
408     int n;
409 
410     (void) archive;
411 
412     n = mc_read (tard, block_buf.buffer, sizeof (block_buf.buffer));
413     if (n != sizeof (block_buf.buffer))
414         return NULL;            /* An error has occurred */
415     current_tar_position += sizeof (block_buf.buffer);
416     return &block_buf;
417 }
418 
419 /* --------------------------------------------------------------------------------------------- */
420 
421 static void
tar_skip_n_records(struct vfs_s_super * archive,int tard,size_t n)422 tar_skip_n_records (struct vfs_s_super *archive, int tard, size_t n)
423 {
424     (void) archive;
425 
426     mc_lseek (tard, n * sizeof (block_buf.buffer), SEEK_CUR);
427     current_tar_position += n * sizeof (block_buf.buffer);
428 }
429 
430 /* --------------------------------------------------------------------------------------------- */
431 
432 static ReadStatus
tar_checksum(const union block * header)433 tar_checksum (const union block *header)
434 {
435     long recsum;
436     long signed_sum = 0;
437     long sum = 0;
438     int i;
439     const char *p = header->buffer;
440 
441     recsum = tar_from_oct (8, header->header.chksum);
442 
443     for (i = sizeof (*header); --i >= 0;)
444     {
445         /*
446          * We can't use unsigned char here because of old compilers,
447          * e.g. V7.
448          */
449         signed_sum += *p;
450         sum += 0xFF & *p++;
451     }
452 
453     /* Adjust checksum to count the "chksum" field as blanks. */
454     for (i = sizeof (header->header.chksum); --i >= 0;)
455     {
456         sum -= 0xFF & header->header.chksum[i];
457         signed_sum -= (char) header->header.chksum[i];
458     }
459 
460     sum += ' ' * sizeof (header->header.chksum);
461     signed_sum += ' ' * sizeof (header->header.chksum);
462 
463     /*
464      * This is a zeroed block... whole block is 0's except
465      * for the 8 blanks we faked for the checksum field.
466      */
467     if (sum == 8 * ' ')
468         return STATUS_EOFMARK;
469 
470     if (sum != recsum && signed_sum != recsum)
471         return STATUS_BADCHECKSUM;
472 
473     return STATUS_SUCCESS;
474 }
475 
476 /* --------------------------------------------------------------------------------------------- */
477 
478 static size_t
tar_decode_header(union block * header,tar_super_t * arch)479 tar_decode_header (union block *header, tar_super_t * arch)
480 {
481     size_t size;
482 
483     /*
484      * Try to determine the archive format.
485      */
486     if (arch->type == TAR_UNKNOWN)
487     {
488         if (strcmp (header->header.magic, TMAGIC) == 0)
489         {
490             if (header->header.typeflag == XGLTYPE)
491                 arch->type = TAR_POSIX;
492             else
493                 arch->type = TAR_USTAR;
494         }
495         else if (strcmp (header->header.magic, OLDGNU_MAGIC) == 0)
496             arch->type = TAR_GNU;
497     }
498 
499     /*
500      * typeflag on BSDI tar (pax) always '\000'
501      */
502     if (header->header.typeflag == '\000')
503     {
504         size_t len;
505 
506         if (header->header.name[sizeof (header->header.name) - 1] != '\0')
507             len = sizeof (header->header.name);
508         else
509             len = strlen (header->header.name);
510 
511         if (len != 0 && IS_PATH_SEP (header->header.name[len - 1]))
512             header->header.typeflag = DIRTYPE;
513     }
514 
515     /*
516      * Good block.  Decode file size and return.
517      */
518     if (header->header.typeflag == LNKTYPE || header->header.typeflag == DIRTYPE)
519         size = 0;               /* Links 0 size on tape */
520     else
521         size = tar_from_oct (1 + 12, header->header.size);
522 
523     if (header->header.typeflag == GNUTYPE_DUMPDIR)
524         if (arch->type == TAR_UNKNOWN)
525             arch->type = TAR_GNU;
526 
527     return size;
528 }
529 
530 /* --------------------------------------------------------------------------------------------- */
531 
532 static void
tar_fill_stat(struct vfs_s_super * archive,struct stat * st,union block * header,size_t h_size)533 tar_fill_stat (struct vfs_s_super *archive, struct stat *st, union block *header, size_t h_size)
534 {
535     tar_super_t *arch = TAR_SUPER (archive);
536 
537     st->st_mode = tar_from_oct (8, header->header.mode);
538 
539     /* Adjust st->st_mode because there are tar-files with
540      * typeflag==SYMTYPE and S_ISLNK(mod)==0. I don't
541      * know about the other modes but I think I cause no new
542      * problem when I adjust them, too. -- Norbert.
543      */
544     if (header->header.typeflag == DIRTYPE || header->header.typeflag == GNUTYPE_DUMPDIR)
545         st->st_mode |= S_IFDIR;
546     else if (header->header.typeflag == SYMTYPE)
547         st->st_mode |= S_IFLNK;
548     else if (header->header.typeflag == CHRTYPE)
549         st->st_mode |= S_IFCHR;
550     else if (header->header.typeflag == BLKTYPE)
551         st->st_mode |= S_IFBLK;
552     else if (header->header.typeflag == FIFOTYPE)
553         st->st_mode |= S_IFIFO;
554     else
555         st->st_mode |= S_IFREG;
556 
557     st->st_dev = 0;
558 #ifdef HAVE_STRUCT_STAT_ST_RDEV
559     st->st_rdev = 0;
560 #endif
561 
562     switch (arch->type)
563     {
564     case TAR_USTAR:
565     case TAR_POSIX:
566     case TAR_GNU:
567         /* *INDENT-OFF* */
568         st->st_uid = *header->header.uname != '\0'
569             ? (uid_t) vfs_finduid (header->header.uname)
570             : tar_from_oct (8, header->header.uid);
571         st->st_gid = *header->header.gname != '\0'
572             ? (gid_t)  vfs_findgid (header->header.gname)
573             : tar_from_oct (8,header->header.gid);
574         /* *INDENT-ON* */
575 
576         switch (header->header.typeflag)
577         {
578         case BLKTYPE:
579         case CHRTYPE:
580 #ifdef HAVE_STRUCT_STAT_ST_RDEV
581             st->st_rdev =
582                 makedev (tar_from_oct (8, header->header.devmajor),
583                          tar_from_oct (8, header->header.devminor));
584 #endif
585             break;
586         default:
587             break;
588         }
589         break;
590 
591     default:
592         st->st_uid = tar_from_oct (8, header->header.uid);
593         st->st_gid = tar_from_oct (8, header->header.gid);
594         break;
595     }
596 
597     st->st_size = h_size;
598 #ifdef HAVE_STRUCT_STAT_ST_MTIM
599     st->st_atim.tv_nsec = st->st_mtim.tv_nsec = st->st_ctim.tv_nsec = 0;
600 #endif
601     st->st_mtime = tar_from_oct (1 + 12, header->header.mtime);
602     st->st_atime = 0;
603     st->st_ctime = 0;
604     if (arch->type == TAR_GNU)
605     {
606         st->st_atime = tar_from_oct (1 + 12, header->oldgnu_header.atime);
607         st->st_ctime = tar_from_oct (1 + 12, header->oldgnu_header.ctime);
608     }
609 
610 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
611     st->st_blksize = 8 * 1024;  /* FIXME */
612 #endif
613     vfs_adjust_stat (st);
614 }
615 
616 /* --------------------------------------------------------------------------------------------- */
617 /**
618  * Return 1 for success, 0 if the checksum is bad, EOF on eof,
619  * 2 for a block full of zeros (EOF marker).
620  *
621  */
622 static ReadStatus
tar_read_header(struct vfs_class * me,struct vfs_s_super * archive,int tard,size_t * h_size)623 tar_read_header (struct vfs_class *me, struct vfs_s_super *archive, int tard, size_t * h_size)
624 {
625     tar_super_t *arch = TAR_SUPER (archive);
626     ReadStatus checksum_status;
627     union block *header;
628     static char *next_long_name = NULL, *next_long_link = NULL;
629 
630     while (TRUE)
631     {
632         header = tar_get_next_block (archive, tard);
633         if (header == NULL)
634             return STATUS_EOF;
635 
636         checksum_status = tar_checksum (header);
637         if (checksum_status != STATUS_SUCCESS)
638             return checksum_status;
639 
640         *h_size = tar_decode_header (header, arch);
641 
642         /* Skip over pax extended header and global extended header records. */
643         if (header->header.typeflag == XHDTYPE || header->header.typeflag == XGLTYPE)
644         {
645             if (arch->type == TAR_UNKNOWN)
646                 arch->type = TAR_POSIX;
647             return STATUS_SUCCESS;
648         }
649 
650         if (header->header.typeflag == GNUTYPE_LONGNAME
651             || header->header.typeflag == GNUTYPE_LONGLINK)
652         {
653             char **longp;
654             char *bp, *data;
655             off_t size;
656             size_t written;
657 
658             if (arch->type == TAR_UNKNOWN)
659                 arch->type = TAR_GNU;
660 
661             if (*h_size > MC_MAXPATHLEN)
662             {
663                 message (D_ERROR, MSG_ERROR, _("Inconsistent tar archive"));
664                 return STATUS_BADCHECKSUM;
665             }
666 
667             longp = header->header.typeflag == GNUTYPE_LONGNAME ? &next_long_name : &next_long_link;
668 
669             g_free (*longp);
670             bp = *longp = g_malloc (*h_size + 1);
671 
672             for (size = *h_size; size > 0; size -= written)
673             {
674                 data = tar_get_next_block (archive, tard)->buffer;
675                 if (data == NULL)
676                 {
677                     MC_PTR_FREE (*longp);
678                     message (D_ERROR, MSG_ERROR, _("Unexpected EOF on archive file"));
679                     return STATUS_BADCHECKSUM;
680                 }
681                 written = BLOCKSIZE;
682                 if ((off_t) written > size)
683                     written = (size_t) size;
684 
685                 memcpy (bp, data, written);
686                 bp += written;
687             }
688 
689             if (bp - *longp == MC_MAXPATHLEN && bp[-1] != '\0')
690             {
691                 MC_PTR_FREE (*longp);
692                 message (D_ERROR, MSG_ERROR, _("Inconsistent tar archive"));
693                 return STATUS_BADCHECKSUM;
694             }
695 
696             *bp = '\0';
697         }
698         else
699             break;
700     }
701 
702     {
703         struct stat st;
704         struct vfs_s_entry *entry;
705         struct vfs_s_inode *inode = NULL, *parent;
706         off_t data_position;
707         char *p, *q;
708         size_t len;
709         char *current_file_name, *current_link_name;
710 
711         current_link_name =
712             next_long_link != NULL ? next_long_link : g_strndup (header->header.linkname,
713                                                                  sizeof (header->header.linkname));
714         len = strlen (current_link_name);
715         if (len > 1 && IS_PATH_SEP (current_link_name[len - 1]))
716             current_link_name[len - 1] = '\0';
717 
718         current_file_name = NULL;
719         switch (arch->type)
720         {
721         case TAR_USTAR:
722         case TAR_POSIX:
723             /* The ustar archive format supports pathnames of upto 256
724              * characters in length. This is achieved by concatenating
725              * the contents of the 'prefix' and 'name' fields like
726              * this:
727              *
728              *   prefix + path_separator + name
729              *
730              * If the 'prefix' field contains an empty string i.e. its
731              * first characters is '\0' the prefix field is ignored.
732              */
733             if (header->header.prefix[0] != '\0')
734             {
735                 char *temp_name, *temp_prefix;
736 
737                 temp_name = g_strndup (header->header.name, sizeof (header->header.name));
738                 temp_prefix = g_strndup (header->header.prefix, sizeof (header->header.prefix));
739                 current_file_name = g_strconcat (temp_prefix, PATH_SEP_STR,
740                                                  temp_name, (char *) NULL);
741                 g_free (temp_name);
742                 g_free (temp_prefix);
743             }
744             break;
745         case TAR_GNU:
746             if (next_long_name != NULL)
747                 current_file_name = next_long_name;
748             break;
749         default:
750             break;
751         }
752 
753         if (current_file_name == NULL)
754         {
755             if (next_long_name != NULL)
756                 current_file_name = g_strdup (next_long_name);
757             else
758                 current_file_name = g_strndup (header->header.name, sizeof (header->header.name));
759         }
760 
761         canonicalize_pathname (current_file_name);
762         len = strlen (current_file_name);
763 
764         data_position = current_tar_position;
765 
766         p = strrchr (current_file_name, PATH_SEP);
767         if (p == NULL)
768         {
769             p = current_file_name;
770             q = current_file_name + len;        /* "" */
771         }
772         else
773         {
774             *(p++) = '\0';
775             q = current_file_name;
776         }
777 
778         parent = vfs_s_find_inode (me, archive, q, LINK_NO_FOLLOW, FL_MKDIR);
779         if (parent == NULL)
780         {
781             message (D_ERROR, MSG_ERROR, _("Inconsistent tar archive"));
782             return STATUS_BADCHECKSUM;
783         }
784 
785         if (header->header.typeflag == LNKTYPE)
786         {
787             inode = vfs_s_find_inode (me, archive, current_link_name, LINK_NO_FOLLOW, FL_NONE);
788             if (inode == NULL)
789                 message (D_ERROR, MSG_ERROR, _("Inconsistent tar archive"));
790             else
791             {
792                 entry = vfs_s_new_entry (me, p, inode);
793                 vfs_s_insert_entry (me, parent, entry);
794                 g_free (current_link_name);
795                 goto done;
796             }
797         }
798 
799         memset (&st, 0, sizeof (st));
800         tar_fill_stat (archive, &st, header, *h_size);
801 
802         if (S_ISDIR (st.st_mode))
803         {
804             entry = VFS_SUBCLASS (me)->find_entry (me, parent, p, LINK_NO_FOLLOW, FL_NONE);
805             if (entry != NULL)
806                 goto done;
807         }
808 
809         inode = vfs_s_new_inode (me, archive, &st);
810         inode->data_offset = data_position;
811 
812         if (*current_link_name != '\0')
813             inode->linkname = current_link_name;
814         else if (current_link_name != next_long_link)
815             g_free (current_link_name);
816 
817         entry = vfs_s_new_entry (me, p, inode);
818         vfs_s_insert_entry (me, parent, entry);
819         g_free (current_file_name);
820 
821       done:
822         next_long_link = next_long_name = NULL;
823 
824         if (arch->type == TAR_GNU && header->oldgnu_header.isextended)
825         {
826             while (tar_get_next_block (archive, tard)->sparse_header.isextended != 0)
827                 ;
828 
829             if (inode != NULL)
830                 inode->data_offset = current_tar_position;
831         }
832         return STATUS_SUCCESS;
833     }
834 }
835 
836 /* --------------------------------------------------------------------------------------------- */
837 /**
838  * Main loop for reading an archive.
839  * Returns 0 on success, -1 on error.
840  */
841 static int
tar_open_archive(struct vfs_s_super * archive,const vfs_path_t * vpath,const vfs_path_element_t * vpath_element)842 tar_open_archive (struct vfs_s_super *archive, const vfs_path_t * vpath,
843                   const vfs_path_element_t * vpath_element)
844 {
845     /* Initial status at start of archive */
846     ReadStatus status = STATUS_EOFMARK;
847     int tard;
848 
849     current_tar_position = 0;
850     /* Open for reading */
851     tard = tar_open_archive_int (vpath_element->class, vpath, archive);
852     if (tard == -1)
853         return -1;
854 
855     while (TRUE)
856     {
857         size_t h_size = 0;
858         ReadStatus prev_status = status;
859 
860         status = tar_read_header (vpath_element->class, archive, tard, &h_size);
861 
862         switch (status)
863         {
864         case STATUS_SUCCESS:
865             tar_skip_n_records (archive, tard, (h_size + BLOCKSIZE - 1) / BLOCKSIZE);
866             continue;
867 
868             /*
869              * Invalid header:
870              *
871              * If the previous header was good, tell them
872              * that we are skipping bad ones.
873              */
874         case STATUS_BADCHECKSUM:
875             switch (prev_status)
876             {
877                 /* Error on first block */
878             case STATUS_EOFMARK:
879                 {
880                     message (D_ERROR, MSG_ERROR, _("%s\ndoesn't look like a tar archive."),
881                              vfs_path_as_str (vpath));
882                     MC_FALLTHROUGH;
883 
884                     /* Error after header rec */
885                 }
886             case STATUS_SUCCESS:
887                 /* Error after error */
888 
889             case STATUS_BADCHECKSUM:
890                 return -1;
891 
892             case STATUS_EOF:
893                 return 0;
894 
895             default:
896                 break;
897             }
898             MC_FALLTHROUGH;
899 
900             /* Record of zeroes */
901         case STATUS_EOFMARK:   /* If error after 0's */
902             MC_FALLTHROUGH;
903             /* exit from loop */
904         case STATUS_EOF:       /* End of archive */
905             break;
906         default:
907             break;
908         }
909         break;
910     }
911     return 0;
912 }
913 
914 /* --------------------------------------------------------------------------------------------- */
915 
916 static void *
tar_super_check(const vfs_path_t * vpath)917 tar_super_check (const vfs_path_t * vpath)
918 {
919     static struct stat stat_buf;
920     int stat_result;
921 
922     stat_result = mc_stat (vpath, &stat_buf);
923 
924     return (stat_result != 0) ? NULL : &stat_buf;
925 }
926 
927 /* --------------------------------------------------------------------------------------------- */
928 
929 static int
tar_super_same(const vfs_path_element_t * vpath_element,struct vfs_s_super * parc,const vfs_path_t * vpath,void * cookie)930 tar_super_same (const vfs_path_element_t * vpath_element, struct vfs_s_super *parc,
931                 const vfs_path_t * vpath, void *cookie)
932 {
933     struct stat *archive_stat = cookie; /* stat of main archive */
934 
935     (void) vpath_element;
936 
937     if (strcmp (parc->name, vfs_path_as_str (vpath)) != 0)
938         return 0;
939 
940     /* Has the cached archive been changed on the disk? */
941     if (parc != NULL && TAR_SUPER (parc)->st.st_mtime < archive_stat->st_mtime)
942     {
943         /* Yes, reload! */
944         vfs_tarfs_ops->free ((vfsid) parc);
945         vfs_rmstamp (vfs_tarfs_ops, (vfsid) parc);
946         return 2;
947     }
948     /* Hasn't been modified, give it a new timeout */
949     vfs_stamp (vfs_tarfs_ops, (vfsid) parc);
950     return 1;
951 }
952 
953 /* --------------------------------------------------------------------------------------------- */
954 
955 static ssize_t
tar_read(void * fh,char * buffer,size_t count)956 tar_read (void *fh, char *buffer, size_t count)
957 {
958     struct vfs_class *me = VFS_FILE_HANDLER_SUPER (fh)->me;
959     vfs_file_handler_t *file = VFS_FILE_HANDLER (fh);
960     off_t begin = file->ino->data_offset;
961     int fd = TAR_SUPER (VFS_FILE_HANDLER_SUPER (fh))->fd;
962     ssize_t res;
963 
964     if (mc_lseek (fd, begin + file->pos, SEEK_SET) != begin + file->pos)
965         ERRNOR (EIO, -1);
966 
967     count = MIN (count, (size_t) (file->ino->st.st_size - file->pos));
968 
969     res = mc_read (fd, buffer, count);
970     if (res == -1)
971         ERRNOR (errno, -1);
972 
973     file->pos += res;
974     return res;
975 }
976 
977 /* --------------------------------------------------------------------------------------------- */
978 
979 static int
tar_fh_open(struct vfs_class * me,vfs_file_handler_t * fh,int flags,mode_t mode)980 tar_fh_open (struct vfs_class *me, vfs_file_handler_t * fh, int flags, mode_t mode)
981 {
982     (void) fh;
983     (void) mode;
984 
985     if ((flags & O_ACCMODE) != O_RDONLY)
986         ERRNOR (EROFS, -1);
987     return 0;
988 }
989 
990 /* --------------------------------------------------------------------------------------------- */
991 /*** public functions ****************************************************************************/
992 /* --------------------------------------------------------------------------------------------- */
993 
994 void
vfs_init_tarfs(void)995 vfs_init_tarfs (void)
996 {
997     /* FIXME: tarfs used own temp files */
998     vfs_init_subclass (&tarfs_subclass, "tarfs", VFSF_READONLY, "utar");
999     vfs_tarfs_ops->read = tar_read;
1000     vfs_tarfs_ops->setctl = NULL;
1001     tarfs_subclass.archive_check = tar_super_check;
1002     tarfs_subclass.archive_same = tar_super_same;
1003     tarfs_subclass.new_archive = tar_new_archive;
1004     tarfs_subclass.open_archive = tar_open_archive;
1005     tarfs_subclass.free_archive = tar_free_archive;
1006     tarfs_subclass.fh_open = tar_fh_open;
1007     vfs_register_class (vfs_tarfs_ops);
1008 }
1009 
1010 /* --------------------------------------------------------------------------------------------- */
1011