2 Virtual File System: GNU Tar file system.
4 Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
6 The Free Software Foundation, Inc.
12 This file is part of the Midnight Commander.
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.
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.
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/>.
30 * \brief Source: Virtual File System: GNU Tar file system
31 * \author Jakub Jelinek
32 * \author Pavel Machek
35 * Namespace: init_tarfs
39 #include <sys/types.h>
45 /* major() and minor() macros (among other things) defined here for hpux */
46 #include <sys/mknod.h>
49 #include "lib/global.h"
51 #include "lib/widget.h" /* message() */
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 */
60 /*** global variables ****************************************************************************/
62 /*** file scope macro definitions ****************************************************************/
65 * Header block on tape.
67 * I'm going to use traditional DP naming conventions here.
68 * A "block" is a big chunk of stuff that we do I/O on.
69 * A "record" is a piece of info that we care about.
70 * Typically many "record"s fit into a "block".
72 #define RECORDSIZE 512
74 #define PREFIX_SIZE 155
77 #define SPARSE_EXT_HDR 21
78 #define SPARSE_IN_HDR 4
80 /* The checksum field is filled with this while the checksum is computed. */
81 #define CHKBLANKS " " /* 8 blanks, no null */
83 /* The magic field is filled with this if uname and gname are valid. */
84 #define TMAGIC "ustar" /* ustar and a null */
85 #define OLDGNU_MAGIC "ustar " /* 7 chars and a null */
87 /* The linkflag defines the type of file */
88 #define LF_OLDNORMAL '\0' /* Normal disk file, Unix compat */
89 #define LF_NORMAL '0' /* Normal disk file */
90 #define LF_LINK '1' /* Link to previously dumped file */
91 #define LF_SYMLINK '2' /* Symbolic link */
92 #define LF_CHR '3' /* Character special file */
93 #define LF_BLK '4' /* Block special file */
94 #define LF_DIR '5' /* Directory */
95 #define LF_FIFO '6' /* FIFO special file */
96 #define LF_CONTIG '7' /* Contiguous file */
97 #define LF_EXTHDR 'x' /* pax Extended Header */
98 #define LF_GLOBAL_EXTHDR 'g' /* pax Global Extended Header */
99 /* Further link types may be defined later. */
101 /* Note that the standards committee allows only capital A through
102 capital Z for user-defined expansion. This means that defining something
103 as, say '8' is a *bad* idea. */
104 #define LF_DUMPDIR 'D' /* This is a dir entry that contains
105 the names of files that were in
106 the dir at the time the dump
108 #define LF_LONGLINK 'K' /* Identifies the NEXT file on the tape
109 as having a long linkname */
110 #define LF_LONGNAME 'L' /* Identifies the NEXT file on the tape
111 as having a long name. */
112 #define LF_MULTIVOL 'M' /* This is the continuation
113 of a file that began on another
115 #define LF_NAMES 'N' /* For storing filenames that didn't
116 fit in 100 characters */
117 #define LF_SPARSE 'S' /* This is for sparse files */
118 #define LF_VOLHDR 'V' /* This file is a tape/volume header */
119 /* Ignore it on extraction */
122 * Exit codes from the "tar" program
124 #define EX_SUCCESS 0 /* success! */
125 #define EX_ARGSBAD 1 /* invalid args */
126 #define EX_BADFILE 2 /* invalid filename */
127 #define EX_BADARCH 3 /* bad archive */
128 #define EX_SYSTEM 4 /* system gave unexpected error */
129 #define EX_BADVOL 5 /* Special error code means
130 Tape volume doesn't match the one
131 specified on the command line */
133 #define isodigit(c) ( ((c) >= '0') && ((c) <= '7') )
135 /*** file scope type declarations ****************************************************************/
160 char charptr
[RECORDSIZE
];
163 char arch_name
[NAMSIZ
];
171 char arch_linkname
[NAMSIZ
];
177 /* The following bytes of the tar header record were originally unused.
179 Archives following the ustar specification use almost all of those
180 bytes to support pathnames of 256 characters in length.
182 GNU tar archives use the "unused" space to support incremental
183 archives and sparse files. */
186 char prefix
[PREFIX_SIZE
];
187 /* GNU extensions to the ustar (POSIX.1-1988) archive format. */
195 struct sparse sp
[SPARSE_IN_HDR
];
197 char realsize
[12]; /* true size of the sparse file */
201 struct extended_header
203 struct sparse sp
[21];
220 int type
; /* Type of the archive */
223 /*** file scope variables ************************************************************************/
225 static struct vfs_class vfs_tarfs_ops
;
227 /* As we open one archive at a time, it is safe to have this static */
228 static int current_tar_position
= 0;
230 static union record rec_buf
;
232 /*** file scope functions ************************************************************************/
233 /* --------------------------------------------------------------------------------------------- */
235 * Quick and dirty octal conversion.
237 * Result is -1 if the field is invalid (all blank, or nonoctal).
240 tar_from_oct (int digs
, char *where
)
244 while (isspace ((unsigned char) *where
))
248 return -1; /* All blank field */
251 while (digs
> 0 && isodigit (*where
))
252 { /* Scan till nonoctal */
253 value
= (value
<< 3) | (*where
++ - '0');
257 if (digs
> 0 && *where
&& !isspace ((unsigned char) *where
))
258 return -1; /* Ended on non-space/nul */
263 /* --------------------------------------------------------------------------------------------- */
266 tar_free_archive (struct vfs_class
*me
, struct vfs_s_super
*archive
)
270 if (archive
->data
!= NULL
)
272 tar_super_data_t
*arch
= (tar_super_data_t
*) archive
->data
;
276 g_free (archive
->data
);
280 /* --------------------------------------------------------------------------------------------- */
282 /* Returns fd of the open tar file */
284 tar_open_archive_int (struct vfs_class
*me
, const vfs_path_t
* vpath
, struct vfs_s_super
*archive
)
287 tar_super_data_t
*arch
;
289 struct vfs_s_inode
*root
;
291 result
= mc_open (vpath
, O_RDONLY
);
296 name
= vfs_path_to_str (vpath
);
297 message (D_ERROR
, MSG_ERROR
, _("Cannot open tar archive\n%s"), name
);
302 archive
->name
= vfs_path_to_str (vpath
);
303 archive
->data
= g_new (tar_super_data_t
, 1);
304 arch
= (tar_super_data_t
*) archive
->data
;
305 mc_stat (vpath
, &arch
->st
);
307 arch
->type
= TAR_UNKNOWN
;
309 /* Find out the method to handle this tar file */
310 type
= get_compression_type (result
, archive
->name
);
311 mc_lseek (result
, 0, SEEK_SET
);
312 if (type
!= COMPRESSION_NONE
)
315 vfs_path_t
*tmp_vpath
;
318 s
= g_strconcat (archive
->name
, decompress_extension (type
), (char *) NULL
);
319 tmp_vpath
= vfs_path_from_str (s
);
320 result
= mc_open (tmp_vpath
, O_RDONLY
);
321 vfs_path_free (tmp_vpath
);
323 message (D_ERROR
, MSG_ERROR
, _("Cannot open tar archive\n%s"), s
);
327 g_free (archive
->name
);
328 archive
->name
= NULL
;
334 mode
= arch
->st
.st_mode
& 07777;
343 root
= vfs_s_new_inode (me
, archive
, &arch
->st
);
344 root
->st
.st_mode
= mode
;
345 root
->data_offset
= -1;
347 root
->st
.st_dev
= MEDATA
->rdev
++;
349 archive
->root
= root
;
354 /* --------------------------------------------------------------------------------------------- */
356 static union record
*
357 tar_get_next_record (struct vfs_s_super
*archive
, int tard
)
363 n
= mc_read (tard
, rec_buf
.charptr
, RECORDSIZE
);
365 return NULL
; /* An error has occurred */
366 current_tar_position
+= RECORDSIZE
;
370 /* --------------------------------------------------------------------------------------------- */
373 tar_skip_n_records (struct vfs_s_super
*archive
, int tard
, int n
)
377 mc_lseek (tard
, n
* RECORDSIZE
, SEEK_CUR
);
378 current_tar_position
+= n
* RECORDSIZE
;
381 /* --------------------------------------------------------------------------------------------- */
384 tar_fill_stat (struct vfs_s_super
*archive
, struct stat
*st
, union record
*header
, size_t h_size
)
386 tar_super_data_t
*arch
= (tar_super_data_t
*) archive
->data
;
388 st
->st_mode
= tar_from_oct (8, header
->header
.mode
);
390 /* Adjust st->st_mode because there are tar-files with
391 * linkflag==LF_SYMLINK and S_ISLNK(mod)==0. I don't
392 * know about the other modes but I think I cause no new
393 * problem when I adjust them, too. -- Norbert.
395 if (header
->header
.linkflag
== LF_DIR
)
396 st
->st_mode
|= S_IFDIR
;
397 else if (header
->header
.linkflag
== LF_SYMLINK
)
398 st
->st_mode
|= S_IFLNK
;
399 else if (header
->header
.linkflag
== LF_CHR
)
400 st
->st_mode
|= S_IFCHR
;
401 else if (header
->header
.linkflag
== LF_BLK
)
402 st
->st_mode
|= S_IFBLK
;
403 else if (header
->header
.linkflag
== LF_FIFO
)
404 st
->st_mode
|= S_IFIFO
;
406 st
->st_mode
|= S_IFREG
;
415 st
->st_uid
= *header
->header
.uname
416 ? vfs_finduid (header
->header
.uname
)
417 : tar_from_oct (8, header
->header
.uid
);
418 st
->st_gid
= *header
->header
.gname
419 ? vfs_findgid (header
->header
.gname
)
420 : tar_from_oct (8,header
->header
.gid
);
423 switch (header
->header
.linkflag
)
428 (tar_from_oct (8, header
->header
.devmajor
) << 8) |
429 tar_from_oct (8, header
->header
.devminor
);
432 st
->st_uid
= tar_from_oct (8, header
->header
.uid
);
433 st
->st_gid
= tar_from_oct (8, header
->header
.gid
);
435 st
->st_size
= h_size
;
436 st
->st_mtime
= tar_from_oct (1 + 12, header
->header
.mtime
);
439 if (arch
->type
== TAR_GNU
)
441 st
->st_atime
= tar_from_oct (1 + 12, header
->header
.unused
.oldgnu
.atime
);
442 st
->st_ctime
= tar_from_oct (1 + 12, header
->header
.unused
.oldgnu
.ctime
);
446 /* --------------------------------------------------------------------------------------------- */
448 * Return 1 for success, 0 if the checksum is bad, EOF on eof,
449 * 2 for a record full of zeros (EOF marker).
453 tar_read_header (struct vfs_class
*me
, struct vfs_s_super
*archive
, int tard
, size_t * h_size
)
455 tar_super_data_t
*arch
= (tar_super_data_t
*) archive
->data
;
458 register long sum
, signed_sum
, recsum
;
460 register union record
*header
;
461 static char *next_long_name
= NULL
, *next_long_link
= NULL
;
465 header
= tar_get_next_record (archive
, tard
);
469 recsum
= tar_from_oct (8, header
->header
.chksum
);
474 for (i
= sizeof (*header
); --i
>= 0;)
477 * We can't use unsigned char here because of old compilers,
484 /* Adjust checksum to count the "chksum" field as blanks. */
485 for (i
= sizeof (header
->header
.chksum
); --i
>= 0;)
487 sum
-= 0xFF & header
->header
.chksum
[i
];
488 signed_sum
-= (char) header
->header
.chksum
[i
];
490 sum
+= ' ' * sizeof header
->header
.chksum
;
491 signed_sum
+= ' ' * sizeof header
->header
.chksum
;
494 * This is a zeroed record...whole record is 0's except
495 * for the 8 blanks we faked for the checksum field.
498 return STATUS_EOFMARK
;
500 if (sum
!= recsum
&& signed_sum
!= recsum
)
501 return STATUS_BADCHECKSUM
;
504 * Try to determine the archive format.
506 if (arch
->type
== TAR_UNKNOWN
)
508 if (strcmp (header
->header
.magic
, TMAGIC
) == 0)
510 if (header
->header
.linkflag
== LF_GLOBAL_EXTHDR
)
511 arch
->type
= TAR_POSIX
;
513 arch
->type
= TAR_USTAR
;
515 else if (strcmp (header
->header
.magic
, OLDGNU_MAGIC
) == 0)
516 arch
->type
= TAR_GNU
;
520 * linkflag on BSDI tar (pax) always '\000'
522 if (header
->header
.linkflag
== '\000')
526 if (header
->header
.arch_name
[NAMSIZ
- 1] != '\0')
529 len
= strlen (header
->header
.arch_name
);
531 if (len
!= 0 && header
->header
.arch_name
[len
- 1] == '/')
532 header
->header
.linkflag
= LF_DIR
;
536 * Good record. Decode file size and return.
538 if (header
->header
.linkflag
== LF_LINK
|| header
->header
.linkflag
== LF_DIR
)
539 *h_size
= 0; /* Links 0 size on tape */
541 *h_size
= tar_from_oct (1 + 12, header
->header
.size
);
544 * Skip over directory snapshot info records that
545 * are stored in incremental tar archives.
547 if (header
->header
.linkflag
== LF_DUMPDIR
)
549 if (arch
->type
== TAR_UNKNOWN
)
550 arch
->type
= TAR_GNU
;
551 return STATUS_SUCCESS
;
555 * Skip over pax extended header and global extended
558 if (header
->header
.linkflag
== LF_EXTHDR
|| header
->header
.linkflag
== LF_GLOBAL_EXTHDR
)
560 if (arch
->type
== TAR_UNKNOWN
)
561 arch
->type
= TAR_POSIX
;
562 return STATUS_SUCCESS
;
565 if (header
->header
.linkflag
== LF_LONGNAME
|| header
->header
.linkflag
== LF_LONGLINK
)
571 if (arch
->type
== TAR_UNKNOWN
)
572 arch
->type
= TAR_GNU
;
574 if (*h_size
> MC_MAXPATHLEN
)
576 message (D_ERROR
, MSG_ERROR
, _("Inconsistent tar archive"));
577 return STATUS_BADCHECKSUM
;
580 longp
= ((header
->header
.linkflag
== LF_LONGNAME
) ? &next_long_name
: &next_long_link
);
583 bp
= *longp
= g_malloc (*h_size
+ 1);
585 for (size
= *h_size
; size
> 0; size
-= written
)
587 data
= tar_get_next_record (archive
, tard
)->charptr
;
592 message (D_ERROR
, MSG_ERROR
, _("Unexpected EOF on archive file"));
593 return STATUS_BADCHECKSUM
;
595 written
= RECORDSIZE
;
599 memcpy (bp
, data
, written
);
603 if (bp
- *longp
== MC_MAXPATHLEN
&& bp
[-1] != '\0')
607 message (D_ERROR
, MSG_ERROR
, _("Inconsistent tar archive"));
608 return STATUS_BADCHECKSUM
;
616 struct vfs_s_entry
*entry
;
617 struct vfs_s_inode
*inode
= NULL
, *parent
;
621 char *current_file_name
, *current_link_name
;
624 (next_long_link
? next_long_link
: g_strndup (header
->header
.arch_linkname
, NAMSIZ
));
625 len
= strlen (current_link_name
);
626 if (len
> 1 && current_link_name
[len
- 1] == '/')
627 current_link_name
[len
- 1] = 0;
629 current_file_name
= NULL
;
634 /* The ustar archive format supports pathnames of upto 256
635 * characters in length. This is achieved by concatenating
636 * the contents of the `prefix' and `arch_name' fields like
639 * prefix + path_separator + arch_name
641 * If the `prefix' field contains an empty string i.e. its
642 * first characters is '\0' the prefix field is ignored.
644 if (header
->header
.unused
.prefix
[0] != '\0')
646 char *temp_name
, *temp_prefix
;
648 temp_name
= g_strndup (header
->header
.arch_name
, NAMSIZ
);
649 temp_prefix
= g_strndup (header
->header
.unused
.prefix
, PREFIX_SIZE
);
650 current_file_name
= g_strconcat (temp_prefix
, PATH_SEP_STR
,
651 temp_name
, (char *) NULL
);
653 g_free (temp_prefix
);
657 if (next_long_name
!= NULL
)
658 current_file_name
= next_long_name
;
664 if (current_file_name
== NULL
)
666 if (next_long_name
!= NULL
)
667 current_file_name
= g_strdup (next_long_name
);
669 current_file_name
= g_strndup (header
->header
.arch_name
, NAMSIZ
);
672 canonicalize_pathname (current_file_name
);
673 len
= strlen (current_file_name
);
675 data_position
= current_tar_position
;
677 p
= strrchr (current_file_name
, '/');
680 p
= current_file_name
;
681 q
= current_file_name
+ len
; /* "" */
686 q
= current_file_name
;
689 parent
= vfs_s_find_inode (me
, archive
, q
, LINK_NO_FOLLOW
, FL_MKDIR
);
692 message (D_ERROR
, MSG_ERROR
, _("Inconsistent tar archive"));
693 return STATUS_BADCHECKSUM
;
696 if (header
->header
.linkflag
== LF_LINK
)
698 inode
= vfs_s_find_inode (me
, archive
, current_link_name
, LINK_NO_FOLLOW
, 0);
701 message (D_ERROR
, MSG_ERROR
, _("Inconsistent tar archive"));
705 entry
= vfs_s_new_entry (me
, p
, inode
);
706 vfs_s_insert_entry (me
, parent
, entry
);
707 g_free (current_link_name
);
712 tar_fill_stat (archive
, &st
, header
, *h_size
);
713 if (S_ISDIR (st
.st_mode
))
715 entry
= MEDATA
->find_entry (me
, parent
, p
, LINK_NO_FOLLOW
, FL_NONE
);
719 inode
= vfs_s_new_inode (me
, archive
, &st
);
721 inode
->data_offset
= data_position
;
722 if (*current_link_name
)
724 inode
->linkname
= current_link_name
;
726 else if (current_link_name
!= next_long_link
)
728 g_free (current_link_name
);
730 entry
= vfs_s_new_entry (me
, p
, inode
);
732 vfs_s_insert_entry (me
, parent
, entry
);
733 g_free (current_file_name
);
736 next_long_link
= next_long_name
= NULL
;
738 if (arch
->type
== TAR_GNU
&& header
->header
.unused
.oldgnu
.isextended
)
740 while (tar_get_next_record (archive
, tard
)->ext_hdr
.isextended
!= 0)
742 inode
->data_offset
= current_tar_position
;
744 return STATUS_SUCCESS
;
748 /* --------------------------------------------------------------------------------------------- */
750 * Main loop for reading an archive.
751 * Returns 0 on success, -1 on error.
754 tar_open_archive (struct vfs_s_super
*archive
, const vfs_path_t
* vpath
,
755 const vfs_path_element_t
* vpath_element
)
757 /* Initial status at start of archive */
758 ReadStatus status
= STATUS_EOFMARK
;
759 ReadStatus prev_status
;
762 current_tar_position
= 0;
763 /* Open for reading */
764 tard
= tar_open_archive_int (vpath_element
->class, vpath
, archive
);
772 prev_status
= status
;
773 status
= tar_read_header (vpath_element
->class, archive
, tard
, &h_size
);
779 tar_skip_n_records (archive
, tard
, (h_size
+ RECORDSIZE
- 1) / RECORDSIZE
);
785 * If the previous header was good, tell them
786 * that we are skipping bad ones.
788 case STATUS_BADCHECKSUM
:
792 /* Error on first record */
795 char *archive_name
= vfs_path_to_str (vpath
);
796 message (D_ERROR
, MSG_ERROR
, _("%s\ndoesn't look like a tar archive."),
798 g_free (archive_name
);
801 /* Error after header rec */
804 /* Error after error */
806 case STATUS_BADCHECKSUM
:
813 /* Record of zeroes */
815 status
= prev_status
; /* If error after 0's */
818 case STATUS_EOF
: /* End of archive */
826 /* --------------------------------------------------------------------------------------------- */
829 tar_super_check (const vfs_path_t
* vpath
)
831 static struct stat stat_buf
;
834 stat_result
= mc_stat (vpath
, &stat_buf
);
836 return (stat_result
!= 0) ? NULL
: &stat_buf
;
839 /* --------------------------------------------------------------------------------------------- */
842 tar_super_same (const vfs_path_element_t
* vpath_element
, struct vfs_s_super
*parc
,
843 const vfs_path_t
* vpath
, void *cookie
)
845 struct stat
*archive_stat
= cookie
; /* stat of main archive */
846 char *archive_name
= vfs_path_to_str (vpath
);
848 (void) vpath_element
;
850 if (strcmp (parc
->name
, archive_name
) != 0)
852 g_free (archive_name
);
855 g_free (archive_name
);
857 /* Has the cached archive been changed on the disk? */
858 if (((tar_super_data_t
*) parc
->data
)->st
.st_mtime
< archive_stat
->st_mtime
)
861 (*vfs_tarfs_ops
.free
) ((vfsid
) parc
);
862 vfs_rmstamp (&vfs_tarfs_ops
, (vfsid
) parc
);
865 /* Hasn't been modified, give it a new timeout */
866 vfs_stamp (&vfs_tarfs_ops
, (vfsid
) parc
);
870 /* --------------------------------------------------------------------------------------------- */
873 tar_read (void *fh
, char *buffer
, size_t count
)
875 off_t begin
= FH
->ino
->data_offset
;
876 int fd
= ((tar_super_data_t
*) FH_SUPER
->data
)->fd
;
877 struct vfs_class
*me
= FH_SUPER
->me
;
880 if (mc_lseek (fd
, begin
+ FH
->pos
, SEEK_SET
) != begin
+ FH
->pos
)
883 count
= MIN (count
, (size_t) (FH
->ino
->st
.st_size
- FH
->pos
));
885 res
= mc_read (fd
, buffer
, count
);
893 /* --------------------------------------------------------------------------------------------- */
896 tar_fh_open (struct vfs_class
*me
, vfs_file_handler_t
* fh
, int flags
, mode_t mode
)
901 if ((flags
& O_ACCMODE
) != O_RDONLY
)
906 /* --------------------------------------------------------------------------------------------- */
907 /*** public functions ****************************************************************************/
908 /* --------------------------------------------------------------------------------------------- */
913 static struct vfs_s_subclass tarfs_subclass
;
915 tarfs_subclass
.flags
= VFS_S_READONLY
; /* FIXME: tarfs used own temp files */
916 tarfs_subclass
.archive_check
= tar_super_check
;
917 tarfs_subclass
.archive_same
= tar_super_same
;
918 tarfs_subclass
.open_archive
= tar_open_archive
;
919 tarfs_subclass
.free_archive
= tar_free_archive
;
920 tarfs_subclass
.fh_open
= tar_fh_open
;
922 vfs_s_init_class (&vfs_tarfs_ops
, &tarfs_subclass
);
923 vfs_tarfs_ops
.name
= "tarfs";
924 vfs_tarfs_ops
.prefix
= "utar";
925 vfs_tarfs_ops
.read
= tar_read
;
926 vfs_tarfs_ops
.setctl
= NULL
;
927 vfs_register_class (&vfs_tarfs_ops
);
930 /* --------------------------------------------------------------------------------------------- */