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. */
22 /* Namespace: init_tarfs */
26 #include <sys/types.h>
30 #include <mhl/memory.h>
31 #include <mhl/string.h>
34 /* major() and minor() macros (among other things) defined here for hpux */
35 #include <sys/mknod.h>
38 #include "../src/global.h"
39 #include "../src/tty.h" /* enable/disable interrupt key */
40 #include "../src/wtools.h" /* message() */
41 #include "../src/main.h" /* print_vfs_message */
43 #include "gc.h" /* vfs_rmstamp */
44 #include "xdirentry.h"
46 static struct vfs_class vfs_tarfs_ops
;
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
83 char charptr
[RECORDSIZE
];
85 char arch_name
[NAMSIZ
];
93 char arch_linkname
[NAMSIZ
];
99 /* The following bytes of the tar header record were originally unused.
101 Archives following the ustar specification use almost all of those
102 bytes to support pathnames of 256 characters in length.
104 GNU tar archives use the "unused" space to support incremental
105 archives and sparse files. */
107 char prefix
[PREFIX_SIZE
];
108 /* GNU extensions to the ustar (POSIX.1-1988) archive format. */
115 struct sparse sp
[SPARSE_IN_HDR
];
117 char realsize
[12]; /* true size of the sparse file */
121 struct extended_header
{
122 struct sparse sp
[21];
127 /* The checksum field is filled with this while the checksum is computed. */
128 #define CHKBLANKS " " /* 8 blanks, no null */
130 /* The magic field is filled with this if uname and gname are valid. */
131 #define TMAGIC "ustar" /* ustar and a null */
132 #define OLDGNU_MAGIC "ustar " /* 7 chars and a null */
134 /* The linkflag defines the type of file */
135 #define LF_OLDNORMAL '\0' /* Normal disk file, Unix compat */
136 #define LF_NORMAL '0' /* Normal disk file */
137 #define LF_LINK '1' /* Link to previously dumped file */
138 #define LF_SYMLINK '2' /* Symbolic link */
139 #define LF_CHR '3' /* Character special file */
140 #define LF_BLK '4' /* Block special file */
141 #define LF_DIR '5' /* Directory */
142 #define LF_FIFO '6' /* FIFO special file */
143 #define LF_CONTIG '7' /* Contiguous file */
144 #define LF_EXTHDR 'x' /* pax Extended Header */
145 #define LF_GLOBAL_EXTHDR 'g' /* pax Global Extended Header */
146 /* Further link types may be defined later. */
148 /* Note that the standards committee allows only capital A through
149 capital Z for user-defined expansion. This means that defining something
150 as, say '8' is a *bad* idea. */
151 #define LF_DUMPDIR 'D' /* This is a dir entry that contains
152 the names of files that were in
153 the dir at the time the dump
155 #define LF_LONGLINK 'K' /* Identifies the NEXT file on the tape
156 as having a long linkname */
157 #define LF_LONGNAME 'L' /* Identifies the NEXT file on the tape
158 as having a long name. */
159 #define LF_MULTIVOL 'M' /* This is the continuation
160 of a file that began on another
162 #define LF_NAMES 'N' /* For storing filenames that didn't
163 fit in 100 characters */
164 #define LF_SPARSE 'S' /* This is for sparse files */
165 #define LF_VOLHDR 'V' /* This file is a tape/volume header */
166 /* Ignore it on extraction */
169 * Exit codes from the "tar" program
171 #define EX_SUCCESS 0 /* success! */
172 #define EX_ARGSBAD 1 /* invalid args */
173 #define EX_BADFILE 2 /* invalid filename */
174 #define EX_BADARCH 3 /* bad archive */
175 #define EX_SYSTEM 4 /* system gave unexpected error */
176 #define EX_BADVOL 5 /* Special error code means
177 Tape volume doesn't match the one
178 specified on the command line */
180 #define isodigit(c) ( ((c) >= '0') && ((c) <= '7') )
183 * Quick and dirty octal conversion.
185 * Result is -1 if the field is invalid (all blank, or nonoctal).
187 static long tar_from_oct (int digs
, char *where
)
191 while (isspace ((unsigned char) *where
)) { /* Skip spaces */
194 return -1; /* All blank field */
197 while (digs
> 0 && isodigit (*where
)) { /* Scan till nonoctal */
198 value
= (value
<< 3) | (*where
++ - '0');
202 if (digs
> 0 && *where
&& !isspace ((unsigned char) *where
))
203 return -1; /* Ended on non-space/nul */
208 static void tar_free_archive (struct vfs_class
*me
, struct vfs_s_super
*archive
)
212 if (archive
->u
.arch
.fd
!= -1)
213 mc_close(archive
->u
.arch
.fd
);
216 /* As we open one archive at a time, it is safe to have this static */
217 static int current_tar_position
= 0;
219 /* Returns fd of the open tar file */
221 tar_open_archive_int (struct vfs_class
*me
, const char *name
,
222 struct vfs_s_super
*archive
)
226 struct vfs_s_inode
*root
;
228 result
= mc_open (name
, O_RDONLY
);
230 message (D_ERROR
, MSG_ERROR
, _("Cannot open tar archive\n%s"), name
);
234 archive
->name
= mhl_str_dup (name
);
235 mc_stat (name
, &(archive
->u
.arch
.st
));
236 archive
->u
.arch
.fd
= -1;
237 archive
->u
.arch
.type
= TAR_UNKNOWN
;
239 /* Find out the method to handle this tar file */
240 type
= get_compression_type (result
);
241 mc_lseek (result
, 0, SEEK_SET
);
242 if (type
!= COMPRESSION_NONE
) {
245 s
= g_strconcat (archive
->name
, decompress_extension (type
), (char *) NULL
);
246 result
= mc_open (s
, O_RDONLY
);
248 message (D_ERROR
, MSG_ERROR
, _("Cannot open tar archive\n%s"), s
);
254 archive
->u
.arch
.fd
= result
;
255 mode
= archive
->u
.arch
.st
.st_mode
& 07777;
264 root
= vfs_s_new_inode (me
, archive
, &archive
->u
.arch
.st
);
265 root
->st
.st_mode
= mode
;
266 root
->data_offset
= -1;
268 root
->st
.st_dev
= MEDATA
->rdev
++;
270 archive
->root
= root
;
275 static union record rec_buf
;
277 static union record
*
278 tar_get_next_record (struct vfs_s_super
*archive
, int tard
)
284 n
= mc_read (tard
, rec_buf
.charptr
, RECORDSIZE
);
286 return NULL
; /* An error has occurred */
287 current_tar_position
+= RECORDSIZE
;
291 static void tar_skip_n_records (struct vfs_s_super
*archive
, int tard
, int n
)
295 mc_lseek (tard
, n
* RECORDSIZE
, SEEK_CUR
);
296 current_tar_position
+= n
* RECORDSIZE
;
300 tar_fill_stat (struct vfs_s_super
*archive
, struct stat
*st
, union record
*header
,
303 st
->st_mode
= tar_from_oct (8, header
->header
.mode
);
305 /* Adjust st->st_mode because there are tar-files with
306 * linkflag==LF_SYMLINK and S_ISLNK(mod)==0. I don't
307 * know about the other modes but I think I cause no new
308 * problem when I adjust them, too. -- Norbert.
310 if (header
->header
.linkflag
== LF_DIR
) {
311 st
->st_mode
|= S_IFDIR
;
312 } else if (header
->header
.linkflag
== LF_SYMLINK
) {
313 st
->st_mode
|= S_IFLNK
;
314 } else if (header
->header
.linkflag
== LF_CHR
) {
315 st
->st_mode
|= S_IFCHR
;
316 } else if (header
->header
.linkflag
== LF_BLK
) {
317 st
->st_mode
|= S_IFBLK
;
318 } else if (header
->header
.linkflag
== LF_FIFO
) {
319 st
->st_mode
|= S_IFIFO
;
321 st
->st_mode
|= S_IFREG
;
324 switch (archive
->u
.arch
.type
) {
329 *header
->header
.uname
? vfs_finduid (header
->header
.
330 uname
) : tar_from_oct (8,
335 *header
->header
.gname
? vfs_findgid (header
->header
.
336 gname
) : tar_from_oct (8,
340 switch (header
->header
.linkflag
) {
344 (tar_from_oct (8, header
->header
.devmajor
) << 8) |
345 tar_from_oct (8, header
->header
.devminor
);
348 st
->st_uid
= tar_from_oct (8, header
->header
.uid
);
349 st
->st_gid
= tar_from_oct (8, header
->header
.gid
);
351 st
->st_size
= h_size
;
352 st
->st_mtime
= tar_from_oct (1 + 12, header
->header
.mtime
);
355 if (archive
->u
.arch
.type
== TAR_GNU
) {
356 st
->st_atime
= tar_from_oct (1 + 12,
357 header
->header
.unused
.oldgnu
.atime
);
358 st
->st_ctime
= tar_from_oct (1 + 12,
359 header
->header
.unused
.oldgnu
.ctime
);
371 * Return 1 for success, 0 if the checksum is bad, EOF on eof,
372 * 2 for a record full of zeros (EOF marker).
376 tar_read_header (struct vfs_class
*me
, struct vfs_s_super
*archive
,
377 int tard
, size_t *h_size
)
380 register long sum
, signed_sum
, recsum
;
382 register union record
*header
;
383 static char *next_long_name
= NULL
, *next_long_link
= NULL
;
387 header
= tar_get_next_record (archive
, tard
);
391 recsum
= tar_from_oct (8, header
->header
.chksum
);
396 for (i
= sizeof (*header
); --i
>= 0;) {
398 * We can't use unsigned char here because of old compilers,
405 /* Adjust checksum to count the "chksum" field as blanks. */
406 for (i
= sizeof (header
->header
.chksum
); --i
>= 0;) {
407 sum
-= 0xFF & header
->header
.chksum
[i
];
408 signed_sum
-= (char) header
->header
.chksum
[i
];
410 sum
+= ' ' * sizeof header
->header
.chksum
;
411 signed_sum
+= ' ' * sizeof header
->header
.chksum
;
414 * This is a zeroed record...whole record is 0's except
415 * for the 8 blanks we faked for the checksum field.
418 return STATUS_EOFMARK
;
420 if (sum
!= recsum
&& signed_sum
!= recsum
)
421 return STATUS_BADCHECKSUM
;
424 * Try to determine the archive format.
426 if (archive
->u
.arch
.type
== TAR_UNKNOWN
) {
427 if (!strcmp (header
->header
.magic
, TMAGIC
)) {
428 if (header
->header
.linkflag
== LF_GLOBAL_EXTHDR
)
429 archive
->u
.arch
.type
= TAR_POSIX
;
431 archive
->u
.arch
.type
= TAR_USTAR
;
432 } else if (!strcmp (header
->header
.magic
, OLDGNU_MAGIC
)) {
433 archive
->u
.arch
.type
= TAR_GNU
;
438 * linkflag on BSDI tar (pax) always '\000'
440 if (header
->header
.linkflag
== '\000') {
441 if (header
->header
.arch_name
[NAMSIZ
- 1] != '\0')
444 i
= strlen (header
->header
.arch_name
);
446 if (i
&& header
->header
.arch_name
[i
- 1] == '/')
447 header
->header
.linkflag
= LF_DIR
;
451 * Good record. Decode file size and return.
453 if (header
->header
.linkflag
== LF_LINK
454 || header
->header
.linkflag
== LF_DIR
)
455 *h_size
= 0; /* Links 0 size on tape */
457 *h_size
= tar_from_oct (1 + 12, header
->header
.size
);
460 * Skip over directory snapshot info records that
461 * are stored in incremental tar archives.
463 if (header
->header
.linkflag
== LF_DUMPDIR
) {
464 if (archive
->u
.arch
.type
== TAR_UNKNOWN
)
465 archive
->u
.arch
.type
= TAR_GNU
;
466 return STATUS_SUCCESS
;
470 * Skip over pax extended header and global extended
473 if (header
->header
.linkflag
== LF_EXTHDR
||
474 header
->header
.linkflag
== LF_GLOBAL_EXTHDR
) {
475 if (archive
->u
.arch
.type
== TAR_UNKNOWN
)
476 archive
->u
.arch
.type
= TAR_POSIX
;
477 return STATUS_SUCCESS
;
480 if (header
->header
.linkflag
== LF_LONGNAME
481 || header
->header
.linkflag
== LF_LONGLINK
) {
486 if (archive
->u
.arch
.type
== TAR_UNKNOWN
)
487 archive
->u
.arch
.type
= TAR_GNU
;
489 if (*h_size
> MC_MAXPATHLEN
) {
490 message (D_ERROR
, MSG_ERROR
, _("Inconsistent tar archive"));
491 return STATUS_BADCHECKSUM
;
494 longp
= ((header
->header
.linkflag
== LF_LONGNAME
)
495 ? &next_long_name
: &next_long_link
);
498 bp
= *longp
= g_malloc (*h_size
+ 1);
500 for (size
= *h_size
; size
> 0; size
-= written
) {
501 data
= tar_get_next_record (archive
, tard
)->charptr
;
505 message (D_ERROR
, MSG_ERROR
,
506 _("Unexpected EOF on archive file"));
507 return STATUS_BADCHECKSUM
;
509 written
= RECORDSIZE
;
513 memcpy (bp
, data
, written
);
517 if (bp
- *longp
== MC_MAXPATHLEN
&& bp
[-1] != '\0') {
520 message (D_ERROR
, MSG_ERROR
, _("Inconsistent tar archive"));
521 return STATUS_BADCHECKSUM
;
527 struct vfs_s_entry
*entry
;
528 struct vfs_s_inode
*inode
, *parent
;
532 char *current_file_name
, *current_link_name
;
535 (next_long_link
? next_long_link
:
536 g_strndup (header
->header
.arch_linkname
, NAMSIZ
));
537 len
= strlen (current_link_name
);
538 if (len
> 1 && current_link_name
[len
- 1] == '/')
539 current_link_name
[len
- 1] = 0;
541 current_file_name
= NULL
;
542 switch (archive
->u
.arch
.type
) {
545 /* The ustar archive format supports pathnames of upto 256
546 * characters in length. This is achieved by concatenating
547 * the contents of the `prefix' and `arch_name' fields like
550 * prefix + path_separator + arch_name
552 * If the `prefix' field contains an empty string i.e. its
553 * first characters is '\0' the prefix field is ignored.
555 if (header
->header
.unused
.prefix
[0] != '\0') {
556 char *temp_name
, *temp_prefix
;
558 temp_name
= g_strndup (header
->header
.arch_name
, NAMSIZ
);
559 temp_prefix
= g_strndup (header
->header
.unused
.prefix
,
561 current_file_name
= g_strconcat (temp_prefix
, PATH_SEP_STR
,
562 temp_name
, (char *) NULL
);
564 g_free (temp_prefix
);
568 if (next_long_name
!= NULL
)
569 current_file_name
= next_long_name
;
575 if (current_file_name
== NULL
)
576 current_file_name
= g_strndup (header
->header
.arch_name
, NAMSIZ
);
578 canonicalize_pathname (current_file_name
);
579 len
= strlen (current_file_name
);
581 data_position
= current_tar_position
;
583 p
= strrchr (current_file_name
, '/');
585 p
= current_file_name
;
586 q
= current_file_name
+ len
; /* "" */
589 q
= current_file_name
;
593 vfs_s_find_inode (me
, archive
, q
, LINK_NO_FOLLOW
, FL_MKDIR
);
594 if (parent
== NULL
) {
595 message (D_ERROR
, MSG_ERROR
, _("Inconsistent tar archive"));
596 return STATUS_BADCHECKSUM
;
599 if (header
->header
.linkflag
== LF_LINK
) {
601 vfs_s_find_inode (me
, archive
, current_link_name
,
604 message (D_ERROR
, MSG_ERROR
, _("Inconsistent tar archive"));
606 entry
= vfs_s_new_entry (me
, p
, inode
);
607 vfs_s_insert_entry (me
, parent
, entry
);
608 g_free (current_link_name
);
613 tar_fill_stat (archive
, &st
, header
, *h_size
);
614 inode
= vfs_s_new_inode (me
, archive
, &st
);
616 inode
->data_offset
= data_position
;
617 if (*current_link_name
) {
618 inode
->linkname
= current_link_name
;
619 } else if (current_link_name
!= next_long_link
) {
620 g_free (current_link_name
);
622 entry
= vfs_s_new_entry (me
, p
, inode
);
624 vfs_s_insert_entry (me
, parent
, entry
);
625 g_free (current_file_name
);
628 next_long_link
= next_long_name
= NULL
;
630 if (archive
->u
.arch
.type
== TAR_GNU
&&
631 header
->header
.unused
.oldgnu
.isextended
) {
632 while (tar_get_next_record (archive
, tard
)->ext_hdr
.
634 inode
->data_offset
= current_tar_position
;
636 return STATUS_SUCCESS
;
641 * Main loop for reading an archive.
642 * Returns 0 on success, -1 on error.
645 tar_open_archive (struct vfs_class
*me
, struct vfs_s_super
*archive
,
646 const char *name
, char *op
)
648 /* Initial status at start of archive */
649 ReadStatus status
= STATUS_EOFMARK
;
650 ReadStatus prev_status
;
655 current_tar_position
= 0;
656 /* Open for reading */
657 if ((tard
= tar_open_archive_int (me
, name
, archive
)) == -1)
663 prev_status
= status
;
664 status
= tar_read_header (me
, archive
, tard
, &h_size
);
669 tar_skip_n_records (archive
, tard
,
670 (h_size
+ RECORDSIZE
-
677 * If the previous header was good, tell them
678 * that we are skipping bad ones.
680 case STATUS_BADCHECKSUM
:
681 switch (prev_status
) {
683 /* Error on first record */
685 message (D_ERROR
, MSG_ERROR
,
687 ("Hmm,...\n%s\ndoesn't look like a tar archive."),
691 /* Error after header rec */
693 /* Error after error */
695 case STATUS_BADCHECKSUM
:
702 /* Record of zeroes */
704 status
= prev_status
; /* If error after 0's */
707 case STATUS_EOF
: /* End of archive */
716 tar_super_check (struct vfs_class
*me
, const char *archive_name
, char *op
)
718 static struct stat stat_buf
;
723 if (mc_stat (archive_name
, &stat_buf
))
729 tar_super_same (struct vfs_class
*me
, struct vfs_s_super
*parc
,
730 const char *archive_name
, char *op
, void *cookie
)
732 struct stat
*archive_stat
= cookie
; /* stat of main archive */
737 if (strcmp (parc
->name
, archive_name
))
740 /* Has the cached archive been changed on the disk? */
741 if (parc
->u
.arch
.st
.st_mtime
< archive_stat
->st_mtime
) {
743 (*vfs_tarfs_ops
.free
) ((vfsid
) parc
);
744 vfs_rmstamp (&vfs_tarfs_ops
, (vfsid
) parc
);
747 /* Hasn't been modified, give it a new timeout */
748 vfs_stamp (&vfs_tarfs_ops
, (vfsid
) parc
);
752 static ssize_t
tar_read (void *fh
, char *buffer
, int count
)
754 off_t begin
= FH
->ino
->data_offset
;
755 int fd
= FH_SUPER
->u
.arch
.fd
;
756 struct vfs_class
*me
= FH_SUPER
->me
;
758 if (mc_lseek (fd
, begin
+ FH
->pos
, SEEK_SET
) !=
759 begin
+ FH
->pos
) ERRNOR (EIO
, -1);
761 count
= MIN(count
, FH
->ino
->st
.st_size
- FH
->pos
);
763 if ((count
= mc_read (fd
, buffer
, count
)) == -1) ERRNOR (errno
, -1);
769 static int tar_fh_open (struct vfs_class
*me
, struct vfs_s_fh
*fh
, int flags
, int mode
)
774 if ((flags
& O_ACCMODE
) != O_RDONLY
) ERRNOR (EROFS
, -1);
781 static struct vfs_s_subclass tarfs_subclass
;
783 tarfs_subclass
.flags
= VFS_S_READONLY
;
784 tarfs_subclass
.archive_check
= tar_super_check
;
785 tarfs_subclass
.archive_same
= tar_super_same
;
786 tarfs_subclass
.open_archive
= tar_open_archive
;
787 tarfs_subclass
.free_archive
= tar_free_archive
;
788 tarfs_subclass
.fh_open
= tar_fh_open
;
790 vfs_s_init_class (&vfs_tarfs_ops
, &tarfs_subclass
);
791 vfs_tarfs_ops
.name
= "tarfs";
792 vfs_tarfs_ops
.prefix
= "utar";
793 vfs_tarfs_ops
.read
= tar_read
;
794 vfs_tarfs_ops
.setctl
= NULL
;
795 vfs_register_class (&vfs_tarfs_ops
);