Don't include lib/util.h via lib/global.h.
[midnight-commander/osp/fridrivaxxx.git] / lib / vfs / mc-vfs / cpio.c
blob7b344f45cf97d72ef7dac849be1a8834a48a8e50
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. */
21 /** \file
22 * \brief Source: Virtual File System: GNU Tar file system.
23 * \author Jan Hudec
24 * \date 2000
27 #include <config.h>
29 #include <errno.h>
30 #include <fcntl.h>
32 #include "lib/global.h"
33 #include "lib/unixcompat.h"
34 #include "lib/util.h"
35 #include "lib/widget/wtools.h" /* message() */
37 #include "vfs-impl.h"
38 #include "utilvfs.h"
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 ****************************************************************/
62 enum
64 STATUS_START,
65 STATUS_OK,
66 STATUS_TRAIL,
67 STATUS_FAIL,
68 STATUS_EOF
71 enum
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;
84 short c_dev;
85 unsigned short c_ino;
86 unsigned short c_mode;
87 unsigned short c_uid;
88 unsigned short c_gid;
89 unsigned short c_nlink;
90 short c_rdev;
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;
99 unsigned long c_ino;
100 unsigned long c_mode;
101 unsigned long c_uid;
102 unsigned long c_gid;
103 unsigned long c_nlink;
104 unsigned long c_mtime;
105 unsigned long c_filesize;
106 long c_dev;
107 long c_devmin;
108 long c_rdev;
109 long c_rdevmin;
110 unsigned long c_namesize;
111 unsigned long c_chksum;
114 struct defer_inode
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))
144 l = l->next;
145 return l;
148 /* --------------------------------------------------------------------------------------------- */
150 static int
151 cpio_skip_padding (struct vfs_s_super *super)
153 switch (super->u.arch.type)
155 case CPIO_BIN:
156 case CPIO_BINRE:
157 return CPIO_SEEK_CUR (super, (2 - (CPIO_POS (super) % 2)) % 2);
158 case CPIO_NEWC:
159 case CPIO_CRC:
160 return CPIO_SEEK_CUR (super, (4 - (CPIO_POS (super) % 4)) % 4);
161 case CPIO_OLDC:
162 return CPIO_POS (super);
163 default:
164 g_assert_not_reached ();
165 return 42; /* & the compiler is happy :-) */
169 /* --------------------------------------------------------------------------------------------- */
171 static void
172 cpio_free_archive (struct vfs_class *me, struct vfs_s_super *super)
174 struct defer_inode *l, *lnext;
176 (void) me;
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)
183 lnext = l->next;
184 g_free (l);
186 super->u.arch.deferred = NULL;
189 /* --------------------------------------------------------------------------------------------- */
191 static int
192 cpio_open_cpio_file (struct vfs_class *me, struct vfs_s_super *super, const char *name)
194 int fd, type;
195 mode_t mode;
196 struct vfs_s_inode *root;
198 fd = mc_open (name, O_RDONLY);
199 if (fd == -1)
201 message (D_ERROR, MSG_ERROR, _("Cannot open cpio archive\n%s"), name);
202 return -1;
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)
213 char *s;
215 mc_close (fd);
216 s = g_strconcat (name, decompress_extension (type), (char *) NULL);
217 fd = mc_open (s, O_RDONLY);
218 if (fd == -1)
220 message (D_ERROR, MSG_ERROR, _("Cannot open cpio archive\n%s"), s);
221 g_free (s);
222 return -1;
224 g_free (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 */
230 mode |= S_IFDIR;
232 root = vfs_s_new_inode (me, super, &(super->u.arch.st));
233 root->st.st_mode = mode;
234 root->data_offset = -1;
235 root->st.st_nlink++;
236 root->st.st_dev = MEDATA->rdev++;
238 super->root = root;
240 CPIO_SEEK_SET (super, 0);
242 return fd;
245 /* --------------------------------------------------------------------------------------------- */
247 static ssize_t
248 cpio_read_head (struct vfs_class *me, struct vfs_s_super *super)
250 switch (cpio_find_head (me, super))
252 case CPIO_UNKNOWN:
253 return -1;
254 case CPIO_BIN:
255 case CPIO_BINRE:
256 return cpio_read_bin_head (me, super);
257 case CPIO_OLDC:
258 return cpio_read_oldc_head (me, super);
259 case CPIO_NEWC:
260 case CPIO_CRC:
261 return cpio_read_crc_head (me, super);
262 default:
263 g_assert_not_reached ();
264 return 42; /* & the compiler is happy :-) */
268 /* --------------------------------------------------------------------------------------------- */
270 static int
271 cpio_find_head (struct vfs_class *me, struct vfs_s_super *super)
273 char buf[256];
274 int ptr = 0;
275 ssize_t top;
276 ssize_t tmp;
278 top = mc_read (super->u.arch.fd, buf, 256);
279 if (top > 0)
280 CPIO_POS (super) += top;
281 for (;;)
283 if (ptr + MAGIC_LENGTH >= top)
285 if (top > 128)
287 memmove (buf, buf + top - 128, 128);
288 ptr -= top - 128;
289 top = 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);
296 return CPIO_UNKNOWN;
298 top += tmp;
300 if (TYPEIS (CPIO_BIN) && ((*(unsigned short *) (buf + ptr)) == 070707))
302 SEEKBACK;
303 RETURN (CPIO_BIN);
305 else if (TYPEIS (CPIO_BINRE)
306 && ((*(unsigned short *) (buf + ptr)) == GUINT16_SWAP_LE_BE_CONSTANT (070707)))
308 SEEKBACK;
309 RETURN (CPIO_BINRE);
311 else if (TYPEIS (CPIO_OLDC) && (!strncmp (buf + ptr, "070707", 6)))
313 SEEKBACK;
314 RETURN (CPIO_OLDC);
316 else if (TYPEIS (CPIO_NEWC) && (!strncmp (buf + ptr, "070701", 6)))
318 SEEKBACK;
319 RETURN (CPIO_NEWC);
321 else if (TYPEIS (CPIO_CRC) && (!strncmp (buf + ptr, "070702", 6)))
323 SEEKBACK;
324 RETURN (CPIO_CRC);
326 ptr++;
330 /* --------------------------------------------------------------------------------------------- */
332 static int
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;
338 char *tn;
340 switch (st->st_mode & S_IFMT)
341 { /* For case of HP/UX archives */
342 case S_IFCHR:
343 case S_IFBLK:
344 #ifdef S_IFSOCK
345 case S_IFSOCK:
346 #endif
347 #ifdef S_IFIFO
348 case S_IFIFO:
349 #endif
350 #ifdef S_IFNAM
351 case S_IFNAM:
352 #endif
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;
358 st->st_size = 0;
360 break;
361 default:
362 break;
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;
371 i.inode = NULL;
373 l = cpio_defer_find (super->u.arch.deferred, &i);
374 if (l != NULL)
376 inode = l->inode;
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"),
381 name, super->name);
382 inode = NULL;
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--)
391 *tn = '\0';
393 tn = strrchr (name, PATH_SEP);
394 if (tn == NULL)
395 tn = name;
396 else if (tn == name + 1)
398 /* started with "./" -- directory in the root of archive */
399 tn++;
401 else
403 *tn = '\0';
404 root = vfs_s_find_inode (me, super, name, LINK_FOLLOW, FL_MKDIR);
405 *tn = PATH_SEP;
406 tn++;
409 entry = MEDATA->find_entry (me, root, tn, LINK_FOLLOW, FL_NONE); /* In case entry is already there */
411 if (entry != NULL)
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);
423 else
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;
433 g_free (name);
435 else
436 { /* !entry */
437 if (inode == NULL)
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;
448 i->inode = inode;
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);
460 g_free (name);
462 if (!S_ISLNK (st->st_mode))
463 CPIO_SEEK_CUR (super, st->st_size);
464 else
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';
471 return STATUS_EOF;
474 inode->linkname[st->st_size] = '\0'; /* Linkname stored without terminating \0 !!! */
475 CPIO_POS (super) += st->st_size;
476 cpio_skip_padding (super);
478 } /* !entry */
480 return STATUS_OK;
483 /* --------------------------------------------------------------------------------------------- */
485 static ssize_t
486 cpio_read_bin_head (struct vfs_class *me, struct vfs_s_super *super)
488 union
490 struct old_cpio_header buf;
491 short shorts[HEAD_LENGTH >> 1];
492 } u;
493 ssize_t len;
494 char *name;
495 struct stat st;
497 len = mc_read (super->u.arch.fd, (char *) &u.buf, HEAD_LENGTH);
498 if (len < HEAD_LENGTH)
499 return STATUS_EOF;
500 CPIO_POS (super) += len;
501 if (super->u.arch.type == CPIO_BINRE)
503 int i;
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);
511 return STATUS_FAIL;
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)
517 g_free (name);
518 return STATUS_EOF;
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 */
526 g_free (name);
527 return STATUS_TRAIL;
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 /* --------------------------------------------------------------------------------------------- */
545 #undef HEAD_LENGTH
546 #define HEAD_LENGTH (76)
548 static ssize_t
549 cpio_read_oldc_head (struct vfs_class *me, struct vfs_s_super *super)
551 struct new_cpio_header hd;
552 union
554 struct stat st;
555 char buf[HEAD_LENGTH + 1];
556 } u;
557 ssize_t len;
558 char *name;
560 if (mc_read (super->u.arch.fd, u.buf, HEAD_LENGTH) != HEAD_LENGTH)
561 return STATUS_EOF;
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);
571 return STATUS_FAIL;
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);
577 return STATUS_FAIL;
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))
583 g_free (name);
584 return STATUS_EOF;
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 */
592 g_free (name);
593 return STATUS_TRAIL;
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 /* --------------------------------------------------------------------------------------------- */
611 #undef HEAD_LENGTH
612 #define HEAD_LENGTH (110)
614 static ssize_t
615 cpio_read_crc_head (struct vfs_class *me, struct vfs_s_super *super)
617 struct new_cpio_header hd;
618 union
620 struct stat st;
621 char buf[HEAD_LENGTH + 1];
622 } u;
623 ssize_t len;
624 char *name;
626 if (mc_read (super->u.arch.fd, u.buf, HEAD_LENGTH) != HEAD_LENGTH)
627 return STATUS_EOF;
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);
640 return STATUS_FAIL;
643 if ((super->u.arch.type == CPIO_NEWC && hd.c_magic != 070701) ||
644 (super->u.arch.type == CPIO_CRC && hd.c_magic != 070702))
645 return STATUS_FAIL;
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);
650 return STATUS_FAIL;
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))
658 g_free (name);
659 return STATUS_EOF;
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 */
667 g_free (name);
668 return STATUS_TRAIL;
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!!!! */
687 static int
688 cpio_open_archive (struct vfs_class *me, struct vfs_s_super *super, const char *name, char *op)
690 int status = STATUS_START;
692 (void) op;
694 if (cpio_open_cpio_file (me, super, name) == -1)
695 return -1;
697 for (;;)
699 status = cpio_read_head (me, super);
701 switch (status)
703 case STATUS_EOF:
704 message (D_ERROR, MSG_ERROR, _("Unexpected end of file\n%s"), name);
705 return 0;
706 case STATUS_OK:
707 continue;
708 case STATUS_TRAIL:
709 break;
711 break;
714 return 0;
717 /* --------------------------------------------------------------------------------------------- */
718 /** Remaining functions are exactly same as for tarfs (and were in fact just copied) */
720 static void *
721 cpio_super_check (struct vfs_class *me, const char *archive_name, char *op)
723 static struct stat sb;
725 (void) me;
726 (void) op;
728 if (mc_stat (archive_name, &sb))
729 return NULL;
730 return &sb;
733 /* --------------------------------------------------------------------------------------------- */
735 static int
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 */
741 (void) me;
742 (void) op;
744 if (strcmp (parc->name, archive_name))
745 return 0;
747 /* Has the cached archive been changed on the disk? */
748 if (parc->u.arch.st.st_mtime < archive_stat->st_mtime)
750 /* Yes, reload! */
751 (*vfs_cpiofs_ops.free) ((vfsid) parc);
752 vfs_rmstamp (&vfs_cpiofs_ops, (vfsid) parc);
753 return 2;
755 /* Hasn't been modified, give it a new timeout */
756 vfs_stamp (&vfs_cpiofs_ops, (vfsid) parc);
757 return 1;
760 /* --------------------------------------------------------------------------------------------- */
762 static ssize_t
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;
768 ssize_t res;
770 if (mc_lseek (fd, begin + FH->pos, SEEK_SET) != begin + FH->pos)
771 ERRNOR (EIO, -1);
773 count = MIN (count, (size_t) (FH->ino->st.st_size - FH->pos));
775 res = mc_read (fd, buffer, count);
776 if (res == -1)
777 ERRNOR (errno, -1);
779 FH->pos += res;
780 return res;
783 /* --------------------------------------------------------------------------------------------- */
785 static int
786 cpio_fh_open (struct vfs_class *me, struct vfs_s_fh *fh, int flags, mode_t mode)
788 (void) fh;
789 (void) mode;
791 if ((flags & O_ACCMODE) != O_RDONLY)
792 ERRNOR (EROFS, -1);
793 return 0;
796 /* --------------------------------------------------------------------------------------------- */
797 /*** public functions ****************************************************************************/
798 /* --------------------------------------------------------------------------------------------- */
800 void
801 init_cpiofs (void)
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 /* --------------------------------------------------------------------------------------------- */