diff options
author | bencollins <tailor@grayson> | 2001-06-06 08:36:13 -0400 |
---|---|---|
committer | Ben Collins <bcollins@ubuntu.com> | 2006-06-01 13:17:52 -0400 |
commit | 1420e495cd615724bc281bab41d0cd8721da1f58 (patch) | |
tree | b7d34872038ea251d2be5aa5ba73edfa4c5beec5 | |
parent | d1e4a5a4f843c0095ba243daee3f0b63bb26f35e (diff) | |
download | silo-1420e495cd615724bc281bab41d0cd8721da1f58.tar.gz |
[silo @ 27]
* docs/README: Updated.
* second/9660.c: Removed.
* second/9660.h: Likewise.
* second/romfs.c: Likewise.
* second/romfs.h: Likewise.
* second/ufs.c: Likewise.
* second/ufs.h: Likewise.
* second/file.c: Stripped down, and rewrote to be more abstract. Now
supports easy addition of new filesystems.
* second/file.h: New file, describe interfaces for filesystem modules
with file.c.
* second/fs/iom.c: I/O Manager for file.c.
* second/fs/ext2.c: EXT2 Filesystem support rewritten for new
interface.
* second/fs/isofs.c: ISO-9660 Filesystem support rewritten for new
interface. This was almost a complete rewrite. It now supports
extended Rock Ridge information, but also supports ls and tab
completion.
* second/fs/rock.h: Rock Ridge definitions for isofs.c.
* second/Makefile: Build new fs/ subdir as libfs.a and tack it into
the second stage boot loader.
* Still need to update the romfs and ufs filesystems to the new
layout.#
-rw-r--r-- | ChangeLog | 31 | ||||
-rw-r--r-- | Rules.make | 2 | ||||
-rw-r--r-- | docs/README | 6 | ||||
-rw-r--r-- | second/9660.c | 274 | ||||
-rw-r--r-- | second/9660.h | 13 | ||||
-rw-r--r-- | second/Makefile | 20 | ||||
-rw-r--r-- | second/file.c | 748 | ||||
-rw-r--r-- | second/file.h | 49 | ||||
-rw-r--r-- | second/fs/ext2.c | 165 | ||||
-rw-r--r-- | second/fs/iom.c | 124 | ||||
-rw-r--r-- | second/fs/isofs.c | 466 | ||||
-rw-r--r-- | second/fs/rock.h | 111 | ||||
-rw-r--r-- | second/romfs.c | 292 | ||||
-rw-r--r-- | second/romfs.h | 32 | ||||
-rw-r--r-- | second/ufs.c | 331 | ||||
-rw-r--r-- | second/ufs.h | 39 |
16 files changed, 1166 insertions, 1537 deletions
@@ -1,3 +1,34 @@ +Wed Jun 6 04:30:21 EDT 2001 Ben Collins <bcollins@debian.org> + + * docs/README: Updated. + + * second/9660.c: Removed. + * second/9660.h: Likewise. + * second/romfs.c: Likewise. + * second/romfs.h: Likewise. + * second/ufs.c: Likewise. + * second/ufs.h: Likewise. + + * second/file.c: Stripped down, and rewrote to be more abstract. Now + supports easy addition of new filesystems. + * second/file.h: New file, describe interfaces for filesystem modules + with file.c. + + * second/fs/iom.c: I/O Manager for file.c. + * second/fs/ext2.c: EXT2 Filesystem support rewritten for new + interface. + * second/fs/isofs.c: ISO-9660 Filesystem support rewritten for new + interface. This was almost a complete rewrite. It now supports + extended Rock Ridge information, but also supports ls and tab + completion. + * second/fs/rock.h: Rock Ridge definitions for isofs.c. + + * second/Makefile: Build new fs/ subdir as libfs.a and tack it into + the second stage boot loader. + + * Still need to update the romfs and ufs filesystems to the new + layout. + Mon Jun 4 22:42:03 EDT 2001 Ben Collins <bcollins@debian.org> * Rules.make: Update for 1.1.0 release. @@ -5,7 +5,7 @@ CC=gcc LD=ld ELFTOAOUT=elftoaout BIN2H=../common/bin2h -CFLAGS=-O2 -Wall -I../include -fomit-frame-pointer +CFLAGS=-O2 -Wall -I. -I../include -fomit-frame-pointer ../common/%: $(MAKE) -C ../common $* diff --git a/docs/README b/docs/README index a61b775..2a3a135 100644 --- a/docs/README +++ b/docs/README @@ -214,7 +214,11 @@ jsflash flash.img All the code is under GPL. 3. TODO - + + * Redo filesystem support so it is easier to plug in more + * Add ls and cat support for more filesystems + * Someway to cache the filesystems, so we don't have to + open/read/close on every access to them. * NetBoot * More silo.conf keywords/commands * Sun4 support diff --git a/second/9660.c b/second/9660.c deleted file mode 100644 index e7744af..0000000 --- a/second/9660.c +++ /dev/null @@ -1,274 +0,0 @@ -/* iso9660 filesystem handling - - Copyright (C) 1999 Jakub Jelinek - Copyright (C) 1993 Eric Youngdale - - 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#ifdef __linux__ - -# include <ctype.h> -# include <sys/types.h> -# include <errno.h> -# include <silo.h> -typedef int FILE; -# include <linux/ext2_fs.h> -# include <linux/iso_fs.h> - -#else - -# include <stdio.h> -# include <sys/types.h> -# include <sys/stat.h> -# include <errno.h> -# include <non-linux/ext2_fs.h> -# include <non-linux/iso_fs.h> - -#endif - -#include <stringops.h> -#include "ext2fs/ext2fs.h" -#include "9660.h" - -void *alloca(size_t size); - -#define SUPISO ((struct iso_primary_descriptor *)fs->io->private_data) -#define ROOTDIR ((struct iso9660_inode *)SUPISO->unused2) - -static int isonum_731 (char * p) -{ - return ((p[0] & 0xff) - | ((p[1] & 0xff) << 8) - | ((p[2] & 0xff) << 16) - | ((p[3] & 0xff) << 24)); -} - -#define isonum_733(p) isonum_731(p) - -static struct iso_primary_descriptor *iso9660_read_super(iso9660_filsys fs) -{ - int i; - struct iso_primary_descriptor *iso = (struct iso_primary_descriptor *) malloc (2048); - struct iso9660_inode *root; - - for (i = 16; i < 100; i++) { - if (io_channel_read_blk (fs->io, i, -2048, (char *)iso)) - return 0; - if (!strncmp (iso->id, ISO_STANDARD_ID, sizeof (iso->id))) - break; - } - - if (i == 100) return 0; - - root = (struct iso9660_inode *)iso->unused2; - root->extent = isonum_733 (((struct iso_directory_record *)(iso->root_directory_record))->extent); - root->size = isonum_733 (((struct iso_directory_record *)(iso->root_directory_record))->size); - - return iso; -} - -int iso9660_open (char *device, io_manager iom, iso9660_filsys *pfs) -{ - iso9660_filsys fs; - fs = (iso9660_filsys) malloc (sizeof (struct struct_ext2_filsys)); - if (!fs) return -1; - if (iom->open (device, 0, &fs->io)) return -1; - io_channel_set_blksize (fs->io, 2048); - fs->io->private_data = iso9660_read_super(fs); - if (!fs->io->private_data) return -1; - *pfs = fs; - return 0; -} - -static void parse_rr (iso9660_filsys fs, unsigned char *rr, unsigned char *end, char *name, char *symlink) -{ - int cont_extent = 0, cont_offset = 0, cont_size = 0; - while (rr < end) { - if (rr[3] != 1) { - printf ("Bad RR version\n"); - break; - } - if (!strncmp (rr, "NM", 2)) { - strncpy (name, rr + 5, rr[2] - 5); - name[rr[2] - 5] = 0; - } else if (!strncmp (rr, "SL", 2)) { - int len = rr[2] - 5; - unsigned char *p = rr + 5; - while (len > 1) { - switch (p[0] & ~1) { - case 0: strncat (symlink, p+2, p[1]); break; - case 2: strcat (symlink, "."); break; - case 4: strcat (symlink, ".."); break; - case 8: strcat (symlink, "/"); break; - default: printf ("Unhandled bit in SL\n"); break; - } - len -= p[1] + 2; - if ((p[0] & 1) == 0 && p[0] != 8 && len > 1) - strcat (symlink, "/"); - p += p[1] + 2; - } - } else if (!strncmp (rr, "CE", 2)) { - cont_extent = isonum_733 (rr + 4); - cont_offset = isonum_733 (rr + 12); - cont_size = isonum_733 (rr + 20); - } - rr += rr[2]; - if (rr >= end && cont_extent) { - char *sect = alloca (2048); - if (io_channel_read_blk (fs->io, cont_extent, 1, sect)) - return; - parse_rr (fs, § [cont_offset], § [cont_offset + cont_size - 3], - name, symlink); - } - } -} - -static int link_count = 0; - -static int open_namei(iso9660_filsys, const char *, struct iso9660_inode *, struct iso9660_inode *); - -static int iso9660_lookup (iso9660_filsys fs, struct iso9660_inode *dir, - const char *name, int len, struct iso9660_inode *result) -{ - char buffer [2048]; - char namebuf [512]; - char symlink [512]; - int block, size, i; - struct iso_directory_record *idr; - unsigned char *rr; - - size = dir->size; - block = dir->extent; - while (size > 0) { - if (io_channel_read_blk (fs->io, block, 1, buffer)) { - printf ("Could not read directory\n"); - return -1; - } - size -= 2048; - block++; - for (i = 0;;) { - idr = (struct iso_directory_record *) (buffer + i); - if (!idr->length[0]) break; - i += (unsigned char)idr->length[0]; - strncpy(namebuf, idr->name, (unsigned char)idr->name_len[0]); - namebuf[(unsigned char)idr->name_len[0]] = 0; - rr = (unsigned char *)(idr + 1); - rr += ((unsigned char)idr->name_len[0]) - sizeof(idr->name); - if (!(idr->name_len[0] & 1)) rr++; - *symlink = 0; - parse_rr (fs, rr, &buffer[i-3], namebuf, symlink); - if (idr->name_len[0] == 1 && !idr->name[0]) - strcpy(namebuf, "."); - else if (idr->name_len[0] == 1 && idr->name[0] == 1) - strcpy(namebuf, ".."); - if ((!len && namebuf[0] == '.' && !namebuf[1]) || - (strlen(namebuf) == len && !memcmp(namebuf, name, len))) { - if (*symlink) { - int error; - if (link_count > 5) { - printf ("Symlink loop\n"); - return -1; /* Loop */ - } - link_count++; - error = open_namei (fs, symlink, result, dir); - link_count--; - return error; - } - result->extent = isonum_733 (idr->extent); - result->size = isonum_733 (idr->size); - return 0; - } - if (i >= 2048 - sizeof(struct iso_directory_record) + sizeof(idr->name)) - break; - } - } - return -1; -} - -static int dir_namei(iso9660_filsys fs, const char *pathname, int *namelen, - const char **name, struct iso9660_inode *base, - struct iso9660_inode *res_inode) -{ - char c; - const char *thisname; - int len; - struct iso9660_inode inode; - - if ((c = *pathname) == '/') { - base = ROOTDIR; - pathname++; - } - while (1) { - thisname = pathname; - for(len=0;(c = *(pathname++))&&(c != '/');len++); - if (!c) break; - if (iso9660_lookup (fs, base, thisname, len, &inode)) return -1; - base = &inode; - } - *name = thisname; - *namelen = len; - *res_inode = *base; - return 0; -} - -static int open_namei(iso9660_filsys fs, const char *pathname, - struct iso9660_inode *res_inode, - struct iso9660_inode *base) -{ - const char *basename; - int namelen; - struct iso9660_inode dir, inode; - - if (dir_namei(fs, pathname, &namelen, &basename, base, &dir)) return -1; - if (!namelen) { /* special case: '/usr/' etc */ - *res_inode=dir; - return 0; - } - if (iso9660_lookup (fs, &dir, basename, namelen, &inode)) return -1; - *res_inode = inode; - return 0; -} - -int iso9660_namei (iso9660_filsys fs, char *filename, struct iso9660_inode *inode) -{ - link_count = 0; - return open_namei (fs, filename, inode, ROOTDIR); -} - -void iso9660_close(iso9660_filsys fs) -{ - free (fs->io); - free (fs); -} - -int iso9660_block_iterate(iso9660_filsys fs, struct iso9660_inode *inode, - int (*func)(iso9660_filsys, blk_t *, int, void *), - void *private) -{ - int i; - blk_t nr; - int size; - - nr = inode->extent; - size = (inode->size + 2047) / 2048; - for (i = 0; i < size; i++, nr++) { - switch ((*func) (fs, &nr, i, private)) { - case BLOCK_ABORT: - case BLOCK_ERROR: - return -1; - } - } - return 0; -} diff --git a/second/9660.h b/second/9660.h deleted file mode 100644 index f90df52..0000000 --- a/second/9660.h +++ /dev/null @@ -1,13 +0,0 @@ -typedef ext2_filsys iso9660_filsys; - -struct iso9660_inode { - unsigned int extent; - unsigned int size; -}; - -int iso9660_open(char *device, io_manager io, iso9660_filsys *fs); -int iso9660_namei(iso9660_filsys fs, char *filename, struct iso9660_inode *inode); -void iso9660_close(iso9660_filsys fs); -int iso9660_block_iterate(iso9660_filsys fs, struct iso9660_inode *inode, - int (*func)(iso9660_filsys, blk_t *, int, void *), - void *private); diff --git a/second/Makefile b/second/Makefile index dd18434..e834e61 100644 --- a/second/Makefile +++ b/second/Makefile @@ -4,6 +4,7 @@ ## AS=as +AR=ar NM=nm DD=dd AWK=awk @@ -24,10 +25,10 @@ LDFLAGS_SMALL=-N -Ttext 0x280000 LDFLAGS_LARGE=-N -Ttext 0x380000 .c.o: - $(CC) $(CFLAGS) -c $*.c + $(CC) $(CFLAGS) -c $*.c -o $@ .S.o: - $(CC) $(CFLAGS) -c $*.S + $(CC) $(CFLAGS) -c $*.S -o $@ # The ordering here is very significant. Please add new object files to OBJS5 only. OBJS1 = crt0.o @@ -39,11 +40,13 @@ OBJS3 = ../common/console.o ../common/printf.o malloc.o ../common/jmp.o \ OBJS4 = main.o OBJS4N = mainnet.o OBJS5 = cmdline.o disk.o file.o misc.o cfg.o strtol.o ranges.o timer.o \ - memory.o ufs.o romfs.o 9660.o divdi3.o mul.o rem.o sdiv.o umul.o \ + memory.o fs/libfs.a divdi3.o mul.o rem.o sdiv.o umul.o \ ../common/stringops2.o ls.o muldi3.o OBJS = $(OBJS1) $(OBJS2) $(OBJS3) bmark.o $(OBJS4) $(OBJS5) OBJSNET = $(OBJS1) $(OBJS2N) $(OBJS3) bmark.o $(OBJS4N) $(OBJS5) +FS_OBJS = fs/iom.o fs/ext2.o fs/isofs.o + ifeq (Linux,$(shell uname)) ifeq (sparc,$(subst sparc64,sparc,$(shell uname -m))) # Should really switch to autoconf... @@ -51,13 +54,17 @@ LIBINC=$(shell if [ ! -f /lib/ld-linux.so.2 -o ! -f /usr/lib/libext2fs.so ]; the all: second.b silotftp.b else all: - @$(ECHO) Second stage bootloader should be build under Linux/Sparc only + @$(ECHO) Second stage bootloader should be built under Linux/Sparc only endif else all: @$(ECHO) Second stage bootloader should be build under Linux/Sparc only endif +fs/libfs.a: $(FS_OBJS) + $(RM) $@ + $(AR) rc $@ $(FS_OBJS) + second: $(OBJS) mark.o $(LD) $(LDFLAGS_SMALL) -Bstatic -o second $(OBJS) $(LIBINC) -lext2fs mark.o $(LD) $(LDFLAGS_LARGE) -Bstatic -o second2 $(OBJS) $(LIBINC) -lext2fs mark.o @@ -71,8 +78,7 @@ silotftp: $(OBJSNET) mark.o second.l: second ( $(ECHO) 'disassemble 0x280000 '`$(GREP) '_etext' second.map | $(SED) 's/ .*$$//' | $(SED) 's/^00/0x/'`; $(ECHO) quit ) | $(GDB) second | $(SED) '1,/^(gdb)/d;/^End /,$$d' > second.l -file.o: file.c ufs.h -ufs.o: ufs.c ufs.h +file.o: file.c decompnet.o: decomp.c $(CC) $(CFLAGS) -DTFTP -c -o decompnet.o decomp.c @@ -86,7 +92,7 @@ util: util.c $(CC) -o util util.c clean: - $(RM) *.o second second2 second.b silotftp silotftp2 silotftp.b second.l *.map core *~ util second.b second.image.tmp *.s + $(RM) *.o fs/*.o *.s second* silotftp* *.map util fs/libfs.a crt0.o: crt0.S $(CC) $(CFLAGS) -c -Wa,-Av9 -DIMGVERSION='"SILO$(IMGVERSION)"' crt0.S diff --git a/second/file.c b/second/file.c index 0c20d51..534c14f 100644 --- a/second/file.c +++ b/second/file.c @@ -16,62 +16,25 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ -/* TODO: This file is a good candidate for rewrite from scratch */ - -#include <ctype.h> #include <sys/types.h> -#include <errno.h> #include <silo.h> -typedef int FILE; -#include <linux/ext2_fs.h> -#include <ext2fs/ext2fs.h> -#define ec ,},{ -static struct { - int errnum; - char *desc; -} ext2errors[] = { -{ 0, "OK" -#include <ext2fs/ext2_err.et> -} -}; +#include <file.h> #include <stringops.h> -#include "ufs.h" -#include "romfs.h" -#include "9660.h" #include <setjmp.h> -static errcode_t linux_open (const char *name, int flags, io_channel * channel); -static errcode_t linux_close (io_channel channel); -static errcode_t linux_set_blksize (io_channel channel, int blksize); -static errcode_t linux_read_blk (io_channel channel, unsigned long block, int count, void *data); -static errcode_t linux_write_blk (io_channel channel, unsigned long block, int count, const void *data); -static errcode_t linux_flush (io_channel channel); +ext2_filsys fs = 0; -static struct struct_io_manager struct_linux_manager = -{ - EXT2_ET_MAGIC_IO_MANAGER, - "linux I/O Manager", - linux_open, - linux_close, - linux_set_blksize, - linux_read_blk, - linux_write_blk, - linux_flush -}; +unsigned int bs; +unsigned char *filebuffer; +ino_t root, cwd; -ext2_filsys fs = 0; -static ino_t root, cwd; -static io_manager linux_io_manager = &struct_linux_manager; static int do_gunzip = 0; static unsigned int *gzipped_blocks; static unsigned int *cur_gzipped_block; -static unsigned int bs; /* Block Size */ -static unsigned long long doff; /* Block where partition starts */ - -static unsigned char *filebuffer; static unsigned char *filelimit; static int first_block; static int block_no; @@ -80,219 +43,53 @@ static int last_blockcnt; static char *gunzip_buffer; static char *gunzip_inp; static char *gunzip_endbuf; -static enum { ext2, ufs, romfs, isofs } type; - -extern int solaris; - -static int read_sun_partition (int partno) -{ - int rc; - sun_partition sdl; - unsigned short csum, *ush; - - rc = read ((char *) &sdl, 512, 0); - if (rc != 512) { - fatal ("Cannot read partition"); - return 0; - } - if (sdl.magic != SUN_LABEL_MAGIC) - fatal ("Wrong disklabel magic"); - for (csum = 0, ush = ((unsigned short *) ((&sdl) + 1)) - 1; ush >= (unsigned short *) &sdl;) - csum ^= *ush--; - if (csum) - printf ("\nWarning: Your disklabel has wrong checksum. Use fdisk to correct it."); - doff = (((unsigned long long)sdl.ntrks) * sdl.nsect * sdl.partitions[partno - 1].start_cylinder) << 9; - return 1; -} +static char *match; -void com_err (const char *a, long i, const char *fmt,...) -{ - printf ((char *) fmt); -} - -static errcode_t linux_open (const char *name, int flags, io_channel * channel) -{ - int partno; - io_channel io; - - if (!name) - return EXT2_ET_BAD_DEVICE_NAME; - io = (io_channel) malloc (sizeof (struct struct_io_channel)); - if (!io) - return EXT2_ET_BAD_DEVICE_NAME; - memset (io, 0, sizeof (struct struct_io_channel)); - io->magic = EXT2_ET_MAGIC_IO_CHANNEL; - io->manager = linux_io_manager; - io->name = (char *) malloc (strlen (name) + 1); - strcpy (io->name, name); - io->block_size = bs; - io->read_error = 0; - io->write_error = 0; - - doff = 0LL; - if (strncmp (name, "/dev/fd0", 8) && partitionable()) { - partno = *(name + strlen (name) - 1) - '0'; - if (partno && !read_sun_partition (partno)) - return EXT2_ET_BAD_DEVICE_NAME; - } - *channel = io; - return 0; -} - -static errcode_t linux_close (io_channel channel) -{ - return 0; -} - -static errcode_t linux_set_blksize (io_channel channel, int blksize) -{ - channel->block_size = bs = blksize; - return 0; -} +/* Externally provided filesystem operations */ +extern struct fs_ops ext2_fs_ops; +extern struct fs_ops iso_fs_ops; -static errcode_t linux_read_blk (io_channel channel, unsigned long block, int count, void *data) -{ - int size; +/* Array of our supported ops */ +static struct fs_ops *silo_fs_ops[] = { &ext2_fs_ops, &iso_fs_ops, NULL }; - size = (count < 0) ? -count : count * bs; - if (read (data, size, ((unsigned long long)block) * bs + doff) != size) { - printf ("\nRead error on block %d\n", block); - return EXT2_ET_SHORT_READ; - } - return 0; -} +static struct fs_ops *cur_ops; -static errcode_t linux_write_blk (io_channel channel, unsigned long block, int count, const void *data) -{ - return 0; -} +extern jmp_buf gunzip_env; -static errcode_t linux_flush (io_channel channel) +void register_silo_inode (unsigned int mtime, unsigned int size, + unsigned int mode, unsigned int uid, + unsigned int gid, const char *name, + const char *symlink) { - return 0; -} + struct silo_inode *sino = (struct silo_inode *)filebuffer; + unsigned char *p; + int name_len = strlen(name); -static void ext2fs_error (int errcode) -{ - int i; - - for (i = 0; i < sizeof (ext2errors) / sizeof (ext2errors[0]); i++) - if (ext2errors [i].errnum == errcode) { - printf ("%s", ext2errors [i].desc); - return; - } - printf ("Unknown ext2 error"); -} + if (match != NULL) + if (strlen(match) > name_len || strncmp(match, name, strlen(match))) + return; -static int open_ext2 (char *device) -{ - int retval; + strncpy(sino->name, name, name_len); + sino->name[name_len] = 0; + sino->mtime = mtime; + sino->size = size; + sino->mode = mode; + sino->uid = uid; + sino->gid = gid; - retval = ext2fs_open (device, EXT2_FLAG_RW, 0, 0, linux_io_manager, &fs); - if (retval == EXT2_ET_BAD_MAGIC) - return 0; - if (retval) { - printf ("\n"); - ext2fs_error (retval); - printf ("\n"); - return 0; + p = strchr (sino->name, 0) + 1; + if (symlink) { + strncpy (p, symlink, size); + p[size] = 0; + p += size + 1; } - root = EXT2_ROOT_INO; - return 1; -} - -static int open_ufs (char *device) -{ - if (ufs_open (device, linux_io_manager, &fs)) return 0; - root = UFS_ROOTINO; - return 1; -} - -static int open_romfs (char *device) -{ - if (romfs_open (device, linux_io_manager, &fs)) return 0; - root = ((struct romfs_super_block *)(fs->io->private_data))->checksum; - return 1; -} - -static int open_isofs (char *device) -{ - return !iso9660_open (device, linux_io_manager, &fs); -} - -static int dump_block (ext2_filsys fs, blk_t * blocknr, int blockcnt, - void *private) -{ - if (blockcnt < 0) - return 0; + if ((long)p & 3) p += 4 - ((long)p & 3); + sino->inolen = p - filebuffer; + filebuffer = p; - if (!first_block && do_gunzip) { - if (blockcnt != last_blockcnt + 1) { - int i; - - for (i = blockcnt - last_blockcnt - 1; i > 0; i--) - *cur_gzipped_block++ = 0xffffffff; - } - *cur_gzipped_block++ = *blocknr; - last_blockcnt = blockcnt; - return 0; - } - if (*blocknr || block_no) { - if (first_block || !*blocknr || blockcnt != last_blockcnt + 1 || (block_no && *blocknr != block_no + block_cnt)) { - if (first_block) { - block_no = *blocknr; - block_cnt = 1; - if (blockcnt) { - fatal ("File cannot have a hole at beginning"); - return BLOCK_ABORT; - } - last_blockcnt = -1; - } - if (filebuffer + (block_cnt + ((*blocknr) ? (blockcnt - last_blockcnt - 1) : 0)) * bs > filelimit) { - fatal ("Image too large to fit in destination"); - return BLOCK_ABORT; - } - if (block_cnt > 0 && io_channel_read_blk (fs->io, block_no, block_cnt, filebuffer)) - return BLOCK_ABORT; - if (first_block) { - first_block = 0; - last_blockcnt = 0; - if (*filebuffer == 037 && (filebuffer[1] == 0213 || filebuffer[1] == 0236)) { /* gzip magic */ - unsigned long sa = (unsigned long)&_start; - gunzip_buffer = malloc (16 * bs); - memcpy (gunzip_buffer, filebuffer, bs); - gzipped_blocks = (unsigned int *) malloc ((sa / 512) * sizeof (int)); - cur_gzipped_block = gzipped_blocks; - *cur_gzipped_block++ = *blocknr; - printf ("Uncompressing image...\n"); - return 0; - } - do_gunzip = 0; - filebuffer += bs; - block_no = 0; - block_cnt = 0; - return 0; - } - filebuffer += block_cnt * bs; - if (*blocknr && blockcnt && blockcnt != last_blockcnt + 1) { - memset (filebuffer, 0, (blockcnt - last_blockcnt - 1) * bs); - filebuffer += (blockcnt - last_blockcnt - 1) * bs; - } - block_no = 0; - } - if (*blocknr) { - if (!block_no) { - block_no = *blocknr; - block_cnt = 1; - } else - block_cnt++; - last_blockcnt = blockcnt; - } - } - return 0; + return; } -extern jmp_buf gunzip_env; static unsigned char get_gzip_input (void) { @@ -303,7 +100,7 @@ static unsigned char get_gzip_input (void) unsigned int first = *cur_gzipped_block++; if (!first) { - printf ("\nDecompression error: run out of compressed data\n"); + printf ("\nDecompression error: ran out of compressed data\n"); longjmp (gunzip_env, 1); } if (first == 0xffffffff) { @@ -342,7 +139,79 @@ static void unget_gzip_input (void) static int gunzipped_len = 0; -static int dump_finish (void) +int dump_block (ext2_filsys fs, blk_t * blocknr, int blockcnt, + void *private) +{ + if (blockcnt < 0) + return 0; + + if (!first_block && do_gunzip) { + if (blockcnt != last_blockcnt + 1) { + int i; + + for (i = blockcnt - last_blockcnt - 1; i > 0; i--) + *cur_gzipped_block++ = 0xffffffff; + } + *cur_gzipped_block++ = *blocknr; + last_blockcnt = blockcnt; + return 0; + } + if (*blocknr || block_no) { + if (first_block || !*blocknr || blockcnt != last_blockcnt + 1 || (block_no && *blocknr != block_no + block_cnt)) { + if (first_block) { + block_no = *blocknr; + block_cnt = 1; + if (blockcnt) { + fatal ("File cannot have a hole at beginning"); + return BLOCK_ABORT; + } + last_blockcnt = -1; + } + if (filebuffer + (block_cnt + ((*blocknr) ? (blockcnt - last_blockcnt - 1) : 0)) * bs > filelimit) { + fatal ("Image too large to fit in destination"); + return BLOCK_ABORT; + } + if (block_cnt > 0 && io_channel_read_blk (fs->io, block_no, block_cnt, filebuffer)) + return BLOCK_ABORT; + if (first_block) { + first_block = 0; + last_blockcnt = 0; + if (*filebuffer == 037 && (filebuffer[1] == 0213 || filebuffer[1] == 0236)) { /* gzip magic */ + unsigned long sa = (unsigned long)&_start; + gunzip_buffer = malloc (16 * bs); + memcpy (gunzip_buffer, filebuffer, bs); + gzipped_blocks = (unsigned int *) malloc ((sa / 512) * sizeof (int)); + cur_gzipped_block = gzipped_blocks; + *cur_gzipped_block++ = *blocknr; + printf ("Uncompressing image...\n"); + return 0; + } + do_gunzip = 0; + filebuffer += bs; + block_no = 0; + block_cnt = 0; + return 0; + } + filebuffer += block_cnt * bs; + if (*blocknr && blockcnt && blockcnt != last_blockcnt + 1) { + memset (filebuffer, 0, (blockcnt - last_blockcnt - 1) * bs); + filebuffer += (blockcnt - last_blockcnt - 1) * bs; + } + block_no = 0; + } + if (*blocknr) { + if (!block_no) { + block_no = *blocknr; + block_cnt = 1; + } else + block_cnt++; + last_blockcnt = blockcnt; + } + } + return 0; +} + +int dump_finish (void) { if (block_no) { blk_t tmp = 0; @@ -363,108 +232,8 @@ static int dump_finish (void) return 1; } -static int dump_ext2 (ino_t inode, char *filename) -{ - errcode_t retval; - - retval = ext2fs_block_iterate (fs, inode, 0, 0, - dump_block, 0); - if (retval) { - printf ("\n"); - ext2fs_error (retval); - printf ("\n"); - return 0; - } - return dump_finish (); -} - -static int ls_ext2_proc(struct ext2_dir_entry *dirent, int offset, - int blocksize, char *buf, void *private) -{ - struct silo_inode *sino = (struct silo_inode *)filebuffer; - struct ext2_inode ino; - unsigned char *p; - int name_len = dirent->name_len & 0xFF; - char *match = (char *)private; - - if (match != NULL) - if (strlen(match) > name_len || strncmp(match, dirent->name, strlen(match))) - return 0; - - strncpy(sino->name, dirent->name, name_len); - sino->name[name_len] = 0; - if (ext2fs_read_inode(fs, dirent->inode, &ino)) - strcpy (sino->name, "--- error ---"); - sino->mtime = ino.i_mtime; - sino->size = ino.i_size; - sino->mode = ino.i_mode; - sino->uid = ino.i_uid; - sino->gid = ino.i_gid; - p = strchr (sino->name, 0) + 1; - if (LINUX_S_ISLNK (ino.i_mode)) { - if (ino.i_blocks) { - if (io_channel_read_blk(fs->io, ino.i_block[0], 1, p)) - ino.i_size = 0; - } else { - strncpy (p, (char *)&(ino.i_block[0]),ino.i_size); - } - p[ino.i_size] = 0; - p += ino.i_size + 1; - } - if ((long)p & 3) p += 4 - ((long)p & 3); - sino->inolen = p - filebuffer; - filebuffer = p; - return 0; -} - -static int ls_ext2 (ino_t inode, char *match) -{ - errcode_t retval; - struct silo_inode *sino; - - retval = ext2fs_dir_iterate (fs, inode, DIRENT_FLAG_INCLUDE_EMPTY, - 0, ls_ext2_proc, match); - - /* Only print an error if we aren't matching */ - if (retval && match == NULL) { - printf ("\n"); - ext2fs_error (retval); - printf ("\n"); - return 0; - } - sino = (struct silo_inode *)filebuffer; - sino->inolen = 0; - return 1; -} - -static int dump_ufs (ino_t inode, char *filename) -{ - if (ufs_block_iterate (fs, inode, dump_block, 0)) { - printf ("Error while loading of %s", filename); - return 0; - } - return dump_finish (); -} - -static int dump_romfs (ino_t inode, char *filename) -{ - if (romfs_block_iterate (fs, inode, dump_block, 0)) { - printf ("Error while loading of %s", filename); - return 0; - } - return dump_finish (); -} - -static int dump_isofs (struct iso9660_inode *inode, char *filename) -{ - if (iso9660_block_iterate (fs, inode, dump_block, 0)) { - printf ("Error while loading of %s", filename); - return 0; - } - return dump_finish (); -} - -int dump_device_range (char *filename, char *bogusdev, int *len, void (*lenfunc)(int, char **, char **)) +static int dump_device_range (char *filename, char *bogusdev, int *len, + void (*lenfunc)(int, char **, char **)) { /* Range of blocks on physical block device */ int start = 0, end = -1; @@ -499,7 +268,7 @@ int dump_device_range (char *filename, char *bogusdev, int *len, void (*lenfunc) (*lenfunc)((end - start) << 9, (char **)&filebuffer, (char **)&filelimit); fs = (ext2_filsys) malloc (sizeof (struct struct_ext2_filsys)); if (fs) { - if (!linux_open (bogusdev, 0, &fs->io)) { + if (!((struct struct_io_manager *)(silo_io_manager))->open (bogusdev, 0, &fs->io)) { blk_t tmp; first_block = do_gunzip; @@ -526,79 +295,25 @@ int dump_device_range (char *filename, char *bogusdev, int *len, void (*lenfunc) return 0; } -static int get_len (ino_t inode) -{ - if (type == ext2) { - struct ext2_inode ei; - int retval; - - if ((retval = ext2fs_read_inode (fs, inode, &ei))) { - printf ("\n"); - ext2fs_error (retval); - printf ("\n"); - return 0; - } - return ei.i_size; - } else if (type == ufs) { - struct ufs_inode ui; - - if (ufs_read_inode (fs, inode, &ui)) - return 0; - /* Hope nobody is so stupid to load 4GB+ kernel into core :)))) */ - return ufsi_size(&ui); - } else if (type == romfs) { - struct romfs_inode ri; - - if (romfs_read_inode (fs, inode, &ri)) - return 0; - if ((ri.next & ROMFH_TYPE) != ROMFH_REG) { - printf("romfs: get_len on non-reg file?\n"); - return 0; - } - return ri.size; - } else if (type == isofs) { - /* XXX */ - return 0; - } - return 0; -} - -static char *get_archstr(void) -{ - char *p = "sun4c"; - - switch (get_architecture()) { - case sun4: p = "sun4"; break; - case sun4c: p = "sun4c"; break; - case sun4m: p = "sun4m"; break; - case sun4d: p = "sun4d"; break; - case sun4e: p = "sun4e"; break; - case sun4u: p = "sun4u"; break; - case sun4p: p = "sun4p"; break; - default: break; - } - return p; -} - -int load_file (char *device, int partno, char *filename, char *buffer, char *limit, int *len, int cmd, void (*lenfunc)(int, char **, char **)) +int load_file (char *device, int partno, char *filename, char *buffer, + char *limit, int *len, int cmd, + void (*lenfunc)(int, char **, char **)) { - ino_t inode = 0; - struct iso9660_inode iso_inode; - int retval; - int syspkg = 0; + struct silo_inode *sino; + int retval = 0, i; int size = -1; char bogusdev[] = "/dev/sdaX"; char *bogdev; void *mmark; - char *match = NULL, *dir = NULL; + char *dir = NULL; + size_t fn_len; mark (&mmark); if (!device) device = bootdevice; -#if 0 - printf ("Loading %s from %d\n", filename, partno); -#endif + bogdev = bogusdev; + if (prom_vers == PROM_V0) { if (device[0] == 'f' && device[1] == 'd') { device = "fd()"; @@ -607,177 +322,116 @@ int load_file (char *device, int partno, char *filename, char *buffer, char *lim bogusdev[8] = partno + '0'; } else bogusdev[8] = partno + '0'; + if (setdisk (device) < 0) - return 0; + goto done_2; + do_gunzip = cmd & LOADFILE_GZIP; filebuffer = buffer; filelimit = limit; + if (*filename == '[') { if (cmd & LOADFILE_LS) { if (!(cmd & LOADFILE_QUIET)) printf ("You cannot ls a device range\n"); - return 0; + goto done_2; } solaris = 0; retval = dump_device_range (filename, bogdev, len, lenfunc); - release (mmark); - return retval; + goto done_2; } - if (!open_ext2 (bogdev)) { - if (!open_romfs (bogdev)) { - if (!open_isofs (bogdev)) { - if (!open_ufs (bogdev)) { - if (!(cmd & LOADFILE_QUIET)) - fatal ("Unable to open filesystem"); - release (mmark); - return 0; - } else type = ufs; - } else - type = isofs; - } else - type = romfs; + + solaris = 0; /* The UFS module will set this if needed */ + for (i = 0; silo_fs_ops[i]; i++) + if (silo_fs_ops[i]->open(bogdev)) + break; + + if (!silo_fs_ops[i]) { + if (!(cmd & LOADFILE_QUIET)) + fatal ("Unable to open filesystem"); + goto done_2; } else - type = ext2; - if (type != ufs) - solaris = 0; - if (type == ext2) { - size_t fn_len = strlen(filename); - retval = 0; - if (cmd & LOADFILE_MATCH && fn_len > 1 && filename[fn_len - 1] != '/') { - dir = strdup(filename); - if ((match = strrchr(dir, '/')) != NULL && strlen(match) > 1) { - char *base = "/"; - if (match != dir) base = dir; - *match = '\0'; - match++; - retval = ext2fs_namei_follow (fs, root, root, base, &inode); - } - } else - retval = ext2fs_namei_follow (fs, root, root, filename, &inode); + cur_ops = silo_fs_ops[i]; - if (retval) { - if (!(cmd & LOADFILE_QUIET)) { - printf ("\nCannot find %s (", dir != NULL ? dir : filename); - ext2fs_error (retval); - printf (")\n"); - } - if (dir) free(dir); - ext2fs_close (fs); - release (mmark); - return 0; + if (cmd & LOADFILE_LS && cur_ops->ls == NULL) { + if (!(cmd & LOADFILE_MATCH)) + printf("\nls is not supported for `%s' filesystems\n", cur_ops->name); + goto done_1; + } + + fn_len = strlen(filename); + + /* Find the inode for the filename. If we are matching, always parse + * basedir and basename. */ + if (cmd & LOADFILE_MATCH && fn_len > 1 && filename[fn_len - 1] != '/') { + dir = strdup(filename); + if ((match = strrchr(dir, '/')) != NULL && strlen(match) > 1) { + char *base = "/"; + if (match != dir) base = dir; + *match = '\0'; + match++; + retval = cur_ops->namei_follow (base); } - } else if (type == romfs) { - if (romfs_namei (fs, root, root, filename, &inode)) { - if (!(cmd & LOADFILE_QUIET)) - printf ("\nCannot find %s\n", filename); - release (mmark); - return 0; - } - } else if (type == isofs) { - if (iso9660_namei (fs, filename, &iso_inode)) { - if (!(cmd & LOADFILE_QUIET)) - printf ("\nCannot find %s\n", filename); - release (mmark); - return 0; + } else { + match = NULL; + retval = cur_ops->namei_follow (filename); + } + + if (retval) { + if (!(cmd & LOADFILE_QUIET)) { + printf ("\nCannot find %s (", dir != NULL ? dir : filename); + cur_ops->print_error (retval); + printf (")\n"); } - inode = 1; - } else if (type == ufs) { - cwd = root; - if (solaris) { - if (!ufs_namei (fs, root, root, "/platform", &cwd)) { - if (!ufs_namei (fs, root, cwd, get_syspackage(), &inode)) { - cwd = inode; - syspkg = 1; - } else { - if (!ufs_namei (fs, root, cwd, get_archstr(), &inode)) - cwd = inode; - } - } - if (cwd != root && *filename == '/') filename++; - } - if (ufs_namei (fs, root, cwd, filename, &inode)) { - if (syspkg) { - syspkg = 0; - ufs_namei (fs, root, root, "/platform", &cwd); - if (!ufs_namei (fs, root, cwd, get_archstr(), &inode)) { - cwd = inode; - if (!ufs_namei (fs, root, cwd, filename, &inode)) - syspkg = 1; - } - } - if (!syspkg) { - if (!(cmd & LOADFILE_QUIET)) - printf ("\nCannot find %s.", filename); - ufs_close (fs); - release (mmark); - return 0; - } - } - if (solaris) { - ino_t sinode; - - if (ufs_namei (fs, root, cwd, "ufsboot", &sinode)) { - if (!(cmd & LOADFILE_QUIET)) - printf ("\nCannot find Solaris kernel bootloader `ufsboot'. Will try to load it,\n" - "but it may fail\n"); - solaris = 0; - } else - inode = sinode; - } + retval = 0; + goto done_1; } + if (lenfunc) { do_gunzip = 0; - if (type == isofs) - size = iso_inode.size; - else - size = get_len (inode); + size = cur_ops->ino_size(); (*lenfunc)(size, (char **)&filebuffer, (char **)&filelimit); do_gunzip = cmd & LOADFILE_GZIP; } + first_block = do_gunzip; last_blockcnt = 0; block_no = 0; block_cnt = 0; retval = 0; - if (inode) { - if (cmd & LOADFILE_LS) - switch (type) { - case ext2: retval = ls_ext2 (inode, match); if (dir) free(dir); break; - default: - if (!(cmd & LOADFILE_QUIET)) - printf ("ls not supported outside of ext2\n"); + + if (cur_ops->have_inode) { + if (cmd & LOADFILE_LS) { + if ((retval = cur_ops->ls())) { + if (!(cmd & LOADFILE_MATCH)) { + printf("\nError: could not list ("); + cur_ops->print_error(retval); + printf(").\n"); + } retval = 0; - break; -#if 0 - case ufs: retval = ls_ufs (inode); break; - case romfs: retval = ls_romfs (inode); break; - case isofs: retval = ls_isofs (&iso_inode); break; -#endif - } - else - switch (type) { - case ext2: retval = dump_ext2 (inode, filename); break; - case ufs: retval = dump_ufs (inode, filename); break; - case romfs: retval = dump_romfs (inode, filename); break; - case isofs: retval = dump_isofs (&iso_inode, filename); break; + } else { + sino = (struct silo_inode *)filebuffer; + sino->inolen = 0; + retval = 1; } - } + } else + retval = cur_ops->dump(filename); + } + if (retval && len) { if (size != -1) *len = size; else if (do_gunzip) *len = gunzipped_len; - else if (type == isofs) - *len = iso_inode.size; else - *len = get_len (inode); - } - switch (type) { - case ext2: ext2fs_close (fs); break; - case ufs: ufs_close (fs); break; - case romfs: romfs_close (fs); break; - case isofs: iso9660_close (fs); break; + *len = cur_ops->ino_size(); } + +done_1: + if (dir) free(dir); + cur_ops->close (fs); +done_2: release (mmark); + return retval; } diff --git a/second/file.h b/second/file.h new file mode 100644 index 0000000..35213d9 --- /dev/null +++ b/second/file.h @@ -0,0 +1,49 @@ +/* Exported filesystem related stuff + + Copyright (C) 2001 Ben Collins + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +typedef int FILE; +#include <linux/ext2_fs.h> +#include <ext2fs/ext2fs.h> + +extern unsigned int bs; /* Block Size */ +extern io_manager silo_io_manager; /* The Filesystem I/O Manager */ +extern unsigned char *filebuffer; +extern ext2_filsys fs; /* Generic filesystem */ +extern ino_t root, cwd; /* root and cwd for current fs */ +extern int solaris; + +extern int dump_block (ext2_filsys, blk_t *, int,void *); +extern int dump_finish (void); +extern void register_silo_inode (unsigned int, unsigned int, + unsigned int, unsigned int, + unsigned int, const char *, + const char *); + +/* Filesystem operations provided by each module */ +struct fs_ops { + char *name; + int (*open) (char *); + int (*ls) (void); + int (*dump) (char *); + int (*ino_size) (void); + int (*namei_follow) (const char *); + void (*print_error) (int); + void (*close) (ext2_filsys); + int have_inode; +}; diff --git a/second/fs/ext2.c b/second/fs/ext2.c new file mode 100644 index 0000000..3f5edd3 --- /dev/null +++ b/second/fs/ext2.c @@ -0,0 +1,165 @@ +/* EXT2 Interface for SILO filesystem access routines + + Copyright (C) 1996 Maurizio Plaza + 1996,1997,1999 Jakub Jelinek + 2001 Ben Collins + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, + USA. */ + +#include <sys/types.h> +#include <silo.h> +#include <file.h> +#include <stringops.h> + +#define ec ,},{ + +static struct { + int errnum; + char *desc; +} ext2errors[] = { +{ 0, "OK" +#include <ext2fs/ext2_err.et> +} +}; + +static ino_t inode = 0; +struct fs_ops ext2_fs_ops; + +void com_err (const char *a, long i, const char *fmt,...) +{ + printf ((char *) fmt); +} + +static void ext2fs_error (int errcode) +{ + int i; + + for (i = 0; i < sizeof (ext2errors) / sizeof (ext2errors[0]); i++) + if (ext2errors[i].errnum == errcode) { + printf ("%s", ext2errors [i].desc); + return; + } + printf ("Unknown ext2 error"); +} + +static int open_ext2 (char *device) +{ + int retval; + + retval = ext2fs_open (device, EXT2_FLAG_RW, 0, 0, silo_io_manager, &fs); + if (retval == EXT2_ET_BAD_MAGIC) + return 0; + if (retval) { + printf ("\n"); + ext2fs_error (retval); + printf ("\n"); + return 0; + } + root = EXT2_ROOT_INO; + return 1; +} + +static int dump_ext2 (char *filename) +{ + errcode_t retval; + + retval = ext2fs_block_iterate (fs, inode, 0, 0, + dump_block, 0); + if (retval) { + printf ("\n"); + ext2fs_error (retval); + printf ("\n"); + return 0; + } + return dump_finish (); +} + +static int ls_ext2_proc(struct ext2_dir_entry *dirent, int offset, + int blocksize, char *buf, void *private) +{ + struct ext2_inode ino; + int sl = 0, name_len = dirent->name_len & 0xFF; + char name[256], symlink[256]; + + strncpy(name, dirent->name, name_len); + name[name_len] = 0; + + if (ext2fs_read_inode(fs, dirent->inode, &ino)) + strcpy (name, "--- error ---"); + + if (LINUX_S_ISLNK (ino.i_mode)) { + sl = 1; + if (ino.i_blocks) { + if (io_channel_read_blk(fs->io, ino.i_block[0], 1, symlink)) + ino.i_size = 0; + } else { + strncpy (symlink, (char *)&(ino.i_block[0]),ino.i_size); + } + symlink[ino.i_size] = 0; + } + + register_silo_inode(ino.i_mtime, ino.i_size, ino.i_mode, ino.i_uid, + ino.i_gid, name, sl ? symlink : NULL); + + return 0; +} + +static int ls_ext2 (void) +{ + return ext2fs_dir_iterate (fs, inode, DIRENT_FLAG_INCLUDE_EMPTY, + 0, ls_ext2_proc, NULL); +} + +static int ino_size_ext2 (void) { + struct ext2_inode ei; + int retval; + + if ((retval = ext2fs_read_inode (fs, inode, &ei))) { + printf ("\n"); + ext2fs_error (retval); + printf ("\n"); + return 0; + } + return ei.i_size; +} + +static int namei_follow_ext2 (const char *filename) { + int ret = ext2fs_namei_follow (fs, root, root, filename, &inode); + + ext2_fs_ops.have_inode = (inode) ? 1 : 0; + + return ret; +} + +static void print_error_ext2 (int error_val) { + ext2fs_error (error_val); +} + +void close_ext2 (ext2_filsys fs) { + ext2fs_close(fs); +} + +struct fs_ops ext2_fs_ops = { + name: "Linux EXT2", + open: open_ext2, + ls: ls_ext2, + dump: dump_ext2, + close: close_ext2, + ino_size: ino_size_ext2, + print_error: print_error_ext2, + namei_follow: namei_follow_ext2, + have_inode: 0, +}; diff --git a/second/fs/iom.c b/second/fs/iom.c new file mode 100644 index 0000000..255e6c6 --- /dev/null +++ b/second/fs/iom.c @@ -0,0 +1,124 @@ +/* SILO I/O Manager for filesystem operations. + + Copyright (C) 1996 Maurizio Plaza + 1996,1997,1999 Jakub Jelinek + 2001 Ben Collins + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +#include <sys/types.h> +#include <silo.h> +#include <file.h> +#include <stringops.h> + +static unsigned long long doff; /* Block where partition starts */ + +static int read_sun_partition (int partno) +{ + int rc; + sun_partition sdl; + unsigned short csum, *ush; + + rc = read ((char *) &sdl, 512, 0); + if (rc != 512) { + fatal ("Cannot read partition"); + return 0; + } + if (sdl.magic != SUN_LABEL_MAGIC) + fatal ("Wrong disklabel magic"); + for (csum = 0, ush = ((unsigned short *) ((&sdl) + 1)) - 1; ush >= (unsigned short *) &sdl;) + csum ^= *ush--; + if (csum) + printf ("\nWarning: Your disklabel has wrong checksum. Use fdisk to correct it."); + doff = (((unsigned long long)sdl.ntrks) * sdl.nsect * sdl.partitions[partno - 1].start_cylinder) << 9; return 1; +} + +static errcode_t silo_open (const char *name, int flags, io_channel * channel) +{ + int partno; + io_channel io; + + if (!name) + return EXT2_ET_BAD_DEVICE_NAME; + io = (io_channel) malloc (sizeof (struct struct_io_channel)); + if (!io) + return EXT2_ET_BAD_DEVICE_NAME; + memset (io, 0, sizeof (struct struct_io_channel)); + io->magic = EXT2_ET_MAGIC_IO_CHANNEL; + io->manager = silo_io_manager; + io->name = (char *) malloc (strlen (name) + 1); + strcpy (io->name, name); + io->block_size = bs; + io->read_error = 0; + io->write_error = 0; + + doff = 0LL; + if (strncmp (name, "/dev/fd0", 8) && partitionable()) { + partno = *(name + strlen (name) - 1) - '0'; + if (partno && !read_sun_partition (partno)) + return EXT2_ET_BAD_DEVICE_NAME; + } + *channel = io; + return 0; +} + +static errcode_t silo_close (io_channel channel) +{ + return 0; +} + +static errcode_t silo_set_blksize (io_channel channel, int blksize) +{ + channel->block_size = bs = blksize; + return 0; +} + +static errcode_t silo_read_blk (io_channel channel, unsigned long block, int count, void *data) +{ + int size; + + size = (count < 0) ? -count : count * bs; + if (read (data, size, ((unsigned long long)block) * bs + doff) != size) { + printf ("\nRead error on block %d\n", block); + return EXT2_ET_SHORT_READ; + } + return 0; +} + +static errcode_t silo_write_blk (io_channel channel, unsigned long block, int count, const void *data) +{ + return 0; +} + +static errcode_t silo_flush (io_channel channel) +{ + return 0; +} + +/* The actual I/O Manager. */ +static struct struct_io_manager struct_silo_manager = +{ + EXT2_ET_MAGIC_IO_MANAGER, + "SILO I/O Manager", + silo_open, + silo_close, + silo_set_blksize, + silo_read_blk, + silo_write_blk, + silo_flush +}; + +io_manager silo_io_manager = &struct_silo_manager; diff --git a/second/fs/isofs.c b/second/fs/isofs.c new file mode 100644 index 0000000..080cbe6 --- /dev/null +++ b/second/fs/isofs.c @@ -0,0 +1,466 @@ +/* ISO9660 (CDROM) Interface for SILO filesystem access routines + + Copyright (C) 1999 Jakub Jelinek + 1992,1993 Eric Youngdale + 2001 Ben Collins + + 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, + USA. */ + +#include <ctype.h> +#include <sys/types.h> +#include <errno.h> +#include <linux/iso_fs.h> +#include <silo.h> +#include <file.h> +#include <stringops.h> +#include <fs/rock.h> + +/* Reuse and abuse */ +typedef ext2_filsys isofs_filsys; + +struct isofs_inode { + unsigned int extent; + unsigned int size; +}; + +#define SUPISO ((struct iso_primary_descriptor *)fs->io->private_data) +#define ROOTDIR ((struct isofs_inode *)SUPISO->unused2) + +static struct isofs_inode inode; +static int link_count = 0; + +void *alloca(size_t); +static int isofs_lookup (isofs_filsys, struct isofs_inode *, + const char *, int, struct isofs_inode *); +static int open_namei(isofs_filsys, const char *, struct isofs_inode *, + struct isofs_inode *); + +static int ino_size_isofs (void) +{ + return inode.size; +} + +static int ls_isofs (void) +{ + link_count = 0; + return isofs_lookup (fs, &inode, "", 0, NULL); +} + +static int isonum_731 (char * p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + +#define isonum_733(p) isonum_731(p) + +static struct iso_primary_descriptor *isofs_read_super(isofs_filsys fs) +{ + int i; + struct iso_primary_descriptor *iso = (struct iso_primary_descriptor *) malloc (2048); + struct isofs_inode *root; + + for (i = 16; i < 100; i++) { + if (io_channel_read_blk (fs->io, i, -2048, (char *)iso)) + return 0; + if (!strncmp (iso->id, ISO_STANDARD_ID, sizeof (iso->id))) + break; + } + + if (i == 100) return 0; + + root = (struct isofs_inode *)iso->unused2; + root->extent = isonum_733 (((struct iso_directory_record *)(iso->root_directory_record))->extent); + root->size = isonum_733 (((struct iso_directory_record *)(iso->root_directory_record))->size); + + return iso; +} + +int open_isofs (char *device) +{ + fs = (isofs_filsys) malloc (sizeof (struct struct_ext2_filsys)); + if (!fs) + return 0; + + if (((struct struct_io_manager *)(silo_io_manager))->open (device, 0, &fs->io)) + return 0; + + io_channel_set_blksize (fs->io, 2048); + + if (!(fs->io->private_data = isofs_read_super(fs))) + return 0; + + return 1; +} + +static int iso_date(char * p, int flag) +{ + int year, month, day, hour, minute, second, tz; + int crtime, days, i; + + year = p[0] - 70; + month = p[1]; + day = p[2]; + hour = p[3]; + minute = p[4]; + second = p[5]; + if (flag == 0) tz = p[6]; /* High sierra has no time zone */ + else tz = 0; + + if (year < 0) { + crtime = 0; + } else { + int monlen[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; + + days = year * 365; + if (year > 2) + days += (year+1) / 4; + for (i = 1; i < month; i++) + days += monlen[i-1]; + if (((year+2) % 4) == 0 && month > 2) + days++; + days += day - 1; + crtime = ((((days * 24) + hour) * 60 + minute) * 60) + + second; + + /* sign extend */ + if (tz & 0x80) + tz |= (-1 << 8); + + if (-52 <= tz && tz <= 52) + crtime -= tz * 15 * 60; + } + return crtime; +} + +#define SIG(A,B) ((A << 8) | B) + +#define CHECK_CE \ + {cont_extent = isonum_733(rr->u.CE.extent); \ + cont_offset = isonum_733(rr->u.CE.offset); \ + cont_size = isonum_733(rr->u.CE.size);} + +static void parse_rr (isofs_filsys fs, unsigned char *chr, unsigned char *end, + char *name, char *symlink, struct silo_inode *sino) +{ + int cont_extent = 0, cont_offset = 0, cont_size = 0; + struct rock_ridge *rr; + int cnt, sig; + int truncate = 0; + int retnamlen = 0; + int symlink_len = 0; + int rootflag; + + *name = 0; + + while (chr < end) { + rr = (struct rock_ridge *) chr; + if (rr->len == 0) goto out; + sig = (chr[0] << 8) + chr[1]; + chr += rr->len; + + switch(sig){ + case SIG('R','R'): + if((rr->u.RR.flags[0] & + (RR_PX | RR_TF | RR_SL | RR_CL | RR_NM | RR_PX | RR_TF)) == 0) + goto out; + break; + case SIG('N','M'): + if (truncate) break; + if (rr->u.NM.flags & 6) break; + if (rr->u.NM.flags & ~1) { + printf ("Unsupported NM flag settings (%d)\n",rr->u.NM.flags); + break; + } + if((strlen(name) + rr->len - 5) >= 254) { + truncate = 1; + break; + } + strncat(name, rr->u.NM.name, rr->len - 5); + retnamlen += rr->len - 5; + break; + case SIG('S','L'): + { + int slen; + struct SL_component * slp; + struct SL_component * oldslp; + slen = rr->len - 5; + slp = &rr->u.SL.link; + sino->size = symlink_len; + + while (slen > 1) { + rootflag = 0; + switch(slp->flags &~1) { + case 0: + sino->size += slp->len; + strncat (symlink, slp->text, slp->len); + break; + case 2: + sino->size += 1; + strcat (symlink, "."); + break; + case 4: + sino->size += 2; + strcat (symlink, ".."); + break; + case 8: + rootflag = 1; + sino->size += 1; + strcat (symlink, "/"); + break; + default: + printf("Symlink component flag not implemented\n"); + } + slen -= slp->len + 2; + oldslp = slp; + slp = (struct SL_component *) (((char *) slp) + slp->len + 2); + + if (slen < 2) { + if(((rr->u.SL.flags & 1) != 0) + && ((oldslp->flags & 1) == 0) ) sino->size += 1; + break; + } + + /* + * If this component record isn't continued, then append a '/'. + */ + if (!rootflag && (oldslp->flags & 1) == 0) { + strcat (symlink, "/"); + sino->size += 1; + } + + } + } + symlink_len = sino->size; + break; + case SIG('C','E'): + CHECK_CE; + break; + case SIG('P','X'): + sino->mode = isonum_733(rr->u.PX.mode); + sino->uid = isonum_733(rr->u.PX.uid); + sino->gid = isonum_733(rr->u.PX.gid); + break; + case SIG('T','F'): + cnt = 0; + if(rr->u.TF.flags & TF_CREATE) + cnt++; + if(rr->u.TF.flags & TF_MODIFY) + sino->mtime = iso_date(rr->u.TF.times[cnt++].time, 0); + break; + } + if (chr >= end && cont_extent) { + char *sect = alloca (2048); + if (io_channel_read_blk (fs->io, cont_extent, 1, sect)) + return; + parse_rr (fs, § [cont_offset], § [cont_offset + cont_size - 3], + name, symlink, sino); + } + } +out: + return; +} + +static int isofs_lookup (isofs_filsys fs, struct isofs_inode *dir, + const char *name, int len, struct isofs_inode *result) +{ + char buffer [2048]; + char namebuf [512]; + char symlink [512]; + int block, size, i; + struct iso_directory_record *idr; + unsigned char *rr; + struct silo_inode sino; + + size = dir->size; + block = dir->extent; + + while (size > 0) { + if (io_channel_read_blk (fs->io, block, 1, buffer)) { + printf ("Could not read directory\n"); + return -1; + } + + size -= 2048; + block++; + + for (i = 0;;) { + idr = (struct iso_directory_record *) (buffer + i); + if (!idr->length[0]) + break; + + i += (unsigned char)idr->length[0]; + strncpy(namebuf, idr->name, (unsigned char)idr->name_len[0]); + namebuf[(unsigned char)idr->name_len[0]] = 0; + + rr = (unsigned char *)(idr + 1); + rr += ((unsigned char)idr->name_len[0]) - sizeof(idr->name); + + if (!(idr->name_len[0] & 1)) + rr++; + + *symlink = 0; + memset(&sino, 0, sizeof(struct silo_inode)); + parse_rr (fs, rr, &buffer[i-3], namebuf, symlink, &sino); + + if (idr->name_len[0] == 1 && !idr->name[0]) + strcpy(namebuf, "."); + else if (idr->name_len[0] == 1 && idr->name[0] == 1) + strcpy(namebuf, ".."); + + if (result == NULL) { + /* We aren't returning a result inode, so we must be + * iterating... */ + register_silo_inode(sino.mtime, sino.size?:isonum_733(idr->size), + sino.mode, sino.uid, sino.gid, namebuf, + *symlink ? symlink : NULL); + } else if ((!len && namebuf[0] == '.' && !namebuf[1]) || + (strlen(namebuf) == len && !memcmp(namebuf, name, len))) { + if (*symlink) { + int error; + if (link_count > 5) { + printf ("Symlink loop, stopping.\n"); + return -1; /* Loop */ + } + link_count++; + error = open_namei (fs, symlink, result, dir); + link_count--; + return error; + } + result->extent = isonum_733 (idr->extent); + result->size = isonum_733 (idr->size); + return 0; + } + + if (i >= 2048 - sizeof(struct iso_directory_record) + sizeof(idr->name)) + break; + } + } + if (result == NULL) + return 0; + else + return -1; +} + +static int dir_namei(isofs_filsys fs, const char *pathname, int *namelen, + const char **name, struct isofs_inode *base, + struct isofs_inode *res_inode) +{ + char c; + const char *thisname; + int len; + struct isofs_inode inode; + + if ((c = *pathname) == '/') { + base = ROOTDIR; + pathname++; + } + while (1) { + thisname = pathname; + for(len=0;(c = *(pathname++))&&(c != '/');len++); + if (!c) break; + if (isofs_lookup (fs, base, thisname, len, &inode)) return -1; + base = &inode; + } + *name = thisname; + *namelen = len; + *res_inode = *base; + return 0; +} + +static int open_namei(isofs_filsys fs, const char *pathname, + struct isofs_inode *res_inode, + struct isofs_inode *base) +{ + const char *basename; + int namelen; + struct isofs_inode dir, inode; + + if (dir_namei(fs, pathname, &namelen, &basename, base, &dir)) return -1; + if (!namelen) { /* special case: '/usr/' etc */ + *res_inode=dir; + return 0; + } + if (isofs_lookup (fs, &dir, basename, namelen, &inode)) return -1; + *res_inode = inode; + return 0; +} + +struct fs_ops iso_fs_ops; + +int isofs_namei (const char *filename) +{ + int ret; + link_count = 0; + + ret = open_namei (fs, filename, &inode, ROOTDIR); + iso_fs_ops.have_inode = (ret) ? 0 : 1; + + return ret; +} + +void isofs_close(isofs_filsys fs) +{ + free (fs->io); + free (fs); +} + +int isofs_block_iterate(isofs_filsys fs, + int (*func)(isofs_filsys, blk_t *, int, void *), + void *private) +{ + int i; + blk_t nr; + int size; + + nr = inode.extent; + size = (inode.size + 2047) / 2048; + for (i = 0; i < size; i++, nr++) { + switch ((*func) (fs, &nr, i, private)) { + case BLOCK_ABORT: + case BLOCK_ERROR: + return -1; + } + } + return 0; +} + +static int dump_isofs (char *filename) +{ + if (isofs_block_iterate (fs, dump_block, 0)) { + printf ("Error while loading of %s", filename); + return 0; + } + return dump_finish (); +} + +static void print_error_isofs (int error_val) { + printf("Unknown isofs error"); +} + +struct fs_ops iso_fs_ops = { + name: "ISO-9660 CDROM", + open: open_isofs, + ls: ls_isofs, + dump: dump_isofs, + close: isofs_close, + ino_size: ino_size_isofs, + print_error: print_error_isofs, + namei_follow: isofs_namei, + have_inode: 0, +}; diff --git a/second/fs/rock.h b/second/fs/rock.h new file mode 100644 index 0000000..36057b8 --- /dev/null +++ b/second/fs/rock.h @@ -0,0 +1,111 @@ +/* These structs are used by the system-use-sharing protocol, in which the + Rock Ridge extensions are embedded. It is quite possible that other + extensions are present on the disk, and this is fine as long as they + all use SUSP */ + +struct SU_SP{ + unsigned char magic[2]; + unsigned char skip; +}; + +struct SU_CE{ + char extent[8]; + char offset[8]; + char size[8]; +}; + +struct SU_ER{ + unsigned char len_id; + unsigned char len_des; + unsigned char len_src; + unsigned char ext_ver; + char data[0]; +}; + +struct RR_RR{ + char flags[1]; +}; + +struct RR_PX{ + char mode[8]; + char n_links[8]; + char uid[8]; + char gid[8]; +}; + +struct RR_PN{ + char dev_high[8]; + char dev_low[8]; +}; + + +struct SL_component{ + unsigned char flags; + unsigned char len; + char text[0]; +}; + +struct RR_SL{ + unsigned char flags; + struct SL_component link; +}; + +struct RR_NM{ + unsigned char flags; + char name[0]; +}; + +struct RR_CL{ + char location[8]; +}; + +struct RR_PL{ + char location[8]; +}; + +struct stamp{ + char time[7]; +}; + +struct RR_TF{ + char flags; + struct stamp times[0]; /* Variable number of these beasts */ +}; + +/* These are the bits and their meanings for flags in the TF structure. */ +#define TF_CREATE 1 +#define TF_MODIFY 2 +#define TF_ACCESS 4 +#define TF_ATTRIBUTES 8 +#define TF_BACKUP 16 +#define TF_EXPIRATION 32 +#define TF_EFFECTIVE 64 +#define TF_LONG_FORM 128 + +struct rock_ridge{ + char signature[2]; + unsigned char len; + unsigned char version; + union{ + struct SU_SP SP; + struct SU_CE CE; + struct SU_ER ER; + struct RR_RR RR; + struct RR_PX PX; + struct RR_PN PN; + struct RR_SL SL; + struct RR_NM NM; + struct RR_CL CL; + struct RR_PL PL; + struct RR_TF TF; + } u; +}; + +#define RR_PX 1 /* POSIX attributes */ +#define RR_PN 2 /* POSIX devices */ +#define RR_SL 4 /* Symbolic link */ +#define RR_NM 8 /* Alternate Name */ +#define RR_CL 16 /* Child link */ +#define RR_PL 32 /* Parent link */ +#define RR_RE 64 /* Relocation directory */ +#define RR_TF 128 /* Timestamps */ diff --git a/second/romfs.c b/second/romfs.c deleted file mode 100644 index c9f039f..0000000 --- a/second/romfs.c +++ /dev/null @@ -1,292 +0,0 @@ -/* ROMFS filesystem handling - - Copyright (C) 1998 Jakub Jelinek <jj@ultra.linux.cz> - Copyright (C) 1997 Janos Farkas <chexum@shadow.banki.hu> - - 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#ifdef __linux__ - -# include <ctype.h> -# include <sys/types.h> -# include <errno.h> -# include <silo.h> -typedef int FILE; -# include <linux/ext2_fs.h> - -#else - -# include <stdio.h> -# include <sys/types.h> -# include <sys/stat.h> -# include <errno.h> -# include <non-linux/ext2_fs.h> - -#endif - -#include <stringops.h> -#include "romfs.h" - -#define SUPROMFS (struct romfs_super_block *)(fs->io->private_data) - -static __s32 -romfs_checksum(void *data, int size) -{ - __s32 sum, *ptr; - sum = 0; ptr = data; - size>>=2; - while (size>0) { - sum += *ptr++; - size--; - } - return sum; -} - -static struct romfs_super_block *romfs_read_super(romfs_filsys fs) -{ - struct romfs_super_block *rsb; - - rsb = (struct romfs_super_block *) malloc (2048+512); - if (!rsb) return 0; - if (io_channel_read_blk (fs->io, 0, 1, (char *)rsb)) - return 0; - if (strncmp((char *)rsb, "-rom1fs-", 8) || rsb->size < ROMFH_SIZE) - return 0; - if (romfs_checksum(rsb, 512)) { - printf("Bad ROMFS initial checksum\n"); - return 0; - } - rsb->checksum = strlen(rsb->name); - if (rsb->checksum > ROMFS_MAXFN) rsb->checksum = ROMFS_MAXFN; - rsb->checksum += (ROMFH_SIZE + 1 + ROMFH_PAD); - rsb->checksum &= ROMFH_MASK; - rsb->word0 = -1; - rsb->word1 = -1; - rsb->name[0] = 0; - return rsb; -} - -static int romfs_copyfrom(romfs_filsys fs, void *dest, unsigned long offset, unsigned long count) -{ - int off; - struct romfs_super_block *rsb = SUPROMFS; - - for (;;) { - if (rsb->word0 != (__u32)-1 && offset >= rsb->word0 && offset < rsb->word0 + 1024) { - int cnt = 1024 - (offset & 1023); - if (count < cnt) - cnt = count; - memcpy(dest, (char *)rsb + 512 + (offset & 1023), cnt); - if (count == cnt) return 0; - dest = (char *)dest + cnt; - offset += cnt; - count -= cnt; - } - if (rsb->word1 != (__u32)-1 && offset >= rsb->word1 && offset < rsb->word1 + 1024) { - int cnt = 1024 - (offset & 1023); - if (count < cnt) - cnt = count; - memcpy(dest, (char *)rsb + 1536 + (offset & 1023), cnt); - if (count == cnt) return 0; - dest = (char *)dest + cnt; - count -= cnt; - } - off = offset & ~1023; - if (io_channel_read_blk (fs->io, off / 512, 2, (char *)rsb + (rsb->name[0] ? 1536 : 512))) { - if (rsb->name[0]) - rsb->word1 = -1; - else - rsb->word0 = -1; - return -1; - } - if (rsb->name[0]) - rsb->word1 = off; - else - rsb->word0 = off; - rsb->name[0] ^= 1; - } -} - -int romfs_open (char *device, io_manager iom, romfs_filsys *pfs) -{ - romfs_filsys fs; - fs = (romfs_filsys) malloc (sizeof (struct struct_ext2_filsys)); - if (!fs) return -1; - if (iom->open (device, 0, &fs->io)) return -1; - io_channel_set_blksize (fs->io, 512); - fs->io->private_data = romfs_read_super(fs); - if (!fs->io->private_data) return -1; - *pfs = fs; - return 0; -} - -int romfs_read_inode (romfs_filsys fs, ino_t inode, struct romfs_inode *ui) -{ - struct romfs_inode romfsip; - struct romfs_super_block *rsb = SUPROMFS; - - if (inode < rsb->checksum || inode >= rsb->size) - return -1; - - if (romfs_copyfrom (fs, &romfsip, inode, 16)) - return -1; - *ui = romfsip; - return 0; -} - -static int romfs_lookup (romfs_filsys fs, ino_t dir, struct romfs_inode *dirui, - const char *name, int len, ino_t *result) -{ - char buffer [8192]; - struct romfs_inode ui; - - dir = dirui->spec & ROMFH_MASK; - while (dir) { - if (romfs_read_inode (fs, dir, &ui)) - return -1; - if (romfs_copyfrom (fs, buffer, dir + 16, ROMFS_MAXFN)) - return -1; - if ((!len && buffer[0] == '.' && !buffer[1]) || - (strlen(buffer) == len && !memcmp(buffer, name, len))) { - if ((ui.next & ROMFH_TYPE) == ROMFH_HRD) - dir = ui.spec; - *result = dir; - return 0; - } - dir = ui.next & ROMFH_MASK; - } - return -1; -} - -static int link_count = 0; - -static int open_namei(romfs_filsys, const char *, ino_t *, ino_t); - -static int romfs_follow_link(romfs_filsys fs, ino_t dir, ino_t inode, - struct romfs_inode *ui, ino_t *res_inode) -{ - int error; - char buffer[1024]; - - if ((ui->next & ROMFH_TYPE) != ROMFH_SYM) { - *res_inode = inode; - return 0; - } - if (link_count > 5) { - printf ("Symlink loop\n"); - return -1; /* Loop */ - } - if (romfs_copyfrom (fs, buffer, inode + 16, ROMFS_MAXFN)) - return -1; - error = inode + 16 + ((strlen(buffer) + 16) & ~15); - if (romfs_copyfrom (fs, buffer, error, ROMFS_MAXFN)) - return -1; - link_count++; - error = open_namei (fs, buffer, res_inode, dir); - link_count--; - return error; -} - -static int dir_namei(romfs_filsys fs, const char *pathname, int *namelen, - const char **name, ino_t base, ino_t *res_inode) -{ - char c; - const char *thisname; - int len; - struct romfs_inode ub; - ino_t inode; - - if ((c = *pathname) == '/') { - base = (ino_t)fs->private; - pathname++; - } - if (romfs_read_inode (fs, base, &ub)) return -1; - while (1) { - thisname = pathname; - for(len=0;(c = *(pathname++))&&(c != '/');len++); - if (!c) break; - if (romfs_lookup (fs, base, &ub, thisname, len, &inode)) return -1; - if (romfs_read_inode (fs, inode, &ub)) return -1; - if (romfs_follow_link (fs, base, inode, &ub, &base)) return -1; - if (base != inode && romfs_read_inode (fs, base, &ub)) return -1; - } - *name = thisname; - *namelen = len; - *res_inode = base; - return 0; -} - -static int open_namei(romfs_filsys fs, const char *pathname, - ino_t *res_inode, ino_t base) -{ - const char *basename; - int namelen; - ino_t dir, inode; - struct romfs_inode ub; - - if (dir_namei(fs, pathname, &namelen, &basename, base, &dir)) return -1; - if (!namelen) { /* special case: '/usr/' etc */ - *res_inode=dir; - return 0; - } - if (romfs_read_inode (fs, dir, &ub)) return -1; - if (romfs_lookup (fs, dir, &ub, basename, namelen, &inode)) return -1; - if (romfs_read_inode (fs, inode, &ub)) return -1; - if (romfs_follow_link (fs, dir, inode, &ub, &inode)) return -1; - *res_inode = inode; - return 0; -} - -int romfs_namei (romfs_filsys fs, ino_t root, ino_t cwd, char *filename, ino_t *inode) -{ - fs->private = (void *)root; - link_count = 0; - return open_namei (fs, filename, inode, cwd); -} - -void romfs_close(romfs_filsys fs) -{ - free (fs->io); - free (fs); -} - -int romfs_block_iterate(romfs_filsys fs, ino_t inode, - int (*func)(romfs_filsys, blk_t *, int, void *), - void *private) -{ - struct romfs_inode ub; - int i; - blk_t nr; - int size; - char buffer[ROMFS_MAXFN]; - - if (romfs_read_inode (fs, inode, &ub)) return -1; - if (romfs_copyfrom (fs, buffer, inode + 16, ROMFS_MAXFN)) return -1; - nr = inode + 16 + ((strlen(buffer) + 16) & ~15); - if (nr & 511) { - printf("romfs: File not aligned on a 512B boundary\n"); - return -1; - } - size = (ub.size + 511) / 512; - nr /= 512; - for (i = 0; i < size; i++, nr++) { - switch ((*func) (fs, &nr, i, private)) { - case BLOCK_ABORT: - case BLOCK_ERROR: - return -1; - } - } - return 0; -} diff --git a/second/romfs.h b/second/romfs.h deleted file mode 100644 index 3e2ede5..0000000 --- a/second/romfs.h +++ /dev/null @@ -1,32 +0,0 @@ -#include <ext2fs/ext2fs.h> - -#ifdef __linux__ - -#include <features.h> -#ifdef __GLIBC__ -# define _LINUX_TIME_H -#endif -#include <linux/version.h> -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,47) -#include <linux/romfs_fs.h> -#else -#include <non-linux/romfs_fs.h> -#endif - -#else - -#include <non-linux/romfs_fs.h> - -#endif - -typedef ext2_filsys romfs_filsys; - -int romfs_open(char *device, io_manager io, romfs_filsys *fs); -int romfs_namei(romfs_filsys fs, ino_t root, ino_t cwd, char *filename, ino_t *inode); -void romfs_close(romfs_filsys fs); -int romfs_read_inode(romfs_filsys fs, ino_t inode, struct romfs_inode *ui); -int romfs_block_iterate(romfs_filsys, ino_t, - int (*)(romfs_filsys, blk_t *, int, void *), void *); diff --git a/second/ufs.c b/second/ufs.c deleted file mode 100644 index 527afca..0000000 --- a/second/ufs.c +++ /dev/null @@ -1,331 +0,0 @@ -/* UFS filesystem handling - - Copyright (C) 1996 Adrian Rodriguez - 1996 Jakub Jelinek - - 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 2 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#ifdef __linux__ - -# include <ctype.h> -# include <sys/types.h> -# include <sys/time.h> -# include <errno.h> -# include <silo.h> -typedef int FILE; -# include <linux/ext2_fs.h> - -#else - -# include <stdio.h> -# include <sys/types.h> -# include <sys/stat.h> -# include <errno.h> -# include <non-linux/ext2_fs.h> - -#endif - -#include "ext2fs/ext2fs.h" -#include "ufs.h" -#ifndef S_ISLNK -#include <sys/stat.h> -#endif - -#include <stringops.h> - -#define SUPUFS (struct ufs_superblock *)(fs->io->private_data) -#define cgstart(cg) ((sb->fs_fpg * (cg)) + sb->fs_cgoffset * ((cg) & ~(sb->fs_cgmask))) -#define cgimin(cg) (cgstart(cg) + sb->fs_iblkno) -#define cgdmin(cg) (cgstart(cg) + sb->fs_dblkno) -#define ino2cg(ino) ((ino) / sb->fs_ipg) - -static struct ufs_superblock *ufs_read_super(ufs_filsys fs) -{ - struct ufs_superblock *usb; - - usb = (struct ufs_superblock *) malloc (2048); - if (!usb) return 0; - if (io_channel_read_blk (fs->io, UFS_SBLOCK/1024, -2048, (char *)usb)) - return 0; - if (usb->fs_magic != UFS_MAGIC) { - /* XXX - replace hard-coded constant with a byte-swap macro */ - if (usb->fs_magic == 0x54190100) { - } - return 0; - } - if (usb->fs_bsize != UFS_BSIZE) - return 0; - if (usb->fs_fsize != UFS_FSIZE) - return 0; - io_channel_set_blksize (fs->io, usb->fs_fsize); - return usb; -} - -int ufs_open (char *device, io_manager iom, ufs_filsys *pfs) -{ - ufs_filsys fs; - fs = (ufs_filsys) malloc (sizeof (struct struct_ext2_filsys)); - if (!fs) return -1; - if (iom->open (device, 0, &fs->io)) return -1; - io_channel_set_blksize (fs->io, 1024); - fs->io->private_data = ufs_read_super(fs); - if (!fs->io->private_data) return -1; - *pfs = fs; - return 0; -} - -int ufs_read_inode (ufs_filsys fs, ino_t inode, struct ufs_inode *ui) -{ - struct ufs_inode *ufsip; - struct ufs_superblock *sb = SUPUFS; - char *buffer; - - if (inode < 2 || inode > (sb->fs_ncg * sb->fs_ipg - 1)) - return -1; - - ufsip = (struct ufs_inode *) malloc (1024); - buffer = (char *) ufsip; - if (io_channel_read_blk (fs->io, - cgimin (ino2cg(inode)) + (inode % sb->fs_ipg) / (sb->fs_inopb / sb->fs_frag), - -1024, (char *)ufsip)) { - printf ("Couldn't read inode\n"); - return -1; - } - ufsip += (inode%(sb->fs_inopb / sb->fs_frag)); - *ui = *ufsip; - free (buffer); - return 0; -} - -static int block_bmap (ufs_filsys fs, int block, int nr) -{ - struct ufs_superblock *sb = SUPUFS; - int tmp = nr >> (sb->fs_fshift - 2); - static int lastbuftmp = -1; - static __u32 *lastdata = 0; - - nr &= ~(sb->fs_fmask) >> 2; - if (block + tmp != lastbuftmp) { - if (!lastdata) lastdata = (__u32 *) malloc (sb->fs_fsize); - lastbuftmp = block + tmp; - if (io_channel_read_blk (fs->io, block + tmp, -sb->fs_fsize, lastdata)) - return 0; - } - return lastdata[nr]; -} - -static int ufs_bmap (ufs_filsys fs, ino_t inode, struct ufs_inode *ui, int block) -{ - struct ufs_superblock *sb = SUPUFS; - int i; - int addr_per_block = sb->fs_bsize >> 2; - int addr_per_block_bits = sb->fs_bshift - 2; - int lbn = block >> (sb->fs_bshift - sb->fs_fshift); - int boff = (block & ((sb->fs_fmask - sb->fs_bmask) >> sb->fs_fshift)); - - if (lbn < 0) return 0; - if (lbn >= UFS_NDADDR + addr_per_block + - (1 << (addr_per_block_bits * 2)) + - ((1 << (addr_per_block_bits * 2)) << addr_per_block_bits)) - return 0; - if (lbn < UFS_NDADDR) - return ufsi_db(ui)[lbn] + boff; - lbn -= UFS_NDADDR; - if (lbn < addr_per_block) { - i = ufsi_ib(ui)[0]; - if (!i) - return 0; - return block_bmap (fs, i, lbn) + boff; - } - lbn -= addr_per_block; - if (lbn < (1 << (addr_per_block_bits * 2))) { - i = ufsi_ib(ui)[1]; - if (!i) return 0; - i = block_bmap (fs, i, lbn >> addr_per_block_bits); - if (!i) return 0; - return block_bmap (fs, i, lbn & (addr_per_block-1)) + boff; - } - lbn -= (1 << (addr_per_block_bits * 2)); - i = ufsi_ib(ui)[2]; - if (!i) return 0; - i = block_bmap (fs, i, lbn >> (addr_per_block_bits * 2)); - if (!i) return 0; - i = block_bmap (fs, i, (lbn >> addr_per_block_bits) & (addr_per_block - 1)); - if (!i) return 0; - return block_bmap (fs, i, lbn & (addr_per_block-1)) + boff; -} - -static int ufs_match (int len, const char *const name, struct ufs_direct * d) -{ - if (!d || len > UFS_MAXNAMLEN) return 0; - if (!len && (ufsd_namlen(d) == 1) && (d->d_name[0] == '.') && (d->d_name[1] == '\0')) - return 1; - if (len != ufsd_namlen(d)) return 0; - return !memcmp(name, d->d_name, len); -} - -static int ufs_lookup (ufs_filsys fs, ino_t dir, struct ufs_inode *dirui, - const char *name, int len, ino_t *result) -{ - unsigned long int lfragno, fragno; - struct ufs_direct * d; - char buffer [8192]; - struct ufs_superblock *sb = SUPUFS; - - for (lfragno = 0; lfragno < (dirui->ui_blocks)>>1; lfragno++) { - fragno = ufs_bmap(fs, dir, dirui, lfragno); - if (!fragno) return -1; - if (io_channel_read_blk (fs->io, fragno, -sb->fs_fsize, buffer)) { - printf ("Couldn't read directory\n"); - return -1; - } - d = (struct ufs_direct *)buffer; - while (((char *)d - buffer + d->d_reclen) <= sb->fs_fsize) { - if (!d->d_reclen || !ufsd_namlen(d)) break; - if (ufsd_namlen(d) == len && ufs_match(len, name, d)) { - *result = d->d_ino; - return 0; - } - d = (struct ufs_direct *)((char *)d + d->d_reclen); - } - } - return -1; -} - -static int link_count = 0; - -static int open_namei(ufs_filsys, const char *, ino_t *, ino_t); - -static int ufs_follow_link(ufs_filsys fs, ino_t dir, ino_t inode, - struct ufs_inode *ui, ino_t *res_inode) -{ - unsigned long int block; - int error; - char *link; - char buffer[1024]; - - if (!S_ISLNK(ui->ui_mode)) { - *res_inode = inode; - return 0; - } - if (link_count > 5) { - printf ("Symlink loop\n"); - return -1; /* Loop */ - } - if (ui->ui_blocks) { - /* read the link from disk */ - block = ufs_bmap(fs, inode, ui, 0); - - if (io_channel_read_blk (fs->io, block, -1024, buffer)) { - printf ("Couldn't readlink\n"); - return -1; - } - link = buffer; - } else { - /* fast symlink */ - link = (char *)&(ufsi_db(ui)[0]); - } - link_count++; - error = open_namei (fs, link, res_inode, dir); - link_count--; - return error; -} - -static int dir_namei(ufs_filsys fs, const char *pathname, int *namelen, - const char **name, ino_t base, ino_t *res_inode) -{ - char c; - const char *thisname; - int len; - struct ufs_inode ub; - ino_t inode; - - if ((c = *pathname) == '/') { - base = (ino_t)fs->private; - pathname++; - } - if (ufs_read_inode (fs, base, &ub)) return -1; - while (1) { - thisname = pathname; - for(len=0;(c = *(pathname++))&&(c != '/');len++); - if (!c) break; - if (ufs_lookup (fs, base, &ub, thisname, len, &inode)) return -1; - if (ufs_read_inode (fs, inode, &ub)) return -1; - if (ufs_follow_link (fs, base, inode, &ub, &base)) return -1; - if (base != inode && ufs_read_inode (fs, base, &ub)) return -1; - } - *name = thisname; - *namelen = len; - *res_inode = base; - return 0; -} - -static int open_namei(ufs_filsys fs, const char *pathname, - ino_t *res_inode, ino_t base) -{ - const char *basename; - int namelen; - ino_t dir, inode; - struct ufs_inode ub; - - if (dir_namei(fs, pathname, &namelen, &basename, base, &dir)) return -1; - if (!namelen) { /* special case: '/usr/' etc */ - *res_inode=dir; - return 0; - } - if (ufs_read_inode (fs, dir, &ub)) return -1; - if (ufs_lookup (fs, dir, &ub, basename, namelen, &inode)) return -1; - if (ufs_read_inode (fs, inode, &ub)) return -1; - if (ufs_follow_link (fs, dir, inode, &ub, &inode)) return -1; - *res_inode = inode; - return 0; -} - -int ufs_namei (ufs_filsys fs, ino_t root, ino_t cwd, char *filename, ino_t *inode) -{ - fs->private = (void *)root; - link_count = 0; - return open_namei (fs, filename, inode, cwd); -} - -void ufs_close(ufs_filsys fs) -{ - free (fs->io); - free (fs); -} - -int ufs_block_iterate(ufs_filsys fs, ino_t inode, - int (*func)(ufs_filsys, blk_t *, int, void *), - void *private) -{ - struct ufs_inode ub; - int i; - blk_t nr; - int frags; - struct ufs_superblock *sb = SUPUFS; - - if (ufs_read_inode (fs, inode, &ub)) return -1; - frags = (ufsi_size(&ub) + sb->fs_fsize - 1) / sb->fs_fsize; - for (i = 0; i < frags; i++) { - nr = ufs_bmap (fs, inode, &ub, i); - if (!nr) return -1; - switch ((*func) (fs, &nr, i, private)) { - case BLOCK_ABORT: - case BLOCK_ERROR: - return -1; - } - } - return 0; -} diff --git a/second/ufs.h b/second/ufs.h deleted file mode 100644 index 6f86824..0000000 --- a/second/ufs.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifdef __linux__ - -#include <features.h> -#ifdef __GLIBC__ -# define _LINUX_TIME_H -#endif -#include <linux/ufs_fs.h> -#else - -#include <non-linux/ufs_fs.h> - -#endif - -typedef ext2_filsys ufs_filsys; - -#ifdef UFS_CIGAM -/* Apparently new header */ -#define ufsi_size(x) ((unsigned int)((x)->ui_size)) -#define ufsi_db(x) ((unsigned int *)((x)->ui_u2.ui_addr.ui_db)) -#define ufsi_ib(x) ((unsigned int *)((x)->ui_u2.ui_addr.ui_ib)) -#define ufsd_namlen(x) ((unsigned char)((x)->d_u.d_44.d_namlen)) -#ifdef UFS_MINFREE -/* Apparently even newer header */ -#define ufs_superblock ufs_super_block -#define ufs_direct ufs_dir_entry -#endif -#else -#define ufsi_size(x) (((x)->ui_size.val[1])) -#define ufsi_db(x) ((unsigned int *)((x)->ui_db)) -#define ufsi_ib(x) ((unsigned int *)((x)->ui_ib)) -#define ufsd_namlen(x) ((unsigned char)((x)->d_namlen)) -#endif - -int ufs_open(char *device, io_manager io, ufs_filsys *fs); -int ufs_namei(ufs_filsys fs, ino_t root, ino_t cwd, char *filename, ino_t *inode); -void ufs_close(ufs_filsys fs); -int ufs_read_inode(ufs_filsys fs, ino_t inode, struct ufs_inode *ui); -int ufs_block_iterate(ufs_filsys, ino_t, - int (*)(ufs_filsys, blk_t *, int, void *), void *); |