* [PATCH] cpio and tar filesystem @ 2007-12-23 19:52 Bean 2007-12-23 20:04 ` Bean 2007-12-23 21:17 ` Robert Millan 0 siblings, 2 replies; 7+ messages in thread From: Bean @ 2007-12-23 19:52 UTC (permalink / raw) To: The development of GRUB 2 I write a filesystem driver for cpio and tar archive file. now you can open the archive with loopback command: loopback aa (hd0,1)/cpio_file loopback bb (hd0,1)/tar_file If you also apply my previous patch on transparent decompression, you can even open a gzip archive, for example: loopback aa (hd0,1)/aa.tar.gz I also fix a serious bug in the loopback device. Note: I only write code for binary mode cpio and new format tar, text mode cpio and old format tar is not supported. 2007-12-24 Bean <bean123ch@gmail.com> * conf/common.rmk (pkgdata_MODULES): Add cpio.mod. (cpio_mod_SOURCES): New variable. (cpio_mod_CFLAGS): Likewise. (cpio_mod_LDFLAGS): Likewise. * fs/cpio.c: New file. * disk/loopback.c (grub_loopback_read): Bug fix. * conf/i386-pc.rmk (grub_emu_SOURCES): Add cpio.c. * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Likewise. * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. diff --git a/conf/common.rmk b/conf/common.rmk index 0e6b81b..f7c8fdb 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -81,7 +81,7 @@ update-grub_DATA += util/grub.d/README # Filing systems. pkgdata_MODULES += fshelp.mod fat.mod ufs.mod ext2.mod ntfs.mod \ ntfscomp.mod minix.mod hfs.mod jfs.mod iso9660.mod xfs.mod \ - affs.mod sfs.mod hfsplus.mod + affs.mod sfs.mod hfsplus.mod cpio.mod # For fshelp.mod. fshelp_mod_SOURCES = fs/fshelp.c @@ -153,6 +153,11 @@ hfsplus_mod_SOURCES = fs/hfsplus.c hfsplus_mod_CFLAGS = $(COMMON_CFLAGS) hfsplus_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For cpio.mod. +cpio_mod_SOURCES = fs/cpio.c +cpio_mod_CFLAGS = $(COMMON_CFLAGS) +cpio_mod_LDFLAGS = $(COMMON_LDFLAGS) + # Partition maps. pkgdata_MODULES += amiga.mod apple.mod pc.mod sun.mod acorn.mod gpt.mod diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk index 305cbe4..397cfbb 100644 --- a/conf/i386-efi.rmk +++ b/conf/i386-efi.rmk @@ -51,7 +51,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \ disk/loopback.c \ fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c \ fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c fs/hfsplus.c \ - fs/ntfs.c fs/ntfscomp.c \ + fs/ntfs.c fs/ntfscomp.c fs/cpio.c \ io/gzio.c \ kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c \ kern/err.c \ diff --git a/conf/i386-linuxbios.rmk b/conf/i386-linuxbios.rmk index 8b98d3b..c33d937 100644 --- a/conf/i386-linuxbios.rmk +++ b/conf/i386-linuxbios.rmk @@ -76,7 +76,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \ disk/host.c disk/loopback.c disk/raid.c disk/lvm.c \ fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c \ fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c fs/hfsplus.c \ - fs/ntfs.c fs/ntfscomp.c \ + fs/ntfs.c fs/ntfscomp.c fs/cpio.c \ io/gzio.c \ kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c \ kern/err.c \ diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index 8c100d7..8e0f31b 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -103,7 +103,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \ disk/host.c disk/loopback.c disk/raid.c disk/lvm.c \ fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c \ fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c fs/hfsplus.c \ - fs/ntfs.c fs/ntfscomp.c \ + fs/ntfs.c fs/ntfscomp.c fs/cpio.c \ io/gzio.c \ kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c \ kern/err.c \ diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index eb440f1..af0773b 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -62,7 +62,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \ disk/loopback.c \ fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c \ fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c fs/hfsplus.c \ - fs/ntfs.c fs/ntfscomp.c \ + fs/ntfs.c fs/ntfscomp.c fs/cpio.c \ io/gzio.c \ kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c \ kern/err.c kern/file.c kern/fs.c kern/loader.c kern/main.c \ diff --git a/disk/loopback.c b/disk/loopback.c index 9d48def..31d8116 100644 --- a/disk/loopback.c +++ b/disk/loopback.c @@ -214,7 +214,7 @@ grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector, if (pos > file->size) { grub_size_t amount = pos - file->size; - grub_memset (buf + size - amount, 0, amount); + grub_memset (buf + (size << GRUB_DISK_SECTOR_BITS) - amount, 0, amount); } return 0; -- Bean ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] cpio and tar filesystem 2007-12-23 19:52 [PATCH] cpio and tar filesystem Bean @ 2007-12-23 20:04 ` Bean 2007-12-23 21:48 ` Robert Millan 2007-12-23 21:17 ` Robert Millan 1 sibling, 1 reply; 7+ messages in thread From: Bean @ 2007-12-23 20:04 UTC (permalink / raw) To: The development of GRUB 2 sorry, forget to add cpio.c, here is the new patch: 2007-12-24 Bean <bean123ch@gmail.com> * conf/common.rmk (pkgdata_MODULES): Add cpio.mod. (cpio_mod_SOURCES): New variable. (cpio_mod_CFLAGS): Likewise. (cpio_mod_LDFLAGS): Likewise. * fs/cpio.c: New file. * disk/loopback.c (grub_loopback_read): Bug fix. * conf/i386-pc.rmk (grub_emu_SOURCES): Add cpio.c. * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Likewise. * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. diff --git a/conf/common.rmk b/conf/common.rmk index 0e6b81b..72edb37 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -81,7 +81,7 @@ update-grub_DATA += util/grub.d/README # Filing systems. pkgdata_MODULES += fshelp.mod fat.mod ufs.mod ext2.mod ntfs.mod \ ntfscomp.mod minix.mod hfs.mod jfs.mod iso9660.mod xfs.mod \ - affs.mod sfs.mod hfsplus.mod + affs.mod sfs.mod hfsplus.mod cpio.mod # For fshelp.mod. fshelp_mod_SOURCES = fs/fshelp.c @@ -153,6 +153,11 @@ hfsplus_mod_SOURCES = fs/hfsplus.c hfsplus_mod_CFLAGS = $(COMMON_CFLAGS) hfsplus_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For cpio.mod. +cpio_mod_SOURCES = fs/cpio.c +cpio_mod_CFLAGS = $(COMMON_CFLAGS) +cpio_mod_LDFLAGS = $(COMMON_LDFLAGS) + # Partition maps. pkgdata_MODULES += amiga.mod apple.mod pc.mod sun.mod acorn.mod gpt.mod diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk index 305cbe4..397cfbb 100644 --- a/conf/i386-efi.rmk +++ b/conf/i386-efi.rmk @@ -51,7 +51,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \ disk/loopback.c \ fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c \ fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c fs/hfsplus.c \ - fs/ntfs.c fs/ntfscomp.c \ + fs/ntfs.c fs/ntfscomp.c fs/cpio.c \ io/gzio.c \ kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c \ kern/err.c \ diff --git a/conf/i386-linuxbios.rmk b/conf/i386-linuxbios.rmk index 8b98d3b..c33d937 100644 --- a/conf/i386-linuxbios.rmk +++ b/conf/i386-linuxbios.rmk @@ -76,7 +76,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \ disk/host.c disk/loopback.c disk/raid.c disk/lvm.c \ fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c \ fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c fs/hfsplus.c \ - fs/ntfs.c fs/ntfscomp.c \ + fs/ntfs.c fs/ntfscomp.c fs/cpio.c \ io/gzio.c \ kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c \ kern/err.c \ diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index 8c100d7..8e0f31b 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -103,7 +103,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \ disk/host.c disk/loopback.c disk/raid.c disk/lvm.c \ fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c \ fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c fs/hfsplus.c \ - fs/ntfs.c fs/ntfscomp.c \ + fs/ntfs.c fs/ntfscomp.c fs/cpio.c \ io/gzio.c \ kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c \ kern/err.c \ diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index eb440f1..af0773b 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -62,7 +62,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \ disk/loopback.c \ fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c \ fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c fs/hfsplus.c \ - fs/ntfs.c fs/ntfscomp.c \ + fs/ntfs.c fs/ntfscomp.c fs/cpio.c \ io/gzio.c \ kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c \ kern/err.c kern/file.c kern/fs.c kern/loader.c kern/main.c \ diff --git a/disk/loopback.c b/disk/loopback.c index 9d48def..31d8116 100644 --- a/disk/loopback.c +++ b/disk/loopback.c @@ -214,7 +214,7 @@ grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector, if (pos > file->size) { grub_size_t amount = pos - file->size; - grub_memset (buf + size - amount, 0, amount); + grub_memset (buf + (size << GRUB_DISK_SECTOR_BITS) - amount, 0, amount); } return 0; diff --git a/fs/cpio.c b/fs/cpio.c new file mode 100755 index 0000000..66959cf --- /dev/null +++ b/fs/cpio.c @@ -0,0 +1,346 @@ +/* cpio.c - cpio and tar filesystem. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/file.h> +#include <grub/mm.h> +#include <grub/misc.h> +#include <grub/disk.h> +#include <grub/dl.h> + +#define MAGIC_BCPIO 070707 + +struct HEAD_BCPIO +{ + grub_uint16_t magic; + grub_uint16_t dev; + grub_uint16_t ino; + grub_uint16_t mode; + grub_uint16_t uid; + grub_uint16_t gid; + grub_uint16_t nlink; + grub_uint16_t rdev; + grub_uint16_t mtime_1; + grub_uint16_t mtime_2; + grub_uint16_t namesize; + grub_uint16_t filesize_1; + grub_uint16_t filesize_2; +} __attribute__ ((packed)); + +#define MAGIC_USTAR "ustar" + +struct HEAD_USTAR +{ + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char chksum[8]; + char typeflag; + char linkname[100]; + char magic[6]; + char version[2]; + char uname[32]; + char gname[32]; + char devmajor[8]; + char devminor[8]; + char prefix[155]; +} __attribute__ ((packed)); + +#define HEAD_LENG sizeof(struct HEAD_USTAR) + +#define MODE_BCPIO 1 +#define MODE_USTAR 2 + +struct grub_cpio_data +{ + grub_disk_t disk; + grub_uint32_t hofs; + grub_uint32_t dofs; + grub_uint32_t size; + int mode; +}; + +#ifndef GRUB_UTIL +static grub_dl_t my_mod; +#endif + +static grub_err_t +grub_cpio_find_file (struct grub_cpio_data *data, char **name, + grub_uint32_t *ofs) +{ + if (data->mode == MODE_BCPIO) + { + struct HEAD_BCPIO hd; + + if (grub_disk_read (data->disk, 0, data->hofs, sizeof(hd), (char*)&hd)) + return grub_errno; + + if (hd.magic != MAGIC_BCPIO) + return grub_error (GRUB_ERR_BAD_FS, "Invalid cpio archive"); + + data->size = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2; + if (data->size == 0) + { + *ofs = 0; + return GRUB_ERR_NONE; + } + + if (hd.namesize & 1) + hd.namesize++; + + if ((*name = grub_malloc (hd.namesize))==NULL) + return grub_errno; + + if (grub_disk_read (data->disk, 0, data->hofs + sizeof(hd), + hd.namesize, *name)) + { + grub_free (*name); + return grub_errno; + } + + data->dofs = data->hofs + sizeof(hd) + hd.namesize; + *ofs = data->dofs + data->size; + if (data->size & 1) + (*ofs)++; + } + else + { + struct HEAD_USTAR hd; + + if (grub_disk_read (data->disk, 0, data->hofs, sizeof(hd), (char*)&hd)) + return grub_errno; + + if (! hd.name[0]) + { + *ofs = 0; + return GRUB_ERR_NONE; + } + + if (grub_memcmp(hd.magic, MAGIC_USTAR, sizeof(MAGIC_USTAR) - 1)) + return grub_error (GRUB_ERR_BAD_FS, "Invalid tar archive"); + + if ((*name = grub_strdup (hd.name))==NULL) + return grub_errno; + + data->size = grub_strtoul(hd.size, NULL, 8); + data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE; + *ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) & + ~(GRUB_DISK_SECTOR_SIZE - 1)); + } + return GRUB_ERR_NONE; +} + +static struct grub_cpio_data * +grub_cpio_mount (grub_disk_t disk) +{ + char hd[HEAD_LENG]; + struct grub_cpio_data *data; + int mode; + + if (grub_disk_read (disk, 0, 0, sizeof (hd), hd)) + goto fail; + + if (((struct HEAD_BCPIO*)hd)->magic == MAGIC_BCPIO) + mode = MODE_BCPIO; + else if (! grub_memcmp(((struct HEAD_USTAR*)hd)->magic, MAGIC_USTAR, + sizeof(MAGIC_USTAR)-1)) + mode = MODE_USTAR; + else + goto fail; + + data = (struct grub_cpio_data *) grub_malloc (sizeof (*data)); + if (! data) + goto fail; + + data->disk = disk; + data->mode = mode; + + return data; + +fail: + grub_error(GRUB_ERR_BAD_FS, "not a cpio filesystem"); + return 0; +} + +static grub_err_t +grub_cpio_dir (grub_device_t device, const char *path, + int (*hook) (const char *filename, int dir)) +{ + struct grub_cpio_data *data; + grub_uint32_t ofs; + char *prev, *name, *np; + int len; + +#ifndef GRUB_UTIL + grub_dl_ref (my_mod); +#endif + + prev = 0; + + data = grub_cpio_mount (device->disk); + if (!data) + goto fail; + + np = path + 1; + len = grub_strlen (path) - 1; + + data->hofs = 0; + while (1) + { + if (grub_cpio_find_file(data, &name, &ofs)) + goto fail; + + if (! ofs) + break; + + if (grub_memcmp (np, name, len) == 0) + { + char *p,*n; + + n = name + len; + if (*n == '/') + n++; + + p = grub_strchr (name + len, '/'); + if (p) + *p = 0; + + if ((! prev) || (grub_strcmp(prev, name) != 0)) + { + hook(name + len, p != NULL); + if (prev) + grub_free(prev); + prev=name; + } + else + grub_free(name); + } + data->hofs = ofs; + } + +fail: + + if (prev) + grub_free(prev); + + if (data) + grub_free(data); + +#ifndef GRUB_UTIL + grub_dl_unref (my_mod); +#endif + + return grub_errno; +} + +static grub_err_t +grub_cpio_open (grub_file_t file, const char *name) +{ + struct grub_cpio_data *data; + grub_uint32_t ofs; + char *fn; + +#ifndef GRUB_UTIL + grub_dl_ref (my_mod); +#endif + + data = grub_cpio_mount (file->device->disk); + if (! data) + goto fail; + + data->hofs = 0; + while (1) + { + if (grub_cpio_find_file (data, &fn, &ofs)) + goto fail; + + if (! ofs) + break; + + if (grub_strcmp(name + 1, fn) == 0) + { + file->data = data; + file->size = data->size; + grub_free (fn); + + return GRUB_ERR_NONE; + } + + grub_free(fn); + data->hofs = ofs; + } + +fail: + + if (data) + grub_free(data); + +#ifndef GRUB_UTIL + grub_dl_unref (my_mod); +#endif + + return grub_errno; +} + +static grub_ssize_t +grub_cpio_read (grub_file_t file, char *buf, grub_size_t len) +{ + struct grub_cpio_data *data; + + data = file->data; + return (grub_disk_read (data->disk, 0, data->dofs + file->offset, + len, buf))?-1:len; +} + +static grub_err_t +grub_cpio_close (grub_file_t file) +{ + grub_free (file->data); + +#ifndef GRUB_UTIL + grub_dl_unref (my_mod); +#endif + + return grub_errno; +} + +static struct grub_fs grub_cpio_fs = { + .name = "cpiofs", + .dir = grub_cpio_dir, + .open = grub_cpio_open, + .read = grub_cpio_read, + .close = grub_cpio_close, + .label = 0, + .next = 0 +}; + +GRUB_MOD_INIT (cpio) +{ + grub_fs_register (&grub_cpio_fs); +#ifndef GRUB_UTIL + my_mod = mod; +#endif +} + +GRUB_MOD_FINI (cpio) +{ + grub_fs_unregister (&grub_cpio_fs); +} -- Bean ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] cpio and tar filesystem 2007-12-23 20:04 ` Bean @ 2007-12-23 21:48 ` Robert Millan 2007-12-24 4:40 ` Bean 0 siblings, 1 reply; 7+ messages in thread From: Robert Millan @ 2007-12-23 21:48 UTC (permalink / raw) To: The development of GRUB 2 On Mon, Dec 24, 2007 at 04:04:31AM +0800, Bean wrote: > > * conf/i386-pc.rmk (grub_emu_SOURCES): Add cpio.c. > > * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. > > * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Likewise. > > * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. Perhaps it'd be a good idea to move the arch-independant part of grub_emu_SOURCES to common.rmk (as grub_emu_SOURCES += foo), to avoid having to update all the files so often ... > diff --git a/disk/loopback.c b/disk/loopback.c > index 9d48def..31d8116 100644 > --- a/disk/loopback.c > +++ b/disk/loopback.c > @@ -214,7 +214,7 @@ grub_loopback_read (grub_disk_t disk, > grub_disk_addr_t sector, > if (pos > file->size) > { > grub_size_t amount = pos - file->size; > - grub_memset (buf + size - amount, 0, amount); > + grub_memset (buf + (size << GRUB_DISK_SECTOR_BITS) - amount, 0, amount); Ugh :-) I check this in right now. > +struct HEAD_USTAR > +{ > + char name[100]; > + char mode[8]; > + char uid[8]; > + char gid[8]; > + char size[12]; > + char mtime[12]; > + char chksum[8]; > + char typeflag; > + char linkname[100]; > + char magic[6]; > + char version[2]; > + char uname[32]; > + char gname[32]; > + char devmajor[8]; > + char devminor[8]; > + char prefix[155]; These tabs should be spaces. > + if (grub_disk_read (data->disk, 0, data->hofs, sizeof(hd), (char*)&hd)) > [...] > + if (grub_disk_read (data->disk, 0, data->hofs, sizeof(hd), (char*)&hd)) `(char *) &hd' here (same for all other casts). Btw, this line seems to be the same on both cases. It can be moved out of `if (data->mode == MODE_BCPIO)' to save some space? > + if (hd.namesize & 1) > + hd.namesize++; > [...] > + if (data->size & 1) > + (*ofs)++; I find this confusing. AFAICT `hd.namesize == 1' would archieve the same and seems to be more consistent with your use of this variable as a counter. > + if ((*name = grub_malloc (hd.namesize))==NULL) > [...] > + if ((*name = grub_strdup (hd.name))==NULL) Please add some spaces: ` == NULL' > + if (grub_memcmp(hd.magic, MAGIC_USTAR, sizeof(MAGIC_USTAR) - 1)) > [...] > + data->size = grub_strtoul(hd.size, NULL, 8); `grub_memcmp (', `grub_strtoul (', etc. Same for other function calls. > + return (grub_disk_read (data->disk, 0, data->dofs + file->offset, > + len, buf))?-1:len; ` ? -1 : len' > +#ifndef GRUB_UTIL > + grub_dl_unref (my_mod); > +#endif > [...] > +#ifndef GRUB_UTIL > + my_mod = mod; > +#endif Are you sure these are still needed? We have a few modules that use them but AFAIK are not necessary at this time. -- Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What use is a phone call, if you are unable to speak? (as seen on /.) ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] cpio and tar filesystem 2007-12-23 21:48 ` Robert Millan @ 2007-12-24 4:40 ` Bean 2007-12-24 12:59 ` Robert Millan 0 siblings, 1 reply; 7+ messages in thread From: Bean @ 2007-12-24 4:40 UTC (permalink / raw) To: The development of GRUB 2 On Dec 24, 2007 5:48 AM, Robert Millan <rmh@aybabtu.com> wrote: >Perhaps it'd be a good idea to move the arch-independant part of >grub_emu_SOURCES to common.rmk (as grub_emu_SOURCES += foo), to avoid >having to update all the files so often ... yes, but i think it should be in a separate patch. > > +struct HEAD_USTAR > > +{ > > + char name[100]; > > + char mode[8]; > > + char uid[8]; > > + char gid[8]; > > + char size[12]; > > + char mtime[12]; > > + char chksum[8]; > > + char typeflag; > > + char linkname[100]; > > + char magic[6]; > > + char version[2]; > > + char uname[32]; > > + char gname[32]; > > + char devmajor[8]; > > + char devminor[8]; > > + char prefix[155]; > > These tabs should be spaces. done. > > > + if (grub_disk_read (data->disk, 0, data->hofs, sizeof(hd), (char*)&hd)) > > [...] > > + if (grub_disk_read (data->disk, 0, data->hofs, sizeof(hd), (char*)&hd)) > > `(char *) &hd' here (same for all other casts). > > Btw, this line seems to be the same on both cases. It can be moved out of > `if (data->mode == MODE_BCPIO)' to save some space? > In fact, it's not the same, in the first case, hd is of type HEAD_BCPIO, while in the second case, hd is of type HEAD_USTAR.The two structure has different size. > > + if (hd.namesize & 1) > > + hd.namesize++; > > [...] > > + if (data->size & 1) > > + (*ofs)++; > > I find this confusing. AFAICT `hd.namesize == 1' would archieve the same and > seems to be more consistent with your use of this variable as a counter. > When the name size is odd number, cpio pad another byte to make it word align, and the same apply to file size. However, I want to keep the original file size, so it use (*ofs)++ instead of data->size++. > > + if ((*name = grub_malloc (hd.namesize))==NULL) > > [...] > > + if ((*name = grub_strdup (hd.name))==NULL) > > Please add some spaces: ` == NULL' > > > + if (grub_memcmp(hd.magic, MAGIC_USTAR, sizeof(MAGIC_USTAR) - 1)) > > [...] > > + data->size = grub_strtoul(hd.size, NULL, 8); > > `grub_memcmp (', `grub_strtoul (', etc. Same for other function calls. > > > + return (grub_disk_read (data->disk, 0, data->dofs + file->offset, > > + len, buf))?-1:len; > > ` ? -1 : len' > done. > > +#ifndef GRUB_UTIL > > + grub_dl_unref (my_mod); > > +#endif > > [...] > > +#ifndef GRUB_UTIL > > + my_mod = mod; > > +#endif > > Are you sure these are still needed? We have a few modules that use them but > AFAIK are not necessary at this time. This is needed, the my_mod variable is used to stored the module pointer, and we need it to increase the module reference when a file is opened, so that the modules can't be unloaded. Here is the new patch. 2007-12-24 Bean <bean123ch@gmail.com> * conf/common.rmk (pkgdata_MODULES): Add cpio.mod. (cpio_mod_SOURCES): New variable. (cpio_mod_CFLAGS): Likewise. (cpio_mod_LDFLAGS): Likewise. * fs/cpio.c: New file. * conf/i386-pc.rmk (grub_emu_SOURCES): Add cpio.c. * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Likewise. * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. diff --git a/conf/common.rmk b/conf/common.rmk index 0e6b81b..72edb37 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -81,7 +81,7 @@ update-grub_DATA += util/grub.d/README # Filing systems. pkgdata_MODULES += fshelp.mod fat.mod ufs.mod ext2.mod ntfs.mod \ ntfscomp.mod minix.mod hfs.mod jfs.mod iso9660.mod xfs.mod \ - affs.mod sfs.mod hfsplus.mod + affs.mod sfs.mod hfsplus.mod cpio.mod # For fshelp.mod. fshelp_mod_SOURCES = fs/fshelp.c @@ -153,6 +153,11 @@ hfsplus_mod_SOURCES = fs/hfsplus.c hfsplus_mod_CFLAGS = $(COMMON_CFLAGS) hfsplus_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For cpio.mod. +cpio_mod_SOURCES = fs/cpio.c +cpio_mod_CFLAGS = $(COMMON_CFLAGS) +cpio_mod_LDFLAGS = $(COMMON_LDFLAGS) + # Partition maps. pkgdata_MODULES += amiga.mod apple.mod pc.mod sun.mod acorn.mod gpt.mod diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk index 305cbe4..397cfbb 100644 --- a/conf/i386-efi.rmk +++ b/conf/i386-efi.rmk @@ -51,7 +51,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \ disk/loopback.c \ fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c \ fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c fs/hfsplus.c \ - fs/ntfs.c fs/ntfscomp.c \ + fs/ntfs.c fs/ntfscomp.c fs/cpio.c \ io/gzio.c \ kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c \ kern/err.c \ diff --git a/conf/i386-linuxbios.rmk b/conf/i386-linuxbios.rmk index 8b98d3b..c33d937 100644 --- a/conf/i386-linuxbios.rmk +++ b/conf/i386-linuxbios.rmk @@ -76,7 +76,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \ disk/host.c disk/loopback.c disk/raid.c disk/lvm.c \ fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c \ fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c fs/hfsplus.c \ - fs/ntfs.c fs/ntfscomp.c \ + fs/ntfs.c fs/ntfscomp.c fs/cpio.c \ io/gzio.c \ kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c \ kern/err.c \ diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index 8c100d7..8e0f31b 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -103,7 +103,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \ disk/host.c disk/loopback.c disk/raid.c disk/lvm.c \ fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c \ fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c fs/hfsplus.c \ - fs/ntfs.c fs/ntfscomp.c \ + fs/ntfs.c fs/ntfscomp.c fs/cpio.c \ io/gzio.c \ kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c \ kern/err.c \ diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index eb440f1..af0773b 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -62,7 +62,7 @@ grub_emu_SOURCES = commands/boot.c commands/cat.c commands/cmp.c \ disk/loopback.c \ fs/affs.c fs/ext2.c fs/fat.c fs/fshelp.c fs/hfs.c fs/iso9660.c \ fs/jfs.c fs/minix.c fs/sfs.c fs/ufs.c fs/xfs.c fs/hfsplus.c \ - fs/ntfs.c fs/ntfscomp.c \ + fs/ntfs.c fs/ntfscomp.c fs/cpio.c \ io/gzio.c \ kern/device.c kern/disk.c kern/dl.c kern/elf.c kern/env.c \ kern/err.c kern/file.c kern/fs.c kern/loader.c kern/main.c \ diff --git a/fs/cpio.c b/fs/cpio.c new file mode 100755 index 0000000..48e0514 --- /dev/null +++ b/fs/cpio.c @@ -0,0 +1,348 @@ +/* cpio.c - cpio and tar filesystem. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007 Free Software Foundation, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <grub/file.h> +#include <grub/mm.h> +#include <grub/misc.h> +#include <grub/disk.h> +#include <grub/dl.h> + +#define MAGIC_BCPIO 070707 + +struct HEAD_BCPIO +{ + grub_uint16_t magic; + grub_uint16_t dev; + grub_uint16_t ino; + grub_uint16_t mode; + grub_uint16_t uid; + grub_uint16_t gid; + grub_uint16_t nlink; + grub_uint16_t rdev; + grub_uint16_t mtime_1; + grub_uint16_t mtime_2; + grub_uint16_t namesize; + grub_uint16_t filesize_1; + grub_uint16_t filesize_2; +} __attribute__ ((packed)); + +#define MAGIC_USTAR "ustar" + +struct HEAD_USTAR +{ + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char chksum[8]; + char typeflag; + char linkname[100]; + char magic[6]; + char version[2]; + char uname[32]; + char gname[32]; + char devmajor[8]; + char devminor[8]; + char prefix[155]; +} __attribute__ ((packed)); + +#define HEAD_LENG sizeof(struct HEAD_USTAR) + +#define MODE_BCPIO 1 +#define MODE_USTAR 2 + +struct grub_cpio_data +{ + grub_disk_t disk; + grub_uint32_t hofs; + grub_uint32_t dofs; + grub_uint32_t size; + int mode; +}; + +#ifndef GRUB_UTIL +static grub_dl_t my_mod; +#endif + +static grub_err_t +grub_cpio_find_file (struct grub_cpio_data *data, char **name, + grub_uint32_t * ofs) +{ + if (data->mode == MODE_BCPIO) + { + struct HEAD_BCPIO hd; + + if (grub_disk_read + (data->disk, 0, data->hofs, sizeof (hd), (char *) &hd)) + return grub_errno; + + if (hd.magic != MAGIC_BCPIO) + return grub_error (GRUB_ERR_BAD_FS, "Invalid cpio archive"); + + data->size = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2; + if (data->size == 0) + { + *ofs = 0; + return GRUB_ERR_NONE; + } + + if (hd.namesize & 1) + hd.namesize++; + + if ((*name = grub_malloc (hd.namesize)) == NULL) + return grub_errno; + + if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd), + hd.namesize, *name)) + { + grub_free (*name); + return grub_errno; + } + + data->dofs = data->hofs + sizeof (hd) + hd.namesize; + *ofs = data->dofs + data->size; + if (data->size & 1) + (*ofs)++; + } + else + { + struct HEAD_USTAR hd; + + if (grub_disk_read + (data->disk, 0, data->hofs, sizeof (hd), (char *) &hd)) + return grub_errno; + + if (!hd.name[0]) + { + *ofs = 0; + return GRUB_ERR_NONE; + } + + if (grub_memcmp (hd.magic, MAGIC_USTAR, sizeof (MAGIC_USTAR) - 1)) + return grub_error (GRUB_ERR_BAD_FS, "Invalid tar archive"); + + if ((*name = grub_strdup (hd.name)) == NULL) + return grub_errno; + + data->size = grub_strtoul (hd.size, NULL, 8); + data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE; + *ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) & + ~(GRUB_DISK_SECTOR_SIZE - 1)); + } + return GRUB_ERR_NONE; +} + +static struct grub_cpio_data * +grub_cpio_mount (grub_disk_t disk) +{ + char hd[HEAD_LENG]; + struct grub_cpio_data *data; + int mode; + + if (grub_disk_read (disk, 0, 0, sizeof (hd), hd)) + goto fail; + + if (((struct HEAD_BCPIO *) hd)->magic == MAGIC_BCPIO) + mode = MODE_BCPIO; + else if (!grub_memcmp (((struct HEAD_USTAR *) hd)->magic, MAGIC_USTAR, + sizeof (MAGIC_USTAR) - 1)) + mode = MODE_USTAR; + else + goto fail; + + data = (struct grub_cpio_data *) grub_malloc (sizeof (*data)); + if (!data) + goto fail; + + data->disk = disk; + data->mode = mode; + + return data; + +fail: + grub_error (GRUB_ERR_BAD_FS, "not a cpio filesystem"); + return 0; +} + +static grub_err_t +grub_cpio_dir (grub_device_t device, const char *path, + int (*hook) (const char *filename, int dir)) +{ + struct grub_cpio_data *data; + grub_uint32_t ofs; + char *prev, *name, *np; + int len; + +#ifndef GRUB_UTIL + grub_dl_ref (my_mod); +#endif + + prev = 0; + + data = grub_cpio_mount (device->disk); + if (!data) + goto fail; + + np = path + 1; + len = grub_strlen (path) - 1; + + data->hofs = 0; + while (1) + { + if (grub_cpio_find_file (data, &name, &ofs)) + goto fail; + + if (!ofs) + break; + + if (grub_memcmp (np, name, len) == 0) + { + char *p, *n; + + n = name + len; + if (*n == '/') + n++; + + p = grub_strchr (name + len, '/'); + if (p) + *p = 0; + + if ((!prev) || (grub_strcmp (prev, name) != 0)) + { + hook (name + len, p != NULL); + if (prev) + grub_free (prev); + prev = name; + } + else + grub_free (name); + } + data->hofs = ofs; + } + +fail: + + if (prev) + grub_free (prev); + + if (data) + grub_free (data); + +#ifndef GRUB_UTIL + grub_dl_unref (my_mod); +#endif + + return grub_errno; +} + +static grub_err_t +grub_cpio_open (grub_file_t file, const char *name) +{ + struct grub_cpio_data *data; + grub_uint32_t ofs; + char *fn; + +#ifndef GRUB_UTIL + grub_dl_ref (my_mod); +#endif + + data = grub_cpio_mount (file->device->disk); + if (!data) + goto fail; + + data->hofs = 0; + while (1) + { + if (grub_cpio_find_file (data, &fn, &ofs)) + goto fail; + + if (!ofs) + break; + + if (grub_strcmp (name + 1, fn) == 0) + { + file->data = data; + file->size = data->size; + grub_free (fn); + + return GRUB_ERR_NONE; + } + + grub_free (fn); + data->hofs = ofs; + } + +fail: + + if (data) + grub_free (data); + +#ifndef GRUB_UTIL + grub_dl_unref (my_mod); +#endif + + return grub_errno; +} + +static grub_ssize_t +grub_cpio_read (grub_file_t file, char *buf, grub_size_t len) +{ + struct grub_cpio_data *data; + + data = file->data; + return (grub_disk_read (data->disk, 0, data->dofs + file->offset, + len, buf)) ? -1 : len; +} + +static grub_err_t +grub_cpio_close (grub_file_t file) +{ + grub_free (file->data); + +#ifndef GRUB_UTIL + grub_dl_unref (my_mod); +#endif + + return grub_errno; +} + +static struct grub_fs grub_cpio_fs = { + .name = "cpiofs", + .dir = grub_cpio_dir, + .open = grub_cpio_open, + .read = grub_cpio_read, + .close = grub_cpio_close, + .label = 0, + .next = 0 +}; + +GRUB_MOD_INIT (cpio) +{ + grub_fs_register (&grub_cpio_fs); +#ifndef GRUB_UTIL + my_mod = mod; +#endif +} + +GRUB_MOD_FINI (cpio) +{ + grub_fs_unregister (&grub_cpio_fs); +} -- Bean ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] cpio and tar filesystem 2007-12-24 4:40 ` Bean @ 2007-12-24 12:59 ` Robert Millan 2007-12-26 7:51 ` Robert Millan 0 siblings, 1 reply; 7+ messages in thread From: Robert Millan @ 2007-12-24 12:59 UTC (permalink / raw) To: The development of GRUB 2 On Mon, Dec 24, 2007 at 12:40:06PM +0800, Bean wrote: > On Dec 24, 2007 5:48 AM, Robert Millan <rmh@aybabtu.com> wrote: > >Perhaps it'd be a good idea to move the arch-independant part of > >grub_emu_SOURCES to common.rmk (as grub_emu_SOURCES += foo), to avoid > >having to update all the files so often ... > > yes, but i think it should be in a separate patch. Agreed. > > Btw, this line seems to be the same on both cases. It can be moved out of > > `if (data->mode == MODE_BCPIO)' to save some space? > > > > In fact, it's not the same, in the first case, hd is of type > HEAD_BCPIO, while in the second case, hd is of type HEAD_USTAR.The two > structure has different size. Ah, right. > > > + if (hd.namesize & 1) > > > + hd.namesize++; > > > [...] > > > + if (data->size & 1) > > > + (*ofs)++; > > > > I find this confusing. AFAICT `hd.namesize == 1' would archieve the same and > > seems to be more consistent with your use of this variable as a counter. > > > When the name size is odd number, cpio pad another byte to make it > word align, and the same apply to file size. However, I want to keep > the original file size, so it use (*ofs)++ instead of data->size++. Ok. > > Are you sure these are still needed? We have a few modules that use them but > > AFAIK are not necessary at this time. > > This is needed, the my_mod variable is used to stored the module > pointer, and we need it to increase the module reference when a file > is opened, so that the modules can't be unloaded. > > Here is the new patch. > > 2007-12-24 Bean <bean123ch@gmail.com> > > * conf/common.rmk (pkgdata_MODULES): Add cpio.mod. > (cpio_mod_SOURCES): New variable. > (cpio_mod_CFLAGS): Likewise. > (cpio_mod_LDFLAGS): Likewise. > > * fs/cpio.c: New file. > > * conf/i386-pc.rmk (grub_emu_SOURCES): Add cpio.c. > > * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. > > * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Likewise. > > * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. Looks good to me. If nobody has any objection, I'll check this in. -- Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What use is a phone call, if you are unable to speak? (as seen on /.) ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] cpio and tar filesystem 2007-12-24 12:59 ` Robert Millan @ 2007-12-26 7:51 ` Robert Millan 0 siblings, 0 replies; 7+ messages in thread From: Robert Millan @ 2007-12-26 7:51 UTC (permalink / raw) To: The development of GRUB 2 On Mon, Dec 24, 2007 at 01:59:53PM +0100, Robert Millan wrote: > > > > 2007-12-24 Bean <bean123ch@gmail.com> > > > > * conf/common.rmk (pkgdata_MODULES): Add cpio.mod. > > (cpio_mod_SOURCES): New variable. > > (cpio_mod_CFLAGS): Likewise. > > (cpio_mod_LDFLAGS): Likewise. > > > > * fs/cpio.c: New file. > > > > * conf/i386-pc.rmk (grub_emu_SOURCES): Add cpio.c. > > > > * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. > > > > * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Likewise. > > > > * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. > > Looks good to me. If nobody has any objection, I'll check this in. Done. -- Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What use is a phone call, if you are unable to speak? (as seen on /.) ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] cpio and tar filesystem 2007-12-23 19:52 [PATCH] cpio and tar filesystem Bean 2007-12-23 20:04 ` Bean @ 2007-12-23 21:17 ` Robert Millan 1 sibling, 0 replies; 7+ messages in thread From: Robert Millan @ 2007-12-23 21:17 UTC (permalink / raw) To: The development of GRUB 2 On Mon, Dec 24, 2007 at 03:52:37AM +0800, Bean wrote: > I write a filesystem driver for cpio and tar archive file. now you can > open the archive with loopback command: Wow, you're fast! :-) I don't know about tar/cpio file format, but I'm impressed about the small size of your code. How is it that the same code is used for both formats? Are they different enough that it'd be an advantage to make them separate modules? -- Robert Millan <GPLv2> I know my rights; I want my phone call! <DRM> What use is a phone call, if you are unable to speak? (as seen on /.) ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2007-12-26 7:51 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-12-23 19:52 [PATCH] cpio and tar filesystem Bean 2007-12-23 20:04 ` Bean 2007-12-23 21:48 ` Robert Millan 2007-12-24 4:40 ` Bean 2007-12-24 12:59 ` Robert Millan 2007-12-26 7:51 ` Robert Millan 2007-12-23 21:17 ` Robert Millan
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.