1 /* Virtual File System: GNU Tar file system.
2 Copyright (C) 2000 The Free Software Foundation
4 Written by: 2000 Jan Hudec
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License
8 as published by the Free Software Foundation; either version 2 of
9 the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24 #include "gc.h" /* vfs_rmstamp */
25 #include "xdirentry.h"
36 CPIO_UNKNOWN
= 0, /* Not determined yet */
37 CPIO_BIN
, /* Binary format */
38 CPIO_BINRE
, /* Binary format, reverse endianity */
39 CPIO_OLDC
, /* Old ASCII format */
40 CPIO_NEWC
, /* New ASCII format */
41 CPIO_CRC
/* New ASCII format + CRC */
44 static struct vfs_class vfs_cpiofs_ops
;
46 struct old_cpio_header
48 unsigned short c_magic
;
51 unsigned short c_mode
;
54 unsigned short c_nlink
;
56 unsigned short c_mtimes
[2];
57 unsigned short c_namesize
;
58 unsigned short c_filesizes
[2];
61 struct new_cpio_header
63 unsigned short c_magic
;
68 unsigned long c_nlink
;
69 unsigned long c_mtime
;
70 unsigned long c_filesize
;
75 unsigned long c_namesize
;
76 unsigned long c_chksum
;
80 struct defer_inode
*next
;
81 unsigned long inumber
;
82 unsigned short device
;
83 struct vfs_s_inode
*inode
;
86 static int cpio_position
;
88 static int cpio_find_head(struct vfs_class
*me
, struct vfs_s_super
*super
);
89 static int cpio_read_bin_head(struct vfs_class
*me
, struct vfs_s_super
*super
);
90 static int cpio_read_oldc_head(struct vfs_class
*me
, struct vfs_s_super
*super
);
91 static int cpio_read_crc_head(struct vfs_class
*me
, struct vfs_s_super
*super
);
92 static int cpio_create_entry(struct vfs_class
*me
, struct vfs_s_super
*super
, struct stat
*, char *name
);
93 static int cpio_read(void *fh
, char *buffer
, int count
);
95 #define CPIO_POS(super) cpio_position
96 /* If some time reentrancy should be needed change it to */
97 /* #define CPIO_POS(super) (super)->u.arch.fd */
99 #define CPIO_SEEK_SET(super, where) mc_lseek((super)->u.arch.fd, CPIO_POS(super) = (where), SEEK_SET)
100 #define CPIO_SEEK_CUR(super, where) mc_lseek((super)->u.arch.fd, CPIO_POS(super) += (where), SEEK_SET)
102 static struct defer_inode
*
103 cpio_defer_find (struct defer_inode
*l
, struct defer_inode
*i
)
107 return l
->inumber
== i
->inumber
108 && l
->device
== i
->device
? l
: cpio_defer_find (l
->next
, i
);
111 static int cpio_skip_padding(struct vfs_s_super
*super
)
113 switch(super
->u
.arch
.type
) {
116 return CPIO_SEEK_CUR(super
, (2 - (CPIO_POS(super
) % 2)) % 2);
119 return CPIO_SEEK_CUR(super
, (4 - (CPIO_POS(super
) % 4)) % 4);
121 return CPIO_POS(super
);
123 g_assert_not_reached();
124 return 42; /* & the compiler is happy :-) */
128 static void cpio_free_archive(struct vfs_class
*me
, struct vfs_s_super
*super
)
130 if(super
->u
.arch
.fd
!= -1)
131 mc_close(super
->u
.arch
.fd
);
135 cpio_open_cpio_file (struct vfs_class
*me
, struct vfs_s_super
*super
,
140 struct vfs_s_inode
*root
;
142 if ((fd
= mc_open (name
, O_RDONLY
)) == -1) {
143 message (1, MSG_ERROR
, _("Cannot open cpio archive\n%s"), name
);
147 super
->name
= g_strdup (name
);
148 super
->u
.arch
.fd
= -1; /* for now */
149 mc_stat (name
, &(super
->u
.arch
.st
));
150 super
->u
.arch
.type
= CPIO_UNKNOWN
;
152 type
= get_compression_type (fd
);
153 if (type
!= COMPRESSION_NONE
) {
157 s
= g_strconcat (name
, decompress_extension (type
), NULL
);
158 if ((fd
= mc_open (s
, O_RDONLY
)) == -1) {
159 message (1, MSG_ERROR
, _("Cannot open cpio archive\n%s"), s
);
166 super
->u
.arch
.fd
= fd
;
167 mode
= super
->u
.arch
.st
.st_mode
& 07777;
168 mode
|= (mode
& 0444) >> 2; /* set eXec where Read is */
171 root
= vfs_s_new_inode (me
, super
, &(super
->u
.arch
.st
));
172 root
->st
.st_mode
= mode
;
173 root
->data_offset
= -1;
175 root
->st
.st_dev
= MEDATA
->rdev
++;
179 CPIO_SEEK_SET (super
, 0);
184 static int cpio_read_head(struct vfs_class
*me
, struct vfs_s_super
*super
)
186 switch(cpio_find_head(me
, super
)) {
191 return cpio_read_bin_head(me
, super
);
193 return cpio_read_oldc_head(me
, super
);
196 return cpio_read_crc_head(me
, super
);
198 g_assert_not_reached();
199 return 42; /* & the compiler is happy :-) */
203 #define MAGIC_LENGTH (6) /* How many bytes we have to read ahead */
204 #define SEEKBACK CPIO_SEEK_CUR(super, ptr - top)
205 #define RETURN(x) return(super->u.arch.type = (x))
206 #define TYPEIS(x) ((super->u.arch.type == CPIO_UNKNOWN) || (super->u.arch.type == (x)))
207 static int cpio_find_head(struct vfs_class
*me
, struct vfs_s_super
*super
)
214 top
= mc_read(super
->u
.arch
.fd
, buf
, 256);
215 CPIO_POS(super
) += top
;
217 if(ptr
+ MAGIC_LENGTH
>= top
) {
219 memmove(buf
, buf
+ top
- 128, 128);
223 if((tmp
= mc_read(super
->u
.arch
.fd
, buf
, top
)) == 0 || tmp
== -1) {
224 message (1, MSG_ERROR
, _("Premature end of cpio archive\n%s"), super
->name
);
225 cpio_free_archive(me
, super
);
230 if(TYPEIS(CPIO_BIN
) && ((*(unsigned short *)(buf
+ ptr
)) == 070707)) {
231 SEEKBACK
; RETURN(CPIO_BIN
);
232 } else if(TYPEIS(CPIO_BINRE
) && ((*(unsigned short *)(buf
+ ptr
)) == GUINT16_SWAP_LE_BE_CONSTANT(070707))) {
233 SEEKBACK
; RETURN(CPIO_BINRE
);
234 } else if(TYPEIS(CPIO_OLDC
) && (!strncmp(buf
+ ptr
, "070707", 6))) {
235 SEEKBACK
; RETURN(CPIO_OLDC
);
236 } else if(TYPEIS(CPIO_NEWC
) && (!strncmp(buf
+ ptr
, "070701", 6))) {
237 SEEKBACK
; RETURN(CPIO_NEWC
);
238 } else if(TYPEIS(CPIO_CRC
) && (!strncmp(buf
+ ptr
, "070702", 6))) {
239 SEEKBACK
; RETURN(CPIO_CRC
);
247 #define HEAD_LENGTH (26)
248 static int cpio_read_bin_head(struct vfs_class
*me
, struct vfs_s_super
*super
)
250 struct old_cpio_header buf
;
255 if((len
= mc_read(super
->u
.arch
.fd
, (char *)&buf
, HEAD_LENGTH
)) < HEAD_LENGTH
)
257 CPIO_POS(super
) += len
;
258 if(super
->u
.arch
.type
== CPIO_BINRE
) {
260 for(i
= 0; i
< (HEAD_LENGTH
>> 1); i
++)
261 ((short *)&buf
)[i
] = GUINT16_SWAP_LE_BE(((short *)&buf
)[i
]);
263 g_assert(buf
.c_magic
== 070707);
265 name
= g_malloc(buf
.c_namesize
);
266 if((len
= mc_read(super
->u
.arch
.fd
, name
, buf
.c_namesize
)) < buf
.c_namesize
) {
270 CPIO_POS(super
) += len
;
271 cpio_skip_padding(super
);
273 if(!strcmp("TRAILER!!!", name
)) { /* We got to the last record */
278 st
.st_dev
= buf
.c_dev
;
279 st
.st_ino
= buf
.c_ino
;
280 st
.st_mode
= buf
.c_mode
;
281 st
.st_nlink
= buf
.c_nlink
;
282 st
.st_uid
= buf
.c_uid
;
283 st
.st_gid
= buf
.c_gid
;
284 st
.st_rdev
= buf
.c_rdev
;
285 st
.st_size
= (buf
.c_filesizes
[0] << 16) | buf
.c_filesizes
[1];
286 st
.st_atime
= st
.st_mtime
= st
.st_ctime
= (buf
.c_mtimes
[0] << 16) | buf
.c_mtimes
[1];
288 return cpio_create_entry(me
, super
, &st
, name
);
292 #define HEAD_LENGTH (76)
293 static int cpio_read_oldc_head(struct vfs_class
*me
, struct vfs_s_super
*super
)
295 struct new_cpio_header hd
;
297 char buf
[HEAD_LENGTH
+ 1];
301 if((len
= mc_read(super
->u
.arch
.fd
, buf
, HEAD_LENGTH
)) < HEAD_LENGTH
)
303 CPIO_POS(super
) += len
;
304 buf
[HEAD_LENGTH
] = 0;
306 if(sscanf(buf
, "070707%6lo%6lo%6lo%6lo%6lo%6lo%6lo%11lo%6lo%11lo",
307 &hd
.c_dev
, &hd
.c_ino
, &hd
.c_mode
, &hd
.c_uid
, &hd
.c_gid
,
308 &hd
.c_nlink
, &hd
.c_rdev
, &hd
.c_mtime
,
309 &hd
.c_namesize
, &hd
.c_filesize
) < 10) {
310 message (1, MSG_ERROR
, _("Corrupted cpio header encountered in\n%s"), super
->name
);
314 name
= g_malloc(hd
.c_namesize
);
315 if((len
= mc_read(super
->u
.arch
.fd
, name
, hd
.c_namesize
)) == -1 ||
316 (unsigned long) len
< hd
.c_namesize
) {
320 CPIO_POS(super
) += len
;
321 cpio_skip_padding(super
);
323 if(!strcmp("TRAILER!!!", name
)) { /* We got to the last record */
328 st
.st_dev
= hd
.c_dev
;
329 st
.st_ino
= hd
.c_ino
;
330 st
.st_mode
= hd
.c_mode
;
331 st
.st_nlink
= hd
.c_nlink
;
332 st
.st_uid
= hd
.c_uid
;
333 st
.st_gid
= hd
.c_gid
;
334 st
.st_rdev
= hd
.c_rdev
;
335 st
.st_size
= hd
.c_filesize
;
336 st
.st_atime
= st
.st_mtime
= st
.st_ctime
= hd
.c_mtime
;
338 return cpio_create_entry(me
, super
, &st
, name
);
342 #define HEAD_LENGTH (110)
343 static int cpio_read_crc_head(struct vfs_class
*me
, struct vfs_s_super
*super
)
345 struct new_cpio_header hd
;
347 char buf
[HEAD_LENGTH
+ 1];
351 if((len
= mc_read(super
->u
.arch
.fd
, buf
, HEAD_LENGTH
)) < HEAD_LENGTH
)
353 CPIO_POS(super
) += len
;
354 buf
[HEAD_LENGTH
] = 0;
356 if(sscanf(buf
, "%6ho%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx",
357 &hd
.c_magic
, &hd
.c_ino
, &hd
.c_mode
, &hd
.c_uid
, &hd
.c_gid
,
358 &hd
.c_nlink
, &hd
.c_mtime
, &hd
.c_filesize
,
359 &hd
.c_dev
, &hd
.c_devmin
, &hd
.c_rdev
, &hd
.c_rdevmin
,
360 &hd
.c_namesize
, &hd
.c_chksum
) < 14) {
361 message (1, MSG_ERROR
, _("Corrupted cpio header encountered in\n%s"),
366 if((super
->u
.arch
.type
== CPIO_NEWC
&& hd
.c_magic
!= 070701) ||
367 (super
->u
.arch
.type
== CPIO_CRC
&& hd
.c_magic
!= 070702))
370 name
= g_malloc(hd
.c_namesize
);
371 if((len
= mc_read(super
->u
.arch
.fd
, name
, hd
.c_namesize
)) != -1 &&
372 (unsigned long) len
< hd
.c_namesize
) {
376 CPIO_POS(super
) += len
;
377 cpio_skip_padding(super
);
379 if(!strcmp("TRAILER!!!", name
)) { /* We got to the last record */
384 st
.st_dev
= (hd
.c_dev
<< 8) + hd
.c_devmin
;
385 st
.st_ino
= hd
.c_ino
;
386 st
.st_mode
= hd
.c_mode
;
387 st
.st_nlink
= hd
.c_nlink
;
388 st
.st_uid
= hd
.c_uid
;
389 st
.st_gid
= hd
.c_gid
;
390 st
.st_rdev
= (hd
.c_rdev
<< 8) + hd
.c_rdevmin
;
391 st
.st_size
= hd
.c_filesize
;
392 st
.st_atime
= st
.st_mtime
= st
.st_ctime
= hd
.c_mtime
;
394 return cpio_create_entry(me
, super
, &st
, name
);
398 cpio_create_entry (struct vfs_class
*me
, struct vfs_s_super
*super
,
399 struct stat
*st
, char *name
)
401 struct vfs_s_inode
*inode
= NULL
;
402 struct vfs_s_inode
*root
= super
->root
;
403 struct vfs_s_entry
*entry
= NULL
;
406 switch (st
->st_mode
& S_IFMT
) { /* For case of HP/UX archives */
415 if ((st
->st_size
!= 0) && (st
->st_rdev
== 0x0001)) {
416 st
->st_rdev
= (unsigned) st
->st_size
;
424 if ((st
->st_nlink
> 1) && (super
->u
.arch
.type
== CPIO_NEWC
|| super
->u
.arch
.type
== CPIO_CRC
)) { /* For case of hardlinked files */
425 struct defer_inode i
, *l
;
426 i
.inumber
= st
->st_ino
;
427 i
.device
= st
->st_dev
;
429 if ((l
= cpio_defer_find (super
->u
.arch
.deferred
, &i
)) != NULL
) {
431 if (inode
->st
.st_size
&& st
->st_size
432 && (inode
->st
.st_size
!= st
->st_size
)) {
433 message (1, MSG_ERROR
,
435 ("Inconsistent hardlinks of\n%s\nin cpio archive\n%s"),
442 for (tn
= name
+ strlen (name
) - 1; tn
>= name
&& *tn
== PATH_SEP
; tn
--)
444 if ((tn
= strrchr (name
, PATH_SEP
))) {
446 root
= vfs_s_find_inode (me
, super
, name
, LINK_FOLLOW
, FL_MKDIR
);
452 entry
= MEDATA
->find_entry (me
, root
, tn
, LINK_FOLLOW
, FL_NONE
); /* In case entry is already there */
454 if (entry
) { /* This shouldn't happen! (well, it can happen if there is a record for a
455 file and than a record for a directory it is in; cpio would die with
456 'No such file or directory' is such case) */
458 if (!S_ISDIR (entry
->ino
->st
.st_mode
)) { /* This can be considered archive inconsistency */
459 message (1, MSG_ERROR
,
460 _("%s contains duplicate entries! Skipping!"),
463 entry
->ino
->st
.st_mode
= st
->st_mode
;
464 entry
->ino
->st
.st_uid
= st
->st_uid
;
465 entry
->ino
->st
.st_gid
= st
->st_gid
;
466 entry
->ino
->st
.st_atime
= st
->st_atime
;
467 entry
->ino
->st
.st_mtime
= st
->st_mtime
;
468 entry
->ino
->st
.st_ctime
= st
->st_ctime
;
471 } else { /* !entry */
474 inode
= vfs_s_new_inode (me
, super
, st
);
475 if ((st
->st_nlink
> 0) && (super
->u
.arch
.type
== CPIO_NEWC
|| super
->u
.arch
.type
== CPIO_CRC
)) { /* For case of hardlinked files */
476 struct defer_inode
*i
;
477 i
= g_new (struct defer_inode
, 1);
478 i
->inumber
= st
->st_ino
;
479 i
->device
= st
->st_dev
;
481 i
->next
= super
->u
.arch
.deferred
;
482 super
->u
.arch
.deferred
= i
;
487 inode
->data_offset
= CPIO_POS (super
);
489 entry
= vfs_s_new_entry (me
, tn
, inode
);
490 vfs_s_insert_entry (me
, root
, entry
);
492 if (S_ISLNK (st
->st_mode
)) {
493 inode
->linkname
= g_malloc (st
->st_size
+ 1);
494 if (mc_read (super
->u
.arch
.fd
, inode
->linkname
, st
->st_size
)
496 inode
->linkname
[0] = 0;
500 inode
->linkname
[st
->st_size
] = 0; /* Linkname stored without terminating \0 !!! */
501 CPIO_POS (super
) += st
->st_size
;
502 cpio_skip_padding (super
);
504 CPIO_SEEK_CUR (super
, st
->st_size
);
513 /* Need to CPIO_SEEK_CUR to skip the file at the end of add entry!!!! */
516 cpio_open_archive (struct vfs_class
*me
, struct vfs_s_super
*super
,
517 const char *name
, char *op
)
519 int status
= STATUS_START
;
521 if (cpio_open_cpio_file (me
, super
, name
) == -1)
525 status
= cpio_read_head (me
, super
);
529 message (1, MSG_ERROR
, _("Unexpected end of file\n%s"), name
);
542 /* Remaining functions are exactly same as for tarfs (and were in fact just copied) */
544 cpio_super_check (struct vfs_class
*me
, const char *archive_name
, char *op
)
546 static struct stat sb
;
547 if (mc_stat (archive_name
, &sb
))
553 cpio_super_same (struct vfs_class
*me
, struct vfs_s_super
*parc
,
554 const char *archive_name
, char *op
, void *cookie
)
556 struct stat
*archive_stat
= cookie
; /* stat of main archive */
558 if (strcmp (parc
->name
, archive_name
))
561 /* Has the cached archive been changed on the disk? */
562 if (parc
->u
.arch
.st
.st_mtime
< archive_stat
->st_mtime
) {
564 (*vfs_cpiofs_ops
.free
) ((vfsid
) parc
);
565 vfs_rmstamp (&vfs_cpiofs_ops
, (vfsid
) parc
);
568 /* Hasn't been modified, give it a new timeout */
569 vfs_stamp (&vfs_cpiofs_ops
, (vfsid
) parc
);
573 static int cpio_read(void *fh
, char *buffer
, int count
)
575 off_t begin
= FH
->ino
->data_offset
;
576 int fd
= FH_SUPER
->u
.arch
.fd
;
577 struct vfs_class
*me
= FH_SUPER
->me
;
579 if (mc_lseek (fd
, begin
+ FH
->pos
, SEEK_SET
) !=
580 begin
+ FH
->pos
) ERRNOR (EIO
, -1);
582 count
= MIN(count
, FH
->ino
->st
.st_size
- FH
->pos
);
584 if ((count
= mc_read (fd
, buffer
, count
)) == -1) ERRNOR (errno
, -1);
590 static int cpio_fh_open(struct vfs_class
*me
, struct vfs_s_fh
*fh
, int flags
, int mode
)
592 if ((flags
& O_ACCMODE
) != O_RDONLY
) ERRNOR (EROFS
, -1);
599 static struct vfs_s_subclass cpio_subclass
;
601 cpio_subclass
.flags
= VFS_S_READONLY
;
602 cpio_subclass
.archive_check
= cpio_super_check
;
603 cpio_subclass
.archive_same
= cpio_super_same
;
604 cpio_subclass
.open_archive
= cpio_open_archive
;
605 cpio_subclass
.free_archive
= cpio_free_archive
;
606 cpio_subclass
.fh_open
= cpio_fh_open
;
608 vfs_s_init_class (&vfs_cpiofs_ops
, &cpio_subclass
);
609 vfs_cpiofs_ops
.name
= "cpiofs";
610 vfs_cpiofs_ops
.prefix
= "ucpio";
611 vfs_cpiofs_ops
.read
= cpio_read
;
612 vfs_cpiofs_ops
.setctl
= NULL
;
613 vfs_register_class (&vfs_cpiofs_ops
);