1 /* Virtual File System: GNU Tar file system.
2 Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3 2006, 2007 Free Software Foundation, Inc.
5 Written by: 1995 Jakub Jelinek
6 Rewritten by: 1998 Pavel Machek
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Library General Public License
10 as published by the Free Software Foundation; either version 2 of
11 the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Library General Public License for more details.
18 You should have received a copy of the GNU Library General Public
19 License along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
24 * \brief Source: Virtual File System: GNU Tar file system
25 * \author Jakub Jelinek
26 * \author Pavel Machek
29 * Namespace: init_tarfs
33 #include <sys/types.h>
39 /* major() and minor() macros (among other things) defined here for hpux */
40 #include <sys/mknod.h>
43 #include "../src/global.h"
45 #include "../src/wtools.h" /* message() */
46 #include "../src/main.h" /* print_vfs_message */
49 #include "gc.h" /* vfs_rmstamp */
50 #include "xdirentry.h"
52 static struct vfs_class vfs_tarfs_ops
;
63 * Header block on tape.
65 * I'm going to use traditional DP naming conventions here.
66 * A "block" is a big chunk of stuff that we do I/O on.
67 * A "record" is a piece of info that we care about.
68 * Typically many "record"s fit into a "block".
70 #define RECORDSIZE 512
72 #define PREFIX_SIZE 155
75 #define SPARSE_EXT_HDR 21
76 #define SPARSE_IN_HDR 4
89 char charptr
[RECORDSIZE
];
91 char arch_name
[NAMSIZ
];
99 char arch_linkname
[NAMSIZ
];
105 /* The following bytes of the tar header record were originally unused.
107 Archives following the ustar specification use almost all of those
108 bytes to support pathnames of 256 characters in length.
110 GNU tar archives use the "unused" space to support incremental
111 archives and sparse files. */
113 char prefix
[PREFIX_SIZE
];
114 /* GNU extensions to the ustar (POSIX.1-1988) archive format. */
121 struct sparse sp
[SPARSE_IN_HDR
];
123 char realsize
[12]; /* true size of the sparse file */
127 struct extended_header
{
128 struct sparse sp
[21];
133 /* The checksum field is filled with this while the checksum is computed. */
134 #define CHKBLANKS " " /* 8 blanks, no null */
136 /* The magic field is filled with this if uname and gname are valid. */
137 #define TMAGIC "ustar" /* ustar and a null */
138 #define OLDGNU_MAGIC "ustar " /* 7 chars and a null */
140 /* The linkflag defines the type of file */
141 #define LF_OLDNORMAL '\0' /* Normal disk file, Unix compat */
142 #define LF_NORMAL '0' /* Normal disk file */
143 #define LF_LINK '1' /* Link to previously dumped file */
144 #define LF_SYMLINK '2' /* Symbolic link */
145 #define LF_CHR '3' /* Character special file */
146 #define LF_BLK '4' /* Block special file */
147 #define LF_DIR '5' /* Directory */
148 #define LF_FIFO '6' /* FIFO special file */
149 #define LF_CONTIG '7' /* Contiguous file */
150 #define LF_EXTHDR 'x' /* pax Extended Header */
151 #define LF_GLOBAL_EXTHDR 'g' /* pax Global Extended Header */
152 /* Further link types may be defined later. */
154 /* Note that the standards committee allows only capital A through
155 capital Z for user-defined expansion. This means that defining something
156 as, say '8' is a *bad* idea. */
157 #define LF_DUMPDIR 'D' /* This is a dir entry that contains
158 the names of files that were in
159 the dir at the time the dump
161 #define LF_LONGLINK 'K' /* Identifies the NEXT file on the tape
162 as having a long linkname */
163 #define LF_LONGNAME 'L' /* Identifies the NEXT file on the tape
164 as having a long name. */
165 #define LF_MULTIVOL 'M' /* This is the continuation
166 of a file that began on another
168 #define LF_NAMES 'N' /* For storing filenames that didn't
169 fit in 100 characters */
170 #define LF_SPARSE 'S' /* This is for sparse files */
171 #define LF_VOLHDR 'V' /* This file is a tape/volume header */
172 /* Ignore it on extraction */
175 * Exit codes from the "tar" program
177 #define EX_SUCCESS 0 /* success! */
178 #define EX_ARGSBAD 1 /* invalid args */
179 #define EX_BADFILE 2 /* invalid filename */
180 #define EX_BADARCH 3 /* bad archive */
181 #define EX_SYSTEM 4 /* system gave unexpected error */
182 #define EX_BADVOL 5 /* Special error code means
183 Tape volume doesn't match the one
184 specified on the command line */
186 #define isodigit(c) ( ((c) >= '0') && ((c) <= '7') )
189 * Quick and dirty octal conversion.
191 * Result is -1 if the field is invalid (all blank, or nonoctal).
193 static long tar_from_oct (int digs
, char *where
)
197 while (isspace ((unsigned char) *where
)) { /* Skip spaces */
200 return -1; /* All blank field */
203 while (digs
> 0 && isodigit (*where
)) { /* Scan till nonoctal */
204 value
= (value
<< 3) | (*where
++ - '0');
208 if (digs
> 0 && *where
&& !isspace ((unsigned char) *where
))
209 return -1; /* Ended on non-space/nul */
214 static void tar_free_archive (struct vfs_class
*me
, struct vfs_s_super
*archive
)
218 if (archive
->u
.arch
.fd
!= -1)
219 mc_close(archive
->u
.arch
.fd
);
222 /* As we open one archive at a time, it is safe to have this static */
223 static int current_tar_position
= 0;
225 /* Returns fd of the open tar file */
227 tar_open_archive_int (struct vfs_class
*me
, const char *name
,
228 struct vfs_s_super
*archive
)
232 struct vfs_s_inode
*root
;
234 result
= mc_open (name
, O_RDONLY
);
236 message (D_ERROR
, MSG_ERROR
, _("Cannot open tar archive\n%s"), name
);
240 archive
->name
= g_strdup (name
);
241 mc_stat (name
, &(archive
->u
.arch
.st
));
242 archive
->u
.arch
.fd
= -1;
243 archive
->u
.arch
.type
= TAR_UNKNOWN
;
245 /* Find out the method to handle this tar file */
246 type
= get_compression_type (result
, name
);
247 mc_lseek (result
, 0, SEEK_SET
);
248 if (type
!= COMPRESSION_NONE
) {
251 s
= g_strconcat (archive
->name
, decompress_extension (type
), (char *) NULL
);
252 result
= mc_open (s
, O_RDONLY
);
254 message (D_ERROR
, MSG_ERROR
, _("Cannot open tar archive\n%s"), s
);
260 archive
->u
.arch
.fd
= result
;
261 mode
= archive
->u
.arch
.st
.st_mode
& 07777;
270 root
= vfs_s_new_inode (me
, archive
, &archive
->u
.arch
.st
);
271 root
->st
.st_mode
= mode
;
272 root
->data_offset
= -1;
274 root
->st
.st_dev
= MEDATA
->rdev
++;
276 archive
->root
= root
;
281 static union record rec_buf
;
283 static union record
*
284 tar_get_next_record (struct vfs_s_super
*archive
, int tard
)
290 n
= mc_read (tard
, rec_buf
.charptr
, RECORDSIZE
);
292 return NULL
; /* An error has occurred */
293 current_tar_position
+= RECORDSIZE
;
297 static void tar_skip_n_records (struct vfs_s_super
*archive
, int tard
, int n
)
301 mc_lseek (tard
, n
* RECORDSIZE
, SEEK_CUR
);
302 current_tar_position
+= n
* RECORDSIZE
;
306 tar_fill_stat (struct vfs_s_super
*archive
, struct stat
*st
, union record
*header
,
309 st
->st_mode
= tar_from_oct (8, header
->header
.mode
);
311 /* Adjust st->st_mode because there are tar-files with
312 * linkflag==LF_SYMLINK and S_ISLNK(mod)==0. I don't
313 * know about the other modes but I think I cause no new
314 * problem when I adjust them, too. -- Norbert.
316 if (header
->header
.linkflag
== LF_DIR
) {
317 st
->st_mode
|= S_IFDIR
;
318 } else if (header
->header
.linkflag
== LF_SYMLINK
) {
319 st
->st_mode
|= S_IFLNK
;
320 } else if (header
->header
.linkflag
== LF_CHR
) {
321 st
->st_mode
|= S_IFCHR
;
322 } else if (header
->header
.linkflag
== LF_BLK
) {
323 st
->st_mode
|= S_IFBLK
;
324 } else if (header
->header
.linkflag
== LF_FIFO
) {
325 st
->st_mode
|= S_IFIFO
;
327 st
->st_mode
|= S_IFREG
;
330 switch (archive
->u
.arch
.type
) {
335 *header
->header
.uname
? vfs_finduid (header
->header
.
336 uname
) : tar_from_oct (8,
341 *header
->header
.gname
? vfs_findgid (header
->header
.
342 gname
) : tar_from_oct (8,
346 switch (header
->header
.linkflag
) {
350 (tar_from_oct (8, header
->header
.devmajor
) << 8) |
351 tar_from_oct (8, header
->header
.devminor
);
354 st
->st_uid
= tar_from_oct (8, header
->header
.uid
);
355 st
->st_gid
= tar_from_oct (8, header
->header
.gid
);
357 st
->st_size
= h_size
;
358 st
->st_mtime
= tar_from_oct (1 + 12, header
->header
.mtime
);
361 if (archive
->u
.arch
.type
== TAR_GNU
) {
362 st
->st_atime
= tar_from_oct (1 + 12,
363 header
->header
.unused
.oldgnu
.atime
);
364 st
->st_ctime
= tar_from_oct (1 + 12,
365 header
->header
.unused
.oldgnu
.ctime
);
377 * Return 1 for success, 0 if the checksum is bad, EOF on eof,
378 * 2 for a record full of zeros (EOF marker).
382 tar_read_header (struct vfs_class
*me
, struct vfs_s_super
*archive
,
383 int tard
, size_t *h_size
)
386 register long sum
, signed_sum
, recsum
;
388 register union record
*header
;
389 static char *next_long_name
= NULL
, *next_long_link
= NULL
;
393 header
= tar_get_next_record (archive
, tard
);
397 recsum
= tar_from_oct (8, header
->header
.chksum
);
402 for (i
= sizeof (*header
); --i
>= 0;) {
404 * We can't use unsigned char here because of old compilers,
411 /* Adjust checksum to count the "chksum" field as blanks. */
412 for (i
= sizeof (header
->header
.chksum
); --i
>= 0;) {
413 sum
-= 0xFF & header
->header
.chksum
[i
];
414 signed_sum
-= (char) header
->header
.chksum
[i
];
416 sum
+= ' ' * sizeof header
->header
.chksum
;
417 signed_sum
+= ' ' * sizeof header
->header
.chksum
;
420 * This is a zeroed record...whole record is 0's except
421 * for the 8 blanks we faked for the checksum field.
424 return STATUS_EOFMARK
;
426 if (sum
!= recsum
&& signed_sum
!= recsum
)
427 return STATUS_BADCHECKSUM
;
430 * Try to determine the archive format.
432 if (archive
->u
.arch
.type
== TAR_UNKNOWN
) {
433 if (!strcmp (header
->header
.magic
, TMAGIC
)) {
434 if (header
->header
.linkflag
== LF_GLOBAL_EXTHDR
)
435 archive
->u
.arch
.type
= TAR_POSIX
;
437 archive
->u
.arch
.type
= TAR_USTAR
;
438 } else if (!strcmp (header
->header
.magic
, OLDGNU_MAGIC
)) {
439 archive
->u
.arch
.type
= TAR_GNU
;
444 * linkflag on BSDI tar (pax) always '\000'
446 if (header
->header
.linkflag
== '\000') {
447 if (header
->header
.arch_name
[NAMSIZ
- 1] != '\0')
450 i
= strlen (header
->header
.arch_name
);
452 if (i
&& header
->header
.arch_name
[i
- 1] == '/')
453 header
->header
.linkflag
= LF_DIR
;
457 * Good record. Decode file size and return.
459 if (header
->header
.linkflag
== LF_LINK
460 || header
->header
.linkflag
== LF_DIR
)
461 *h_size
= 0; /* Links 0 size on tape */
463 *h_size
= tar_from_oct (1 + 12, header
->header
.size
);
466 * Skip over directory snapshot info records that
467 * are stored in incremental tar archives.
469 if (header
->header
.linkflag
== LF_DUMPDIR
) {
470 if (archive
->u
.arch
.type
== TAR_UNKNOWN
)
471 archive
->u
.arch
.type
= TAR_GNU
;
472 return STATUS_SUCCESS
;
476 * Skip over pax extended header and global extended
479 if (header
->header
.linkflag
== LF_EXTHDR
||
480 header
->header
.linkflag
== LF_GLOBAL_EXTHDR
) {
481 if (archive
->u
.arch
.type
== TAR_UNKNOWN
)
482 archive
->u
.arch
.type
= TAR_POSIX
;
483 return STATUS_SUCCESS
;
486 if (header
->header
.linkflag
== LF_LONGNAME
487 || header
->header
.linkflag
== LF_LONGLINK
) {
492 if (archive
->u
.arch
.type
== TAR_UNKNOWN
)
493 archive
->u
.arch
.type
= TAR_GNU
;
495 if (*h_size
> MC_MAXPATHLEN
) {
496 message (D_ERROR
, MSG_ERROR
, _("Inconsistent tar archive"));
497 return STATUS_BADCHECKSUM
;
500 longp
= ((header
->header
.linkflag
== LF_LONGNAME
)
501 ? &next_long_name
: &next_long_link
);
504 bp
= *longp
= g_malloc (*h_size
+ 1);
506 for (size
= *h_size
; size
> 0; size
-= written
) {
507 data
= tar_get_next_record (archive
, tard
)->charptr
;
511 message (D_ERROR
, MSG_ERROR
,
512 _("Unexpected EOF on archive file"));
513 return STATUS_BADCHECKSUM
;
515 written
= RECORDSIZE
;
519 memcpy (bp
, data
, written
);
523 if (bp
- *longp
== MC_MAXPATHLEN
&& bp
[-1] != '\0') {
526 message (D_ERROR
, MSG_ERROR
, _("Inconsistent tar archive"));
527 return STATUS_BADCHECKSUM
;
533 struct vfs_s_entry
*entry
;
534 struct vfs_s_inode
*inode
= NULL
, *parent
;
538 char *current_file_name
, *current_link_name
;
541 (next_long_link
? next_long_link
:
542 g_strndup (header
->header
.arch_linkname
, NAMSIZ
));
543 len
= strlen (current_link_name
);
544 if (len
> 1 && current_link_name
[len
- 1] == '/')
545 current_link_name
[len
- 1] = 0;
547 current_file_name
= NULL
;
548 switch (archive
->u
.arch
.type
) {
551 /* The ustar archive format supports pathnames of upto 256
552 * characters in length. This is achieved by concatenating
553 * the contents of the `prefix' and `arch_name' fields like
556 * prefix + path_separator + arch_name
558 * If the `prefix' field contains an empty string i.e. its
559 * first characters is '\0' the prefix field is ignored.
561 if (header
->header
.unused
.prefix
[0] != '\0') {
562 char *temp_name
, *temp_prefix
;
564 temp_name
= g_strndup (header
->header
.arch_name
, NAMSIZ
);
565 temp_prefix
= g_strndup (header
->header
.unused
.prefix
,
567 current_file_name
= g_strconcat (temp_prefix
, PATH_SEP_STR
,
568 temp_name
, (char *) NULL
);
570 g_free (temp_prefix
);
574 if (next_long_name
!= NULL
)
575 current_file_name
= next_long_name
;
581 if (current_file_name
== NULL
)
582 current_file_name
= g_strndup (header
->header
.arch_name
, NAMSIZ
);
584 canonicalize_pathname (current_file_name
);
585 len
= strlen (current_file_name
);
587 data_position
= current_tar_position
;
589 p
= strrchr (current_file_name
, '/');
591 p
= current_file_name
;
592 q
= current_file_name
+ len
; /* "" */
595 q
= current_file_name
;
599 vfs_s_find_inode (me
, archive
, q
, LINK_NO_FOLLOW
, FL_MKDIR
);
600 if (parent
== NULL
) {
601 message (D_ERROR
, MSG_ERROR
, _("Inconsistent tar archive"));
602 return STATUS_BADCHECKSUM
;
605 if (header
->header
.linkflag
== LF_LINK
) {
607 vfs_s_find_inode (me
, archive
, current_link_name
,
610 message (D_ERROR
, MSG_ERROR
, _("Inconsistent tar archive"));
612 entry
= vfs_s_new_entry (me
, p
, inode
);
613 vfs_s_insert_entry (me
, parent
, entry
);
614 g_free (current_link_name
);
619 tar_fill_stat (archive
, &st
, header
, *h_size
);
620 if (S_ISDIR(st
.st_mode
)) {
621 entry
= MEDATA
->find_entry (me
, parent
, p
, LINK_NO_FOLLOW
, FL_NONE
);
625 inode
= vfs_s_new_inode (me
, archive
, &st
);
627 inode
->data_offset
= data_position
;
628 if (*current_link_name
) {
629 inode
->linkname
= current_link_name
;
630 } else if (current_link_name
!= next_long_link
) {
631 g_free (current_link_name
);
633 entry
= vfs_s_new_entry (me
, p
, inode
);
635 vfs_s_insert_entry (me
, parent
, entry
);
636 g_free (current_file_name
);
639 next_long_link
= next_long_name
= NULL
;
641 if (archive
->u
.arch
.type
== TAR_GNU
&&
642 header
->header
.unused
.oldgnu
.isextended
) {
643 while (tar_get_next_record (archive
, tard
)->ext_hdr
.
645 inode
->data_offset
= current_tar_position
;
647 return STATUS_SUCCESS
;
652 * Main loop for reading an archive.
653 * Returns 0 on success, -1 on error.
656 tar_open_archive (struct vfs_class
*me
, struct vfs_s_super
*archive
,
657 const char *name
, char *op
)
659 /* Initial status at start of archive */
660 ReadStatus status
= STATUS_EOFMARK
;
661 ReadStatus prev_status
;
666 current_tar_position
= 0;
667 /* Open for reading */
668 if ((tard
= tar_open_archive_int (me
, name
, archive
)) == -1)
674 prev_status
= status
;
675 status
= tar_read_header (me
, archive
, tard
, &h_size
);
680 tar_skip_n_records (archive
, tard
,
681 (h_size
+ RECORDSIZE
-
688 * If the previous header was good, tell them
689 * that we are skipping bad ones.
691 case STATUS_BADCHECKSUM
:
692 switch (prev_status
) {
694 /* Error on first record */
696 message (D_ERROR
, MSG_ERROR
,
698 ("Hmm,...\n%s\ndoesn't look like a tar archive."),
702 /* Error after header rec */
704 /* Error after error */
706 case STATUS_BADCHECKSUM
:
713 /* Record of zeroes */
715 status
= prev_status
; /* If error after 0's */
718 case STATUS_EOF
: /* End of archive */
727 tar_super_check (struct vfs_class
*me
, const char *archive_name
, char *op
)
729 static struct stat stat_buf
;
734 if (mc_stat (archive_name
, &stat_buf
))
740 tar_super_same (struct vfs_class
*me
, struct vfs_s_super
*parc
,
741 const char *archive_name
, char *op
, void *cookie
)
743 struct stat
*archive_stat
= cookie
; /* stat of main archive */
748 if (strcmp (parc
->name
, archive_name
))
751 /* Has the cached archive been changed on the disk? */
752 if (parc
->u
.arch
.st
.st_mtime
< archive_stat
->st_mtime
) {
754 (*vfs_tarfs_ops
.free
) ((vfsid
) parc
);
755 vfs_rmstamp (&vfs_tarfs_ops
, (vfsid
) parc
);
758 /* Hasn't been modified, give it a new timeout */
759 vfs_stamp (&vfs_tarfs_ops
, (vfsid
) parc
);
763 static ssize_t
tar_read (void *fh
, char *buffer
, int count
)
765 off_t begin
= FH
->ino
->data_offset
;
766 int fd
= FH_SUPER
->u
.arch
.fd
;
767 struct vfs_class
*me
= FH_SUPER
->me
;
769 if (mc_lseek (fd
, begin
+ FH
->pos
, SEEK_SET
) !=
770 begin
+ FH
->pos
) ERRNOR (EIO
, -1);
772 count
= MIN(count
, FH
->ino
->st
.st_size
- FH
->pos
);
774 if ((count
= mc_read (fd
, buffer
, count
)) == -1) ERRNOR (errno
, -1);
780 static int tar_fh_open (struct vfs_class
*me
, struct vfs_s_fh
*fh
, int flags
, int mode
)
785 if ((flags
& O_ACCMODE
) != O_RDONLY
) ERRNOR (EROFS
, -1);
792 static struct vfs_s_subclass tarfs_subclass
;
794 tarfs_subclass
.flags
= VFS_S_READONLY
;
795 tarfs_subclass
.archive_check
= tar_super_check
;
796 tarfs_subclass
.archive_same
= tar_super_same
;
797 tarfs_subclass
.open_archive
= tar_open_archive
;
798 tarfs_subclass
.free_archive
= tar_free_archive
;
799 tarfs_subclass
.fh_open
= tar_fh_open
;
801 vfs_s_init_class (&vfs_tarfs_ops
, &tarfs_subclass
);
802 vfs_tarfs_ops
.name
= "tarfs";
803 vfs_tarfs_ops
.prefix
= "utar";
804 vfs_tarfs_ops
.read
= tar_read
;
805 vfs_tarfs_ops
.setctl
= NULL
;
806 vfs_register_class (&vfs_tarfs_ops
);