2 Virtual File System: GNU Tar file system.
4 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2011
5 The Free Software Foundation, Inc.
10 This file is part of the Midnight Commander.
12 The Midnight Commander is free software: you can redistribute it
13 and/or modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation, either version 3 of the License,
15 or (at your option) any later version.
17 The Midnight Commander is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 * \brief Source: Virtual File System: GNU Tar file system.
36 #include <sys/types.h>
40 #include "lib/global.h"
41 #include "lib/unixcompat.h"
43 #include "lib/widget.h" /* message() */
45 #include "lib/vfs/vfs.h"
46 #include "lib/vfs/utilvfs.h"
47 #include "lib/vfs/xdirentry.h"
48 #include "lib/vfs/gc.h" /* vfs_rmstamp */
52 /*** global variables ****************************************************************************/
54 /*** file scope macro definitions ****************************************************************/
56 #define CPIO_POS(super) cpio_position
57 /* If some time reentrancy should be needed change it to */
58 /* #define CPIO_POS(super) (super)->u.arch.fd */
60 #define CPIO_SEEK_SET(super, where) \
61 mc_lseek (((cpio_super_data_t *)(super)->data)->fd, \
62 CPIO_POS(super) = (where), SEEK_SET)
63 #define CPIO_SEEK_CUR(super, where) \
64 mc_lseek (((cpio_super_data_t *)(super)->data)->fd, \
65 CPIO_POS(super) += (where), SEEK_SET)
67 #define MAGIC_LENGTH (6) /* How many bytes we have to read ahead */
68 #define SEEKBACK CPIO_SEEK_CUR(super, ptr - top)
69 #define RETURN(x) return (((cpio_super_data_t *)super->data)->type = (x))
71 ((((cpio_super_data_t *)super->data)->type == CPIO_UNKNOWN) || \
72 (((cpio_super_data_t *)super->data)->type == (x)))
74 #define HEAD_LENGTH (26)
76 /*** file scope type declarations ****************************************************************/
89 CPIO_UNKNOWN
= 0, /* Not determined yet */
90 CPIO_BIN
, /* Binary format */
91 CPIO_BINRE
, /* Binary format, reverse endianity */
92 CPIO_OLDC
, /* Old ASCII format */
93 CPIO_NEWC
, /* New ASCII format */
94 CPIO_CRC
/* New ASCII format + CRC */
97 struct old_cpio_header
99 unsigned short c_magic
;
101 unsigned short c_ino
;
102 unsigned short c_mode
;
103 unsigned short c_uid
;
104 unsigned short c_gid
;
105 unsigned short c_nlink
;
107 unsigned short c_mtimes
[2];
108 unsigned short c_namesize
;
109 unsigned short c_filesizes
[2];
112 struct new_cpio_header
114 unsigned short c_magic
;
116 unsigned long c_mode
;
119 unsigned long c_nlink
;
120 unsigned long c_mtime
;
121 unsigned long c_filesize
;
126 unsigned long c_namesize
;
127 unsigned long c_chksum
;
132 unsigned long inumber
;
133 unsigned short device
;
134 struct vfs_s_inode
*inode
;
141 int type
; /* Type of the archive */
142 GSList
*deferred
; /* List of inodes for which another entries may appear */
145 /*** file scope variables ************************************************************************/
147 static struct vfs_class vfs_cpiofs_ops
;
149 /* FIXME: should be off_t instead of int. */
150 static int cpio_position
;
152 /*** file scope functions ************************************************************************/
153 /* --------------------------------------------------------------------------------------------- */
155 static int cpio_find_head (struct vfs_class
*me
, struct vfs_s_super
*super
);
156 static ssize_t
cpio_read_bin_head (struct vfs_class
*me
, struct vfs_s_super
*super
);
157 static ssize_t
cpio_read_oldc_head (struct vfs_class
*me
, struct vfs_s_super
*super
);
158 static ssize_t
cpio_read_crc_head (struct vfs_class
*me
, struct vfs_s_super
*super
);
159 static ssize_t
cpio_read (void *fh
, char *buffer
, size_t count
);
161 /* --------------------------------------------------------------------------------------------- */
164 cpio_defer_find (const void *a
, const void *b
)
166 const defer_inode
*a1
= (const defer_inode
*) a
;
167 const defer_inode
*b1
= (const defer_inode
*) b
;
169 return (a1
->inumber
== b1
->inumber
&& a1
->device
== b1
->device
) ? 0 : 1;
172 /* --------------------------------------------------------------------------------------------- */
175 cpio_skip_padding (struct vfs_s_super
*super
)
177 switch (((cpio_super_data_t
*) super
->data
)->type
)
181 return CPIO_SEEK_CUR (super
, (2 - (CPIO_POS (super
) % 2)) % 2);
184 return CPIO_SEEK_CUR (super
, (4 - (CPIO_POS (super
) % 4)) % 4);
186 return CPIO_POS (super
);
188 g_assert_not_reached ();
189 return 42; /* & the compiler is happy :-) */
193 /* --------------------------------------------------------------------------------------------- */
196 cpio_free_archive (struct vfs_class
*me
, struct vfs_s_super
*super
)
198 cpio_super_data_t
*arch
= (cpio_super_data_t
*) super
->data
;
202 if (super
->data
== NULL
)
208 g_slist_foreach (arch
->deferred
, (GFunc
) g_free
, NULL
);
209 g_slist_free (arch
->deferred
);
210 arch
->deferred
= NULL
;
211 g_free (super
->data
);
215 /* --------------------------------------------------------------------------------------------- */
218 cpio_open_cpio_file (struct vfs_class
*me
, struct vfs_s_super
*super
, const vfs_path_t
* vpath
)
221 cpio_super_data_t
*arch
;
223 struct vfs_s_inode
*root
;
225 fd
= mc_open (vpath
, O_RDONLY
);
230 name
= vfs_path_to_str (vpath
);
231 message (D_ERROR
, MSG_ERROR
, _("Cannot open cpio archive\n%s"), name
);
236 super
->name
= vfs_path_to_str (vpath
);
237 super
->data
= g_new (cpio_super_data_t
, 1);
238 arch
= (cpio_super_data_t
*) super
->data
;
239 arch
->fd
= -1; /* for now */
240 mc_stat (vpath
, &arch
->st
);
241 arch
->type
= CPIO_UNKNOWN
;
242 arch
->deferred
= NULL
;
244 type
= get_compression_type (fd
, super
->name
);
245 if (type
!= COMPRESSION_NONE
)
248 vfs_path_t
*tmp_vpath
;
251 s
= g_strconcat (super
->name
, decompress_extension (type
), (char *) NULL
);
252 tmp_vpath
= vfs_path_from_str_flags (s
, VPF_NO_CANON
);
253 fd
= mc_open (tmp_vpath
, O_RDONLY
);
254 vfs_path_free (tmp_vpath
);
257 message (D_ERROR
, MSG_ERROR
, _("Cannot open cpio archive\n%s"), s
);
259 g_free (super
->name
);
267 mode
= arch
->st
.st_mode
& 07777;
268 mode
|= (mode
& 0444) >> 2; /* set eXec where Read is */
271 root
= vfs_s_new_inode (me
, super
, &arch
->st
);
272 root
->st
.st_mode
= mode
;
273 root
->data_offset
= -1;
275 root
->st
.st_dev
= MEDATA
->rdev
++;
279 CPIO_SEEK_SET (super
, 0);
284 /* --------------------------------------------------------------------------------------------- */
287 cpio_read_head (struct vfs_class
*me
, struct vfs_s_super
*super
)
289 switch (cpio_find_head (me
, super
))
295 return cpio_read_bin_head (me
, super
);
297 return cpio_read_oldc_head (me
, super
);
300 return cpio_read_crc_head (me
, super
);
302 g_assert_not_reached ();
303 return 42; /* & the compiler is happy :-) */
307 /* --------------------------------------------------------------------------------------------- */
310 cpio_find_head (struct vfs_class
*me
, struct vfs_s_super
*super
)
312 cpio_super_data_t
*arch
= (cpio_super_data_t
*) super
->data
;
313 char buf
[BUF_SMALL
* 2];
318 top
= mc_read (arch
->fd
, buf
, sizeof (buf
));
320 CPIO_POS (super
) += top
;
324 if (ptr
+ MAGIC_LENGTH
>= top
)
326 if (top
> (ssize_t
) (sizeof (buf
) / 2))
328 memmove (buf
, buf
+ top
- sizeof (buf
) / 2, sizeof (buf
) / 2);
329 ptr
-= top
- sizeof (buf
) / 2;
330 top
= sizeof (buf
) / 2;
332 tmp
= mc_read (arch
->fd
, buf
, top
);
333 if (tmp
== 0 || tmp
== -1)
335 message (D_ERROR
, MSG_ERROR
, _("Premature end of cpio archive\n%s"), super
->name
);
336 cpio_free_archive (me
, super
);
341 if (TYPEIS (CPIO_BIN
) && ((*(unsigned short *) (buf
+ ptr
)) == 070707))
346 else if (TYPEIS (CPIO_BINRE
)
347 && ((*(unsigned short *) (buf
+ ptr
)) == GUINT16_SWAP_LE_BE_CONSTANT (070707)))
352 else if (TYPEIS (CPIO_OLDC
) && (strncmp (buf
+ ptr
, "070707", 6) == 0))
357 else if (TYPEIS (CPIO_NEWC
) && (strncmp (buf
+ ptr
, "070701", 6) == 0))
362 else if (TYPEIS (CPIO_CRC
) && (strncmp (buf
+ ptr
, "070702", 6) == 0))
371 /* --------------------------------------------------------------------------------------------- */
374 cpio_create_entry (struct vfs_class
*me
, struct vfs_s_super
*super
, struct stat
*st
, char *name
)
376 cpio_super_data_t
*arch
= (cpio_super_data_t
*) super
->data
;
377 struct vfs_s_inode
*inode
= NULL
;
378 struct vfs_s_inode
*root
= super
->root
;
379 struct vfs_s_entry
*entry
= NULL
;
382 switch (st
->st_mode
& S_IFMT
)
383 { /* For case of HP/UX archives */
395 if ((st
->st_size
!= 0) && (st
->st_rdev
== 0x0001))
397 /* FIXME: representation of major/minor differs between */
398 /* different operating systems. */
399 st
->st_rdev
= (unsigned) st
->st_size
;
407 if ((st
->st_nlink
> 1) && ((arch
->type
== CPIO_NEWC
) || (arch
->type
== CPIO_CRC
)))
408 { /* For case of hardlinked files */
409 defer_inode i
= { st
->st_ino
, st
->st_dev
, NULL
};
412 l
= g_slist_find_custom (arch
->deferred
, &i
, cpio_defer_find
);
415 inode
= ((defer_inode
*) l
->data
)->inode
;
416 if (inode
->st
.st_size
!= 0 && st
->st_size
!= 0 && (inode
->st
.st_size
!= st
->st_size
))
418 message (D_ERROR
, MSG_ERROR
,
419 _("Inconsistent hardlinks of\n%s\nin cpio archive\n%s"),
423 else if (inode
->st
.st_size
== 0)
424 inode
->st
.st_size
= st
->st_size
;
428 /* remove trailing slashes */
429 for (tn
= name
+ strlen (name
) - 1; tn
>= name
&& *tn
== PATH_SEP
; tn
--)
432 tn
= strrchr (name
, PATH_SEP
);
435 else if (tn
== name
+ 1)
437 /* started with "./" -- directory in the root of archive */
443 root
= vfs_s_find_inode (me
, super
, name
, LINK_FOLLOW
, FL_MKDIR
);
448 entry
= MEDATA
->find_entry (me
, root
, tn
, LINK_FOLLOW
, FL_NONE
); /* In case entry is already there */
452 /* This shouldn't happen! (well, it can happen if there is a record for a
453 file and than a record for a directory it is in; cpio would die with
454 'No such file or directory' is such case) */
456 if (!S_ISDIR (entry
->ino
->st
.st_mode
))
458 /* This can be considered archive inconsistency */
459 message (D_ERROR
, MSG_ERROR
,
460 _("%s contains duplicate entries! Skipping!"), super
->name
);
464 entry
->ino
->st
.st_mode
= st
->st_mode
;
465 entry
->ino
->st
.st_uid
= st
->st_uid
;
466 entry
->ino
->st
.st_gid
= st
->st_gid
;
467 entry
->ino
->st
.st_atime
= st
->st_atime
;
468 entry
->ino
->st
.st_mtime
= st
->st_mtime
;
469 entry
->ino
->st
.st_ctime
= st
->st_ctime
;
478 inode
= vfs_s_new_inode (me
, super
, st
);
479 if ((st
->st_nlink
> 0) && ((arch
->type
== CPIO_NEWC
) || (arch
->type
== CPIO_CRC
)))
481 /* For case of hardlinked files */
484 i
= g_new (defer_inode
, 1);
485 i
->inumber
= st
->st_ino
;
486 i
->device
= st
->st_dev
;
489 arch
->deferred
= g_slist_prepend (arch
->deferred
, i
);
493 if (st
->st_size
!= 0)
494 inode
->data_offset
= CPIO_POS (super
);
496 entry
= vfs_s_new_entry (me
, tn
, inode
);
497 vfs_s_insert_entry (me
, root
, entry
);
501 if (!S_ISLNK (st
->st_mode
))
502 CPIO_SEEK_CUR (super
, st
->st_size
);
505 inode
->linkname
= g_malloc (st
->st_size
+ 1);
507 if (mc_read (arch
->fd
, inode
->linkname
, st
->st_size
) < st
->st_size
)
509 inode
->linkname
[0] = '\0';
513 inode
->linkname
[st
->st_size
] = '\0'; /* Linkname stored without terminating \0 !!! */
514 CPIO_POS (super
) += st
->st_size
;
515 cpio_skip_padding (super
);
522 /* --------------------------------------------------------------------------------------------- */
525 cpio_read_bin_head (struct vfs_class
*me
, struct vfs_s_super
*super
)
529 struct old_cpio_header buf
;
530 short shorts
[HEAD_LENGTH
>> 1];
533 cpio_super_data_t
*arch
= (cpio_super_data_t
*) super
->data
;
538 len
= mc_read (arch
->fd
, (char *) &u
.buf
, HEAD_LENGTH
);
539 if (len
< HEAD_LENGTH
)
541 CPIO_POS (super
) += len
;
542 if (arch
->type
== CPIO_BINRE
)
545 for (i
= 0; i
< (HEAD_LENGTH
>> 1); i
++)
546 u
.shorts
[i
] = GUINT16_SWAP_LE_BE_CONSTANT (u
.shorts
[i
]);
549 if (u
.buf
.c_magic
!= 070707 || u
.buf
.c_namesize
== 0 || u
.buf
.c_namesize
> MC_MAXPATHLEN
)
551 message (D_ERROR
, MSG_ERROR
, _("Corrupted cpio header encountered in\n%s"), super
->name
);
554 name
= g_malloc (u
.buf
.c_namesize
);
555 len
= mc_read (arch
->fd
, name
, u
.buf
.c_namesize
);
556 if (len
< u
.buf
.c_namesize
)
561 name
[u
.buf
.c_namesize
- 1] = '\0';
562 CPIO_POS (super
) += len
;
563 cpio_skip_padding (super
);
565 if (!strcmp ("TRAILER!!!", name
))
566 { /* We got to the last record */
571 st
.st_dev
= u
.buf
.c_dev
;
572 st
.st_ino
= u
.buf
.c_ino
;
573 st
.st_mode
= u
.buf
.c_mode
;
574 st
.st_nlink
= u
.buf
.c_nlink
;
575 st
.st_uid
= u
.buf
.c_uid
;
576 st
.st_gid
= u
.buf
.c_gid
;
577 st
.st_rdev
= u
.buf
.c_rdev
;
578 st
.st_size
= (u
.buf
.c_filesizes
[0] << 16) | u
.buf
.c_filesizes
[1];
579 st
.st_atime
= st
.st_mtime
= st
.st_ctime
= (u
.buf
.c_mtimes
[0] << 16) | u
.buf
.c_mtimes
[1];
581 return cpio_create_entry (me
, super
, &st
, name
);
584 /* --------------------------------------------------------------------------------------------- */
587 #define HEAD_LENGTH (76)
590 cpio_read_oldc_head (struct vfs_class
*me
, struct vfs_s_super
*super
)
592 cpio_super_data_t
*arch
= (cpio_super_data_t
*) super
->data
;
593 struct new_cpio_header hd
;
597 char buf
[HEAD_LENGTH
+ 1];
602 if (mc_read (arch
->fd
, u
.buf
, HEAD_LENGTH
) != HEAD_LENGTH
)
604 CPIO_POS (super
) += HEAD_LENGTH
;
605 u
.buf
[HEAD_LENGTH
] = 0;
607 if (sscanf (u
.buf
, "070707%6lo%6lo%6lo%6lo%6lo%6lo%6lo%11lo%6lo%11lo",
608 (unsigned long *) &hd
.c_dev
, &hd
.c_ino
, &hd
.c_mode
, &hd
.c_uid
, &hd
.c_gid
,
609 &hd
.c_nlink
, (unsigned long *) &hd
.c_rdev
, &hd
.c_mtime
,
610 &hd
.c_namesize
, &hd
.c_filesize
) < 10)
612 message (D_ERROR
, MSG_ERROR
, _("Corrupted cpio header encountered in\n%s"), super
->name
);
616 if (hd
.c_namesize
== 0 || hd
.c_namesize
> MC_MAXPATHLEN
)
618 message (D_ERROR
, MSG_ERROR
, _("Corrupted cpio header encountered in\n%s"), super
->name
);
621 name
= g_malloc (hd
.c_namesize
);
622 len
= mc_read (arch
->fd
, name
, hd
.c_namesize
);
623 if ((len
== -1) || ((unsigned long) len
< hd
.c_namesize
))
628 name
[hd
.c_namesize
- 1] = '\0';
629 CPIO_POS (super
) += len
;
630 cpio_skip_padding (super
);
632 if (!strcmp ("TRAILER!!!", name
))
633 { /* We got to the last record */
638 u
.st
.st_dev
= hd
.c_dev
;
639 u
.st
.st_ino
= hd
.c_ino
;
640 u
.st
.st_mode
= hd
.c_mode
;
641 u
.st
.st_nlink
= hd
.c_nlink
;
642 u
.st
.st_uid
= hd
.c_uid
;
643 u
.st
.st_gid
= hd
.c_gid
;
644 u
.st
.st_rdev
= hd
.c_rdev
;
645 u
.st
.st_size
= hd
.c_filesize
;
646 u
.st
.st_atime
= u
.st
.st_mtime
= u
.st
.st_ctime
= hd
.c_mtime
;
648 return cpio_create_entry (me
, super
, &u
.st
, name
);
651 /* --------------------------------------------------------------------------------------------- */
654 #define HEAD_LENGTH (110)
657 cpio_read_crc_head (struct vfs_class
*me
, struct vfs_s_super
*super
)
659 cpio_super_data_t
*arch
= (cpio_super_data_t
*) super
->data
;
660 struct new_cpio_header hd
;
664 char buf
[HEAD_LENGTH
+ 1];
669 if (mc_read (arch
->fd
, u
.buf
, HEAD_LENGTH
) != HEAD_LENGTH
)
672 CPIO_POS (super
) += HEAD_LENGTH
;
673 u
.buf
[HEAD_LENGTH
] = '\0';
675 if (sscanf (u
.buf
, "%6ho%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx",
676 &hd
.c_magic
, &hd
.c_ino
, &hd
.c_mode
, &hd
.c_uid
, &hd
.c_gid
,
677 &hd
.c_nlink
, &hd
.c_mtime
, &hd
.c_filesize
,
678 (unsigned long *) &hd
.c_dev
, (unsigned long *) &hd
.c_devmin
,
679 (unsigned long *) &hd
.c_rdev
, (unsigned long *) &hd
.c_rdevmin
,
680 &hd
.c_namesize
, &hd
.c_chksum
) < 14)
682 message (D_ERROR
, MSG_ERROR
, _("Corrupted cpio header encountered in\n%s"), super
->name
);
686 if ((arch
->type
== CPIO_NEWC
&& hd
.c_magic
!= 070701) ||
687 (arch
->type
== CPIO_CRC
&& hd
.c_magic
!= 070702))
690 if (hd
.c_namesize
== 0 || hd
.c_namesize
> MC_MAXPATHLEN
)
692 message (D_ERROR
, MSG_ERROR
, _("Corrupted cpio header encountered in\n%s"), super
->name
);
696 name
= g_malloc (hd
.c_namesize
);
697 len
= mc_read (arch
->fd
, name
, hd
.c_namesize
);
699 if ((len
== -1) || ((unsigned long) len
< hd
.c_namesize
))
704 name
[hd
.c_namesize
- 1] = '\0';
705 CPIO_POS (super
) += len
;
706 cpio_skip_padding (super
);
708 if (strcmp ("TRAILER!!!", name
) == 0)
709 { /* We got to the last record */
714 u
.st
.st_dev
= makedev (hd
.c_dev
, hd
.c_devmin
);
715 u
.st
.st_ino
= hd
.c_ino
;
716 u
.st
.st_mode
= hd
.c_mode
;
717 u
.st
.st_nlink
= hd
.c_nlink
;
718 u
.st
.st_uid
= hd
.c_uid
;
719 u
.st
.st_gid
= hd
.c_gid
;
720 u
.st
.st_rdev
= makedev (hd
.c_rdev
, hd
.c_rdevmin
);
721 u
.st
.st_size
= hd
.c_filesize
;
722 u
.st
.st_atime
= u
.st
.st_mtime
= u
.st
.st_ctime
= hd
.c_mtime
;
724 return cpio_create_entry (me
, super
, &u
.st
, name
);
727 /* --------------------------------------------------------------------------------------------- */
728 /** Need to CPIO_SEEK_CUR to skip the file at the end of add entry!!!! */
731 cpio_open_archive (struct vfs_s_super
*super
, const vfs_path_t
* vpath
,
732 const vfs_path_element_t
* vpath_element
)
734 int status
= STATUS_START
;
736 (void) vpath_element
;
738 if (cpio_open_cpio_file (vpath_element
->class, super
, vpath
) == -1)
743 status
= cpio_read_head (vpath_element
->class, super
);
751 archive_name
= vfs_path_to_str (vpath
);
752 message (D_ERROR
, MSG_ERROR
, _("Unexpected end of file\n%s"), archive_name
);
753 g_free (archive_name
);
767 /* --------------------------------------------------------------------------------------------- */
768 /** Remaining functions are exactly same as for tarfs (and were in fact just copied) */
771 cpio_super_check (const vfs_path_t
* vpath
)
773 static struct stat sb
;
776 stat_result
= mc_stat (vpath
, &sb
);
777 return (stat_result
== 0 ? &sb
: NULL
);
780 /* --------------------------------------------------------------------------------------------- */
783 cpio_super_same (const vfs_path_element_t
* vpath_element
, struct vfs_s_super
*parc
,
784 const vfs_path_t
* vpath
, void *cookie
)
786 struct stat
*archive_stat
= cookie
; /* stat of main archive */
787 char *archive_name
= vfs_path_to_str (vpath
);
789 (void) vpath_element
;
791 if (strcmp (parc
->name
, archive_name
))
793 g_free (archive_name
);
796 g_free (archive_name
);
798 /* Has the cached archive been changed on the disk? */
799 if (((cpio_super_data_t
*) parc
->data
)->st
.st_mtime
< archive_stat
->st_mtime
)
802 (*vfs_cpiofs_ops
.free
) ((vfsid
) parc
);
803 vfs_rmstamp (&vfs_cpiofs_ops
, (vfsid
) parc
);
806 /* Hasn't been modified, give it a new timeout */
807 vfs_stamp (&vfs_cpiofs_ops
, (vfsid
) parc
);
811 /* --------------------------------------------------------------------------------------------- */
814 cpio_read (void *fh
, char *buffer
, size_t count
)
816 off_t begin
= FH
->ino
->data_offset
;
817 int fd
= ((cpio_super_data_t
*) FH_SUPER
->data
)->fd
;
818 struct vfs_class
*me
= FH_SUPER
->me
;
821 if (mc_lseek (fd
, begin
+ FH
->pos
, SEEK_SET
) != begin
+ FH
->pos
)
824 count
= MIN (count
, (size_t) (FH
->ino
->st
.st_size
- FH
->pos
));
826 res
= mc_read (fd
, buffer
, count
);
834 /* --------------------------------------------------------------------------------------------- */
837 cpio_fh_open (struct vfs_class
*me
, vfs_file_handler_t
* fh
, int flags
, mode_t mode
)
843 if ((flags
& O_ACCMODE
) != O_RDONLY
)
848 /* --------------------------------------------------------------------------------------------- */
849 /*** public functions ****************************************************************************/
850 /* --------------------------------------------------------------------------------------------- */
855 static struct vfs_s_subclass cpio_subclass
;
857 cpio_subclass
.flags
= VFS_S_READONLY
; /* FIXME: cpiofs used own temp files */
858 cpio_subclass
.archive_check
= cpio_super_check
;
859 cpio_subclass
.archive_same
= cpio_super_same
;
860 cpio_subclass
.open_archive
= cpio_open_archive
;
861 cpio_subclass
.free_archive
= cpio_free_archive
;
862 cpio_subclass
.fh_open
= cpio_fh_open
;
864 vfs_s_init_class (&vfs_cpiofs_ops
, &cpio_subclass
);
865 vfs_cpiofs_ops
.name
= "cpiofs";
866 vfs_cpiofs_ops
.prefix
= "ucpio";
867 vfs_cpiofs_ops
.read
= cpio_read
;
868 vfs_cpiofs_ops
.setctl
= NULL
;
869 vfs_register_class (&vfs_cpiofs_ops
);
872 /* --------------------------------------------------------------------------------------------- */