1 /* Virtual File System: GNU Tar file system.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007
3 Free Software Foundation, Inc.
5 Written by: 2000 Jan Hudec
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License
9 as published by the Free Software Foundation; either version 2 of
10 the License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
22 * \brief Source: Virtual File System: GNU Tar file system.
32 #include "lib/global.h"
33 #include "lib/unixcompat.h"
35 #include "lib/widget/wtools.h" /* message() */
39 #include "xdirentry.h"
40 #include "gc.h" /* vfs_rmstamp */
42 /*** global variables ****************************************************************************/
44 /*** file scope macro definitions ****************************************************************/
46 #define CPIO_POS(super) cpio_position
47 /* If some time reentrancy should be needed change it to */
48 /* #define CPIO_POS(super) (super)->u.arch.fd */
50 #define CPIO_SEEK_SET(super, where) mc_lseek((super)->u.arch.fd, CPIO_POS(super) = (where), SEEK_SET)
51 #define CPIO_SEEK_CUR(super, where) mc_lseek((super)->u.arch.fd, CPIO_POS(super) += (where), SEEK_SET)
53 #define MAGIC_LENGTH (6) /* How many bytes we have to read ahead */
54 #define SEEKBACK CPIO_SEEK_CUR(super, ptr - top)
55 #define RETURN(x) return(super->u.arch.type = (x))
56 #define TYPEIS(x) ((super->u.arch.type == CPIO_UNKNOWN) || (super->u.arch.type == (x)))
58 #define HEAD_LENGTH (26)
60 /*** file scope type declarations ****************************************************************/
73 CPIO_UNKNOWN
= 0, /* Not determined yet */
74 CPIO_BIN
, /* Binary format */
75 CPIO_BINRE
, /* Binary format, reverse endianity */
76 CPIO_OLDC
, /* Old ASCII format */
77 CPIO_NEWC
, /* New ASCII format */
78 CPIO_CRC
/* New ASCII format + CRC */
81 struct old_cpio_header
83 unsigned short c_magic
;
86 unsigned short c_mode
;
89 unsigned short c_nlink
;
91 unsigned short c_mtimes
[2];
92 unsigned short c_namesize
;
93 unsigned short c_filesizes
[2];
96 struct new_cpio_header
98 unsigned short c_magic
;
100 unsigned long c_mode
;
103 unsigned long c_nlink
;
104 unsigned long c_mtime
;
105 unsigned long c_filesize
;
110 unsigned long c_namesize
;
111 unsigned long c_chksum
;
116 struct defer_inode
*next
;
117 unsigned long inumber
;
118 unsigned short device
;
119 struct vfs_s_inode
*inode
;
122 /*** file scope variables ************************************************************************/
124 static struct vfs_class vfs_cpiofs_ops
;
126 /* FIXME: should be off_t instead of int. */
127 static int cpio_position
;
129 /*** file scope functions ************************************************************************/
130 /* --------------------------------------------------------------------------------------------- */
132 static int cpio_find_head (struct vfs_class
*me
, struct vfs_s_super
*super
);
133 static ssize_t
cpio_read_bin_head (struct vfs_class
*me
, struct vfs_s_super
*super
);
134 static ssize_t
cpio_read_oldc_head (struct vfs_class
*me
, struct vfs_s_super
*super
);
135 static ssize_t
cpio_read_crc_head (struct vfs_class
*me
, struct vfs_s_super
*super
);
136 static ssize_t
cpio_read (void *fh
, char *buffer
, size_t count
);
138 /* --------------------------------------------------------------------------------------------- */
140 static struct defer_inode
*
141 cpio_defer_find (struct defer_inode
*l
, struct defer_inode
*i
)
143 while (l
&& (l
->inumber
!= i
->inumber
|| l
->device
!= i
->device
))
148 /* --------------------------------------------------------------------------------------------- */
151 cpio_skip_padding (struct vfs_s_super
*super
)
153 switch (super
->u
.arch
.type
)
157 return CPIO_SEEK_CUR (super
, (2 - (CPIO_POS (super
) % 2)) % 2);
160 return CPIO_SEEK_CUR (super
, (4 - (CPIO_POS (super
) % 4)) % 4);
162 return CPIO_POS (super
);
164 g_assert_not_reached ();
165 return 42; /* & the compiler is happy :-) */
169 /* --------------------------------------------------------------------------------------------- */
172 cpio_free_archive (struct vfs_class
*me
, struct vfs_s_super
*super
)
174 struct defer_inode
*l
, *lnext
;
178 if (super
->u
.arch
.fd
!= -1)
179 mc_close (super
->u
.arch
.fd
);
180 super
->u
.arch
.fd
= -1;
181 for (l
= super
->u
.arch
.deferred
; l
; l
= lnext
)
186 super
->u
.arch
.deferred
= NULL
;
189 /* --------------------------------------------------------------------------------------------- */
192 cpio_open_cpio_file (struct vfs_class
*me
, struct vfs_s_super
*super
, const char *name
)
196 struct vfs_s_inode
*root
;
198 fd
= mc_open (name
, O_RDONLY
);
201 message (D_ERROR
, MSG_ERROR
, _("Cannot open cpio archive\n%s"), name
);
205 super
->name
= g_strdup (name
);
206 super
->u
.arch
.fd
= -1; /* for now */
207 mc_stat (name
, &(super
->u
.arch
.st
));
208 super
->u
.arch
.type
= CPIO_UNKNOWN
;
210 type
= get_compression_type (fd
, name
);
211 if (type
!= COMPRESSION_NONE
)
216 s
= g_strconcat (name
, decompress_extension (type
), (char *) NULL
);
217 fd
= mc_open (s
, O_RDONLY
);
220 message (D_ERROR
, MSG_ERROR
, _("Cannot open cpio archive\n%s"), s
);
227 super
->u
.arch
.fd
= fd
;
228 mode
= super
->u
.arch
.st
.st_mode
& 07777;
229 mode
|= (mode
& 0444) >> 2; /* set eXec where Read is */
232 root
= vfs_s_new_inode (me
, super
, &(super
->u
.arch
.st
));
233 root
->st
.st_mode
= mode
;
234 root
->data_offset
= -1;
236 root
->st
.st_dev
= MEDATA
->rdev
++;
240 CPIO_SEEK_SET (super
, 0);
245 /* --------------------------------------------------------------------------------------------- */
248 cpio_read_head (struct vfs_class
*me
, struct vfs_s_super
*super
)
250 switch (cpio_find_head (me
, super
))
256 return cpio_read_bin_head (me
, super
);
258 return cpio_read_oldc_head (me
, super
);
261 return cpio_read_crc_head (me
, super
);
263 g_assert_not_reached ();
264 return 42; /* & the compiler is happy :-) */
268 /* --------------------------------------------------------------------------------------------- */
271 cpio_find_head (struct vfs_class
*me
, struct vfs_s_super
*super
)
278 top
= mc_read (super
->u
.arch
.fd
, buf
, 256);
280 CPIO_POS (super
) += top
;
283 if (ptr
+ MAGIC_LENGTH
>= top
)
287 memmove (buf
, buf
+ top
- 128, 128);
291 tmp
= mc_read (super
->u
.arch
.fd
, buf
, top
);
292 if (tmp
== 0 || tmp
== -1)
294 message (D_ERROR
, MSG_ERROR
, _("Premature end of cpio archive\n%s"), super
->name
);
295 cpio_free_archive (me
, super
);
300 if (TYPEIS (CPIO_BIN
) && ((*(unsigned short *) (buf
+ ptr
)) == 070707))
305 else if (TYPEIS (CPIO_BINRE
)
306 && ((*(unsigned short *) (buf
+ ptr
)) == GUINT16_SWAP_LE_BE_CONSTANT (070707)))
311 else if (TYPEIS (CPIO_OLDC
) && (!strncmp (buf
+ ptr
, "070707", 6)))
316 else if (TYPEIS (CPIO_NEWC
) && (!strncmp (buf
+ ptr
, "070701", 6)))
321 else if (TYPEIS (CPIO_CRC
) && (!strncmp (buf
+ ptr
, "070702", 6)))
330 /* --------------------------------------------------------------------------------------------- */
333 cpio_create_entry (struct vfs_class
*me
, struct vfs_s_super
*super
, struct stat
*st
, char *name
)
335 struct vfs_s_inode
*inode
= NULL
;
336 struct vfs_s_inode
*root
= super
->root
;
337 struct vfs_s_entry
*entry
= NULL
;
340 switch (st
->st_mode
& S_IFMT
)
341 { /* For case of HP/UX archives */
353 if ((st
->st_size
!= 0) && (st
->st_rdev
== 0x0001))
355 /* FIXME: representation of major/minor differs between */
356 /* different operating systems. */
357 st
->st_rdev
= (unsigned) st
->st_size
;
365 if ((st
->st_nlink
> 1)
366 && ((super
->u
.arch
.type
== CPIO_NEWC
) || (super
->u
.arch
.type
== CPIO_CRC
)))
367 { /* For case of hardlinked files */
368 struct defer_inode i
, *l
;
369 i
.inumber
= st
->st_ino
;
370 i
.device
= st
->st_dev
;
373 l
= cpio_defer_find (super
->u
.arch
.deferred
, &i
);
377 if (inode
->st
.st_size
!= 0 && st
->st_size
!= 0 && (inode
->st
.st_size
!= st
->st_size
))
379 message (D_ERROR
, MSG_ERROR
,
380 _("Inconsistent hardlinks of\n%s\nin cpio archive\n%s"),
384 else if (inode
->st
.st_size
== 0)
385 inode
->st
.st_size
= st
->st_size
;
389 /* remove trailing slashes */
390 for (tn
= name
+ strlen (name
) - 1; tn
>= name
&& *tn
== PATH_SEP
; tn
--)
393 tn
= strrchr (name
, PATH_SEP
);
396 else if (tn
== name
+ 1)
398 /* started with "./" -- directory in the root of archive */
404 root
= vfs_s_find_inode (me
, super
, name
, LINK_FOLLOW
, FL_MKDIR
);
409 entry
= MEDATA
->find_entry (me
, root
, tn
, LINK_FOLLOW
, FL_NONE
); /* In case entry is already there */
413 /* This shouldn't happen! (well, it can happen if there is a record for a
414 file and than a record for a directory it is in; cpio would die with
415 'No such file or directory' is such case) */
417 if (!S_ISDIR (entry
->ino
->st
.st_mode
))
419 /* This can be considered archive inconsistency */
420 message (D_ERROR
, MSG_ERROR
,
421 _("%s contains duplicate entries! Skipping!"), super
->name
);
425 entry
->ino
->st
.st_mode
= st
->st_mode
;
426 entry
->ino
->st
.st_uid
= st
->st_uid
;
427 entry
->ino
->st
.st_gid
= st
->st_gid
;
428 entry
->ino
->st
.st_atime
= st
->st_atime
;
429 entry
->ino
->st
.st_mtime
= st
->st_mtime
;
430 entry
->ino
->st
.st_ctime
= st
->st_ctime
;
439 inode
= vfs_s_new_inode (me
, super
, st
);
440 if ((st
->st_nlink
> 0)
441 && ((super
->u
.arch
.type
== CPIO_NEWC
) || (super
->u
.arch
.type
== CPIO_CRC
)))
443 /* For case of hardlinked files */
444 struct defer_inode
*i
;
445 i
= g_new (struct defer_inode
, 1);
446 i
->inumber
= st
->st_ino
;
447 i
->device
= st
->st_dev
;
449 i
->next
= super
->u
.arch
.deferred
;
450 super
->u
.arch
.deferred
= i
;
454 if (st
->st_size
!= 0)
455 inode
->data_offset
= CPIO_POS (super
);
457 entry
= vfs_s_new_entry (me
, tn
, inode
);
458 vfs_s_insert_entry (me
, root
, entry
);
462 if (!S_ISLNK (st
->st_mode
))
463 CPIO_SEEK_CUR (super
, st
->st_size
);
466 inode
->linkname
= g_malloc (st
->st_size
+ 1);
468 if (mc_read (super
->u
.arch
.fd
, inode
->linkname
, st
->st_size
) < st
->st_size
)
470 inode
->linkname
[0] = '\0';
474 inode
->linkname
[st
->st_size
] = '\0'; /* Linkname stored without terminating \0 !!! */
475 CPIO_POS (super
) += st
->st_size
;
476 cpio_skip_padding (super
);
483 /* --------------------------------------------------------------------------------------------- */
486 cpio_read_bin_head (struct vfs_class
*me
, struct vfs_s_super
*super
)
490 struct old_cpio_header buf
;
491 short shorts
[HEAD_LENGTH
>> 1];
497 len
= mc_read (super
->u
.arch
.fd
, (char *) &u
.buf
, HEAD_LENGTH
);
498 if (len
< HEAD_LENGTH
)
500 CPIO_POS (super
) += len
;
501 if (super
->u
.arch
.type
== CPIO_BINRE
)
504 for (i
= 0; i
< (HEAD_LENGTH
>> 1); i
++)
505 u
.shorts
[i
] = GUINT16_SWAP_LE_BE_CONSTANT (u
.shorts
[i
]);
508 if (u
.buf
.c_magic
!= 070707 || u
.buf
.c_namesize
== 0 || u
.buf
.c_namesize
> MC_MAXPATHLEN
)
510 message (D_ERROR
, MSG_ERROR
, _("Corrupted cpio header encountered in\n%s"), super
->name
);
513 name
= g_malloc (u
.buf
.c_namesize
);
514 len
= mc_read (super
->u
.arch
.fd
, name
, u
.buf
.c_namesize
);
515 if (len
< u
.buf
.c_namesize
)
520 name
[u
.buf
.c_namesize
- 1] = '\0';
521 CPIO_POS (super
) += len
;
522 cpio_skip_padding (super
);
524 if (!strcmp ("TRAILER!!!", name
))
525 { /* We got to the last record */
530 st
.st_dev
= u
.buf
.c_dev
;
531 st
.st_ino
= u
.buf
.c_ino
;
532 st
.st_mode
= u
.buf
.c_mode
;
533 st
.st_nlink
= u
.buf
.c_nlink
;
534 st
.st_uid
= u
.buf
.c_uid
;
535 st
.st_gid
= u
.buf
.c_gid
;
536 st
.st_rdev
= u
.buf
.c_rdev
;
537 st
.st_size
= (u
.buf
.c_filesizes
[0] << 16) | u
.buf
.c_filesizes
[1];
538 st
.st_atime
= st
.st_mtime
= st
.st_ctime
= (u
.buf
.c_mtimes
[0] << 16) | u
.buf
.c_mtimes
[1];
540 return cpio_create_entry (me
, super
, &st
, name
);
543 /* --------------------------------------------------------------------------------------------- */
546 #define HEAD_LENGTH (76)
549 cpio_read_oldc_head (struct vfs_class
*me
, struct vfs_s_super
*super
)
551 struct new_cpio_header hd
;
555 char buf
[HEAD_LENGTH
+ 1];
560 if (mc_read (super
->u
.arch
.fd
, u
.buf
, HEAD_LENGTH
) != HEAD_LENGTH
)
562 CPIO_POS (super
) += HEAD_LENGTH
;
563 u
.buf
[HEAD_LENGTH
] = 0;
565 if (sscanf (u
.buf
, "070707%6lo%6lo%6lo%6lo%6lo%6lo%6lo%11lo%6lo%11lo",
566 (unsigned long *) &hd
.c_dev
, &hd
.c_ino
, &hd
.c_mode
, &hd
.c_uid
, &hd
.c_gid
,
567 &hd
.c_nlink
, (unsigned long *) &hd
.c_rdev
, &hd
.c_mtime
,
568 &hd
.c_namesize
, &hd
.c_filesize
) < 10)
570 message (D_ERROR
, MSG_ERROR
, _("Corrupted cpio header encountered in\n%s"), super
->name
);
574 if (hd
.c_namesize
== 0 || hd
.c_namesize
> MC_MAXPATHLEN
)
576 message (D_ERROR
, MSG_ERROR
, _("Corrupted cpio header encountered in\n%s"), super
->name
);
579 name
= g_malloc (hd
.c_namesize
);
580 len
= mc_read (super
->u
.arch
.fd
, name
, hd
.c_namesize
);
581 if ((len
== -1) || ((unsigned long) len
< hd
.c_namesize
))
586 name
[hd
.c_namesize
- 1] = '\0';
587 CPIO_POS (super
) += len
;
588 cpio_skip_padding (super
);
590 if (!strcmp ("TRAILER!!!", name
))
591 { /* We got to the last record */
596 u
.st
.st_dev
= hd
.c_dev
;
597 u
.st
.st_ino
= hd
.c_ino
;
598 u
.st
.st_mode
= hd
.c_mode
;
599 u
.st
.st_nlink
= hd
.c_nlink
;
600 u
.st
.st_uid
= hd
.c_uid
;
601 u
.st
.st_gid
= hd
.c_gid
;
602 u
.st
.st_rdev
= hd
.c_rdev
;
603 u
.st
.st_size
= hd
.c_filesize
;
604 u
.st
.st_atime
= u
.st
.st_mtime
= u
.st
.st_ctime
= hd
.c_mtime
;
606 return cpio_create_entry (me
, super
, &u
.st
, name
);
609 /* --------------------------------------------------------------------------------------------- */
612 #define HEAD_LENGTH (110)
615 cpio_read_crc_head (struct vfs_class
*me
, struct vfs_s_super
*super
)
617 struct new_cpio_header hd
;
621 char buf
[HEAD_LENGTH
+ 1];
626 if (mc_read (super
->u
.arch
.fd
, u
.buf
, HEAD_LENGTH
) != HEAD_LENGTH
)
629 CPIO_POS (super
) += HEAD_LENGTH
;
630 u
.buf
[HEAD_LENGTH
] = '\0';
632 if (sscanf (u
.buf
, "%6ho%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx",
633 &hd
.c_magic
, &hd
.c_ino
, &hd
.c_mode
, &hd
.c_uid
, &hd
.c_gid
,
634 &hd
.c_nlink
, &hd
.c_mtime
, &hd
.c_filesize
,
635 (unsigned long *) &hd
.c_dev
, (unsigned long *) &hd
.c_devmin
,
636 (unsigned long *) &hd
.c_rdev
, (unsigned long *) &hd
.c_rdevmin
,
637 &hd
.c_namesize
, &hd
.c_chksum
) < 14)
639 message (D_ERROR
, MSG_ERROR
, _("Corrupted cpio header encountered in\n%s"), super
->name
);
643 if ((super
->u
.arch
.type
== CPIO_NEWC
&& hd
.c_magic
!= 070701) ||
644 (super
->u
.arch
.type
== CPIO_CRC
&& hd
.c_magic
!= 070702))
647 if (hd
.c_namesize
== 0 || hd
.c_namesize
> MC_MAXPATHLEN
)
649 message (D_ERROR
, MSG_ERROR
, _("Corrupted cpio header encountered in\n%s"), super
->name
);
653 name
= g_malloc (hd
.c_namesize
);
654 len
= mc_read (super
->u
.arch
.fd
, name
, hd
.c_namesize
);
656 if ((len
== -1) || ((unsigned long) len
< hd
.c_namesize
))
661 name
[hd
.c_namesize
- 1] = '\0';
662 CPIO_POS (super
) += len
;
663 cpio_skip_padding (super
);
665 if (strcmp ("TRAILER!!!", name
) == 0)
666 { /* We got to the last record */
671 u
.st
.st_dev
= makedev (hd
.c_dev
, hd
.c_devmin
);
672 u
.st
.st_ino
= hd
.c_ino
;
673 u
.st
.st_mode
= hd
.c_mode
;
674 u
.st
.st_nlink
= hd
.c_nlink
;
675 u
.st
.st_uid
= hd
.c_uid
;
676 u
.st
.st_gid
= hd
.c_gid
;
677 u
.st
.st_rdev
= makedev (hd
.c_rdev
, hd
.c_rdevmin
);
678 u
.st
.st_size
= hd
.c_filesize
;
679 u
.st
.st_atime
= u
.st
.st_mtime
= u
.st
.st_ctime
= hd
.c_mtime
;
681 return cpio_create_entry (me
, super
, &u
.st
, name
);
684 /* --------------------------------------------------------------------------------------------- */
685 /** Need to CPIO_SEEK_CUR to skip the file at the end of add entry!!!! */
688 cpio_open_archive (struct vfs_class
*me
, struct vfs_s_super
*super
, const char *name
, char *op
)
690 int status
= STATUS_START
;
694 if (cpio_open_cpio_file (me
, super
, name
) == -1)
699 status
= cpio_read_head (me
, super
);
704 message (D_ERROR
, MSG_ERROR
, _("Unexpected end of file\n%s"), name
);
717 /* --------------------------------------------------------------------------------------------- */
718 /** Remaining functions are exactly same as for tarfs (and were in fact just copied) */
721 cpio_super_check (struct vfs_class
*me
, const char *archive_name
, char *op
)
723 static struct stat sb
;
728 if (mc_stat (archive_name
, &sb
))
733 /* --------------------------------------------------------------------------------------------- */
736 cpio_super_same (struct vfs_class
*me
, struct vfs_s_super
*parc
,
737 const char *archive_name
, char *op
, void *cookie
)
739 struct stat
*archive_stat
= cookie
; /* stat of main archive */
744 if (strcmp (parc
->name
, archive_name
))
747 /* Has the cached archive been changed on the disk? */
748 if (parc
->u
.arch
.st
.st_mtime
< archive_stat
->st_mtime
)
751 (*vfs_cpiofs_ops
.free
) ((vfsid
) parc
);
752 vfs_rmstamp (&vfs_cpiofs_ops
, (vfsid
) parc
);
755 /* Hasn't been modified, give it a new timeout */
756 vfs_stamp (&vfs_cpiofs_ops
, (vfsid
) parc
);
760 /* --------------------------------------------------------------------------------------------- */
763 cpio_read (void *fh
, char *buffer
, size_t 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
;
770 if (mc_lseek (fd
, begin
+ FH
->pos
, SEEK_SET
) != begin
+ FH
->pos
)
773 count
= MIN (count
, (size_t) (FH
->ino
->st
.st_size
- FH
->pos
));
775 res
= mc_read (fd
, buffer
, count
);
783 /* --------------------------------------------------------------------------------------------- */
786 cpio_fh_open (struct vfs_class
*me
, struct vfs_s_fh
*fh
, int flags
, mode_t mode
)
791 if ((flags
& O_ACCMODE
) != O_RDONLY
)
796 /* --------------------------------------------------------------------------------------------- */
797 /*** public functions ****************************************************************************/
798 /* --------------------------------------------------------------------------------------------- */
803 static struct vfs_s_subclass cpio_subclass
;
805 cpio_subclass
.flags
= VFS_S_READONLY
;
806 cpio_subclass
.archive_check
= cpio_super_check
;
807 cpio_subclass
.archive_same
= cpio_super_same
;
808 cpio_subclass
.open_archive
= cpio_open_archive
;
809 cpio_subclass
.free_archive
= cpio_free_archive
;
810 cpio_subclass
.fh_open
= cpio_fh_open
;
812 vfs_s_init_class (&vfs_cpiofs_ops
, &cpio_subclass
);
813 vfs_cpiofs_ops
.name
= "cpiofs";
814 vfs_cpiofs_ops
.prefix
= "ucpio";
815 vfs_cpiofs_ops
.read
= cpio_read
;
816 vfs_cpiofs_ops
.setctl
= NULL
;
817 vfs_register_class (&vfs_cpiofs_ops
);
820 /* --------------------------------------------------------------------------------------------- */