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 "lib/global.h"
45 #include "lib/widget.h" /* message() */
49 #include "xdirentry.h"
50 #include "gc.h" /* vfs_rmstamp */
52 /*** global variables ****************************************************************************/
54 /*** file scope macro definitions ****************************************************************/
57 * Header block on tape.
59 * I'm going to use traditional DP naming conventions here.
60 * A "block" is a big chunk of stuff that we do I/O on.
61 * A "record" is a piece of info that we care about.
62 * Typically many "record"s fit into a "block".
64 #define RECORDSIZE 512
66 #define PREFIX_SIZE 155
69 #define SPARSE_EXT_HDR 21
70 #define SPARSE_IN_HDR 4
72 /* The checksum field is filled with this while the checksum is computed. */
73 #define CHKBLANKS " " /* 8 blanks, no null */
75 /* The magic field is filled with this if uname and gname are valid. */
76 #define TMAGIC "ustar" /* ustar and a null */
77 #define OLDGNU_MAGIC "ustar " /* 7 chars and a null */
79 /* The linkflag defines the type of file */
80 #define LF_OLDNORMAL '\0' /* Normal disk file, Unix compat */
81 #define LF_NORMAL '0' /* Normal disk file */
82 #define LF_LINK '1' /* Link to previously dumped file */
83 #define LF_SYMLINK '2' /* Symbolic link */
84 #define LF_CHR '3' /* Character special file */
85 #define LF_BLK '4' /* Block special file */
86 #define LF_DIR '5' /* Directory */
87 #define LF_FIFO '6' /* FIFO special file */
88 #define LF_CONTIG '7' /* Contiguous file */
89 #define LF_EXTHDR 'x' /* pax Extended Header */
90 #define LF_GLOBAL_EXTHDR 'g' /* pax Global Extended Header */
91 /* Further link types may be defined later. */
93 /* Note that the standards committee allows only capital A through
94 capital Z for user-defined expansion. This means that defining something
95 as, say '8' is a *bad* idea. */
96 #define LF_DUMPDIR 'D' /* This is a dir entry that contains
97 the names of files that were in
98 the dir at the time the dump
100 #define LF_LONGLINK 'K' /* Identifies the NEXT file on the tape
101 as having a long linkname */
102 #define LF_LONGNAME 'L' /* Identifies the NEXT file on the tape
103 as having a long name. */
104 #define LF_MULTIVOL 'M' /* This is the continuation
105 of a file that began on another
107 #define LF_NAMES 'N' /* For storing filenames that didn't
108 fit in 100 characters */
109 #define LF_SPARSE 'S' /* This is for sparse files */
110 #define LF_VOLHDR 'V' /* This file is a tape/volume header */
111 /* Ignore it on extraction */
114 * Exit codes from the "tar" program
116 #define EX_SUCCESS 0 /* success! */
117 #define EX_ARGSBAD 1 /* invalid args */
118 #define EX_BADFILE 2 /* invalid filename */
119 #define EX_BADARCH 3 /* bad archive */
120 #define EX_SYSTEM 4 /* system gave unexpected error */
121 #define EX_BADVOL 5 /* Special error code means
122 Tape volume doesn't match the one
123 specified on the command line */
125 #define isodigit(c) ( ((c) >= '0') && ((c) <= '7') )
127 /*** file scope type declarations ****************************************************************/
152 char charptr
[RECORDSIZE
];
155 char arch_name
[NAMSIZ
];
163 char arch_linkname
[NAMSIZ
];
169 /* The following bytes of the tar header record were originally unused.
171 Archives following the ustar specification use almost all of those
172 bytes to support pathnames of 256 characters in length.
174 GNU tar archives use the "unused" space to support incremental
175 archives and sparse files. */
178 char prefix
[PREFIX_SIZE
];
179 /* GNU extensions to the ustar (POSIX.1-1988) archive format. */
187 struct sparse sp
[SPARSE_IN_HDR
];
189 char realsize
[12]; /* true size of the sparse file */
193 struct extended_header
195 struct sparse sp
[21];
208 /*** file scope variables ************************************************************************/
210 static struct vfs_class vfs_tarfs_ops
;
212 /* As we open one archive at a time, it is safe to have this static */
213 static int current_tar_position
= 0;
215 static union record rec_buf
;
217 /*** file scope functions ************************************************************************/
218 /* --------------------------------------------------------------------------------------------- */
220 * Quick and dirty octal conversion.
222 * Result is -1 if the field is invalid (all blank, or nonoctal).
225 tar_from_oct (int digs
, char *where
)
229 while (isspace ((unsigned char) *where
))
233 return -1; /* All blank field */
236 while (digs
> 0 && isodigit (*where
))
237 { /* Scan till nonoctal */
238 value
= (value
<< 3) | (*where
++ - '0');
242 if (digs
> 0 && *where
&& !isspace ((unsigned char) *where
))
243 return -1; /* Ended on non-space/nul */
248 /* --------------------------------------------------------------------------------------------- */
251 tar_free_archive (struct vfs_class
*me
, struct vfs_s_super
*archive
)
255 if (archive
->u
.arch
.fd
!= -1)
256 mc_close (archive
->u
.arch
.fd
);
259 /* --------------------------------------------------------------------------------------------- */
261 /* Returns fd of the open tar file */
263 tar_open_archive_int (struct vfs_class
*me
, const char *name
, struct vfs_s_super
*archive
)
267 struct vfs_s_inode
*root
;
269 result
= mc_open (name
, O_RDONLY
);
272 message (D_ERROR
, MSG_ERROR
, _("Cannot open tar archive\n%s"), name
);
276 archive
->name
= g_strdup (name
);
277 mc_stat (name
, &(archive
->u
.arch
.st
));
278 archive
->u
.arch
.fd
= -1;
279 archive
->u
.arch
.type
= TAR_UNKNOWN
;
281 /* Find out the method to handle this tar file */
282 type
= get_compression_type (result
, name
);
283 mc_lseek (result
, 0, SEEK_SET
);
284 if (type
!= COMPRESSION_NONE
)
288 s
= g_strconcat (archive
->name
, decompress_extension (type
), (char *) NULL
);
289 result
= mc_open (s
, O_RDONLY
);
291 message (D_ERROR
, MSG_ERROR
, _("Cannot open tar archive\n%s"), s
);
297 archive
->u
.arch
.fd
= result
;
298 mode
= archive
->u
.arch
.st
.st_mode
& 07777;
307 root
= vfs_s_new_inode (me
, archive
, &archive
->u
.arch
.st
);
308 root
->st
.st_mode
= mode
;
309 root
->data_offset
= -1;
311 root
->st
.st_dev
= MEDATA
->rdev
++;
313 archive
->root
= root
;
318 /* --------------------------------------------------------------------------------------------- */
320 static union record
*
321 tar_get_next_record (struct vfs_s_super
*archive
, int tard
)
327 n
= mc_read (tard
, rec_buf
.charptr
, RECORDSIZE
);
329 return NULL
; /* An error has occurred */
330 current_tar_position
+= RECORDSIZE
;
334 /* --------------------------------------------------------------------------------------------- */
337 tar_skip_n_records (struct vfs_s_super
*archive
, int tard
, int n
)
341 mc_lseek (tard
, n
* RECORDSIZE
, SEEK_CUR
);
342 current_tar_position
+= n
* RECORDSIZE
;
345 /* --------------------------------------------------------------------------------------------- */
348 tar_fill_stat (struct vfs_s_super
*archive
, struct stat
*st
, union record
*header
, size_t h_size
)
350 st
->st_mode
= tar_from_oct (8, header
->header
.mode
);
352 /* Adjust st->st_mode because there are tar-files with
353 * linkflag==LF_SYMLINK and S_ISLNK(mod)==0. I don't
354 * know about the other modes but I think I cause no new
355 * problem when I adjust them, too. -- Norbert.
357 if (header
->header
.linkflag
== LF_DIR
)
359 st
->st_mode
|= S_IFDIR
;
361 else if (header
->header
.linkflag
== LF_SYMLINK
)
363 st
->st_mode
|= S_IFLNK
;
365 else if (header
->header
.linkflag
== LF_CHR
)
367 st
->st_mode
|= S_IFCHR
;
369 else if (header
->header
.linkflag
== LF_BLK
)
371 st
->st_mode
|= S_IFBLK
;
373 else if (header
->header
.linkflag
== LF_FIFO
)
375 st
->st_mode
|= S_IFIFO
;
378 st
->st_mode
|= S_IFREG
;
381 switch (archive
->u
.arch
.type
)
387 *header
->header
.uname
? vfs_finduid (header
->header
.uname
) : tar_from_oct (8,
391 *header
->header
.gname
? vfs_findgid (header
->header
.gname
) : tar_from_oct (8,
394 switch (header
->header
.linkflag
)
399 (tar_from_oct (8, header
->header
.devmajor
) << 8) |
400 tar_from_oct (8, header
->header
.devminor
);
403 st
->st_uid
= tar_from_oct (8, header
->header
.uid
);
404 st
->st_gid
= tar_from_oct (8, header
->header
.gid
);
406 st
->st_size
= h_size
;
407 st
->st_mtime
= tar_from_oct (1 + 12, header
->header
.mtime
);
410 if (archive
->u
.arch
.type
== TAR_GNU
)
412 st
->st_atime
= tar_from_oct (1 + 12, header
->header
.unused
.oldgnu
.atime
);
413 st
->st_ctime
= tar_from_oct (1 + 12, header
->header
.unused
.oldgnu
.ctime
);
417 /* --------------------------------------------------------------------------------------------- */
419 * Return 1 for success, 0 if the checksum is bad, EOF on eof,
420 * 2 for a record full of zeros (EOF marker).
424 tar_read_header (struct vfs_class
*me
, struct vfs_s_super
*archive
, int tard
, size_t * h_size
)
427 register long sum
, signed_sum
, recsum
;
429 register union record
*header
;
430 static char *next_long_name
= NULL
, *next_long_link
= NULL
;
434 header
= tar_get_next_record (archive
, tard
);
438 recsum
= tar_from_oct (8, header
->header
.chksum
);
443 for (i
= sizeof (*header
); --i
>= 0;)
446 * We can't use unsigned char here because of old compilers,
453 /* Adjust checksum to count the "chksum" field as blanks. */
454 for (i
= sizeof (header
->header
.chksum
); --i
>= 0;)
456 sum
-= 0xFF & header
->header
.chksum
[i
];
457 signed_sum
-= (char) header
->header
.chksum
[i
];
459 sum
+= ' ' * sizeof header
->header
.chksum
;
460 signed_sum
+= ' ' * sizeof header
->header
.chksum
;
463 * This is a zeroed record...whole record is 0's except
464 * for the 8 blanks we faked for the checksum field.
467 return STATUS_EOFMARK
;
469 if (sum
!= recsum
&& signed_sum
!= recsum
)
470 return STATUS_BADCHECKSUM
;
473 * Try to determine the archive format.
475 if (archive
->u
.arch
.type
== TAR_UNKNOWN
)
477 if (!strcmp (header
->header
.magic
, TMAGIC
))
479 if (header
->header
.linkflag
== LF_GLOBAL_EXTHDR
)
480 archive
->u
.arch
.type
= TAR_POSIX
;
482 archive
->u
.arch
.type
= TAR_USTAR
;
484 else if (!strcmp (header
->header
.magic
, OLDGNU_MAGIC
))
486 archive
->u
.arch
.type
= TAR_GNU
;
491 * linkflag on BSDI tar (pax) always '\000'
493 if (header
->header
.linkflag
== '\000')
495 if (header
->header
.arch_name
[NAMSIZ
- 1] != '\0')
498 i
= strlen (header
->header
.arch_name
);
500 if (i
&& header
->header
.arch_name
[i
- 1] == '/')
501 header
->header
.linkflag
= LF_DIR
;
505 * Good record. Decode file size and return.
507 if (header
->header
.linkflag
== LF_LINK
|| header
->header
.linkflag
== LF_DIR
)
508 *h_size
= 0; /* Links 0 size on tape */
510 *h_size
= tar_from_oct (1 + 12, header
->header
.size
);
513 * Skip over directory snapshot info records that
514 * are stored in incremental tar archives.
516 if (header
->header
.linkflag
== LF_DUMPDIR
)
518 if (archive
->u
.arch
.type
== TAR_UNKNOWN
)
519 archive
->u
.arch
.type
= TAR_GNU
;
520 return STATUS_SUCCESS
;
524 * Skip over pax extended header and global extended
527 if (header
->header
.linkflag
== LF_EXTHDR
|| header
->header
.linkflag
== LF_GLOBAL_EXTHDR
)
529 if (archive
->u
.arch
.type
== TAR_UNKNOWN
)
530 archive
->u
.arch
.type
= TAR_POSIX
;
531 return STATUS_SUCCESS
;
534 if (header
->header
.linkflag
== LF_LONGNAME
|| header
->header
.linkflag
== LF_LONGLINK
)
540 if (archive
->u
.arch
.type
== TAR_UNKNOWN
)
541 archive
->u
.arch
.type
= TAR_GNU
;
543 if (*h_size
> MC_MAXPATHLEN
)
545 message (D_ERROR
, MSG_ERROR
, _("Inconsistent tar archive"));
546 return STATUS_BADCHECKSUM
;
549 longp
= ((header
->header
.linkflag
== LF_LONGNAME
) ? &next_long_name
: &next_long_link
);
552 bp
= *longp
= g_malloc (*h_size
+ 1);
554 for (size
= *h_size
; size
> 0; size
-= written
)
556 data
= tar_get_next_record (archive
, tard
)->charptr
;
561 message (D_ERROR
, MSG_ERROR
, _("Unexpected EOF on archive file"));
562 return STATUS_BADCHECKSUM
;
564 written
= RECORDSIZE
;
568 memcpy (bp
, data
, written
);
572 if (bp
- *longp
== MC_MAXPATHLEN
&& bp
[-1] != '\0')
576 message (D_ERROR
, MSG_ERROR
, _("Inconsistent tar archive"));
577 return STATUS_BADCHECKSUM
;
585 struct vfs_s_entry
*entry
;
586 struct vfs_s_inode
*inode
= NULL
, *parent
;
590 char *current_file_name
, *current_link_name
;
593 (next_long_link
? next_long_link
: g_strndup (header
->header
.arch_linkname
, NAMSIZ
));
594 len
= strlen (current_link_name
);
595 if (len
> 1 && current_link_name
[len
- 1] == '/')
596 current_link_name
[len
- 1] = 0;
598 current_file_name
= NULL
;
599 switch (archive
->u
.arch
.type
)
603 /* The ustar archive format supports pathnames of upto 256
604 * characters in length. This is achieved by concatenating
605 * the contents of the `prefix' and `arch_name' fields like
608 * prefix + path_separator + arch_name
610 * If the `prefix' field contains an empty string i.e. its
611 * first characters is '\0' the prefix field is ignored.
613 if (header
->header
.unused
.prefix
[0] != '\0')
615 char *temp_name
, *temp_prefix
;
617 temp_name
= g_strndup (header
->header
.arch_name
, NAMSIZ
);
618 temp_prefix
= g_strndup (header
->header
.unused
.prefix
, PREFIX_SIZE
);
619 current_file_name
= g_strconcat (temp_prefix
, PATH_SEP_STR
,
620 temp_name
, (char *) NULL
);
622 g_free (temp_prefix
);
626 if (next_long_name
!= NULL
)
627 current_file_name
= next_long_name
;
633 if (current_file_name
== NULL
)
635 if (next_long_name
!= NULL
)
636 current_file_name
= g_strdup (next_long_name
);
638 current_file_name
= g_strndup (header
->header
.arch_name
, NAMSIZ
);
641 canonicalize_pathname (current_file_name
);
642 len
= strlen (current_file_name
);
644 data_position
= current_tar_position
;
646 p
= strrchr (current_file_name
, '/');
649 p
= current_file_name
;
650 q
= current_file_name
+ len
; /* "" */
655 q
= current_file_name
;
658 parent
= vfs_s_find_inode (me
, archive
, q
, LINK_NO_FOLLOW
, FL_MKDIR
);
661 message (D_ERROR
, MSG_ERROR
, _("Inconsistent tar archive"));
662 return STATUS_BADCHECKSUM
;
665 if (header
->header
.linkflag
== LF_LINK
)
667 inode
= vfs_s_find_inode (me
, archive
, current_link_name
, LINK_NO_FOLLOW
, 0);
670 message (D_ERROR
, MSG_ERROR
, _("Inconsistent tar archive"));
674 entry
= vfs_s_new_entry (me
, p
, inode
);
675 vfs_s_insert_entry (me
, parent
, entry
);
676 g_free (current_link_name
);
681 tar_fill_stat (archive
, &st
, header
, *h_size
);
682 if (S_ISDIR (st
.st_mode
))
684 entry
= MEDATA
->find_entry (me
, parent
, p
, LINK_NO_FOLLOW
, FL_NONE
);
688 inode
= vfs_s_new_inode (me
, archive
, &st
);
690 inode
->data_offset
= data_position
;
691 if (*current_link_name
)
693 inode
->linkname
= current_link_name
;
695 else if (current_link_name
!= next_long_link
)
697 g_free (current_link_name
);
699 entry
= vfs_s_new_entry (me
, p
, inode
);
701 vfs_s_insert_entry (me
, parent
, entry
);
702 g_free (current_file_name
);
705 next_long_link
= next_long_name
= NULL
;
707 if (archive
->u
.arch
.type
== TAR_GNU
&& header
->header
.unused
.oldgnu
.isextended
)
709 while (tar_get_next_record (archive
, tard
)->ext_hdr
.isextended
);
710 inode
->data_offset
= current_tar_position
;
712 return STATUS_SUCCESS
;
716 /* --------------------------------------------------------------------------------------------- */
718 * Main loop for reading an archive.
719 * Returns 0 on success, -1 on error.
722 tar_open_archive (struct vfs_class
*me
, struct vfs_s_super
*archive
, const char *name
, char *op
)
724 /* Initial status at start of archive */
725 ReadStatus status
= STATUS_EOFMARK
;
726 ReadStatus prev_status
;
731 current_tar_position
= 0;
732 /* Open for reading */
733 tard
= tar_open_archive_int (me
, name
, archive
);
741 prev_status
= status
;
742 status
= tar_read_header (me
, archive
, tard
, &h_size
);
748 tar_skip_n_records (archive
, tard
, (h_size
+ RECORDSIZE
- 1) / RECORDSIZE
);
754 * If the previous header was good, tell them
755 * that we are skipping bad ones.
757 case STATUS_BADCHECKSUM
:
761 /* Error on first record */
763 message (D_ERROR
, MSG_ERROR
, _("%s\ndoesn't look like a tar archive."), name
);
766 /* Error after header rec */
768 /* Error after error */
770 case STATUS_BADCHECKSUM
:
777 /* Record of zeroes */
779 status
= prev_status
; /* If error after 0's */
782 case STATUS_EOF
: /* End of archive */
790 /* --------------------------------------------------------------------------------------------- */
793 tar_super_check (struct vfs_class
*me
, const char *archive_name
, char *op
)
795 static struct stat stat_buf
;
800 if (mc_stat (archive_name
, &stat_buf
))
805 /* --------------------------------------------------------------------------------------------- */
808 tar_super_same (struct vfs_class
*me
, struct vfs_s_super
*parc
,
809 const char *archive_name
, char *op
, void *cookie
)
811 struct stat
*archive_stat
= cookie
; /* stat of main archive */
816 if (strcmp (parc
->name
, archive_name
))
819 /* Has the cached archive been changed on the disk? */
820 if (parc
->u
.arch
.st
.st_mtime
< archive_stat
->st_mtime
)
823 (*vfs_tarfs_ops
.free
) ((vfsid
) parc
);
824 vfs_rmstamp (&vfs_tarfs_ops
, (vfsid
) parc
);
827 /* Hasn't been modified, give it a new timeout */
828 vfs_stamp (&vfs_tarfs_ops
, (vfsid
) parc
);
832 /* --------------------------------------------------------------------------------------------- */
835 tar_read (void *fh
, char *buffer
, size_t count
)
837 off_t begin
= FH
->ino
->data_offset
;
838 int fd
= FH_SUPER
->u
.arch
.fd
;
839 struct vfs_class
*me
= FH_SUPER
->me
;
842 if (mc_lseek (fd
, begin
+ FH
->pos
, SEEK_SET
) != begin
+ FH
->pos
)
845 count
= MIN (count
, (size_t) (FH
->ino
->st
.st_size
- FH
->pos
));
847 res
= mc_read (fd
, buffer
, count
);
855 /* --------------------------------------------------------------------------------------------- */
858 tar_fh_open (struct vfs_class
*me
, struct vfs_s_fh
*fh
, int flags
, mode_t mode
)
863 if ((flags
& O_ACCMODE
) != O_RDONLY
)
868 /* --------------------------------------------------------------------------------------------- */
869 /*** public functions ****************************************************************************/
870 /* --------------------------------------------------------------------------------------------- */
875 static struct vfs_s_subclass tarfs_subclass
;
877 tarfs_subclass
.flags
= VFS_S_READONLY
;
878 tarfs_subclass
.archive_check
= tar_super_check
;
879 tarfs_subclass
.archive_same
= tar_super_same
;
880 tarfs_subclass
.open_archive
= tar_open_archive
;
881 tarfs_subclass
.free_archive
= tar_free_archive
;
882 tarfs_subclass
.fh_open
= tar_fh_open
;
884 vfs_s_init_class (&vfs_tarfs_ops
, &tarfs_subclass
);
885 vfs_tarfs_ops
.name
= "tarfs";
886 vfs_tarfs_ops
.prefix
= "utar";
887 vfs_tarfs_ops
.read
= tar_read
;
888 vfs_tarfs_ops
.setctl
= NULL
;
889 vfs_register_class (&vfs_tarfs_ops
);
892 /* --------------------------------------------------------------------------------------------- */