direct-io.hg

changeset 12324:f54e29a3be1f

Add libfsimage, a C library for reading files from filesystem images.
Initial support is provided for Solaris UFS, ext2 (both using libext2fs
and not), and reiserfs.

Signed-off-by: John Levon <john.levon@sun.com>
author Tim Deegan <Tim.Deegan@xensource.com>
date Thu Nov 09 14:09:53 2006 +0000 (2006-11-09)
parents 8fc5abda5200
children 72579f0cdaf7
files tools/Makefile tools/libfsimage/Makefile tools/libfsimage/Rules.mk tools/libfsimage/check-libext2fs tools/libfsimage/common/Makefile tools/libfsimage/common/fsimage.c tools/libfsimage/common/fsimage.h tools/libfsimage/common/fsimage_grub.c tools/libfsimage/common/fsimage_grub.h tools/libfsimage/common/fsimage_plugin.c tools/libfsimage/common/fsimage_plugin.h tools/libfsimage/common/fsimage_priv.h tools/libfsimage/common/mapfile-GNU tools/libfsimage/common/mapfile-SunOS tools/libfsimage/ext2fs-lib/Makefile tools/libfsimage/ext2fs-lib/ext2fs-lib.c tools/libfsimage/ext2fs/Makefile tools/libfsimage/ext2fs/fsys_ext2fs.c tools/libfsimage/reiserfs/Makefile tools/libfsimage/reiserfs/fsys_reiserfs.c tools/libfsimage/ufs/Makefile tools/libfsimage/ufs/fsys_ufs.c tools/libfsimage/ufs/ufs.h
line diff
     1.1 --- a/tools/Makefile	Thu Nov 09 14:00:40 2006 +0000
     1.2 +++ b/tools/Makefile	Thu Nov 09 14:09:53 2006 +0000
     1.3 @@ -18,6 +18,7 @@ SUBDIRS-$(VTPM_TOOLS) += vtpm
     1.4  SUBDIRS-y += xenstat
     1.5  SUBDIRS-y += libaio
     1.6  SUBDIRS-y += blktap
     1.7 +SUBDIRS-y += libfsimage
     1.8  
     1.9  # These don't cross-compile
    1.10  ifeq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH))
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/libfsimage/Makefile	Thu Nov 09 14:09:53 2006 +0000
     2.3 @@ -0,0 +1,13 @@
     2.4 +XEN_ROOT = ../..
     2.5 +include $(XEN_ROOT)/tools/Rules.mk
     2.6 +
     2.7 +SUBDIRS-y = common ufs reiserfs
     2.8 +SUBDIRS-y += $(shell ./check-libext2fs)
     2.9 +
    2.10 +.PHONY: all
    2.11 +all install clean:
    2.12 +	@set -e; for subdir in $(SUBDIRS-y); do \
    2.13 +		$(MAKE) -C $$subdir $@; \
    2.14 +	done
    2.15 +
    2.16 +distclean: clean
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/libfsimage/Rules.mk	Thu Nov 09 14:09:53 2006 +0000
     3.3 @@ -0,0 +1,32 @@
     3.4 +include $(XEN_ROOT)/tools/Rules.mk
     3.5 +
     3.6 +DEPS = .*.d
     3.7 +
     3.8 +CFLAGS += -I$(XEN_ROOT)/tools/libfsimage/common/ -Werror -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -Wp,-MD,.$(@F).d
     3.9 +LDFLAGS += -L../common/
    3.10 +
    3.11 +PIC_OBJS := $(patsubst %.c,%.opic,$(LIB_SRCS-y))
    3.12 +
    3.13 +FSDIR-$(CONFIG_Linux) = $(LIBDIR)/fs/$(FS)
    3.14 +FSDIR-$(CONFIG_SunOS)-x86_64 = lib/fs/$(FS)/64
    3.15 +FSDIR-$(CONFIG_SunOS)-x86_32 = lib/fs/$(FS)/
    3.16 +FSDIR-$(CONFIG_SunOS) = $(FSDIR-$(CONFIG_SunOS)-$(XEN_TARGET_ARCH))
    3.17 +FSDIR = $(FSDIR-y)
    3.18 +
    3.19 +FSLIB = fsimage.so
    3.20 +
    3.21 +.PHONY: fs-all
    3.22 +fs-all: $(FSLIB)
    3.23 +
    3.24 +.PHONY: fs-install
    3.25 +fs-install: fs-all
    3.26 +	$(INSTALL_DIR) $(DESTDIR)/usr/$(FSDIR)
    3.27 +	$(INSTALL_PROG) $(FSLIB) $(DESTDIR)/usr/$(FSDIR)
    3.28 +
    3.29 +$(FSLIB): $(PIC_OBJS)
    3.30 +	$(CC) $(CFLAGS) $(LDFLAGS) $(SHLIB_CFLAGS) -o $@ $^ -lfsimage $(FS_LIBDEPS)
    3.31 +
    3.32 +clean distclean:
    3.33 +	rm -f $(PIC_OBJS) $(FSLIB)
    3.34 +
    3.35 +-include $(DEPS)
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/libfsimage/check-libext2fs	Thu Nov 09 14:09:53 2006 +0000
     4.3 @@ -0,0 +1,21 @@
     4.4 +#!/bin/bash
     4.5 +
     4.6 +cat >ext2-test.c <<EOF
     4.7 +#include <ext2fs/ext2fs.h>
     4.8 +
     4.9 +int main()
    4.10 +{
    4.11 +	ext2fs_open2;
    4.12 +}
    4.13 +EOF
    4.14 +
    4.15 +gcc -o ext2-test ext2-test.c -lext2fs >/dev/null 2>&1
    4.16 +if [ $? = 0 ]; then
    4.17 +	echo ext2fs-lib
    4.18 +else
    4.19 +	echo ext2fs
    4.20 +fi
    4.21 +
    4.22 +rm -f ext2-test ext2-test.c
    4.23 +
    4.24 +exit 0
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/libfsimage/common/Makefile	Thu Nov 09 14:09:53 2006 +0000
     5.3 @@ -0,0 +1,46 @@
     5.4 +XEN_ROOT = ../../..
     5.5 +include $(XEN_ROOT)/tools/Rules.mk
     5.6 +
     5.7 +MAJOR = 1.0
     5.8 +MINOR = 0
     5.9 +
    5.10 +CFLAGS += -Werror -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -Wp,-MD,.$(@F).d
    5.11 +DEPS = .*.d
    5.12 +
    5.13 +LDFLAGS-$(CONFIG_SunOS) = -Wl,-M -Wl,mapfile-SunOS
    5.14 +LDFLAGS-$(CONFIG_Linux) = -Wl,mapfile-GNU
    5.15 +LDFLAGS = $(LDFLAGS-y)
    5.16 +
    5.17 +LIB_SRCS-y = fsimage.c fsimage_plugin.c fsimage_grub.c
    5.18 +
    5.19 +PIC_OBJS := $(patsubst %.c,%.opic,$(LIB_SRCS-y))
    5.20 +
    5.21 +LIB = libfsimage.so libfsimage.so.$(MAJOR) libfsimage.so.$(MAJOR).$(MINOR)
    5.22 +
    5.23 +.PHONY: all
    5.24 +all: $(LIB)
    5.25 +
    5.26 +.PHONY: install
    5.27 +install: all
    5.28 +	[ -d $(DESTDIR)/usr/$(LIBDIR) ] || $(INSTALL_DIR) $(DESTDIR)/usr/$(LIBDIR)
    5.29 +	[ -d $(DESTDIR)/usr/include ] || $(INSTALL_DIR) $(DESTDIR)/usr/include
    5.30 +	$(INSTALL_PROG) libfsimage.so.$(MAJOR).$(MINOR) $(DESTDIR)/usr/$(LIBDIR)
    5.31 +	ln -sf libfsimage.so.$(MAJOR).$(MINOR) $(DESTDIR)/usr/$(LIBDIR)/libfsimage.so.$(MAJOR)
    5.32 +	ln -sf libfsimage.so.$(MAJOR) $(DESTDIR)/usr/$(LIBDIR)/libfsimage.so
    5.33 +	$(INSTALL_DATA) fsimage.h $(DESTDIR)/usr/include
    5.34 +	$(INSTALL_DATA) fsimage_plugin.h $(DESTDIR)/usr/include
    5.35 +	$(INSTALL_DATA) fsimage_grub.h $(DESTDIR)/usr/include
    5.36 +
    5.37 +clean distclean:
    5.38 +	rm -f $(PIC_OBJS) $(LIB)
    5.39 +
    5.40 +libfsimage.so: libfsimage.so.$(MAJOR)
    5.41 +	ln -sf $< $@
    5.42 +libfsimage.so.$(MAJOR): libfsimage.so.$(MAJOR).$(MINOR)
    5.43 +	ln -sf $< $@
    5.44 +
    5.45 +libfsimage.so.$(MAJOR).$(MINOR): $(PIC_OBJS)
    5.46 +	$(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libfsimage.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $^ -lpthread
    5.47 +
    5.48 +-include $(DEPS)
    5.49 +
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/libfsimage/common/fsimage.c	Thu Nov 09 14:09:53 2006 +0000
     6.3 @@ -0,0 +1,140 @@
     6.4 +/*
     6.5 + * Permission is hereby granted, free of charge, to any person obtaining a copy
     6.6 + * of this software and associated documentation files (the "Software"), to
     6.7 + * deal in the Software without restriction, including without limitation the
     6.8 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
     6.9 + * sell copies of the Software, and to permit persons to whom the Software is
    6.10 + * furnished to do so, subject to the following conditions:
    6.11 + * 
    6.12 + * The above copyright notice and this permission notice shall be included in
    6.13 + * all copies or substantial portions of the Software.
    6.14 + * 
    6.15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    6.16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    6.17 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    6.18 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    6.19 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    6.20 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    6.21 + * DEALINGS IN THE SOFTWARE.
    6.22 + *
    6.23 + * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
    6.24 + * Use is subject to license terms.
    6.25 + */
    6.26 +
    6.27 +#include <sys/stat.h>
    6.28 +#include <sys/types.h>
    6.29 +#include <strings.h>
    6.30 +#include <unistd.h>
    6.31 +#include <stdlib.h>
    6.32 +#include <stdio.h>
    6.33 +#include <fcntl.h>
    6.34 +#include <errno.h>
    6.35 +#include <pthread.h>
    6.36 +
    6.37 +#include "fsimage_plugin.h"
    6.38 +#include "fsimage_priv.h"
    6.39 +
    6.40 +static pthread_mutex_t fsi_lock = PTHREAD_MUTEX_INITIALIZER;
    6.41 +
    6.42 +fsi_t *fsi_open_fsimage(const char *path, uint64_t off)
    6.43 +{
    6.44 +	fsi_t *fsi = NULL;
    6.45 +	int fd;
    6.46 +	int err;
    6.47 +
    6.48 +	if ((fd = open(path, O_RDONLY)) == -1)
    6.49 +		goto fail;
    6.50 +
    6.51 +	if ((fsi = malloc(sizeof(*fsi))) == NULL)
    6.52 +		goto fail;
    6.53 +
    6.54 +	fsi->f_fd = fd;
    6.55 +	fsi->f_off = off;
    6.56 +	fsi->f_data = NULL;
    6.57 +
    6.58 +	pthread_mutex_lock(&fsi_lock);
    6.59 +	err = find_plugin(fsi, path);
    6.60 +	pthread_mutex_unlock(&fsi_lock);
    6.61 +	if (err != 0)
    6.62 +		goto fail;
    6.63 +
    6.64 +	return (fsi);
    6.65 +
    6.66 +fail:
    6.67 +	err = errno;
    6.68 +	if (fd != -1)
    6.69 +		(void) close(fd);
    6.70 +	free(fsi);
    6.71 +	errno = err;
    6.72 +	return (NULL);
    6.73 +}
    6.74 +
    6.75 +void fsi_close_fsimage(fsi_t *fsi)
    6.76 +{
    6.77 +	pthread_mutex_lock(&fsi_lock);
    6.78 +	fsip_fs_free(fsi);
    6.79 +	pthread_mutex_unlock(&fsi_lock);
    6.80 +}
    6.81 +
    6.82 +int fsi_file_exists(fsi_t *fsi, const char *path)
    6.83 +{
    6.84 +	fsi_file_t *ffi;
    6.85 +
    6.86 +	if ((ffi = fsi_open_file(fsi, path)) == NULL)
    6.87 +		return (0);
    6.88 +
    6.89 +	fsi_close_file(ffi);
    6.90 +	return (1);
    6.91 +}
    6.92 +
    6.93 +fsi_file_t *fsi_open_file(fsi_t *fsi, const char *path)
    6.94 +{
    6.95 +	fsi_plugin_ops_t *ops;
    6.96 +	fsi_file_t *ffi;
    6.97 +
    6.98 +	pthread_mutex_lock(&fsi_lock);
    6.99 +	ops = fsi->f_plugin->fp_ops;
   6.100 +	ffi = ops->fpo_open(fsi, path);
   6.101 +	pthread_mutex_unlock(&fsi_lock);
   6.102 +
   6.103 +	return (ffi);
   6.104 +}
   6.105 +
   6.106 +int fsi_close_file(fsi_file_t *ffi)
   6.107 +{
   6.108 +	fsi_plugin_ops_t *ops;
   6.109 +	int err;
   6.110 + 
   6.111 +	pthread_mutex_lock(&fsi_lock);
   6.112 +	ops = ffi->ff_fsi->f_plugin->fp_ops;
   6.113 +	err = ops->fpo_close(ffi);
   6.114 +	pthread_mutex_unlock(&fsi_lock);
   6.115 +
   6.116 +	return (err);
   6.117 +}
   6.118 +
   6.119 +ssize_t fsi_read_file(fsi_file_t *ffi, void *buf, size_t nbytes)
   6.120 +{
   6.121 +	fsi_plugin_ops_t *ops;
   6.122 +	ssize_t ret;
   6.123 + 
   6.124 +	pthread_mutex_lock(&fsi_lock);
   6.125 +	ops = ffi->ff_fsi->f_plugin->fp_ops;
   6.126 +	ret = ops->fpo_read(ffi, buf, nbytes);
   6.127 +	pthread_mutex_unlock(&fsi_lock);
   6.128 +
   6.129 +	return (ret);
   6.130 +}
   6.131 +
   6.132 +ssize_t fsi_pread_file(fsi_file_t *ffi, void *buf, size_t nbytes, uint64_t off)
   6.133 +{
   6.134 +	fsi_plugin_ops_t *ops;
   6.135 +	ssize_t ret;
   6.136 + 
   6.137 +	pthread_mutex_lock(&fsi_lock);
   6.138 +	ops = ffi->ff_fsi->f_plugin->fp_ops;
   6.139 +	ret = ops->fpo_pread(ffi, buf, nbytes, off);
   6.140 +	pthread_mutex_unlock(&fsi_lock);
   6.141 +
   6.142 +	return (ret);
   6.143 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/libfsimage/common/fsimage.h	Thu Nov 09 14:09:53 2006 +0000
     7.3 @@ -0,0 +1,52 @@
     7.4 +/*
     7.5 + * Permission is hereby granted, free of charge, to any person obtaining a copy
     7.6 + * of this software and associated documentation files (the "Software"), to
     7.7 + * deal in the Software without restriction, including without limitation the
     7.8 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
     7.9 + * sell copies of the Software, and to permit persons to whom the Software is
    7.10 + * furnished to do so, subject to the following conditions:
    7.11 + * 
    7.12 + * The above copyright notice and this permission notice shall be included in
    7.13 + * all copies or substantial portions of the Software.
    7.14 + * 
    7.15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    7.16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    7.17 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    7.18 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    7.19 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    7.20 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    7.21 + * DEALINGS IN THE SOFTWARE.
    7.22 + *
    7.23 + * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
    7.24 + * Use is subject to license terms.
    7.25 + */
    7.26 +
    7.27 +#ifndef _FSIMAGE_H
    7.28 +#define	_FSIMAGE_H
    7.29 +
    7.30 +#ifdef __cplusplus
    7.31 +extern C {
    7.32 +#endif
    7.33 +
    7.34 +#include <sys/types.h>
    7.35 +#include <stdint.h>
    7.36 +#include <unistd.h>
    7.37 +
    7.38 +typedef struct fsi fsi_t;
    7.39 +typedef struct fsi_file fsi_file_t;
    7.40 +
    7.41 +fsi_t *fsi_open_fsimage(const char *, uint64_t);
    7.42 +void fsi_close_fsimage(fsi_t *);
    7.43 +
    7.44 +int fsi_file_exists(fsi_t *, const char *);
    7.45 +fsi_file_t *fsi_open_file(fsi_t *, const char *);
    7.46 +int fsi_close_file(fsi_file_t *);
    7.47 +
    7.48 +ssize_t fsi_read_file(fsi_file_t *, void *, size_t);
    7.49 +ssize_t fsi_pread_file(fsi_file_t *, void *, size_t, uint64_t);
    7.50 +
    7.51 +#ifdef __cplusplus
    7.52 +};
    7.53 +#endif
    7.54 +
    7.55 +#endif /* _FSIMAGE_H */
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/libfsimage/common/fsimage_grub.c	Thu Nov 09 14:09:53 2006 +0000
     8.3 @@ -0,0 +1,277 @@
     8.4 +/*
     8.5 + * Permission is hereby granted, free of charge, to any person obtaining a copy
     8.6 + * of this software and associated documentation files (the "Software"), to
     8.7 + * deal in the Software without restriction, including without limitation the
     8.8 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
     8.9 + * sell copies of the Software, and to permit persons to whom the Software is
    8.10 + * furnished to do so, subject to the following conditions:
    8.11 + * 
    8.12 + * The above copyright notice and this permission notice shall be included in
    8.13 + * all copies or substantial portions of the Software.
    8.14 + * 
    8.15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    8.16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    8.17 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    8.18 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    8.19 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    8.20 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    8.21 + * DEALINGS IN THE SOFTWARE.
    8.22 + *
    8.23 + * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
    8.24 + * Use is subject to license terms.
    8.25 + */
    8.26 +
    8.27 +#ifndef __sun__
    8.28 +#define	_XOPEN_SOURCE 500
    8.29 +#endif
    8.30 +#include <stdlib.h>
    8.31 +#include <strings.h>
    8.32 +#include <errno.h>
    8.33 +
    8.34 +#include "fsimage_grub.h"
    8.35 +#include "fsimage_priv.h"
    8.36 +
    8.37 +static char *disk_read_junk;
    8.38 +
    8.39 +typedef struct fsig_data {
    8.40 +	char fd_buf[FSYS_BUFLEN];
    8.41 +} fsig_data_t;
    8.42 +
    8.43 +typedef struct fsig_file_data {
    8.44 +	char ffd_buf[FSYS_BUFLEN];
    8.45 +	uint64_t ffd_curpos;
    8.46 +	uint64_t ffd_filepos;
    8.47 +	uint64_t ffd_filemax;
    8.48 +	int ffd_int1;
    8.49 +	int ffd_int2;
    8.50 +	int ffd_errnum;
    8.51 +} fsig_file_data_t;
    8.52 +
    8.53 +fsi_file_t *
    8.54 +fsig_file_alloc(fsi_t *fsi)
    8.55 +{
    8.56 +	fsi_file_t *ffi;
    8.57 +	fsig_file_data_t *data = malloc(sizeof (fsig_file_data_t));
    8.58 +
    8.59 +	if (data == NULL)
    8.60 +		return (NULL);
    8.61 +
    8.62 +	bzero(data, sizeof (fsig_file_data_t));
    8.63 +	bcopy(fsig_fs_buf(fsi), data->ffd_buf, FSYS_BUFLEN);
    8.64 +
    8.65 +	if ((ffi = fsip_file_alloc(fsi, data)) == NULL) {
    8.66 +		free(data);
    8.67 +		return (NULL);
    8.68 +	}
    8.69 +
    8.70 +	return (ffi);
    8.71 +}
    8.72 +
    8.73 +void *
    8.74 +fsig_fs_buf(fsi_t *fsi)
    8.75 +{
    8.76 +	fsig_data_t *data = fsip_fs_data(fsi);
    8.77 +	return ((void *)data->fd_buf);
    8.78 +}
    8.79 +
    8.80 +void *
    8.81 +fsig_file_buf(fsi_file_t *ffi)
    8.82 +{
    8.83 +	fsig_file_data_t *data = fsip_file_data(ffi);
    8.84 +	return ((void *)data->ffd_buf);
    8.85 +}
    8.86 +
    8.87 +uint64_t *
    8.88 +fsig_filepos(fsi_file_t *ffi)
    8.89 +{
    8.90 +	fsig_file_data_t *data = fsip_file_data(ffi);
    8.91 +	return (&data->ffd_filepos);
    8.92 +}
    8.93 +
    8.94 +uint64_t *
    8.95 +fsig_filemax(fsi_file_t *ffi)
    8.96 +{
    8.97 +	fsig_file_data_t *data = fsip_file_data(ffi);
    8.98 +	return (&data->ffd_filemax);
    8.99 +}
   8.100 +
   8.101 +int *
   8.102 +fsig_int1(fsi_file_t *ffi)
   8.103 +{
   8.104 +	fsig_file_data_t *data = fsip_file_data(ffi);
   8.105 +	return (&data->ffd_int1);
   8.106 +}
   8.107 +
   8.108 +int *
   8.109 +fsig_int2(fsi_file_t *ffi)
   8.110 +{
   8.111 +	fsig_file_data_t *data = fsip_file_data(ffi);
   8.112 +	return (&data->ffd_int2);
   8.113 +}
   8.114 +
   8.115 +int *
   8.116 +fsig_errnum(fsi_file_t *ffi)
   8.117 +{
   8.118 +	fsig_file_data_t *data = fsip_file_data(ffi);
   8.119 +	return (&data->ffd_errnum);
   8.120 +}
   8.121 +
   8.122 +char **
   8.123 +fsig_disk_read_junk(void)
   8.124 +{
   8.125 +	return (&disk_read_junk);
   8.126 +}
   8.127 +
   8.128 +int
   8.129 +fsig_devread(fsi_file_t *ffi, unsigned int sector, unsigned int offset,
   8.130 +    unsigned int bufsize, char *buf)
   8.131 +{
   8.132 +	uint64_t off = ffi->ff_fsi->f_off + ((uint64_t)(sector * 512)) + offset;
   8.133 +	ssize_t bytes_read = 0;
   8.134 +
   8.135 +	while (bufsize) {
   8.136 +		ssize_t ret = pread(ffi->ff_fsi->f_fd, buf + bytes_read,
   8.137 +		    bufsize, (off_t)off);
   8.138 +		if (ret == -1)
   8.139 +			return (0);
   8.140 +		if (ret == 0)
   8.141 +			return (0);
   8.142 +
   8.143 +		bytes_read += ret;
   8.144 +		bufsize -= ret;
   8.145 +	}
   8.146 +
   8.147 +	return (1);
   8.148 +}
   8.149 +
   8.150 +int
   8.151 +fsig_substring(const char *s1, const char *s2)
   8.152 +{
   8.153 +	while (*s1 == *s2) {
   8.154 +		if (*s1 == '\0')
   8.155 +			return (0);
   8.156 +		s1++;
   8.157 +		s2++;
   8.158 +	}
   8.159 +
   8.160 +	if (*s1 == '\0')
   8.161 +		return (-1);
   8.162 +
   8.163 +	return (1);
   8.164 +}
   8.165 +
   8.166 +static int
   8.167 +fsig_mount(fsi_t *fsi, const char *path)
   8.168 +{
   8.169 +	fsig_plugin_ops_t *ops = fsi->f_plugin->fp_data;
   8.170 +	fsi_file_t *ffi;
   8.171 +	fsi->f_data = malloc(sizeof (fsig_data_t));
   8.172 +
   8.173 +	if (fsi->f_data == NULL)
   8.174 +		return (-1);
   8.175 +
   8.176 +	if ((ffi = fsig_file_alloc(fsi)) == NULL) {
   8.177 +		free(fsi->f_data);
   8.178 +		fsi->f_data = NULL;
   8.179 +		return (-1);
   8.180 +	}
   8.181 +
   8.182 +	bzero(fsi->f_data, sizeof (fsig_data_t));
   8.183 +
   8.184 +	if (!ops->fpo_mount(ffi)) {
   8.185 +		fsip_file_free(ffi);
   8.186 +		free(fsi->f_data);
   8.187 +		fsi->f_data = NULL;
   8.188 +		return (-1);
   8.189 +	}
   8.190 +
   8.191 +	bcopy(fsig_file_buf(ffi), fsig_fs_buf(fsi), FSYS_BUFLEN);
   8.192 +	fsip_file_free(ffi);
   8.193 +	return (0);
   8.194 +}
   8.195 +
   8.196 +static int
   8.197 +fsig_umount(fsi_t *fsi)
   8.198 +{
   8.199 +	fsip_fs_free(fsi);
   8.200 +	return (0);
   8.201 +}
   8.202 +
   8.203 +static fsi_file_t *
   8.204 +fsig_open(fsi_t *fsi, const char *name)
   8.205 +{
   8.206 +	fsig_plugin_ops_t *ops = fsi->f_plugin->fp_data;
   8.207 +	char *path = strdup(name);
   8.208 +	fsi_file_t *ffi = NULL;
   8.209 +
   8.210 +	if (path == NULL || (ffi = fsig_file_alloc(fsi)) == NULL)
   8.211 +		goto out;
   8.212 +
   8.213 +	if (ops->fpo_dir(ffi, path) == 0) {
   8.214 +		fsip_file_free(ffi);
   8.215 +		ffi = NULL;
   8.216 +		errno = ENOENT;
   8.217 +	}
   8.218 +
   8.219 +out:
   8.220 +	free(path);
   8.221 +	return (ffi);
   8.222 +}
   8.223 +
   8.224 +static ssize_t
   8.225 +fsig_pread(fsi_file_t *ffi, void *buf, size_t nbytes, uint64_t off)
   8.226 +{
   8.227 +	fsig_plugin_ops_t *ops = ffi->ff_fsi->f_plugin->fp_data;
   8.228 +	fsig_file_data_t *data = fsip_file_data(ffi);
   8.229 +
   8.230 +	data->ffd_filepos = off;
   8.231 +
   8.232 +	if (data->ffd_filepos >= data->ffd_filemax)
   8.233 +		return (0);
   8.234 +
   8.235 +	/* FIXME: check */
   8.236 +	if (data->ffd_filepos + nbytes > data->ffd_filemax)
   8.237 +		nbytes = data->ffd_filemax - data->ffd_filepos;
   8.238 +
   8.239 +	errnum = 0;
   8.240 +	return (ops->fpo_read(ffi, buf, nbytes));
   8.241 +}
   8.242 +
   8.243 +static ssize_t
   8.244 +fsig_read(fsi_file_t *ffi, void *buf, size_t nbytes)
   8.245 +{
   8.246 +	fsig_file_data_t *data = fsip_file_data(ffi);
   8.247 +	ssize_t ret;
   8.248 +
   8.249 +	ret = fsig_pread(ffi, buf, nbytes, data->ffd_curpos);
   8.250 +	data->ffd_curpos = data->ffd_filepos;
   8.251 +	return (ret);
   8.252 +}
   8.253 +
   8.254 +static int
   8.255 +fsig_close(fsi_file_t *ffi)
   8.256 +{
   8.257 +	fsip_file_free(ffi);
   8.258 +	return (0);
   8.259 +}
   8.260 +
   8.261 +static fsi_plugin_ops_t fsig_grub_ops = {
   8.262 +	.fpo_version = FSIMAGE_PLUGIN_VERSION,
   8.263 +	.fpo_mount = fsig_mount,
   8.264 +	.fpo_umount = fsig_umount,
   8.265 +	.fpo_open = fsig_open,
   8.266 +	.fpo_read = fsig_read,
   8.267 +	.fpo_pread = fsig_pread,
   8.268 +	.fpo_close = fsig_close
   8.269 +};
   8.270 +
   8.271 +fsi_plugin_ops_t *
   8.272 +fsig_init(fsi_plugin_t *plugin, fsig_plugin_ops_t *ops)
   8.273 +{
   8.274 +	if (ops->fpo_version > FSIMAGE_PLUGIN_VERSION)
   8.275 +		return (NULL);
   8.276 +
   8.277 +	plugin->fp_data = ops;
   8.278 +
   8.279 +	return (&fsig_grub_ops);
   8.280 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/libfsimage/common/fsimage_grub.h	Thu Nov 09 14:09:53 2006 +0000
     9.3 @@ -0,0 +1,92 @@
     9.4 +/*
     9.5 + * Permission is hereby granted, free of charge, to any person obtaining a copy
     9.6 + * of this software and associated documentation files (the "Software"), to
     9.7 + * deal in the Software without restriction, including without limitation the
     9.8 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
     9.9 + * sell copies of the Software, and to permit persons to whom the Software is
    9.10 + * furnished to do so, subject to the following conditions:
    9.11 + * 
    9.12 + * The above copyright notice and this permission notice shall be included in
    9.13 + * all copies or substantial portions of the Software.
    9.14 + * 
    9.15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    9.16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    9.17 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    9.18 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    9.19 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    9.20 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    9.21 + * DEALINGS IN THE SOFTWARE.
    9.22 + *
    9.23 + * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
    9.24 + * Use is subject to license terms.
    9.25 + */
    9.26 +
    9.27 +#ifndef _FSIMAGE_GRUB_H
    9.28 +#define	_FSIMAGE_GRUB_H
    9.29 +
    9.30 +#ifdef __cplusplus
    9.31 +extern C {
    9.32 +#endif
    9.33 +
    9.34 +#include <sys/types.h>
    9.35 +#include <string.h>
    9.36 +#include <stdlib.h>
    9.37 +#include <ctype.h>
    9.38 +
    9.39 +#include "fsimage.h"
    9.40 +#include "fsimage_plugin.h"
    9.41 +
    9.42 +typedef struct fsig_plugin_ops {
    9.43 +	int fpo_version;
    9.44 +	int (*fpo_mount)(fsi_file_t *);
    9.45 +	int (*fpo_dir)(fsi_file_t *, char *);
    9.46 +	int (*fpo_read)(fsi_file_t *, char *, int);
    9.47 +} fsig_plugin_ops_t;
    9.48 +
    9.49 +#define	STAGE1_5
    9.50 +#define FSYS_BUFLEN 0x8000
    9.51 +#define	SECTOR_BITS 9
    9.52 +#define	SECTOR_SIZE 0x200
    9.53 +
    9.54 +#define	FSYS_BUF (fsig_file_buf(ffi))
    9.55 +#define	filepos (*fsig_filepos(ffi))
    9.56 +#define	filemax (*fsig_filemax(ffi))
    9.57 +#define	devread fsig_devread
    9.58 +#define substring fsig_substring
    9.59 +#define	errnum (*fsig_errnum(ffi))
    9.60 +#define	disk_read_func (*fsig_disk_read_junk())
    9.61 +#define	disk_read_hook (*fsig_disk_read_junk())
    9.62 +#define	print_possibilities 0
    9.63 +
    9.64 +#define	grub_memset memset
    9.65 +#define	grub_memmove memmove
    9.66 +
    9.67 +extern char **fsig_disk_read_junk(void);
    9.68 +
    9.69 +#define	ERR_FSYS_CORRUPT 1
    9.70 +#define	ERR_SYMLINK_LOOP 1
    9.71 +#define	ERR_FILELENGTH 1
    9.72 +#define	ERR_BAD_FILETYPE 1
    9.73 +#define	ERR_BAD_FILETYPE 1
    9.74 +#define	ERR_FILE_NOT_FOUND 1
    9.75 +
    9.76 +fsi_plugin_ops_t *fsig_init(fsi_plugin_t *, fsig_plugin_ops_t *);
    9.77 +
    9.78 +int fsig_devread(fsi_file_t *, unsigned int, unsigned int, unsigned int, char *);
    9.79 +int fsig_substring(const char *, const char *);
    9.80 +
    9.81 +void *fsig_fs_buf(fsi_t *);
    9.82 +
    9.83 +fsi_file_t *fsig_file_alloc(fsi_t *);
    9.84 +void *fsig_file_buf(fsi_file_t *);
    9.85 +uint64_t *fsig_filepos(fsi_file_t *);
    9.86 +uint64_t *fsig_filemax(fsi_file_t *);
    9.87 +int *fsig_int1(fsi_file_t *);
    9.88 +int *fsig_int2(fsi_file_t *);
    9.89 +int *fsig_errnum(fsi_file_t *);
    9.90 +
    9.91 +#ifdef __cplusplus
    9.92 +};
    9.93 +#endif
    9.94 +
    9.95 +#endif /* _FSIMAGE_GRUB_H */
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/tools/libfsimage/common/fsimage_plugin.c	Thu Nov 09 14:09:53 2006 +0000
    10.3 @@ -0,0 +1,214 @@
    10.4 +/*
    10.5 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    10.6 + * of this software and associated documentation files (the "Software"), to
    10.7 + * deal in the Software without restriction, including without limitation the
    10.8 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    10.9 + * sell copies of the Software, and to permit persons to whom the Software is
   10.10 + * furnished to do so, subject to the following conditions:
   10.11 + * 
   10.12 + * The above copyright notice and this permission notice shall be included in
   10.13 + * all copies or substantial portions of the Software.
   10.14 + * 
   10.15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   10.16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   10.17 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   10.18 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   10.19 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   10.20 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   10.21 + * DEALINGS IN THE SOFTWARE.
   10.22 + *
   10.23 + * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
   10.24 + * Use is subject to license terms.
   10.25 + */
   10.26 +
   10.27 +#include <stdlib.h>
   10.28 +#include <stdio.h>
   10.29 +#include <strings.h>
   10.30 +#include <string.h>
   10.31 +#include <dirent.h>
   10.32 +#include <dlfcn.h>
   10.33 +#include <errno.h>
   10.34 +
   10.35 +#include "fsimage_plugin.h"
   10.36 +#include "fsimage_priv.h"
   10.37 +
   10.38 +static fsi_plugin_t *plugins;
   10.39 +
   10.40 +void
   10.41 +fsip_fs_set_data(fsi_t *fsi, void *data)
   10.42 +{
   10.43 +	fsi->f_data = data;
   10.44 +}
   10.45 +
   10.46 +void
   10.47 +fsip_fs_free(fsi_t *fsi)
   10.48 +{
   10.49 +	free(fsi->f_data);
   10.50 +	free(fsi);
   10.51 +}
   10.52 +
   10.53 +fsi_file_t *
   10.54 +fsip_file_alloc(fsi_t *fsi, void *data)
   10.55 +{
   10.56 +	fsi_file_t *ffi = malloc(sizeof (fsi_file_t));
   10.57 +	if (ffi == NULL)
   10.58 +		return (NULL);
   10.59 +
   10.60 +	bzero(ffi, sizeof (fsi_file_t));
   10.61 +
   10.62 +	ffi->ff_fsi = fsi;
   10.63 +	ffi->ff_data = data;
   10.64 +	return (ffi);
   10.65 +}
   10.66 +
   10.67 +void
   10.68 +fsip_file_free(fsi_file_t *ffi)
   10.69 +{
   10.70 +	free(ffi->ff_data);
   10.71 +	free(ffi);
   10.72 +}
   10.73 +
   10.74 +fsi_t *
   10.75 +fsip_fs(fsi_file_t *ffi)
   10.76 +{
   10.77 +	return (ffi->ff_fsi);
   10.78 +}
   10.79 +
   10.80 +uint64_t
   10.81 +fsip_fs_offset(fsi_t *fsi)
   10.82 +{
   10.83 +	return (fsi->f_off);
   10.84 +}
   10.85 +
   10.86 +void *
   10.87 +fsip_fs_data(fsi_t *fsi)
   10.88 +{
   10.89 +	return (fsi->f_data);
   10.90 +}
   10.91 +
   10.92 +void *
   10.93 +fsip_file_data(fsi_file_t *ffi)
   10.94 +{
   10.95 +	return (ffi->ff_data);
   10.96 +}
   10.97 +
   10.98 +static int init_plugin(const char *lib)
   10.99 +{
  10.100 +	fsi_plugin_init_t init;
  10.101 +	fsi_plugin_t *fp = malloc(sizeof (fsi_plugin_t));
  10.102 +
  10.103 +	if (fp == NULL)
  10.104 +		return (-1);
  10.105 +
  10.106 +	bzero(fp, sizeof (fsi_plugin_t));
  10.107 +
  10.108 +	if ((fp->fp_dlh = dlopen(lib, RTLD_LAZY | RTLD_LOCAL)) == NULL) {
  10.109 +		free(fp);
  10.110 +		return (0);
  10.111 +	}
  10.112 +
  10.113 +	init = dlsym(fp->fp_dlh, "fsi_init_plugin");
  10.114 +
  10.115 +	if (init == NULL)
  10.116 +		goto fail;
  10.117 +
  10.118 +	fp->fp_ops = init(FSIMAGE_PLUGIN_VERSION, fp, &fp->fp_name);
  10.119 +	if (fp->fp_ops == NULL ||
  10.120 +	    fp->fp_ops->fpo_version > FSIMAGE_PLUGIN_VERSION)
  10.121 +		goto fail;
  10.122 +
  10.123 +	fp->fp_next = plugins;
  10.124 +	plugins = fp;
  10.125 +
  10.126 +	return (0);
  10.127 +fail:
  10.128 +	(void) dlclose(fp->fp_dlh);
  10.129 +	free(fp);
  10.130 +	return (-1);
  10.131 +}
  10.132 +
  10.133 +static int load_plugins(void)
  10.134 +{
  10.135 +	const char *fsdir = getenv("FSIMAGE_FSDIR");
  10.136 +	const char *isadir = "";
  10.137 +	struct dirent *dp = NULL;
  10.138 +	struct dirent *dpp;
  10.139 +	DIR *dir = NULL;
  10.140 +	char *tmp = NULL;
  10.141 +	size_t name_max;
  10.142 +	int err;
  10.143 +	int ret = -1;
  10.144 +
  10.145 +#ifdef __sun__
  10.146 +	if (fsdir == NULL)
  10.147 +		fsdir = "/usr/lib/fs";
  10.148 +
  10.149 +	if (sizeof(void *) == 8)
  10.150 +		isadir = "64/";
  10.151 +#else
  10.152 +	if (fsdir == NULL) {
  10.153 +		if (sizeof(void *) == 8)
  10.154 +			fsdir = "/usr/lib64/fs";
  10.155 +		else
  10.156 +			fsdir = "/usr/lib/fs";
  10.157 +	}
  10.158 +#endif
  10.159 +
  10.160 +	if ((name_max = pathconf(fsdir, _PC_NAME_MAX)) == -1)
  10.161 +		goto fail;
  10.162 +
  10.163 +	if ((tmp = malloc(name_max + 1)) == NULL)
  10.164 +		goto fail;
  10.165 +
  10.166 +	if ((dp = malloc(sizeof (struct dirent) + name_max + 1)) == NULL)
  10.167 +		goto fail;
  10.168 +
  10.169 +	if ((dir = opendir(fsdir)) == NULL)
  10.170 +		goto fail;
  10.171 +
  10.172 +	bzero(dp, sizeof (struct dirent) + name_max + 1);
  10.173 +
  10.174 +	while (readdir_r(dir, dp, &dpp) == 0 && dpp != NULL) {
  10.175 +		if (strcmp(dpp->d_name, ".") == 0)
  10.176 +			continue;
  10.177 +		if (strcmp(dpp->d_name, "..") == 0)
  10.178 +			continue;
  10.179 +
  10.180 +		(void) snprintf(tmp, name_max, "%s/%s/%sfsimage.so", fsdir,
  10.181 +		    dpp->d_name, isadir);
  10.182 +
  10.183 +		if (init_plugin(tmp) != 0)
  10.184 +			goto fail;
  10.185 +	}
  10.186 +
  10.187 +	ret = 0;
  10.188 +
  10.189 +fail:
  10.190 +	err = errno;
  10.191 +	if (dir != NULL)
  10.192 +		(void) closedir(dir);
  10.193 +	free(tmp);
  10.194 +	free(dp);
  10.195 +	errno = err;
  10.196 +	return (ret);
  10.197 +}
  10.198 +
  10.199 +int find_plugin(fsi_t *fsi, const char *path)
  10.200 +{
  10.201 +	fsi_plugin_t *fp;
  10.202 +	int ret = 0;
  10.203 +
  10.204 +	if (plugins == NULL && (ret = load_plugins()) != 0)
  10.205 +		goto out;
  10.206 +
  10.207 +	for (fp = plugins; fp != NULL; fp = fp->fp_next) {
  10.208 +		fsi->f_plugin = fp;
  10.209 +		if (fp->fp_ops->fpo_mount(fsi, path) == 0)
  10.210 +			goto out;
  10.211 +	}
  10.212 +
  10.213 +	ret = -1;
  10.214 +	errno = ENOTSUP;
  10.215 +out:
  10.216 +	return (ret);
  10.217 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/tools/libfsimage/common/fsimage_plugin.h	Thu Nov 09 14:09:53 2006 +0000
    11.3 @@ -0,0 +1,65 @@
    11.4 +/*
    11.5 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    11.6 + * of this software and associated documentation files (the "Software"), to
    11.7 + * deal in the Software without restriction, including without limitation the
    11.8 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    11.9 + * sell copies of the Software, and to permit persons to whom the Software is
   11.10 + * furnished to do so, subject to the following conditions:
   11.11 + * 
   11.12 + * The above copyright notice and this permission notice shall be included in
   11.13 + * all copies or substantial portions of the Software.
   11.14 + * 
   11.15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   11.16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   11.17 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   11.18 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   11.19 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   11.20 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   11.21 + * DEALINGS IN THE SOFTWARE.
   11.22 + *
   11.23 + * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
   11.24 + * Use is subject to license terms.
   11.25 + */
   11.26 +
   11.27 +#ifndef _FSIMAGE_PLUGIN_H
   11.28 +#define	_FSIMAGE_PLUGIN_H
   11.29 +
   11.30 +#ifdef __cplusplus
   11.31 +extern C {
   11.32 +#endif
   11.33 +
   11.34 +#include <sys/types.h>
   11.35 +
   11.36 +#include "fsimage.h"
   11.37 +
   11.38 +#define	FSIMAGE_PLUGIN_VERSION 1
   11.39 +
   11.40 +typedef struct fsi_plugin fsi_plugin_t;
   11.41 +
   11.42 +typedef struct fsi_plugin_ops {
   11.43 +	int fpo_version;
   11.44 +	int (*fpo_mount)(fsi_t *, const char *);
   11.45 +	int (*fpo_umount)(fsi_t *);
   11.46 +	fsi_file_t *(*fpo_open)(fsi_t *, const char *);
   11.47 +	ssize_t (*fpo_read)(fsi_file_t *, void *, size_t);
   11.48 +	ssize_t (*fpo_pread)(fsi_file_t *, void *, size_t, uint64_t);
   11.49 +	int (*fpo_close)(fsi_file_t *);
   11.50 +} fsi_plugin_ops_t;
   11.51 +
   11.52 +typedef fsi_plugin_ops_t *
   11.53 +    (*fsi_plugin_init_t)(int, fsi_plugin_t *, const char **);
   11.54 +
   11.55 +void fsip_fs_set_data(fsi_t *, void *);
   11.56 +void fsip_fs_free(fsi_t *);
   11.57 +fsi_file_t *fsip_file_alloc(fsi_t *, void *);
   11.58 +void fsip_file_free(fsi_file_t *);
   11.59 +fsi_t * fsip_fs(fsi_file_t *ffi);
   11.60 +uint64_t fsip_fs_offset(fsi_t *fsi);
   11.61 +void *fsip_fs_data(fsi_t *);
   11.62 +void *fsip_file_data(fsi_file_t *);
   11.63 +
   11.64 +#ifdef __cplusplus
   11.65 +};
   11.66 +#endif
   11.67 +
   11.68 +#endif /* _FSIMAGE_PLUGIN_H */
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/tools/libfsimage/common/fsimage_priv.h	Thu Nov 09 14:09:53 2006 +0000
    12.3 @@ -0,0 +1,62 @@
    12.4 +/*
    12.5 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    12.6 + * of this software and associated documentation files (the "Software"), to
    12.7 + * deal in the Software without restriction, including without limitation the
    12.8 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    12.9 + * sell copies of the Software, and to permit persons to whom the Software is
   12.10 + * furnished to do so, subject to the following conditions:
   12.11 + * 
   12.12 + * The above copyright notice and this permission notice shall be included in
   12.13 + * all copies or substantial portions of the Software.
   12.14 + * 
   12.15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   12.16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   12.17 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   12.18 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   12.19 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   12.20 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   12.21 + * DEALINGS IN THE SOFTWARE.
   12.22 + *
   12.23 + * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
   12.24 + * Use is subject to license terms.
   12.25 + */
   12.26 +
   12.27 +#ifndef _FSIMAGE_PRIV_H
   12.28 +#define	_FSIMAGE_PRIV_H
   12.29 +
   12.30 +#ifdef __cplusplus
   12.31 +extern C {
   12.32 +#endif
   12.33 +
   12.34 +#include <sys/types.h>
   12.35 +
   12.36 +#include "fsimage.h"
   12.37 +#include "fsimage_plugin.h"
   12.38 +
   12.39 +struct fsi_plugin {
   12.40 +	const char *fp_name;
   12.41 +	void *fp_dlh;
   12.42 +	fsi_plugin_ops_t *fp_ops;
   12.43 +	struct fsi_plugin *fp_next;
   12.44 +	void *fp_data;
   12.45 +};
   12.46 +
   12.47 +struct fsi {
   12.48 +	int f_fd;
   12.49 +	uint64_t f_off;
   12.50 +	void *f_data;
   12.51 +	fsi_plugin_t *f_plugin;
   12.52 +};
   12.53 +
   12.54 +struct fsi_file {
   12.55 +	fsi_t *ff_fsi;
   12.56 +	void *ff_data;
   12.57 +};
   12.58 +
   12.59 +int find_plugin(fsi_t *, const char *);
   12.60 +
   12.61 +#ifdef __cplusplus
   12.62 +};
   12.63 +#endif
   12.64 +
   12.65 +#endif /* _FSIMAGE_PRIV_H */
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/tools/libfsimage/common/mapfile-GNU	Thu Nov 09 14:09:53 2006 +0000
    13.3 @@ -0,0 +1,37 @@
    13.4 +VERSION {
    13.5 +	libfsimage.so.1.1 {
    13.6 +		global:
    13.7 +			fsi_open_fsimage;
    13.8 +			fsi_close_fsimage;
    13.9 +			fsi_file_exists;
   13.10 +			fsi_open_file;
   13.11 +			fsi_close_file;
   13.12 +			fsi_read_file;
   13.13 +			fsi_pread_file;
   13.14 +	
   13.15 +			fsip_fs_set_data;
   13.16 +			fsip_fs_free;
   13.17 +			fsip_file_alloc;
   13.18 +			fsip_file_free;
   13.19 +			fsip_fs;
   13.20 +			fsip_fs_offset;
   13.21 +			fsip_fs_data;
   13.22 +			fsip_file_data;
   13.23 +	
   13.24 +			fsig_init;
   13.25 +			fsig_devread;
   13.26 +			fsig_substring;
   13.27 +			fsig_fs_buf;
   13.28 +			fsig_file_alloc;
   13.29 +			fsig_file_buf;
   13.30 +			fsig_filepos;
   13.31 +			fsig_filemax;
   13.32 +			fsig_int1;
   13.33 +			fsig_int2;
   13.34 +			fsig_errnum;
   13.35 +			fsig_disk_read_junk;
   13.36 +	
   13.37 +		local:
   13.38 +			*;
   13.39 +	};
   13.40 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/tools/libfsimage/common/mapfile-SunOS	Thu Nov 09 14:09:53 2006 +0000
    14.3 @@ -0,0 +1,35 @@
    14.4 +libfsimage.so.1.1 {
    14.5 +	global:
    14.6 +		fsi_open_fsimage;
    14.7 +		fsi_close_fsimage;
    14.8 +		fsi_file_exists;
    14.9 +		fsi_open_file;
   14.10 +		fsi_close_file;
   14.11 +		fsi_read_file;
   14.12 +		fsi_pread_file;
   14.13 +
   14.14 +		fsip_fs_set_data;
   14.15 +		fsip_fs_free;
   14.16 +		fsip_file_alloc;
   14.17 +		fsip_file_free;
   14.18 +		fsip_fs;
   14.19 +		fsip_fs_data;
   14.20 +		fsip_fs_offset;
   14.21 +		fsip_file_data;
   14.22 +
   14.23 +		fsig_init;
   14.24 +		fsig_devread;
   14.25 +		fsig_substring;
   14.26 +		fsig_fs_buf;
   14.27 +		fsig_file_alloc;
   14.28 +		fsig_file_buf;
   14.29 +		fsig_filepos;
   14.30 +		fsig_filemax;
   14.31 +		fsig_int1;
   14.32 +		fsig_int2;
   14.33 +		fsig_errnum;
   14.34 +		fsig_disk_read_junk;
   14.35 +
   14.36 +	local:
   14.37 +		*;
   14.38 +};
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/tools/libfsimage/ext2fs-lib/Makefile	Thu Nov 09 14:09:53 2006 +0000
    15.3 @@ -0,0 +1,15 @@
    15.4 +XEN_ROOT = ../../..
    15.5 +
    15.6 +LIB_SRCS-y = ext2fs-lib.c
    15.7 +
    15.8 +FS = ext2fs-lib
    15.9 +
   15.10 +FS_LIBDEPS = -lext2fs
   15.11 +
   15.12 +.PHONY: all
   15.13 +all: fs-all
   15.14 +
   15.15 +.PHONY: install
   15.16 +install: fs-install
   15.17 +
   15.18 +include $(XEN_ROOT)/tools/libfsimage/Rules.mk
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/tools/libfsimage/ext2fs-lib/ext2fs-lib.c	Thu Nov 09 14:09:53 2006 +0000
    16.3 @@ -0,0 +1,171 @@
    16.4 +/*
    16.5 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    16.6 + * of this software and associated documentation files (the "Software"), to
    16.7 + * deal in the Software without restriction, including without limitation the
    16.8 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    16.9 + * sell copies of the Software, and to permit persons to whom the Software is
   16.10 + * furnished to do so, subject to the following conditions:
   16.11 + * 
   16.12 + * The above copyright notice and this permission notice shall be included in
   16.13 + * all copies or substantial portions of the Software.
   16.14 + * 
   16.15 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   16.16 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   16.17 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   16.18 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   16.19 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   16.20 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   16.21 + * DEALINGS IN THE SOFTWARE.
   16.22 + *
   16.23 + * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
   16.24 + * Use is subject to license terms.
   16.25 + */
   16.26 +
   16.27 +#include <fsimage_plugin.h>
   16.28 +#include <ext2fs/ext2fs.h>
   16.29 +#include <errno.h>
   16.30 +
   16.31 +static int
   16.32 +ext2lib_mount(fsi_t *fsi, const char *name)
   16.33 +{
   16.34 +	int err;
   16.35 +	char opts[30] = "";
   16.36 +	ext2_filsys *fs;
   16.37 +	uint64_t offset = fsip_fs_offset(fsi);
   16.38 +
   16.39 +	if (offset)
   16.40 +		snprintf(opts, 29, "offset=%lld", offset);
   16.41 +
   16.42 +	fs = malloc(sizeof (*fs));
   16.43 +	if (fs == NULL)
   16.44 +		return (-1);
   16.45 +
   16.46 +	err = ext2fs_open2(name, opts, 0, 0, 0, unix_io_manager, fs);
   16.47 +
   16.48 +	if (err != 0) {
   16.49 +		free(fs);
   16.50 +		errno = EINVAL;
   16.51 +		return (-1);
   16.52 +	}
   16.53 +
   16.54 +	fsip_fs_set_data(fsi, fs);
   16.55 +	return (0);
   16.56 +}
   16.57 +
   16.58 +static int
   16.59 +ext2lib_umount(fsi_t *fsi)
   16.60 +{
   16.61 +	ext2_filsys *fs = fsip_fs_data(fsi);
   16.62 +	if (ext2fs_close(*fs) != 0) {
   16.63 +		errno = EINVAL;
   16.64 +		return (-1);
   16.65 +	}
   16.66 +	return (0);
   16.67 +}
   16.68 +
   16.69 +fsi_file_t *
   16.70 +ext2lib_open(fsi_t *fsi, const char *path)
   16.71 +{
   16.72 +	ext2_ino_t ino;
   16.73 +	ext2_filsys *fs = fsip_fs_data(fsi);
   16.74 +	ext2_file_t *f;
   16.75 +	fsi_file_t *file;
   16.76 +	int err;
   16.77 +
   16.78 +	err = ext2fs_namei_follow(*fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
   16.79 +	    path, &ino);
   16.80 +
   16.81 +	if (err != 0) {
   16.82 +		errno = ENOENT;
   16.83 +		return (NULL);
   16.84 +	}
   16.85 +
   16.86 +	f = malloc(sizeof (*f));
   16.87 +	if (f == NULL)
   16.88 +		return (NULL);
   16.89 +
   16.90 +	err = ext2fs_file_open(*fs, ino, 0, f);
   16.91 +
   16.92 +	if (err != 0) {
   16.93 +		free(f);
   16.94 +		errno = EINVAL;
   16.95 +		return (NULL);
   16.96 +	}
   16.97 +
   16.98 +	file = fsip_file_alloc(fsi, f);
   16.99 +	if (file == NULL)
  16.100 +		free(f);
  16.101 +	return (file);
  16.102 +}
  16.103 +
  16.104 +ssize_t
  16.105 +ext2lib_read(fsi_file_t *file, void *buf, size_t nbytes)
  16.106 +{
  16.107 +	ext2_file_t *f = fsip_file_data(file);
  16.108 +	unsigned int n;
  16.109 +	int err;
  16.110 +
  16.111 +	err = ext2fs_file_read(*f, buf, nbytes, &n);
  16.112 +	if (err != 0) {
  16.113 +		errno = EINVAL;
  16.114 +		return (-1);
  16.115 +	}
  16.116 +
  16.117 +	return (n);
  16.118 +}
  16.119 +
  16.120 +ssize_t
  16.121 +ext2lib_pread(fsi_file_t *file, void *buf, size_t nbytes, uint64_t off)
  16.122 +{
  16.123 +	ext2_file_t *f = fsip_file_data(file);
  16.124 +	uint64_t tmpoff;
  16.125 +	unsigned int n;
  16.126 +	int err;
  16.127 +
  16.128 +	if ((err = ext2fs_file_llseek(*f, 0, EXT2_SEEK_CUR, &tmpoff)) != 0) {
  16.129 +		errno = EINVAL;
  16.130 +		return (-1);
  16.131 +	}
  16.132 +
  16.133 +	if ((err = ext2fs_file_llseek(*f, off, EXT2_SEEK_SET, NULL)) != 0) {
  16.134 +		errno = EINVAL;
  16.135 +		return (-1);
  16.136 +	}
  16.137 +
  16.138 +	err = ext2fs_file_read(*f, buf, nbytes, &n);
  16.139 +
  16.140 +	ext2fs_file_llseek(*f, tmpoff, EXT2_SEEK_SET, NULL);
  16.141 +
  16.142 +	if (err != 0) {
  16.143 +		errno = EINVAL;
  16.144 +		return (-1);
  16.145 +	}
  16.146 +
  16.147 +	return (n);
  16.148 +}
  16.149 +
  16.150 +int
  16.151 +ext2lib_close(fsi_file_t *file)
  16.152 +{
  16.153 +	ext2_file_t *f = fsip_file_data(file);
  16.154 +	ext2fs_file_close(*f);
  16.155 +	free(f);
  16.156 +	return (0);
  16.157 +}
  16.158 +
  16.159 +fsi_plugin_ops_t *
  16.160 +fsi_init_plugin(int version, fsi_plugin_t *fp, const char **name)
  16.161 +{
  16.162 +	static fsi_plugin_ops_t ops = {
  16.163 +		FSIMAGE_PLUGIN_VERSION,
  16.164 +		.fpo_mount = ext2lib_mount,
  16.165 +		.fpo_umount = ext2lib_umount,
  16.166 +		.fpo_open = ext2lib_open,
  16.167 +		.fpo_read = ext2lib_read,
  16.168 +		.fpo_pread = ext2lib_pread,
  16.169 +		.fpo_close = ext2lib_close
  16.170 +	};
  16.171 +
  16.172 +	*name = "ext2fs-lib";
  16.173 +	return (&ops);
  16.174 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/tools/libfsimage/ext2fs/Makefile	Thu Nov 09 14:09:53 2006 +0000
    17.3 @@ -0,0 +1,13 @@
    17.4 +XEN_ROOT = ../../..
    17.5 +
    17.6 +LIB_SRCS-y = fsys_ext2fs.c
    17.7 +
    17.8 +FS = ext2fs
    17.9 +
   17.10 +.PHONY: all
   17.11 +all: fs-all
   17.12 +
   17.13 +.PHONY: install
   17.14 +install: fs-install
   17.15 +
   17.16 +include $(XEN_ROOT)/tools/libfsimage/Rules.mk
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/tools/libfsimage/ext2fs/fsys_ext2fs.c	Thu Nov 09 14:09:53 2006 +0000
    18.3 @@ -0,0 +1,804 @@
    18.4 +/*
    18.5 + *  GRUB  --  GRand Unified Bootloader
    18.6 + *  Copyright (C) 1999, 2001, 2003  Free Software Foundation, Inc.
    18.7 + *
    18.8 + *  This program is free software; you can redistribute it and/or modify
    18.9 + *  it under the terms of the GNU General Public License as published by
   18.10 + *  the Free Software Foundation; either version 2 of the License, or
   18.11 + *  (at your option) any later version.
   18.12 + *
   18.13 + *  This program is distributed in the hope that it will be useful,
   18.14 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   18.15 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18.16 + *  GNU General Public License for more details.
   18.17 + *
   18.18 + *  You should have received a copy of the GNU General Public License
   18.19 + *  along with this program; if not, write to the Free Software
   18.20 + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   18.21 + */
   18.22 +
   18.23 +#include <fsimage_grub.h>
   18.24 +
   18.25 +#define	mapblock1 (*fsig_int1(ffi))
   18.26 +#define	mapblock2 (*fsig_int2(ffi))
   18.27 +
   18.28 +/* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */
   18.29 +#define DEV_BSIZE 512
   18.30 +
   18.31 +/* include/linux/fs.h */
   18.32 +#define BLOCK_SIZE 1024		/* initial block size for superblock read */
   18.33 +/* made up, defaults to 1 but can be passed via mount_opts */
   18.34 +#define WHICH_SUPER 1
   18.35 +/* kind of from fs/ext2/super.c */
   18.36 +#define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE)	/* = 2 */
   18.37 +
   18.38 +/* include/asm-i386/types.h */
   18.39 +typedef __signed__ char __s8;
   18.40 +typedef unsigned char __u8;
   18.41 +typedef __signed__ short __s16;
   18.42 +typedef unsigned short __u16;
   18.43 +typedef __signed__ int __s32;
   18.44 +typedef unsigned int __u32;
   18.45 +
   18.46 +/*
   18.47 + * Constants relative to the data blocks, from ext2_fs.h
   18.48 + */
   18.49 +#define EXT2_NDIR_BLOCKS                12
   18.50 +#define EXT2_IND_BLOCK                  EXT2_NDIR_BLOCKS
   18.51 +#define EXT2_DIND_BLOCK                 (EXT2_IND_BLOCK + 1)
   18.52 +#define EXT2_TIND_BLOCK                 (EXT2_DIND_BLOCK + 1)
   18.53 +#define EXT2_N_BLOCKS                   (EXT2_TIND_BLOCK + 1)
   18.54 +
   18.55 +/* include/linux/ext2_fs.h */
   18.56 +struct ext2_super_block
   18.57 +  {
   18.58 +    __u32 s_inodes_count;	/* Inodes count */
   18.59 +    __u32 s_blocks_count;	/* Blocks count */
   18.60 +    __u32 s_r_blocks_count;	/* Reserved blocks count */
   18.61 +    __u32 s_free_blocks_count;	/* Free blocks count */
   18.62 +    __u32 s_free_inodes_count;	/* Free inodes count */
   18.63 +    __u32 s_first_data_block;	/* First Data Block */
   18.64 +    __u32 s_log_block_size;	/* Block size */
   18.65 +    __s32 s_log_frag_size;	/* Fragment size */
   18.66 +    __u32 s_blocks_per_group;	/* # Blocks per group */
   18.67 +    __u32 s_frags_per_group;	/* # Fragments per group */
   18.68 +    __u32 s_inodes_per_group;	/* # Inodes per group */
   18.69 +    __u32 s_mtime;		/* Mount time */
   18.70 +    __u32 s_wtime;		/* Write time */
   18.71 +    __u16 s_mnt_count;		/* Mount count */
   18.72 +    __s16 s_max_mnt_count;	/* Maximal mount count */
   18.73 +    __u16 s_magic;		/* Magic signature */
   18.74 +    __u16 s_state;		/* File system state */
   18.75 +    __u16 s_errors;		/* Behaviour when detecting errors */
   18.76 +    __u16 s_pad;
   18.77 +    __u32 s_lastcheck;		/* time of last check */
   18.78 +    __u32 s_checkinterval;	/* max. time between checks */
   18.79 +    __u32 s_creator_os;		/* OS */
   18.80 +    __u32 s_rev_level;		/* Revision level */
   18.81 +    __u16 s_def_resuid;		/* Default uid for reserved blocks */
   18.82 +    __u16 s_def_resgid;		/* Default gid for reserved blocks */
   18.83 +    __u32 s_reserved[235];	/* Padding to the end of the block */
   18.84 +  };
   18.85 +
   18.86 +struct ext2_group_desc
   18.87 +  {
   18.88 +    __u32 bg_block_bitmap;	/* Blocks bitmap block */
   18.89 +    __u32 bg_inode_bitmap;	/* Inodes bitmap block */
   18.90 +    __u32 bg_inode_table;	/* Inodes table block */
   18.91 +    __u16 bg_free_blocks_count;	/* Free blocks count */
   18.92 +    __u16 bg_free_inodes_count;	/* Free inodes count */
   18.93 +    __u16 bg_used_dirs_count;	/* Directories count */
   18.94 +    __u16 bg_pad;
   18.95 +    __u32 bg_reserved[3];
   18.96 +  };
   18.97 +
   18.98 +struct ext2_inode
   18.99 +  {
  18.100 +    __u16 i_mode;		/* File mode */
  18.101 +    __u16 i_uid;		/* Owner Uid */
  18.102 +    __u32 i_size;		/* 4: Size in bytes */
  18.103 +    __u32 i_atime;		/* Access time */
  18.104 +    __u32 i_ctime;		/* 12: Creation time */
  18.105 +    __u32 i_mtime;		/* Modification time */
  18.106 +    __u32 i_dtime;		/* 20: Deletion Time */
  18.107 +    __u16 i_gid;		/* Group Id */
  18.108 +    __u16 i_links_count;	/* 24: Links count */
  18.109 +    __u32 i_blocks;		/* Blocks count */
  18.110 +    __u32 i_flags;		/* 32: File flags */
  18.111 +    union
  18.112 +      {
  18.113 +	struct
  18.114 +	  {
  18.115 +	    __u32 l_i_reserved1;
  18.116 +	  }
  18.117 +	linux1;
  18.118 +	struct
  18.119 +	  {
  18.120 +	    __u32 h_i_translator;
  18.121 +	  }
  18.122 +	hurd1;
  18.123 +	struct
  18.124 +	  {
  18.125 +	    __u32 m_i_reserved1;
  18.126 +	  }
  18.127 +	masix1;
  18.128 +      }
  18.129 +    osd1;			/* OS dependent 1 */
  18.130 +    __u32 i_block[EXT2_N_BLOCKS];	/* 40: Pointers to blocks */
  18.131 +    __u32 i_version;		/* File version (for NFS) */
  18.132 +    __u32 i_file_acl;		/* File ACL */
  18.133 +    __u32 i_dir_acl;		/* Directory ACL */
  18.134 +    __u32 i_faddr;		/* Fragment address */
  18.135 +    union
  18.136 +      {
  18.137 +	struct
  18.138 +	  {
  18.139 +	    __u8 l_i_frag;	/* Fragment number */
  18.140 +	    __u8 l_i_fsize;	/* Fragment size */
  18.141 +	    __u16 i_pad1;
  18.142 +	    __u32 l_i_reserved2[2];
  18.143 +	  }
  18.144 +	linux2;
  18.145 +	struct
  18.146 +	  {
  18.147 +	    __u8 h_i_frag;	/* Fragment number */
  18.148 +	    __u8 h_i_fsize;	/* Fragment size */
  18.149 +	    __u16 h_i_mode_high;
  18.150 +	    __u16 h_i_uid_high;
  18.151 +	    __u16 h_i_gid_high;
  18.152 +	    __u32 h_i_author;
  18.153 +	  }
  18.154 +	hurd2;
  18.155 +	struct
  18.156 +	  {
  18.157 +	    __u8 m_i_frag;	/* Fragment number */
  18.158 +	    __u8 m_i_fsize;	/* Fragment size */
  18.159 +	    __u16 m_pad1;
  18.160 +	    __u32 m_i_reserved2[2];
  18.161 +	  }
  18.162 +	masix2;
  18.163 +      }
  18.164 +    osd2;			/* OS dependent 2 */
  18.165 +  };
  18.166 +
  18.167 +/* linux/limits.h */
  18.168 +#define NAME_MAX         255	/* # chars in a file name */
  18.169 +
  18.170 +/* linux/posix_type.h */
  18.171 +typedef long linux_off_t;
  18.172 +
  18.173 +/* linux/ext2fs.h */
  18.174 +#define EXT2_NAME_LEN 255
  18.175 +struct ext2_dir_entry
  18.176 +  {
  18.177 +    __u32 inode;		/* Inode number */
  18.178 +    __u16 rec_len;		/* Directory entry length */
  18.179 +    __u8 name_len;		/* Name length */
  18.180 +    __u8 file_type;
  18.181 +    char name[EXT2_NAME_LEN];	/* File name */
  18.182 +  };
  18.183 +
  18.184 +/* linux/ext2fs.h */
  18.185 +/*
  18.186 + * EXT2_DIR_PAD defines the directory entries boundaries
  18.187 + *
  18.188 + * NOTE: It must be a multiple of 4
  18.189 + */
  18.190 +#define EXT2_DIR_PAD                    4
  18.191 +#define EXT2_DIR_ROUND                  (EXT2_DIR_PAD - 1)
  18.192 +#define EXT2_DIR_REC_LEN(name_len)      (((name_len) + 8 + EXT2_DIR_ROUND) & \
  18.193 +                                         ~EXT2_DIR_ROUND)
  18.194 +
  18.195 +
  18.196 +/* ext2/super.c */
  18.197 +#define log2(n) ffz(~(n))
  18.198 +
  18.199 +#define EXT2_SUPER_MAGIC      0xEF53	/* include/linux/ext2_fs.h */
  18.200 +#define EXT2_ROOT_INO              2	/* include/linux/ext2_fs.h */
  18.201 +#define PATH_MAX                1024	/* include/linux/limits.h */
  18.202 +#define MAX_LINK_COUNT             5	/* number of symbolic links to follow */
  18.203 +
  18.204 +/* made up, these are pointers into FSYS_BUF */
  18.205 +/* read once, always stays there: */
  18.206 +#define SUPERBLOCK \
  18.207 +    ((struct ext2_super_block *)(FSYS_BUF))
  18.208 +#define GROUP_DESC \
  18.209 +    ((struct ext2_group_desc *) \
  18.210 +     ((char *)SUPERBLOCK + sizeof(struct ext2_super_block)))
  18.211 +#define INODE \
  18.212 +    ((struct ext2_inode *)((caddr_t)GROUP_DESC + EXT2_BLOCK_SIZE(SUPERBLOCK)))
  18.213 +#define DATABLOCK1 \
  18.214 +    ((char *)((caddr_t)INODE + sizeof(struct ext2_inode)))
  18.215 +#define DATABLOCK2 \
  18.216 +    ((char *)((caddr_t)DATABLOCK1 + EXT2_BLOCK_SIZE(SUPERBLOCK)))
  18.217 +
  18.218 +/* linux/ext2_fs.h */
  18.219 +#define EXT2_ADDR_PER_BLOCK(s)          (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
  18.220 +#define EXT2_ADDR_PER_BLOCK_BITS(s)		(log2(EXT2_ADDR_PER_BLOCK(s)))
  18.221 +
  18.222 +/* linux/ext2_fs.h */
  18.223 +#define EXT2_BLOCK_SIZE_BITS(s)        ((s)->s_log_block_size + 10)
  18.224 +/* kind of from ext2/super.c */
  18.225 +#define EXT2_BLOCK_SIZE(s)	(1 << EXT2_BLOCK_SIZE_BITS(s))
  18.226 +/* linux/ext2fs.h */
  18.227 +#define EXT2_DESC_PER_BLOCK(s) \
  18.228 +     (EXT2_BLOCK_SIZE(s) / sizeof (struct ext2_group_desc))
  18.229 +/* linux/stat.h */
  18.230 +#define S_IFMT  00170000
  18.231 +#define S_IFLNK  0120000
  18.232 +#define S_IFREG  0100000
  18.233 +#define S_IFDIR  0040000
  18.234 +#define S_ISLNK(m)	(((m) & S_IFMT) == S_IFLNK)
  18.235 +#define S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
  18.236 +#define S_ISDIR(m)      (((m) & S_IFMT) == S_IFDIR)
  18.237 +
  18.238 +/* include/asm-i386/bitops.h */
  18.239 +/*
  18.240 + * ffz = Find First Zero in word. Undefined if no zero exists,
  18.241 + * so code should check against ~0UL first..
  18.242 + */
  18.243 +#ifdef __amd64
  18.244 +#define BSF "bsfq"
  18.245 +#else
  18.246 +#define BSF "bsfl"
  18.247 +#endif
  18.248 +static __inline__ unsigned long
  18.249 +ffz (unsigned long word)
  18.250 +{
  18.251 +  __asm__ (BSF " %1,%0"
  18.252 +:	   "=r" (word)
  18.253 +:	   "r" (~word));
  18.254 +  return word;
  18.255 +}
  18.256 +
  18.257 +/* check filesystem types and read superblock into memory buffer */
  18.258 +int
  18.259 +ext2fs_mount (fsi_file_t *ffi)
  18.260 +{
  18.261 +  int retval = 1;
  18.262 +
  18.263 +  if (/*(((current_drive & 0x80) || (current_slice != 0))
  18.264 +       && (current_slice != PC_SLICE_TYPE_EXT2FS)
  18.265 +       && (current_slice != PC_SLICE_TYPE_LINUX_RAID)
  18.266 +       && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_EXT2FS))
  18.267 +       && (! IS_PC_SLICE_TYPE_BSD_WITH_FS (current_slice, FS_OTHER)))
  18.268 +      || part_length < (SBLOCK + (sizeof (struct ext2_super_block) / DEV_BSIZE))
  18.269 +      || */ !devread (ffi, SBLOCK, 0, sizeof (struct ext2_super_block),
  18.270 +		   (char *) SUPERBLOCK)
  18.271 +      || SUPERBLOCK->s_magic != EXT2_SUPER_MAGIC)
  18.272 +      retval = 0;
  18.273 +
  18.274 +  return retval;
  18.275 +}
  18.276 +
  18.277 +/* Takes a file system block number and reads it into BUFFER. */
  18.278 +static int
  18.279 +ext2_rdfsb (fsi_file_t *ffi, int fsblock, char *buffer)
  18.280 +{
  18.281 +#ifdef E2DEBUG
  18.282 +  printf ("fsblock %d buffer %d\n", fsblock, buffer);
  18.283 +#endif /* E2DEBUG */
  18.284 +  return devread (ffi, fsblock * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE), 0,
  18.285 +		  EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer);
  18.286 +}
  18.287 +
  18.288 +/* from
  18.289 +  ext2/inode.c:ext2_bmap()
  18.290 +*/
  18.291 +/* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into
  18.292 +   a physical block (the location in the file system) via an inode. */
  18.293 +static int
  18.294 +ext2fs_block_map (fsi_file_t *ffi, int logical_block)
  18.295 +{
  18.296 +
  18.297 +#ifdef E2DEBUG
  18.298 +  unsigned char *i;
  18.299 +  for (i = (unsigned char *) INODE;
  18.300 +       i < ((unsigned char *) INODE + sizeof (struct ext2_inode));
  18.301 +       i++)
  18.302 +    {
  18.303 +      printf ("%c", "0123456789abcdef"[*i >> 4]);
  18.304 +      printf ("%c", "0123456789abcdef"[*i % 16]);
  18.305 +      if (!((i + 1 - (unsigned char *) INODE) % 16))
  18.306 +	{
  18.307 +	  printf ("\n");
  18.308 +	}
  18.309 +      else
  18.310 +	{
  18.311 +	  printf (" ");
  18.312 +	}
  18.313 +    }
  18.314 +  printf ("logical block %d\n", logical_block);
  18.315 +#endif /* E2DEBUG */
  18.316 +
  18.317 +  /* if it is directly pointed to by the inode, return that physical addr */
  18.318 +  if (logical_block < EXT2_NDIR_BLOCKS)
  18.319 +    {
  18.320 +#ifdef E2DEBUG
  18.321 +      printf ("returning %d\n", (unsigned char *) (INODE->i_block[logical_block]));
  18.322 +      printf ("returning %d\n", INODE->i_block[logical_block]);
  18.323 +#endif /* E2DEBUG */
  18.324 +      return INODE->i_block[logical_block];
  18.325 +    }
  18.326 +  /* else */
  18.327 +  logical_block -= EXT2_NDIR_BLOCKS;
  18.328 +  /* try the indirect block */
  18.329 +  if (logical_block < EXT2_ADDR_PER_BLOCK (SUPERBLOCK))
  18.330 +    {
  18.331 +      if (mapblock1 != 1
  18.332 +	  && !ext2_rdfsb (ffi, INODE->i_block[EXT2_IND_BLOCK], DATABLOCK1))
  18.333 +	{
  18.334 +	  errnum = ERR_FSYS_CORRUPT;
  18.335 +	  return -1;
  18.336 +	}
  18.337 +      mapblock1 = 1;
  18.338 +      return ((__u32 *) DATABLOCK1)[logical_block];
  18.339 +    }
  18.340 +  /* else */
  18.341 +  logical_block -= EXT2_ADDR_PER_BLOCK (SUPERBLOCK);
  18.342 +  /* now try the double indirect block */
  18.343 +  if (logical_block < (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2)))
  18.344 +    {
  18.345 +      int bnum;
  18.346 +      if (mapblock1 != 2
  18.347 +	  && !ext2_rdfsb (ffi, INODE->i_block[EXT2_DIND_BLOCK], DATABLOCK1))
  18.348 +	{
  18.349 +	  errnum = ERR_FSYS_CORRUPT;
  18.350 +	  return -1;
  18.351 +	}
  18.352 +      mapblock1 = 2;
  18.353 +      if ((bnum = (((__u32 *) DATABLOCK1)
  18.354 +		   [logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)]))
  18.355 +	  != mapblock2
  18.356 +	  && !ext2_rdfsb (ffi, bnum, DATABLOCK2))
  18.357 +	{
  18.358 +	  errnum = ERR_FSYS_CORRUPT;
  18.359 +	  return -1;
  18.360 +	}
  18.361 +      mapblock2 = bnum;
  18.362 +      return ((__u32 *) DATABLOCK2)
  18.363 +	[logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
  18.364 +    }
  18.365 +  /* else */
  18.366 +  mapblock2 = -1;
  18.367 +  logical_block -= (1 << (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK) * 2));
  18.368 +  if (mapblock1 != 3
  18.369 +      && !ext2_rdfsb (ffi, INODE->i_block[EXT2_TIND_BLOCK], DATABLOCK1))
  18.370 +    {
  18.371 +      errnum = ERR_FSYS_CORRUPT;
  18.372 +      return -1;
  18.373 +    }
  18.374 +  mapblock1 = 3;
  18.375 +  if (!ext2_rdfsb (ffi, ((__u32 *) DATABLOCK1)
  18.376 +		   [logical_block >> (EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK)
  18.377 +				      * 2)],
  18.378 +		   DATABLOCK2))
  18.379 +    {
  18.380 +      errnum = ERR_FSYS_CORRUPT;
  18.381 +      return -1;
  18.382 +    }
  18.383 +  if (!ext2_rdfsb (ffi, ((__u32 *) DATABLOCK2)
  18.384 +		   [(logical_block >> EXT2_ADDR_PER_BLOCK_BITS (SUPERBLOCK))
  18.385 +		    & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)],
  18.386 +		   DATABLOCK2))
  18.387 +    {
  18.388 +      errnum = ERR_FSYS_CORRUPT;
  18.389 +      return -1;
  18.390 +    }
  18.391 +  return ((__u32 *) DATABLOCK2)
  18.392 +    [logical_block & (EXT2_ADDR_PER_BLOCK (SUPERBLOCK) - 1)];
  18.393 +}
  18.394 +
  18.395 +/* preconditions: all preconds of ext2fs_block_map */
  18.396 +int
  18.397 +ext2fs_read (fsi_file_t *ffi, char *buf, int len)
  18.398 +{
  18.399 +  int logical_block;
  18.400 +  int offset;
  18.401 +  int map;
  18.402 +  int ret = 0;
  18.403 +  int size = 0;
  18.404 +
  18.405 +#ifdef E2DEBUG
  18.406 +  static char hexdigit[] = "0123456789abcdef";
  18.407 +  unsigned char *i;
  18.408 +  for (i = (unsigned char *) INODE;
  18.409 +       i < ((unsigned char *) INODE + sizeof (struct ext2_inode));
  18.410 +       i++)
  18.411 +    {
  18.412 +      printf ("%c", hexdigit[*i >> 4]);
  18.413 +      printf ("%c", hexdigit[*i % 16]);
  18.414 +      if (!((i + 1 - (unsigned char *) INODE) % 16))
  18.415 +	{
  18.416 +	  printf ("\n");
  18.417 +	}
  18.418 +      else
  18.419 +	{
  18.420 +	  printf (" ");
  18.421 +	}
  18.422 +    }
  18.423 +#endif /* E2DEBUG */
  18.424 +  while (len > 0)
  18.425 +    {
  18.426 +      /* find the (logical) block component of our location */
  18.427 +      logical_block = filepos >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
  18.428 +      offset = filepos & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
  18.429 +      map = ext2fs_block_map (ffi, logical_block);
  18.430 +#ifdef E2DEBUG
  18.431 +      printf ("map=%d\n", map);
  18.432 +#endif /* E2DEBUG */
  18.433 +      if (map < 0)
  18.434 +	break;
  18.435 +
  18.436 +      size = EXT2_BLOCK_SIZE (SUPERBLOCK);
  18.437 +      size -= offset;
  18.438 +      if (size > len)
  18.439 +	size = len;
  18.440 +
  18.441 +      if (map == 0) {
  18.442 +        memset ((char *) buf, 0, size);
  18.443 +      } else {
  18.444 +        disk_read_func = disk_read_hook;
  18.445 +
  18.446 +        devread (ffi, map * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE),
  18.447 +	         offset, size, buf);
  18.448 +
  18.449 +        disk_read_func = NULL;
  18.450 +      }
  18.451 +
  18.452 +      buf += size;
  18.453 +      len -= size;
  18.454 +      filepos += size;
  18.455 +      ret += size;
  18.456 +    }
  18.457 +
  18.458 +  if (errnum)
  18.459 +    ret = 0;
  18.460 +
  18.461 +  return ret;
  18.462 +}
  18.463 +
  18.464 +
  18.465 +/* Based on:
  18.466 +   def_blk_fops points to
  18.467 +   blkdev_open, which calls (I think):
  18.468 +   sys_open()
  18.469 +   do_open()
  18.470 +   open_namei()
  18.471 +   dir_namei() which accesses current->fs->root
  18.472 +     fs->root was set during original mount:
  18.473 +     (something)... which calls (I think):
  18.474 +     ext2_read_super()
  18.475 +     iget()
  18.476 +     __iget()
  18.477 +     read_inode()
  18.478 +     ext2_read_inode()
  18.479 +       uses desc_per_block_bits, which is set in ext2_read_super()
  18.480 +       also uses group descriptors loaded during ext2_read_super()
  18.481 +   lookup()
  18.482 +   ext2_lookup()
  18.483 +   ext2_find_entry()
  18.484 +   ext2_getblk()
  18.485 +
  18.486 +*/
  18.487 +
  18.488 +static inline
  18.489 +int ext2_is_fast_symlink (fsi_file_t *ffi)
  18.490 +{
  18.491 +  int ea_blocks;
  18.492 +  ea_blocks = INODE->i_file_acl ? EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE : 0;
  18.493 +  return INODE->i_blocks == ea_blocks;
  18.494 +}
  18.495 +
  18.496 +/* preconditions: ext2fs_mount already executed, therefore supblk in buffer
  18.497 + *   known as SUPERBLOCK
  18.498 + * returns: 0 if error, nonzero iff we were able to find the file successfully
  18.499 + * postconditions: on a nonzero return, buffer known as INODE contains the
  18.500 + *   inode of the file we were trying to look up
  18.501 + * side effects: messes up GROUP_DESC buffer area
  18.502 + */
  18.503 +int
  18.504 +ext2fs_dir (fsi_file_t *ffi, char *dirname)
  18.505 +{
  18.506 +  int current_ino = EXT2_ROOT_INO;	/* start at the root */
  18.507 +  int updir_ino = current_ino;	/* the parent of the current directory */
  18.508 +  int group_id;			/* which group the inode is in */
  18.509 +  int group_desc;		/* fs pointer to that group */
  18.510 +  int desc;			/* index within that group */
  18.511 +  int ino_blk;			/* fs pointer of the inode's information */
  18.512 +  int str_chk = 0;		/* used to hold the results of a string compare */
  18.513 +  struct ext2_group_desc *gdp;
  18.514 +  struct ext2_inode *raw_inode;	/* inode info corresponding to current_ino */
  18.515 +
  18.516 +  char linkbuf[PATH_MAX];	/* buffer for following symbolic links */
  18.517 +  int link_count = 0;
  18.518 +
  18.519 +  char *rest;
  18.520 +  char ch;			/* temp char holder */
  18.521 +
  18.522 +  int off;			/* offset within block of directory entry (off mod blocksize) */
  18.523 +  int loc;			/* location within a directory */
  18.524 +  int blk;			/* which data blk within dir entry (off div blocksize) */
  18.525 +  long map;			/* fs pointer of a particular block from dir entry */
  18.526 +  struct ext2_dir_entry *dp;	/* pointer to directory entry */
  18.527 +#ifdef E2DEBUG
  18.528 +  unsigned char *i;
  18.529 +#endif	/* E2DEBUG */
  18.530 +
  18.531 +  /* loop invariants:
  18.532 +     current_ino = inode to lookup
  18.533 +     dirname = pointer to filename component we are cur looking up within
  18.534 +     the directory known pointed to by current_ino (if any)
  18.535 +   */
  18.536 +
  18.537 +  while (1)
  18.538 +    {
  18.539 +#ifdef E2DEBUG
  18.540 +      printf ("inode %d\n", current_ino);
  18.541 +      printf ("dirname=%s\n", dirname);
  18.542 +#endif /* E2DEBUG */
  18.543 +
  18.544 +      /* look up an inode */
  18.545 +      group_id = (current_ino - 1) / (SUPERBLOCK->s_inodes_per_group);
  18.546 +      group_desc = group_id >> log2 (EXT2_DESC_PER_BLOCK (SUPERBLOCK));
  18.547 +      desc = group_id & (EXT2_DESC_PER_BLOCK (SUPERBLOCK) - 1);
  18.548 +#ifdef E2DEBUG
  18.549 +      printf ("ipg=%d, dpb=%d\n", SUPERBLOCK->s_inodes_per_group,
  18.550 +	      EXT2_DESC_PER_BLOCK (SUPERBLOCK));
  18.551 +      printf ("group_id=%d group_desc=%d desc=%d\n", group_id, group_desc, desc);
  18.552 +#endif /* E2DEBUG */
  18.553 +      if (!ext2_rdfsb (ffi, 
  18.554 +			(WHICH_SUPER + group_desc + SUPERBLOCK->s_first_data_block),
  18.555 +			(char *)GROUP_DESC))
  18.556 +	{
  18.557 +	  return 0;
  18.558 +	}
  18.559 +      gdp = GROUP_DESC;
  18.560 +      ino_blk = gdp[desc].bg_inode_table +
  18.561 +	(((current_ino - 1) % (SUPERBLOCK->s_inodes_per_group))
  18.562 +	 >> log2 (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)));
  18.563 +#ifdef E2DEBUG
  18.564 +      printf ("inode table fsblock=%d\n", ino_blk);
  18.565 +#endif /* E2DEBUG */
  18.566 +      if (!ext2_rdfsb (ffi, ino_blk, (char *)INODE))
  18.567 +	{
  18.568 +	  return 0;
  18.569 +	}
  18.570 +
  18.571 +      /* reset indirect blocks! */
  18.572 +      mapblock2 = mapblock1 = -1;
  18.573 +
  18.574 +      raw_inode = INODE +
  18.575 +	((current_ino - 1)
  18.576 +	 & (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode) - 1));
  18.577 +#ifdef E2DEBUG
  18.578 +      printf ("ipb=%d, sizeof(inode)=%d\n",
  18.579 +	      (EXT2_BLOCK_SIZE (SUPERBLOCK) / sizeof (struct ext2_inode)),
  18.580 +	      sizeof (struct ext2_inode));
  18.581 +      printf ("inode=%x, raw_inode=%x\n", INODE, raw_inode);
  18.582 +      printf ("offset into inode table block=%d\n", (int) raw_inode - (int) INODE);
  18.583 +      for (i = (unsigned char *) INODE; i <= (unsigned char *) raw_inode;
  18.584 +	   i++)
  18.585 +	{
  18.586 +	  printf ("%c", "0123456789abcdef"[*i >> 4]);
  18.587 +	  printf ("%c", "0123456789abcdef"[*i % 16]);
  18.588 +	  if (!((i + 1 - (unsigned char *) INODE) % 16))
  18.589 +	    {
  18.590 +	      printf ("\n");
  18.591 +	    }
  18.592 +	  else
  18.593 +	    {
  18.594 +	      printf (" ");
  18.595 +	    }
  18.596 +	}
  18.597 +      printf ("first word=%x\n", *((int *) raw_inode));
  18.598 +#endif /* E2DEBUG */
  18.599 +
  18.600 +      /* copy inode to fixed location */
  18.601 +      memmove ((void *) INODE, (void *) raw_inode, sizeof (struct ext2_inode));
  18.602 +
  18.603 +#ifdef E2DEBUG
  18.604 +      printf ("first word=%x\n", *((int *) INODE));
  18.605 +#endif /* E2DEBUG */
  18.606 +
  18.607 +      /* If we've got a symbolic link, then chase it. */
  18.608 +      if (S_ISLNK (INODE->i_mode))
  18.609 +	{
  18.610 +	  int len;
  18.611 +	  if (++link_count > MAX_LINK_COUNT)
  18.612 +	    {
  18.613 +	      errnum = ERR_SYMLINK_LOOP;
  18.614 +	      return 0;
  18.615 +	    }
  18.616 +
  18.617 +	  /* Find out how long our remaining name is. */
  18.618 +	  len = 0;
  18.619 +	  while (dirname[len] && !isspace (dirname[len]))
  18.620 +	    len++;
  18.621 +
  18.622 +	  /* Get the symlink size. */
  18.623 +	  filemax = (INODE->i_size);
  18.624 +	  if (filemax + len > sizeof (linkbuf) - 2)
  18.625 +	    {
  18.626 +	      errnum = ERR_FILELENGTH;
  18.627 +	      return 0;
  18.628 +	    }
  18.629 +
  18.630 +	  if (len)
  18.631 +	    {
  18.632 +	      /* Copy the remaining name to the end of the symlink data.
  18.633 +	         Note that DIRNAME and LINKBUF may overlap! */
  18.634 +	      memmove (linkbuf + filemax, dirname, len);
  18.635 +	    }
  18.636 +	  linkbuf[filemax + len] = '\0';
  18.637 +
  18.638 +	  /* Read the symlink data. */
  18.639 +	  if (! ext2_is_fast_symlink (ffi))
  18.640 +	    {
  18.641 +	      /* Read the necessary blocks, and reset the file pointer. */
  18.642 +	      len = ext2fs_read (ffi, linkbuf, filemax);
  18.643 +	      filepos = 0;
  18.644 +	      if (!len)
  18.645 +		return 0;
  18.646 +	    }
  18.647 +	  else
  18.648 +	    {
  18.649 +	      /* Copy the data directly from the inode. */
  18.650 +	      len = filemax;
  18.651 +	      memmove (linkbuf, (char *) INODE->i_block, len);
  18.652 +	    }
  18.653 +
  18.654 +#ifdef E2DEBUG
  18.655 +	  printf ("symlink=%s\n", linkbuf);
  18.656 +#endif
  18.657 +
  18.658 +	  dirname = linkbuf;
  18.659 +	  if (*dirname == '/')
  18.660 +	    {
  18.661 +	      /* It's an absolute link, so look it up in root. */
  18.662 +	      current_ino = EXT2_ROOT_INO;
  18.663 +	      updir_ino = current_ino;
  18.664 +	    }
  18.665 +	  else
  18.666 +	    {
  18.667 +	      /* Relative, so look it up in our parent directory. */
  18.668 +	      current_ino = updir_ino;
  18.669 +	    }
  18.670 +
  18.671 +	  /* Try again using the new name. */
  18.672 +	  continue;
  18.673 +	}
  18.674 +
  18.675 +      /* if end of filename, INODE points to the file's inode */
  18.676 +      if (!*dirname || isspace (*dirname))
  18.677 +	{
  18.678 +	  if (!S_ISREG (INODE->i_mode))
  18.679 +	    {
  18.680 +	      errnum = ERR_BAD_FILETYPE;
  18.681 +	      return 0;
  18.682 +	    }
  18.683 +
  18.684 +	  filemax = (INODE->i_size);
  18.685 +	  return 1;
  18.686 +	}
  18.687 +
  18.688 +      /* else we have to traverse a directory */
  18.689 +      updir_ino = current_ino;
  18.690 +
  18.691 +      /* skip over slashes */
  18.692 +      while (*dirname == '/')
  18.693 +	dirname++;
  18.694 +
  18.695 +      /* if this isn't a directory of sufficient size to hold our file, abort */
  18.696 +      if (!(INODE->i_size) || !S_ISDIR (INODE->i_mode))
  18.697 +	{
  18.698 +	  errnum = ERR_BAD_FILETYPE;
  18.699 +	  return 0;
  18.700 +	}
  18.701 +
  18.702 +      /* skip to next slash or end of filename (space) */
  18.703 +      for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/';
  18.704 +	   rest++);
  18.705 +
  18.706 +      /* look through this directory and find the next filename component */
  18.707 +      /* invariant: rest points to slash after the next filename component */
  18.708 +      *rest = 0;
  18.709 +      loc = 0;
  18.710 +
  18.711 +      do
  18.712 +	{
  18.713 +
  18.714 +#ifdef E2DEBUG
  18.715 +	  printf ("dirname=%s, rest=%s, loc=%d\n", dirname, rest, loc);
  18.716 +#endif /* E2DEBUG */
  18.717 +
  18.718 +	  /* if our location/byte offset into the directory exceeds the size,
  18.719 +	     give up */
  18.720 +	  if (loc >= INODE->i_size)
  18.721 +	    {
  18.722 +	      if (print_possibilities < 0)
  18.723 +		{
  18.724 +# if 0
  18.725 +		  putchar ('\n');
  18.726 +# endif
  18.727 +		}
  18.728 +	      else
  18.729 +		{
  18.730 +		  errnum = ERR_FILE_NOT_FOUND;
  18.731 +		  *rest = ch;
  18.732 +		}
  18.733 +	      return (print_possibilities < 0);
  18.734 +	    }
  18.735 +
  18.736 +	  /* else, find the (logical) block component of our location */
  18.737 +	  blk = loc >> EXT2_BLOCK_SIZE_BITS (SUPERBLOCK);
  18.738 +
  18.739 +	  /* we know which logical block of the directory entry we are looking
  18.740 +	     for, now we have to translate that to the physical (fs) block on
  18.741 +	     the disk */
  18.742 +	  map = ext2fs_block_map (ffi, blk);
  18.743 +#ifdef E2DEBUG
  18.744 +	  printf ("fs block=%d\n", map);
  18.745 +#endif /* E2DEBUG */
  18.746 +	  mapblock2 = -1;
  18.747 +	  if ((map < 0) || !ext2_rdfsb (ffi, map, DATABLOCK2))
  18.748 +	    {
  18.749 +	      errnum = ERR_FSYS_CORRUPT;
  18.750 +	      *rest = ch;
  18.751 +	      return 0;
  18.752 +	    }
  18.753 +	  off = loc & (EXT2_BLOCK_SIZE (SUPERBLOCK) - 1);
  18.754 +	  dp = (struct ext2_dir_entry *) (DATABLOCK2 + off);
  18.755 +	  /* advance loc prematurely to next on-disk directory entry  */
  18.756 +	  loc += dp->rec_len;
  18.757 +
  18.758 +	  /* NOTE: ext2fs filenames are NOT null-terminated */
  18.759 +
  18.760 +#ifdef E2DEBUG
  18.761 +	  printf ("directory entry ino=%d\n", dp->inode);
  18.762 +	  if (dp->inode)
  18.763 +	    printf ("entry=%s\n", dp->name);
  18.764 +#endif /* E2DEBUG */
  18.765 +
  18.766 +	  if (dp->inode)
  18.767 +	    {
  18.768 +	      int saved_c = dp->name[dp->name_len];
  18.769 +
  18.770 +	      dp->name[dp->name_len] = 0;
  18.771 +	      str_chk = substring (dirname, dp->name);
  18.772 +
  18.773 +# ifndef STAGE1_5
  18.774 +	      if (print_possibilities && ch != '/'
  18.775 +		  && (!*dirname || str_chk <= 0))
  18.776 +		{
  18.777 +		  if (print_possibilities > 0)
  18.778 +		    print_possibilities = -print_possibilities;
  18.779 +		  print_a_completion (dp->name);
  18.780 +		}
  18.781 +# endif
  18.782 +
  18.783 +	      dp->name[dp->name_len] = saved_c;
  18.784 +	    }
  18.785 +
  18.786 +	}
  18.787 +      while (!dp->inode || (str_chk || (print_possibilities && ch != '/')));
  18.788 +
  18.789 +      current_ino = dp->inode;
  18.790 +      *(dirname = rest) = ch;
  18.791 +    }
  18.792 +  /* never get here */
  18.793 +}
  18.794 +
  18.795 +fsi_plugin_ops_t *
  18.796 +fsi_init_plugin(int version, fsi_plugin_t *fp, const char **name)
  18.797 +{
  18.798 +	static fsig_plugin_ops_t ops = {
  18.799 +		FSIMAGE_PLUGIN_VERSION,
  18.800 +		.fpo_mount = ext2fs_mount,
  18.801 +		.fpo_dir = ext2fs_dir,
  18.802 +		.fpo_read = ext2fs_read
  18.803 +	};
  18.804 +
  18.805 +	*name = "ext2fs";
  18.806 +	return (fsig_init(fp, &ops));
  18.807 +}
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/tools/libfsimage/reiserfs/Makefile	Thu Nov 09 14:09:53 2006 +0000
    19.3 @@ -0,0 +1,13 @@
    19.4 +XEN_ROOT = ../../..
    19.5 +
    19.6 +LIB_SRCS-y = fsys_reiserfs.c
    19.7 +
    19.8 +FS = reiserfs
    19.9 +
   19.10 +.PHONY: all
   19.11 +all: fs-all
   19.12 +
   19.13 +.PHONY: install
   19.14 +install: fs-install
   19.15 +
   19.16 +include $(XEN_ROOT)/tools/libfsimage/Rules.mk
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/tools/libfsimage/reiserfs/fsys_reiserfs.c	Thu Nov 09 14:09:53 2006 +0000
    20.3 @@ -0,0 +1,1254 @@
    20.4 +/* fsys_reiserfs.c - an implementation for the ReiserFS filesystem */
    20.5 +/*
    20.6 + *  GRUB  --  GRand Unified Bootloader
    20.7 + *  Copyright (C) 2000, 2001  Free Software Foundation, Inc.
    20.8 + *
    20.9 + *  This program is free software; you can redistribute it and/or modify
   20.10 + *  it under the terms of the GNU General Public License as published by
   20.11 + *  the Free Software Foundation; either version 2 of the License, or
   20.12 + *  (at your option) any later version.
   20.13 + *
   20.14 + *  This program is distributed in the hope that it will be useful,
   20.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   20.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   20.17 + *  GNU General Public License for more details.
   20.18 + *
   20.19 + *  You should have received a copy of the GNU General Public License
   20.20 + *  along with this program; if not, write to the Free Software
   20.21 + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   20.22 + */
   20.23 +
   20.24 +#include <fsimage_grub.h>
   20.25 +
   20.26 +#undef REISERDEBUG
   20.27 +
   20.28 +/* Some parts of this code (mainly the structures and defines) are
   20.29 + * from the original reiser fs code, as found in the linux kernel.
   20.30 + */
   20.31 +
   20.32 +/* include/asm-i386/types.h */
   20.33 +typedef __signed__ char __s8;
   20.34 +typedef unsigned char __u8;
   20.35 +typedef __signed__ short __s16;
   20.36 +typedef unsigned short __u16;
   20.37 +typedef __signed__ int __s32;
   20.38 +typedef unsigned int __u32;
   20.39 +typedef unsigned long long __u64;
   20.40 +
   20.41 +/* linux/posix_type.h */
   20.42 +typedef long linux_off_t;
   20.43 +
   20.44 +/* linux/little_endian.h */
   20.45 +#define __cpu_to_le64(x) ((__u64) (x))
   20.46 +#define __le64_to_cpu(x) ((__u64) (x))
   20.47 +#define __cpu_to_le32(x) ((__u32) (x))
   20.48 +#define __le32_to_cpu(x) ((__u32) (x))
   20.49 +#define __cpu_to_le16(x) ((__u16) (x))
   20.50 +#define __le16_to_cpu(x) ((__u16) (x))
   20.51 +
   20.52 +/* include/linux/reiser_fs.h */
   20.53 +/* This is the new super block of a journaling reiserfs system */
   20.54 +struct reiserfs_super_block
   20.55 +{
   20.56 +  __u32 s_block_count;			/* blocks count         */
   20.57 +  __u32 s_free_blocks;                  /* free blocks count    */
   20.58 +  __u32 s_root_block;           	/* root block number    */
   20.59 +  __u32 s_journal_block;           	/* journal block number    */
   20.60 +  __u32 s_journal_dev;           	/* journal device number  */
   20.61 +  __u32 s_journal_size; 		/* size of the journal on FS creation.  used to make sure they don't overflow it */
   20.62 +  __u32 s_journal_trans_max;            /* max number of blocks in a transaction.  */
   20.63 +  __u32 s_journal_magic;                /* random value made on fs creation */
   20.64 +  __u32 s_journal_max_batch;            /* max number of blocks to batch into a trans */
   20.65 +  __u32 s_journal_max_commit_age;       /* in seconds, how old can an async commit be */
   20.66 +  __u32 s_journal_max_trans_age;        /* in seconds, how old can a transaction be */
   20.67 +  __u16 s_blocksize;                   	/* block size           */
   20.68 +  __u16 s_oid_maxsize;			/* max size of object id array  */
   20.69 +  __u16 s_oid_cursize;			/* current size of object id array */
   20.70 +  __u16 s_state;                       	/* valid or error       */
   20.71 +  char s_magic[16];                     /* reiserfs magic string indicates that file system is reiserfs */
   20.72 +  __u16 s_tree_height;                  /* height of disk tree */
   20.73 +  __u16 s_bmap_nr;                      /* amount of bitmap blocks needed to address each block of file system */
   20.74 +  __u16 s_version;
   20.75 +  char s_unused[128];			/* zero filled by mkreiserfs */
   20.76 +};
   20.77 +
   20.78 +#define REISERFS_MAX_SUPPORTED_VERSION 2
   20.79 +#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"
   20.80 +#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
   20.81 +#define REISER3FS_SUPER_MAGIC_STRING "ReIsEr3Fs"
   20.82 +
   20.83 +#define MAX_HEIGHT 7
   20.84 +
   20.85 +/* must be correct to keep the desc and commit structs at 4k */
   20.86 +#define JOURNAL_TRANS_HALF 1018
   20.87 +
   20.88 +/* first block written in a commit.  */
   20.89 +struct reiserfs_journal_desc {
   20.90 +  __u32 j_trans_id;			/* id of commit */
   20.91 +  __u32 j_len;				/* length of commit. len +1 is the commit block */
   20.92 +  __u32 j_mount_id;			/* mount id of this trans*/
   20.93 +  __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the first blocks */
   20.94 +  char j_magic[12];
   20.95 +};
   20.96 +
   20.97 +/* last block written in a commit */
   20.98 +struct reiserfs_journal_commit {
   20.99 +  __u32 j_trans_id;			/* must match j_trans_id from the desc block */
  20.100 +  __u32 j_len;			/* ditto */
  20.101 +  __u32 j_realblock[JOURNAL_TRANS_HALF]; /* real locations for the last blocks */
  20.102 +  char j_digest[16];			/* md5 sum of all the blocks involved, including desc and commit. not used, kill it */
  20.103 +};
  20.104 +
  20.105 +/* this header block gets written whenever a transaction is considered
  20.106 +   fully flushed, and is more recent than the last fully flushed
  20.107 +   transaction.  
  20.108 +   fully flushed means all the log blocks and all the real blocks are
  20.109 +   on disk, and this transaction does not need to be replayed.  
  20.110 +*/
  20.111 +struct reiserfs_journal_header {
  20.112 +  /* id of last fully flushed transaction */
  20.113 +  __u32 j_last_flush_trans_id;
  20.114 +  /* offset in the log of where to start replay after a crash */
  20.115 +  __u32 j_first_unflushed_offset;
  20.116 +  /* mount id to detect very old transactions */
  20.117 +  __u32 j_mount_id;
  20.118 +};
  20.119 +
  20.120 +/* magic string to find desc blocks in the journal */
  20.121 +#define JOURNAL_DESC_MAGIC "ReIsErLB" 
  20.122 +
  20.123 +
  20.124 +/*
  20.125 + * directories use this key as well as old files
  20.126 + */
  20.127 +struct offset_v1
  20.128 +{
  20.129 +  /*
  20.130 +   * for regular files this is the offset to the first byte of the
  20.131 +   * body, contained in the object-item, as measured from the start of
  20.132 +   * the entire body of the object.
  20.133 +   *
  20.134 +   * for directory entries, k_offset consists of hash derived from
  20.135 +   * hashing the name and using few bits (23 or more) of the resulting
  20.136 +   * hash, and generation number that allows distinguishing names with
  20.137 +   * hash collisions. If number of collisions overflows generation
  20.138 +   * number, we return EEXIST.  High order bit is 0 always 
  20.139 +   */
  20.140 +  __u32 k_offset;
  20.141 +  __u32 k_uniqueness;
  20.142 +};
  20.143 +
  20.144 +struct offset_v2
  20.145 +{
  20.146 +  /*
  20.147 +   * for regular files this is the offset to the first byte of the
  20.148 +   * body, contained in the object-item, as measured from the start of
  20.149 +   * the entire body of the object.
  20.150 +   *
  20.151 +   * for directory entries, k_offset consists of hash derived from
  20.152 +   * hashing the name and using few bits (23 or more) of the resulting
  20.153 +   * hash, and generation number that allows distinguishing names with
  20.154 +   * hash collisions. If number of collisions overflows generation
  20.155 +   * number, we return EEXIST.  High order bit is 0 always 
  20.156 +   */
  20.157 +  __u64 k_offset:60;
  20.158 +  __u64 k_type: 4;
  20.159 +};
  20.160 +
  20.161 +
  20.162 +struct key
  20.163 +{
  20.164 +  /* packing locality: by default parent directory object id */
  20.165 +  __u32 k_dir_id;
  20.166 +  /* object identifier */
  20.167 +  __u32 k_objectid;
  20.168 +  /* the offset and node type (old and new form) */
  20.169 +  union
  20.170 +  {
  20.171 +    struct offset_v1 v1;
  20.172 +    struct offset_v2 v2;
  20.173 +  }
  20.174 +  u;
  20.175 +};
  20.176 +
  20.177 +#define KEY_SIZE (sizeof (struct key))
  20.178 +
  20.179 +/* Header of a disk block.  More precisely, header of a formatted leaf
  20.180 +   or internal node, and not the header of an unformatted node. */
  20.181 +struct block_head
  20.182 +{       
  20.183 +  __u16 blk_level;        /* Level of a block in the tree. */
  20.184 +  __u16 blk_nr_item;      /* Number of keys/items in a block. */
  20.185 +  __u16 blk_free_space;   /* Block free space in bytes. */
  20.186 +  struct key  blk_right_delim_key; /* Right delimiting key for this block (supported for leaf level nodes
  20.187 +				      only) */
  20.188 +};
  20.189 +#define BLKH_SIZE (sizeof (struct block_head))
  20.190 +#define DISK_LEAF_NODE_LEVEL  1 /* Leaf node level.                       */
  20.191 +
  20.192 +struct item_head
  20.193 +{
  20.194 +  struct key ih_key; 	/* Everything in the tree is found by searching for it based on its key.*/
  20.195 +  
  20.196 +  union
  20.197 +  {
  20.198 +    __u16 ih_free_space; /* The free space in the last unformatted node of an indirect item if this
  20.199 +			    is an indirect item.  This equals 0xFFFF iff this is a direct item or
  20.200 +			    stat data item. Note that the key, not this field, is used to determine
  20.201 +			    the item type, and thus which field this union contains. */
  20.202 +    __u16 ih_entry_count; /* Iff this is a directory item, this field equals the number of directory
  20.203 +			     entries in the directory item. */
  20.204 +  }
  20.205 +  u;
  20.206 +  __u16 ih_item_len;           /* total size of the item body                  */
  20.207 +  __u16 ih_item_location;      /* an offset to the item body within the block  */
  20.208 +  __u16 ih_version;	       /* ITEM_VERSION_1 for all old items, 
  20.209 +				  ITEM_VERSION_2 for new ones. 
  20.210 +				  Highest bit is set by fsck
  20.211 +                                  temporary, cleaned after all done */
  20.212 +};
  20.213 +/* size of item header     */
  20.214 +#define IH_SIZE (sizeof (struct item_head))
  20.215 +
  20.216 +#define ITEM_VERSION_1 0
  20.217 +#define ITEM_VERSION_2 1
  20.218 +#define IH_KEY_OFFSET(ih) ((ih)->ih_version == ITEM_VERSION_1 \
  20.219 +			   ? (ih)->ih_key.u.v1.k_offset \
  20.220 +			   : (ih)->ih_key.u.v2.k_offset)
  20.221 +
  20.222 +#define IH_KEY_ISTYPE(ih, type) ((ih)->ih_version == ITEM_VERSION_1 \
  20.223 +				 ? (ih)->ih_key.u.v1.k_uniqueness == V1_##type \
  20.224 +				 : (ih)->ih_key.u.v2.k_type == V2_##type)
  20.225 +
  20.226 +struct disk_child
  20.227 +{
  20.228 +  unsigned long       dc_block_number;              /* Disk child's block number. */
  20.229 +  unsigned short      dc_size;		            /* Disk child's used space.   */
  20.230 +};
  20.231 +
  20.232 +#define DC_SIZE (sizeof (struct disk_child))
  20.233 +
  20.234 +/* Stat Data on disk.
  20.235 + *
  20.236 + * Note that reiserfs has two different forms of stat data.  Luckily
  20.237 + * the fields needed by grub are at the same position.
  20.238 + */
  20.239 +struct stat_data
  20.240 +{
  20.241 +  __u16 sd_mode;	/* file type, permissions */
  20.242 +  __u16 sd_notused1[3]; /* fields not needed by reiserfs */
  20.243 +  __u32 sd_size;	/* file size */
  20.244 +  __u32 sd_size_hi;	/* file size high 32 bits (since version 2) */
  20.245 +};
  20.246 +
  20.247 +struct reiserfs_de_head
  20.248 +{
  20.249 +  __u32 deh_offset;  /* third component of the directory entry key */
  20.250 +  __u32 deh_dir_id;  /* objectid of the parent directory of the
  20.251 +			object, that is referenced by directory entry */
  20.252 +  __u32 deh_objectid;/* objectid of the object, that is referenced by
  20.253 +                        directory entry */
  20.254 +  __u16 deh_location;/* offset of name in the whole item */
  20.255 +  __u16 deh_state;   /* whether 1) entry contains stat data (for
  20.256 +			future), and 2) whether entry is hidden
  20.257 +			(unlinked) */
  20.258 +};
  20.259 +
  20.260 +#define DEH_SIZE (sizeof (struct reiserfs_de_head))
  20.261 +
  20.262 +#define DEH_Statdata (1 << 0)			/* not used now */
  20.263 +#define DEH_Visible  (1 << 2)
  20.264 +
  20.265 +#define SD_OFFSET  0
  20.266 +#define SD_UNIQUENESS 0
  20.267 +#define DOT_OFFSET 1
  20.268 +#define DOT_DOT_OFFSET 2
  20.269 +#define DIRENTRY_UNIQUENESS 500
  20.270 +
  20.271 +#define V1_TYPE_STAT_DATA 0x0
  20.272 +#define V1_TYPE_DIRECT 0xffffffff
  20.273 +#define V1_TYPE_INDIRECT 0xfffffffe
  20.274 +#define V1_TYPE_DIRECTORY_MAX 0xfffffffd
  20.275 +#define V2_TYPE_STAT_DATA 0
  20.276 +#define V2_TYPE_INDIRECT 1
  20.277 +#define V2_TYPE_DIRECT 2
  20.278 +#define V2_TYPE_DIRENTRY 3 
  20.279 +
  20.280 +#define REISERFS_ROOT_OBJECTID 2
  20.281 +#define REISERFS_ROOT_PARENT_OBJECTID 1
  20.282 +#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024)
  20.283 +/* the spot for the super in versions 3.5 - 3.5.11 (inclusive) */
  20.284 +#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024)
  20.285 +#define REISERFS_OLD_BLOCKSIZE 4096
  20.286 +
  20.287 +#define S_ISREG(mode) (((mode) & 0170000) == 0100000)
  20.288 +#define S_ISDIR(mode) (((mode) & 0170000) == 0040000)
  20.289 +#define S_ISLNK(mode) (((mode) & 0170000) == 0120000)
  20.290 +
  20.291 +#define PATH_MAX       1024	/* include/linux/limits.h */
  20.292 +#define MAX_LINK_COUNT    5	/* number of symbolic links to follow */
  20.293 +
  20.294 +/* The size of the node cache */
  20.295 +#define FSYSREISER_CACHE_SIZE 24*1024
  20.296 +#define FSYSREISER_MIN_BLOCKSIZE SECTOR_SIZE
  20.297 +#define FSYSREISER_MAX_BLOCKSIZE FSYSREISER_CACHE_SIZE / 3
  20.298 +
  20.299 +/* Info about currently opened file */
  20.300 +struct fsys_reiser_fileinfo
  20.301 +{
  20.302 +  __u32 k_dir_id;
  20.303 +  __u32 k_objectid;
  20.304 +};
  20.305 +
  20.306 +/* In memory info about the currently mounted filesystem */
  20.307 +struct fsys_reiser_info
  20.308 +{
  20.309 +  /* The last read item head */
  20.310 +  struct item_head *current_ih;
  20.311 +  /* The last read item */
  20.312 +  char *current_item;
  20.313 +  /* The information for the currently opened file */
  20.314 +  struct fsys_reiser_fileinfo fileinfo;
  20.315 +  /* The start of the journal */
  20.316 +  __u32 journal_block;
  20.317 +  /* The size of the journal */
  20.318 +  __u32 journal_block_count;
  20.319 +  /* The first valid descriptor block in journal
  20.320 +     (relative to journal_block) */
  20.321 +  __u32 journal_first_desc;
  20.322 +
  20.323 +  /* The ReiserFS version. */
  20.324 +  __u16 version;
  20.325 +  /* The current depth of the reiser tree. */
  20.326 +  __u16 tree_depth;
  20.327 +  /* SECTOR_SIZE << blocksize_shift == blocksize. */
  20.328 +  __u8  blocksize_shift;
  20.329 +  /* 1 << full_blocksize_shift == blocksize. */
  20.330 +  __u8  fullblocksize_shift;
  20.331 +  /* The reiserfs block size  (must be a power of 2) */
  20.332 +  __u16 blocksize;
  20.333 +  /* The number of cached tree nodes */
  20.334 +  __u16 cached_slots;
  20.335 +  /* The number of valid transactions in journal */
  20.336 +  __u16 journal_transactions;
  20.337 +  
  20.338 +  unsigned int blocks[MAX_HEIGHT];
  20.339 +  unsigned int next_key_nr[MAX_HEIGHT];
  20.340 +};
  20.341 +
  20.342 +/* The cached s+tree blocks in FSYS_BUF,  see below
  20.343 + * for a more detailed description.
  20.344 + */
  20.345 +#define ROOT     ((char *) FSYS_BUF)
  20.346 +#define CACHE(i) (ROOT + ((i) << INFO->fullblocksize_shift))
  20.347 +#define LEAF     CACHE (DISK_LEAF_NODE_LEVEL)
  20.348 +
  20.349 +#define BLOCKHEAD(cache) ((struct block_head *) cache)
  20.350 +#define ITEMHEAD         ((struct item_head  *) ((char *) LEAF + BLKH_SIZE))
  20.351 +#define KEY(cache)       ((struct key        *) ((char *) cache + BLKH_SIZE))
  20.352 +#define DC(cache)        ((struct disk_child *) \
  20.353 +			  ((char *) cache + BLKH_SIZE + KEY_SIZE * nr_item))
  20.354 +/* The fsys_reiser_info block.
  20.355 + */
  20.356 +#define INFO \
  20.357 +    ((struct fsys_reiser_info *) ((char *) FSYS_BUF + FSYSREISER_CACHE_SIZE))
  20.358 +/* 
  20.359 + * The journal cache.  For each transaction it contains the number of
  20.360 + * blocks followed by the real block numbers of this transaction.  
  20.361 + *
  20.362 + * If the block numbers of some transaction won't fit in this space,
  20.363 + * this list is stopped with a 0xffffffff marker and the remaining
  20.364 + * uncommitted transactions aren't cached.  
  20.365 + */
  20.366 +#define JOURNAL_START    ((__u32 *) (INFO + 1))
  20.367 +#define JOURNAL_END      ((__u32 *) (FSYS_BUF + FSYS_BUFLEN))
  20.368 +
  20.369 +#ifdef __amd64
  20.370 +#define BSF "bsfq"
  20.371 +#else
  20.372 +#define BSF "bsfl"
  20.373 +#endif
  20.374 +static __inline__ unsigned long
  20.375 +grub_log2 (unsigned long word)
  20.376 +{
  20.377 +  __asm__ (BSF " %1,%0"
  20.378 +	   : "=r" (word)
  20.379 +	   : "r" (word));
  20.380 +  return word;
  20.381 +}
  20.382 +#define log2 grub_log2
  20.383 +
  20.384 +static __inline__ int
  20.385 +is_power_of_two (unsigned long word)
  20.386 +{
  20.387 +  return (word & -word) == word;
  20.388 +}
  20.389 +
  20.390 +static int 
  20.391 +journal_read (fsi_file_t *ffi, int block, int len, char *buffer) 
  20.392 +{
  20.393 +  return devread (ffi, (INFO->journal_block + block) << INFO->blocksize_shift, 
  20.394 +		  0, len, buffer);
  20.395 +}
  20.396 +
  20.397 +/* Read a block from ReiserFS file system, taking the journal into
  20.398 + * account.  If the block nr is in the journal, the block from the
  20.399 + * journal taken.  
  20.400 + */
  20.401 +static int
  20.402 +block_read (fsi_file_t *ffi, int blockNr, int start, int len, char *buffer)
  20.403 +{
  20.404 +  int transactions = INFO->journal_transactions;
  20.405 +  int desc_block = INFO->journal_first_desc;
  20.406 +  int journal_mask = INFO->journal_block_count - 1;
  20.407 +  int translatedNr = blockNr;
  20.408 +  __u32 *journal_table = JOURNAL_START;
  20.409 +  while (transactions-- > 0) 
  20.410 +    {
  20.411 +      int i = 0;
  20.412 +      int j_len;
  20.413 +      if (*journal_table != 0xffffffff)
  20.414 +	{
  20.415 +	  /* Search for the blockNr in cached journal */
  20.416 +	  j_len = *journal_table++;
  20.417 +	  while (i++ < j_len)
  20.418 +	    {
  20.419 +	      if (*journal_table++ == blockNr)
  20.420 +		{
  20.421 +		  journal_table += j_len - i;
  20.422 +		  goto found;
  20.423 +		}
  20.424 +	    }
  20.425 +	}
  20.426 +      else
  20.427 +	{
  20.428 +	  /* This is the end of cached journal marker.  The remaining
  20.429 +	   * transactions are still on disk.
  20.430 +	   */
  20.431 +	  struct reiserfs_journal_desc   desc;
  20.432 +	  struct reiserfs_journal_commit commit;
  20.433 +
  20.434 +	  if (! journal_read (ffi, desc_block, sizeof (desc), (char *) &desc))
  20.435 +	    return 0;
  20.436 +
  20.437 +	  j_len = desc.j_len;
  20.438 +	  while (i < j_len && i < JOURNAL_TRANS_HALF)
  20.439 +	    if (desc.j_realblock[i++] == blockNr)
  20.440 +	      goto found;
  20.441 +	  
  20.442 +	  if (j_len >= JOURNAL_TRANS_HALF)
  20.443 +	    {
  20.444 +	      int commit_block = (desc_block + 1 + j_len) & journal_mask;
  20.445 +	      if (! journal_read (ffi, commit_block, 
  20.446 +				  sizeof (commit), (char *) &commit))
  20.447 +		return 0;
  20.448 +	      while (i < j_len)
  20.449 +		if (commit.j_realblock[i++ - JOURNAL_TRANS_HALF] == blockNr)
  20.450 +		  goto found;
  20.451 +	    }
  20.452 +	}
  20.453 +      goto not_found;
  20.454 +      
  20.455 +    found:
  20.456 +      translatedNr = INFO->journal_block + ((desc_block + i) & journal_mask);
  20.457 +#ifdef REISERDEBUG
  20.458 +      printf ("block_read: block %d is mapped to journal block %d.\n", 
  20.459 +	      blockNr, translatedNr - INFO->journal_block);
  20.460 +#endif
  20.461 +      /* We must continue the search, as this block may be overwritten
  20.462 +       * in later transactions.
  20.463 +       */
  20.464 +    not_found:
  20.465 +      desc_block = (desc_block + 2 + j_len) & journal_mask;
  20.466 +    }
  20.467 +  return devread (ffi, translatedNr << INFO->blocksize_shift, start, len, buffer);
  20.468 +}
  20.469 +
  20.470 +/* Init the journal data structure.  We try to cache as much as
  20.471 + * possible in the JOURNAL_START-JOURNAL_END space, but if it is full
  20.472 + * we can still read the rest from the disk on demand.
  20.473 + *
  20.474 + * The first number of valid transactions and the descriptor block of the
  20.475 + * first valid transaction are held in INFO.  The transactions are all 
  20.476 + * adjacent, but we must take care of the journal wrap around. 
  20.477 + */
  20.478 +static int
  20.479 +journal_init (fsi_file_t *ffi)
  20.480 +{
  20.481 +  unsigned int block_count = INFO->journal_block_count;
  20.482 +  unsigned int desc_block;
  20.483 +  unsigned int commit_block;
  20.484 +  unsigned int next_trans_id;
  20.485 +  struct reiserfs_journal_header header;
  20.486 +  struct reiserfs_journal_desc   desc;
  20.487 +  struct reiserfs_journal_commit commit;
  20.488 +  __u32 *journal_table = JOURNAL_START;
  20.489 +
  20.490 +  journal_read (ffi, block_count, sizeof (header), (char *) &header);
  20.491 +  desc_block = header.j_first_unflushed_offset;
  20.492 +  if (desc_block >= block_count)
  20.493 +    return 0;
  20.494 +
  20.495 +  INFO->journal_first_desc = desc_block;
  20.496 +  next_trans_id = header.j_last_flush_trans_id + 1;
  20.497 +
  20.498 +#ifdef REISERDEBUG
  20.499 +  printf ("journal_init: last flushed %d\n", 
  20.500 +	  header.j_last_flush_trans_id);
  20.501 +#endif
  20.502 +
  20.503 +  while (1) 
  20.504 +    {
  20.505 +      journal_read (ffi, desc_block, sizeof (desc), (char *) &desc);
  20.506 +      if (substring (JOURNAL_DESC_MAGIC, desc.j_magic)
  20.507 +	  || desc.j_trans_id != next_trans_id
  20.508 +	  || desc.j_mount_id != header.j_mount_id)
  20.509 +	/* no more valid transactions */
  20.510 +	break;
  20.511 +      
  20.512 +      commit_block = (desc_block + desc.j_len + 1) & (block_count - 1);
  20.513 +      journal_read (ffi, commit_block, sizeof (commit), (char *) &commit);
  20.514 +      if (desc.j_trans_id != commit.j_trans_id
  20.515 +	  || desc.j_len != commit.j_len)
  20.516 +	/* no more valid transactions */
  20.517 +	break;
  20.518 +      
  20.519 +#ifdef REISERDEBUG
  20.520 +      printf ("Found valid transaction %d/%d at %d.\n", 
  20.521 +	      desc.j_trans_id, desc.j_mount_id, desc_block);
  20.522 +#endif
  20.523 +
  20.524 +      next_trans_id++;
  20.525 +      if (journal_table < JOURNAL_END)
  20.526 +	{
  20.527 +	  if ((journal_table + 1 + desc.j_len) >= JOURNAL_END)
  20.528 +	    {
  20.529 +	      /* The table is almost full; mark the end of the cached
  20.530 +	       * journal.*/
  20.531 +	      *journal_table = 0xffffffff;
  20.532 +	      journal_table = JOURNAL_END;
  20.533 +	    }
  20.534 +	  else
  20.535 +	    {
  20.536 +	      int i;
  20.537 +	      /* Cache the length and the realblock numbers in the table.
  20.538 +	       * The block number of descriptor can easily be computed.
  20.539 +	       * and need not to be stored here.
  20.540 +	       */
  20.541 +	      *journal_table++ = desc.j_len;
  20.542 +	      for (i = 0; i < desc.j_len && i < JOURNAL_TRANS_HALF; i++)
  20.543 +		{
  20.544 +		  *journal_table++ = desc.j_realblock[i];
  20.545 +#ifdef REISERDEBUG
  20.546 +		  printf ("block %d is in journal %d.\n", 
  20.547 +			  desc.j_realblock[i], desc_block);
  20.548 +#endif
  20.549 +		}
  20.550 +	      for (     ; i < desc.j_len; i++)
  20.551 +		{
  20.552 +		  *journal_table++ = commit.j_realblock[i-JOURNAL_TRANS_HALF];
  20.553 +#ifdef REISERDEBUG
  20.554 +		  printf ("block %d is in journal %d.\n", 
  20.555 +			  commit.j_realblock[i-JOURNAL_TRANS_HALF], 
  20.556 +			  desc_block);
  20.557 +#endif
  20.558 +		}
  20.559 +	    }
  20.560 +	}
  20.561 +      desc_block = (commit_block + 1) & (block_count - 1);
  20.562 +    }
  20.563 +#ifdef REISERDEBUG
  20.564 +  printf ("Transaction %d/%d at %d isn't valid.\n", 
  20.565 +	  desc.j_trans_id, desc.j_mount_id, desc_block);
  20.566 +#endif
  20.567 +
  20.568 +  INFO->journal_transactions
  20.569 +    = next_trans_id - header.j_last_flush_trans_id - 1;
  20.570 +  return errnum == 0;
  20.571 +}
  20.572 +
  20.573 +/* check filesystem types and read superblock into memory buffer */
  20.574 +int
  20.575 +reiserfs_mount (fsi_file_t *ffi)
  20.576 +{
  20.577 +  struct reiserfs_super_block super;
  20.578 +  int superblock = REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS;
  20.579 +
  20.580 +  if (/*part_length < superblock + (sizeof (super) >> SECTOR_BITS)
  20.581 +      || */ !devread (ffi, superblock, 0, sizeof (struct reiserfs_super_block), 
  20.582 +		(char *) &super)
  20.583 +      || (substring (REISER3FS_SUPER_MAGIC_STRING, super.s_magic) > 0
  20.584 +	  && substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0
  20.585 +	  && substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0)
  20.586 +      || (/* check that this is not a copy inside the journal log */
  20.587 +	  super.s_journal_block * super.s_blocksize
  20.588 +	  <= REISERFS_DISK_OFFSET_IN_BYTES))
  20.589 +    {
  20.590 +      /* Try old super block position */
  20.591 +      superblock = REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS;
  20.592 +      if (/*part_length < superblock + (sizeof (super) >> SECTOR_BITS)
  20.593 +	|| */ ! devread (ffi, superblock, 0, sizeof (struct reiserfs_super_block), 
  20.594 +			(char *) &super))
  20.595 +	return 0;
  20.596 +
  20.597 +      if (substring (REISER3FS_SUPER_MAGIC_STRING, super.s_magic) > 0
  20.598 +	  && substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) > 0
  20.599 +	  && substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) > 0)
  20.600 +	{
  20.601 +	  /* pre journaling super block ? */
  20.602 +	  if (substring (REISERFS_SUPER_MAGIC_STRING, 
  20.603 +			 (char*) ((char *) &super + 20)) > 0)
  20.604 +	    return 0;
  20.605 +	  
  20.606 +	  super.s_blocksize = REISERFS_OLD_BLOCKSIZE;
  20.607 +	  super.s_journal_block = 0;
  20.608 +	  super.s_version = 0;
  20.609 +	}
  20.610 +    }
  20.611 +
  20.612 +  /* check the version number.  */
  20.613 +  if (super.s_version > REISERFS_MAX_SUPPORTED_VERSION)
  20.614 +    return 0;
  20.615 +  
  20.616 +  INFO->version = super.s_version;
  20.617 +  INFO->blocksize = super.s_blocksize;
  20.618 +  INFO->fullblocksize_shift = log2 (super.s_blocksize);
  20.619 +  INFO->blocksize_shift = INFO->fullblocksize_shift - SECTOR_BITS;
  20.620 +  INFO->cached_slots = 
  20.621 +    (FSYSREISER_CACHE_SIZE >> INFO->fullblocksize_shift) - 1;
  20.622 +
  20.623 +#ifdef REISERDEBUG
  20.624 +  printf ("reiserfs_mount: version=%d, blocksize=%d\n", 
  20.625 +	  INFO->version, INFO->blocksize);
  20.626 +#endif /* REISERDEBUG */
  20.627 +
  20.628 +  /* Clear node cache. */
  20.629 +  memset (INFO->blocks, 0, sizeof (INFO->blocks));
  20.630 +
  20.631 +  if (super.s_blocksize < FSYSREISER_MIN_BLOCKSIZE
  20.632 +      || super.s_blocksize > FSYSREISER_MAX_BLOCKSIZE
  20.633 +      || (SECTOR_SIZE << INFO->blocksize_shift) != super.s_blocksize)
  20.634 +    return 0;
  20.635 +
  20.636 +  /* Initialize journal code.  If something fails we end with zero
  20.637 +   * journal_transactions, so we don't access the journal at all.  
  20.638 +   */
  20.639 +  INFO->journal_transactions = 0;
  20.640 +  if (super.s_journal_block != 0 && super.s_journal_dev == 0)
  20.641 +    {
  20.642 +      INFO->journal_block = super.s_journal_block;
  20.643 +      INFO->journal_block_count = super.s_journal_size;
  20.644 +      if (is_power_of_two (INFO->journal_block_count))
  20.645 +	journal_init (ffi);
  20.646 +
  20.647 +      /* Read in super block again, maybe it is in the journal */
  20.648 +      block_read (ffi, superblock >> INFO->blocksize_shift, 
  20.649 +		  0, sizeof (struct reiserfs_super_block), (char *) &super);
  20.650 +    }
  20.651 +
  20.652 +  if (! block_read (ffi, super.s_root_block, 0, INFO->blocksize, (char*) ROOT))
  20.653 +    return 0;
  20.654 +  
  20.655 +  INFO->tree_depth = BLOCKHEAD (ROOT)->blk_level;
  20.656 +  
  20.657 +#ifdef REISERDEBUG
  20.658 +  printf ("root read_in: block=%d, depth=%d\n", 
  20.659 +	  super.s_root_block, INFO->tree_depth);
  20.660 +#endif /* REISERDEBUG */
  20.661 +
  20.662 +  if (INFO->tree_depth >= MAX_HEIGHT)
  20.663 +    return 0;
  20.664 +  if (INFO->tree_depth == DISK_LEAF_NODE_LEVEL)
  20.665 +    {
  20.666 +      /* There is only one node in the whole filesystem, 
  20.667 +       * which is simultanously leaf and root */
  20.668 +      memcpy (LEAF, ROOT, INFO->blocksize);
  20.669 +    }
  20.670 +  return 1;
  20.671 +}
  20.672 +
  20.673 +/***************** TREE ACCESSING METHODS *****************************/
  20.674 +
  20.675 +/* I assume you are familiar with the ReiserFS tree, if not go to
  20.676 + * http://www.namesys.com/content_table.html
  20.677 + *
  20.678 + * My tree node cache is organized as following
  20.679 + *   0   ROOT node
  20.680 + *   1   LEAF node  (if the ROOT is also a LEAF it is copied here
  20.681 + *   2-n other nodes on current path from bottom to top.  
  20.682 + *       if there is not enough space in the cache, the top most are
  20.683 + *       omitted.
  20.684 + *
  20.685 + * I have only two methods to find a key in the tree:
  20.686 + *   search_stat(dir_id, objectid) searches for the stat entry (always
  20.687 + *       the first entry) of an object.
  20.688 + *   next_key() gets the next key in tree order.
  20.689 + *
  20.690 + * This means, that I can only sequential reads of files are
  20.691 + * efficient, but this really doesn't hurt for grub.  
  20.692 + */
  20.693 +
  20.694 +/* Read in the node at the current path and depth into the node cache.
  20.695 + * You must set INFO->blocks[depth] before.
  20.696 + */
  20.697 +static char *
  20.698 +read_tree_node (fsi_file_t *ffi, unsigned int blockNr, int depth)
  20.699 +{
  20.700 +  char* cache = CACHE(depth);
  20.701 +  int num_cached = INFO->cached_slots;
  20.702 +  if (depth < num_cached)
  20.703 +    {
  20.704 +      /* This is the cached part of the path.  Check if same block is
  20.705 +       * needed.  
  20.706 +       */
  20.707 +      if (blockNr == INFO->blocks[depth])
  20.708 +	return cache;
  20.709 +    }
  20.710 +  else
  20.711 +    cache = CACHE(num_cached);
  20.712 +
  20.713 +#ifdef REISERDEBUG
  20.714 +  printf ("  next read_in: block=%d (depth=%d)\n",
  20.715 +	  blockNr, depth);
  20.716 +#endif /* REISERDEBUG */
  20.717 +  if (! block_read (ffi, blockNr, 0, INFO->blocksize, cache))
  20.718 +    return 0;
  20.719 +  /* Make sure it has the right node level */
  20.720 +  if (BLOCKHEAD (cache)->blk_level != depth)
  20.721 +    {
  20.722 +      errnum = ERR_FSYS_CORRUPT;
  20.723 +      return 0;
  20.724 +    }
  20.725 +
  20.726 +  INFO->blocks[depth] = blockNr;
  20.727 +  return cache;
  20.728 +}
  20.729 +
  20.730 +/* Get the next key, i.e. the key following the last retrieved key in
  20.731 + * tree order.  INFO->current_ih and 
  20.732 + * INFO->current_info are adapted accordingly.  */
  20.733 +static int
  20.734 +next_key (fsi_file_t *ffi)
  20.735 +{
  20.736 +  int depth;
  20.737 +  struct item_head *ih = INFO->current_ih + 1;
  20.738 +  char *cache;
  20.739 +  
  20.740 +#ifdef REISERDEBUG
  20.741 +  printf ("next_key:\n  old ih: key %d:%d:%d:%d version:%d\n", 
  20.742 +	  INFO->current_ih->ih_key.k_dir_id, 
  20.743 +	  INFO->current_ih->ih_key.k_objectid, 
  20.744 +	  INFO->current_ih->ih_key.u.v1.k_offset,
  20.745 +	  INFO->current_ih->ih_key.u.v1.k_uniqueness,
  20.746 +	  INFO->current_ih->ih_version);
  20.747 +#endif /* REISERDEBUG */
  20.748 +  
  20.749 +  if (ih == &ITEMHEAD[BLOCKHEAD (LEAF)->blk_nr_item])
  20.750 +    {
  20.751 +      depth = DISK_LEAF_NODE_LEVEL;
  20.752 +      /* The last item, was the last in the leaf node.  
  20.753 +       * Read in the next block 
  20.754 +       */
  20.755 +      do
  20.756 +	{
  20.757 +	  if (depth == INFO->tree_depth)
  20.758 +	    {
  20.759 +	      /* There are no more keys at all.
  20.760 +	       * Return a dummy item with MAX_KEY */
  20.761 +	      ih = (struct item_head *) &BLOCKHEAD (LEAF)->blk_right_delim_key;
  20.762 +	      goto found;
  20.763 +	    }
  20.764 +	  depth++;
  20.765 +#ifdef REISERDEBUG
  20.766 +	  printf ("  depth=%d, i=%d\n", depth, INFO->next_key_nr[depth]);
  20.767 +#endif /* REISERDEBUG */
  20.768 +	}
  20.769 +      while (INFO->next_key_nr[depth] == 0);
  20.770 +      
  20.771 +      if (depth == INFO->tree_depth)
  20.772 +	cache = ROOT;
  20.773 +      else if (depth <= INFO->cached_slots)
  20.774 +	cache = CACHE (depth);
  20.775 +      else 
  20.776 +	{
  20.777 +	  cache = read_tree_node (ffi, INFO->blocks[depth], depth);
  20.778 +	  if (! cache)
  20.779 +	    return 0;
  20.780 +	}
  20.781 +      
  20.782 +      do
  20.783 +	{
  20.784 +	  int nr_item = BLOCKHEAD (cache)->blk_nr_item;
  20.785 +	  int key_nr = INFO->next_key_nr[depth]++;
  20.786 +#ifdef REISERDEBUG
  20.787 +	  printf ("  depth=%d, i=%d/%d\n", depth, key_nr, nr_item);
  20.788 +#endif /* REISERDEBUG */
  20.789 +	  if (key_nr == nr_item)
  20.790 +	    /* This is the last item in this block, set the next_key_nr to 0 */
  20.791 +	    INFO->next_key_nr[depth] = 0;
  20.792 +
  20.793 +	  cache = read_tree_node (ffi, DC (cache)[key_nr].dc_block_number, --depth);
  20.794 +	  if (! cache)
  20.795 +	    return 0;
  20.796 +	}
  20.797 +      while (depth > DISK_LEAF_NODE_LEVEL);
  20.798 +      
  20.799 +      ih = ITEMHEAD;
  20.800 +    }
  20.801 + found:
  20.802 +  INFO->current_ih   = ih;
  20.803 +  INFO->current_item = &LEAF[ih->ih_item_location];
  20.804 +#ifdef REISERDEBUG
  20.805 +  printf ("  new ih: key %d:%d:%d:%d version:%d\n", 
  20.806 +	  INFO->current_ih->ih_key.k_dir_id, 
  20.807 +	  INFO->current_ih->ih_key.k_objectid, 
  20.808 +	  INFO->current_ih->ih_key.u.v1.k_offset,
  20.809 +	  INFO->current_ih->ih_key.u.v1.k_uniqueness,
  20.810 +	  INFO->current_ih->ih_version);
  20.811 +#endif /* REISERDEBUG */
  20.812 +  return 1;
  20.813 +}
  20.814 +
  20.815 +/* preconditions: reiserfs_mount already executed, therefore 
  20.816 + *   INFO block is valid
  20.817 + * returns: 0 if error (errnum is set), 
  20.818 + *   nonzero iff we were able to find the key successfully.
  20.819 + * postconditions: on a nonzero return, the current_ih and 
  20.820 + *   current_item fields describe the key that equals the
  20.821 + *   searched key.  INFO->next_key contains the next key after
  20.822 + *   the searched key.
  20.823 + * side effects: messes around with the cache.
  20.824 + */
  20.825 +static int
  20.826 +search_stat (fsi_file_t *ffi, __u32 dir_id, __u32 objectid) 
  20.827 +{
  20.828 +  char *cache;
  20.829 +  int depth;
  20.830 +  int nr_item;
  20.831 +  int i;
  20.832 +  struct item_head *ih;
  20.833 +#ifdef REISERDEBUG
  20.834 +  printf ("search_stat:\n  key %d:%d:0:0\n", dir_id, objectid);
  20.835 +#endif /* REISERDEBUG */
  20.836 +  
  20.837 +  depth = INFO->tree_depth;
  20.838 +  cache = ROOT;
  20.839 +  
  20.840 +  while (depth > DISK_LEAF_NODE_LEVEL)
  20.841 +    {
  20.842 +      struct key *key;
  20.843 +      nr_item = BLOCKHEAD (cache)->blk_nr_item;
  20.844 +      
  20.845 +      key = KEY (cache);
  20.846 +      
  20.847 +      for (i = 0; i < nr_item; i++) 
  20.848 +	{
  20.849 +	  if (key->k_dir_id > dir_id
  20.850 +	      || (key->k_dir_id == dir_id 
  20.851 +		  && (key->k_objectid > objectid
  20.852 +		      || (key->k_objectid == objectid
  20.853 +			  && (key->u.v1.k_offset
  20.854 +			      | key->u.v1.k_uniqueness) > 0))))
  20.855 +	    break;
  20.856 +	  key++;
  20.857 +	}
  20.858 +      
  20.859 +#ifdef REISERDEBUG
  20.860 +      printf ("  depth=%d, i=%d/%d\n", depth, i, nr_item);
  20.861 +#endif /* REISERDEBUG */
  20.862 +      INFO->next_key_nr[depth] = (i == nr_item) ? 0 : i+1;
  20.863 +      cache = read_tree_node (ffi, DC (cache)[i].dc_block_number, --depth);
  20.864 +      if (! cache)
  20.865 +	return 0;
  20.866 +    }
  20.867 +  
  20.868 +  /* cache == LEAF */
  20.869 +  nr_item = BLOCKHEAD (LEAF)->blk_nr_item;
  20.870 +  ih = ITEMHEAD;
  20.871 +  for (i = 0; i < nr_item; i++) 
  20.872 +    {
  20.873 +      if (ih->ih_key.k_dir_id == dir_id 
  20.874 +	  && ih->ih_key.k_objectid == objectid
  20.875 +	  && ih->ih_key.u.v1.k_offset == 0
  20.876 +	  && ih->ih_key.u.v1.k_uniqueness == 0)
  20.877 +	{
  20.878 +#ifdef REISERDEBUG
  20.879 +	  printf ("  depth=%d, i=%d/%d\n", depth, i, nr_item);
  20.880 +#endif /* REISERDEBUG */
  20.881 +	  INFO->current_ih   = ih;
  20.882 +	  INFO->current_item = &LEAF[ih->ih_item_location];
  20.883 +	  return 1;
  20.884 +	}
  20.885 +      ih++;
  20.886 +    }
  20.887 +  errnum = ERR_FSYS_CORRUPT;
  20.888 +  return 0;
  20.889 +}
  20.890 +
  20.891 +int
  20.892 +reiserfs_read (fsi_file_t *ffi, char *buf, int len)
  20.893 +{
  20.894 +  unsigned int blocksize;
  20.895 +  unsigned int offset;
  20.896 +  unsigned int to_read;
  20.897 +  char *prev_buf = buf;
  20.898 +  
  20.899 +#ifdef REISERDEBUG
  20.900 +  printf ("reiserfs_read: filepos=%d len=%d, offset=%x:%x\n",
  20.901 +	  filepos, len, (__u64) IH_KEY_OFFSET (INFO->current_ih) - 1);
  20.902 +#endif /* REISERDEBUG */
  20.903 +  
  20.904 +  if (INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid
  20.905 +      || IH_KEY_OFFSET (INFO->current_ih) > filepos + 1)
  20.906 +    {
  20.907 +      search_stat (ffi, INFO->fileinfo.k_dir_id, INFO->fileinfo.k_objectid);
  20.908 +      goto get_next_key;
  20.909 +    }
  20.910 +  
  20.911 +  while (! errnum)
  20.912 +    {
  20.913 +      if (INFO->current_ih->ih_key.k_objectid != INFO->fileinfo.k_objectid)
  20.914 +	break;
  20.915 +      
  20.916 +      offset = filepos - IH_KEY_OFFSET (INFO->current_ih) + 1;
  20.917 +      blocksize = INFO->current_ih->ih_item_len;
  20.918 +      
  20.919 +#ifdef REISERDEBUG
  20.920 +      printf ("  loop: filepos=%d len=%d, offset=%d blocksize=%d\n",
  20.921 +	      filepos, len, offset, blocksize);
  20.922 +#endif /* REISERDEBUG */
  20.923 +      
  20.924 +      if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_DIRECT)
  20.925 +	  && offset < blocksize)
  20.926 +	{
  20.927 +#ifdef REISERDEBUG
  20.928 +	  printf ("direct_read: offset=%d, blocksize=%d\n",
  20.929 +		  offset, blocksize);
  20.930 +#endif /* REISERDEBUG */
  20.931 +	  to_read = blocksize - offset;
  20.932 +	  if (to_read > len)
  20.933 +	    to_read = len;
  20.934 +	  
  20.935 +	  if (disk_read_hook != NULL)
  20.936 +	    {
  20.937 +	      disk_read_func = disk_read_hook;
  20.938 +	      
  20.939 +	      block_read (ffi, INFO->blocks[DISK_LEAF_NODE_LEVEL],
  20.940 +			  (INFO->current_item - LEAF + offset), to_read, buf);
  20.941 +	      
  20.942 +	      disk_read_func = NULL;
  20.943 +	    }
  20.944 +	  else
  20.945 +	    memcpy (buf, INFO->current_item + offset, to_read);
  20.946 +	  goto update_buf_len;
  20.947 +	}
  20.948 +      else if (IH_KEY_ISTYPE(INFO->current_ih, TYPE_INDIRECT))
  20.949 +	{
  20.950 +	  blocksize = (blocksize >> 2) << INFO->fullblocksize_shift;
  20.951 +#ifdef REISERDEBUG
  20.952 +	  printf ("indirect_read: offset=%d, blocksize=%d\n",
  20.953 +		  offset, blocksize);
  20.954 +#endif /* REISERDEBUG */
  20.955 +	  
  20.956 +	  while (offset < blocksize)
  20.957 +	    {
  20.958 +	      __u32 blocknr = ((__u32 *) INFO->current_item)
  20.959 +		[offset >> INFO->fullblocksize_shift];
  20.960 +	      int blk_offset = offset & (INFO->blocksize-1);
  20.961 +	      
  20.962 +	      to_read = INFO->blocksize - blk_offset;
  20.963 +	      if (to_read > len)
  20.964 +		to_read = len;
  20.965 +	      
  20.966 +	      disk_read_func = disk_read_hook;
  20.967 +	      
  20.968 +	      /* Journal is only for meta data.  Data blocks can be read
  20.969 +	       * directly without using block_read
  20.970 +	       */
  20.971 +	      devread (ffi, blocknr << INFO->blocksize_shift,
  20.972 +		       blk_offset, to_read, buf);
  20.973 +	      
  20.974 +	      disk_read_func = NULL;
  20.975 +	    update_buf_len:
  20.976 +	      len -= to_read;
  20.977 +	      buf += to_read;
  20.978 +	      offset += to_read;
  20.979 +	      filepos += to_read;
  20.980 +	      if (len == 0)
  20.981 +		goto done;
  20.982 +	    }
  20.983 +	}
  20.984 +    get_next_key:
  20.985 +      next_key (ffi);
  20.986 +    }
  20.987 + done:
  20.988 +  return errnum ? 0 : buf - prev_buf;
  20.989 +}
  20.990 +
  20.991 +
  20.992 +/* preconditions: reiserfs_mount already executed, therefore 
  20.993 + *   INFO block is valid
  20.994 + * returns: 0 if error, nonzero iff we were able to find the file successfully
  20.995 + * postconditions: on a nonzero return, INFO->fileinfo contains the info
  20.996 + *   of the file we were trying to look up, filepos is 0 and filemax is 
  20.997 + *   the size of the file.
  20.998 + */
  20.999 +int
 20.1000 +reiserfs_dir (fsi_file_t *ffi, char *dirname)
 20.1001 +{
 20.1002 +  struct reiserfs_de_head *de_head;
 20.1003 +  char *rest, ch;
 20.1004 +  __u32 dir_id, objectid, parent_dir_id = 0, parent_objectid = 0;
 20.1005 +#ifndef STAGE1_5
 20.1006 +  int do_possibilities = 0;
 20.1007 +#endif /* ! STAGE1_5 */
 20.1008 +  char linkbuf[PATH_MAX];	/* buffer for following symbolic links */
 20.1009 +  int link_count = 0;
 20.1010 +  int mode;
 20.1011 +
 20.1012 +  dir_id = REISERFS_ROOT_PARENT_OBJECTID;
 20.1013 +  objectid = REISERFS_ROOT_OBJECTID;
 20.1014 +  
 20.1015 +  while (1)
 20.1016 +    {
 20.1017 +#ifdef REISERDEBUG
 20.1018 +      printf ("dirname=%s\n", dirname);
 20.1019 +#endif /* REISERDEBUG */
 20.1020 +      
 20.1021 +      /* Search for the stat info first. */
 20.1022 +      if (! search_stat (ffi, dir_id, objectid))
 20.1023 +	return 0;
 20.1024 +      
 20.1025 +#ifdef REISERDEBUG
 20.1026 +      printf ("sd_mode=%x sd_size=%d\n", 
 20.1027 +	      ((struct stat_data *) INFO->current_item)->sd_mode,
 20.1028 +	      ((struct stat_data *) INFO->current_item)->sd_size);
 20.1029 +#endif /* REISERDEBUG */
 20.1030 +      
 20.1031 +      mode = ((struct stat_data *) INFO->current_item)->sd_mode;
 20.1032 +
 20.1033 +      /* If we've got a symbolic link, then chase it. */
 20.1034 +      if (S_ISLNK (mode))
 20.1035 +	{
 20.1036 +	  int len;
 20.1037 +	  if (++link_count > MAX_LINK_COUNT)
 20.1038 +	    {
 20.1039 +	      errnum = ERR_SYMLINK_LOOP;
 20.1040 +	      return 0;
 20.1041 +	    }
 20.1042 +
 20.1043 +	  /* Get the symlink size. */
 20.1044 +	  filemax = ((struct stat_data *) INFO->current_item)->sd_size;
 20.1045 +
 20.1046 +	  /* Find out how long our remaining name is. */
 20.1047 +	  len = 0;
 20.1048 +	  while (dirname[len] && !isspace (dirname[len]))
 20.1049 +	    len++;
 20.1050 +
 20.1051 +	  if (filemax + len > sizeof (linkbuf) - 1)
 20.1052 +	    {
 20.1053 +	      errnum = ERR_FILELENGTH;
 20.1054 +	      return 0;
 20.1055 +	    }
 20.1056 + 	  
 20.1057 +	  /* Copy the remaining name to the end of the symlink data.
 20.1058 +	     Note that DIRNAME and LINKBUF may overlap! */
 20.1059 +	  grub_memmove (linkbuf + filemax, dirname, len+1);
 20.1060 +
 20.1061 +	  INFO->fileinfo.k_dir_id = dir_id;
 20.1062 +	  INFO->fileinfo.k_objectid = objectid;
 20.1063 +  	  filepos = 0;
 20.1064 +	  if (! next_key (ffi)
 20.1065 +	      || reiserfs_read (ffi, linkbuf, filemax) != filemax)
 20.1066 +	    {
 20.1067 +	      if (! errnum)
 20.1068 +		errnum = ERR_FSYS_CORRUPT;
 20.1069 +	      return 0;
 20.1070 +	    }
 20.1071 +
 20.1072 +#ifdef REISERDEBUG
 20.1073 +	  printf ("symlink=%s\n", linkbuf);
 20.1074 +#endif /* REISERDEBUG */
 20.1075 +
 20.1076 +	  dirname = linkbuf;
 20.1077 +	  if (*dirname == '/')
 20.1078 +	    {
 20.1079 +	      /* It's an absolute link, so look it up in root. */
 20.1080 +	      dir_id = REISERFS_ROOT_PARENT_OBJECTID;
 20.1081 +	      objectid = REISERFS_ROOT_OBJECTID;
 20.1082 +	    }
 20.1083 +	  else
 20.1084 +	    {
 20.1085 +	      /* Relative, so look it up in our parent directory. */
 20.1086 +	      dir_id   = parent_dir_id;
 20.1087 +	      objectid = parent_objectid;
 20.1088 +	    }
 20.1089 +
 20.1090 +	  /* Now lookup the new name. */
 20.1091 +	  continue;
 20.1092 +	}
 20.1093 +
 20.1094 +      /* if we have a real file (and we're not just printing possibilities),
 20.1095 +	 then this is where we want to exit */
 20.1096 +      
 20.1097 +      if (! *dirname || isspace (*dirname))
 20.1098 +	{
 20.1099 +	  if (! S_ISREG (mode))
 20.1100 +	    {
 20.1101 +	      errnum = ERR_BAD_FILETYPE;
 20.1102 +	      return 0;
 20.1103 +	    }
 20.1104 +	  
 20.1105 +	  filepos = 0;
 20.1106 +	  filemax = ((struct stat_data *) INFO->current_item)->sd_size;
 20.1107 +	  
 20.1108 +	  /* If this is a new stat data and size is > 4GB set filemax to 
 20.1109 +	   * maximum
 20.1110 +	   */
 20.1111 +	  if (INFO->current_ih->ih_version == ITEM_VERSION_2
 20.1112 +	      && ((struct stat_data *) INFO->current_item)->sd_size_hi > 0)
 20.1113 +	    filemax = 0xffffffff;
 20.1114 +	  
 20.1115 +	  INFO->fileinfo.k_dir_id = dir_id;
 20.1116 +	  INFO->fileinfo.k_objectid = objectid;
 20.1117 +	  return next_key (ffi);
 20.1118 +	}
 20.1119 +      
 20.1120 +      /* continue with the file/directory name interpretation */
 20.1121 +      while (*dirname == '/')
 20.1122 +	dirname++;
 20.1123 +      if (! S_ISDIR (mode))
 20.1124 +	{
 20.1125 +	  errnum = ERR_BAD_FILETYPE;
 20.1126 +	  return 0;
 20.1127 +	}
 20.1128 +      for (rest = dirname; (ch = *rest) && ! isspace (ch) && ch != '/'; rest++);
 20.1129 +      *rest = 0;
 20.1130 +      
 20.1131 +# ifndef STAGE1_5
 20.1132 +      if (print_possibilities && ch != '/')
 20.1133 +	do_possibilities = 1;
 20.1134 +# endif /* ! STAGE1_5 */
 20.1135 +      
 20.1136 +      while (1)
 20.1137 +	{
 20.1138 +	  char *name_end;
 20.1139 +	  int num_entries;
 20.1140 +	  
 20.1141 +	  if (! next_key (ffi))
 20.1142 +	    return 0;
 20.1143 +#ifdef REISERDEBUG
 20.1144 +	  printf ("ih: key %d:%d:%d:%d version:%d\n", 
 20.1145 +		  INFO->current_ih->ih_key.k_dir_id, 
 20.1146 +		  INFO->current_ih->ih_key.k_objectid, 
 20.1147 +		  INFO->current_ih->ih_key.u.v1.k_offset,
 20.1148 +		  INFO->current_ih->ih_key.u.v1.k_uniqueness,
 20.1149 +		  INFO->current_ih->ih_version);
 20.1150 +#endif /* REISERDEBUG */
 20.1151 +	  
 20.1152 +	  if (INFO->current_ih->ih_key.k_objectid != objectid)
 20.1153 +	    break;
 20.1154 +	  
 20.1155 +	  name_end = INFO->current_item + INFO->current_ih->ih_item_len;
 20.1156 +	  de_head = (struct reiserfs_de_head *) INFO->current_item;
 20.1157 +	  num_entries = INFO->current_ih->u.ih_entry_count;
 20.1158 +	  while (num_entries > 0)
 20.1159 +	    {
 20.1160 +	      char *filename = INFO->current_item + de_head->deh_location;
 20.1161 +	      char  tmp = *name_end;
 20.1162 +	      if ((de_head->deh_state & DEH_Visible))
 20.1163 +		{
 20.1164 +		  int cmp;
 20.1165 +		  /* Directory names in ReiserFS are not null
 20.1166 +		   * terminated.  We write a temporary 0 behind it.
 20.1167 +		   * NOTE: that this may overwrite the first block in
 20.1168 +		   * the tree cache.  That doesn't hurt as long as we
 20.1169 +		   * don't call next_key () in between.  
 20.1170 +		   */
 20.1171 +		  *name_end = 0;
 20.1172 +		  cmp = substring (dirname, filename);
 20.1173 +		  *name_end = tmp;
 20.1174 +# ifndef STAGE1_5
 20.1175 +		  if (do_possibilities)
 20.1176 +		    {
 20.1177 +		      if (cmp <= 0)
 20.1178 +			{
 20.1179 +			  if (print_possibilities > 0)
 20.1180 +			    print_possibilities = -print_possibilities;
 20.1181 +			  *name_end = 0;
 20.1182 +			  print_a_completion (filename);
 20.1183 +			  *name_end = tmp;
 20.1184 +			}
 20.1185 +		    }
 20.1186 +		  else
 20.1187 +# endif /* ! STAGE1_5 */
 20.1188 +		    if (cmp == 0)
 20.1189 +		      goto found;
 20.1190 +		}
 20.1191 +	      /* The beginning of this name marks the end of the next name.
 20.1192 +	       */
 20.1193 +	      name_end = filename;
 20.1194 +	      de_head++;
 20.1195 +	      num_entries--;
 20.1196 +	    }
 20.1197 +	}
 20.1198 +      
 20.1199 +# ifndef STAGE1_5
 20.1200 +      if (print_possibilities < 0)
 20.1201 +	return 1;
 20.1202 +# endif /* ! STAGE1_5 */
 20.1203 +      
 20.1204 +      errnum = ERR_FILE_NOT_FOUND;
 20.1205 +      *rest = ch;
 20.1206 +      return 0;
 20.1207 +      
 20.1208 +    found:
 20.1209 +      
 20.1210 +      *rest = ch;
 20.1211 +      dirname = rest;
 20.1212 +
 20.1213 +      parent_dir_id = dir_id;
 20.1214 +      parent_objectid = objectid;
 20.1215 +      dir_id = de_head->deh_dir_id;
 20.1216 +      objectid = de_head->deh_objectid;
 20.1217 +    }
 20.1218 +}
 20.1219 +
 20.1220 +int
 20.1221 +reiserfs_embed (fsi_file_t *ffi, int *start_sector, int needed_sectors)
 20.1222 +{
 20.1223 +  struct reiserfs_super_block super;
 20.1224 +  int num_sectors;
 20.1225 +  
 20.1226 +  if (! devread (ffi, REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS, 0, 
 20.1227 +		 sizeof (struct reiserfs_super_block), (char *) &super))
 20.1228 +    return 0;
 20.1229 +  
 20.1230 +  *start_sector = 1; /* reserve first sector for stage1 */
 20.1231 +  if ((substring (REISERFS_SUPER_MAGIC_STRING, super.s_magic) <= 0
 20.1232 +       || substring (REISER2FS_SUPER_MAGIC_STRING, super.s_magic) <= 0
 20.1233 +       || substring (REISER3FS_SUPER_MAGIC_STRING, super.s_magic) <= 0)
 20.1234 +      && (/* check that this is not a super block copy inside
 20.1235 +	   * the journal log */
 20.1236 +	  super.s_journal_block * super.s_blocksize 
 20.1237 +	  > REISERFS_DISK_OFFSET_IN_BYTES))
 20.1238 +    num_sectors = (REISERFS_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1;
 20.1239 +  else
 20.1240 +    num_sectors = (REISERFS_OLD_DISK_OFFSET_IN_BYTES >> SECTOR_BITS) - 1;
 20.1241 +  
 20.1242 +  return (needed_sectors <= num_sectors);
 20.1243 +}
 20.1244 +
 20.1245 +fsi_plugin_ops_t *
 20.1246 +fsi_init_plugin(int version, fsi_plugin_t *fp, const char **name)
 20.1247 +{
 20.1248 +	static fsig_plugin_ops_t ops = {
 20.1249 +		FSIMAGE_PLUGIN_VERSION,
 20.1250 +		.fpo_mount = reiserfs_mount,
 20.1251 +		.fpo_dir = reiserfs_dir,
 20.1252 +		.fpo_read = reiserfs_read
 20.1253 +	};
 20.1254 +
 20.1255 +	*name = "reiserfs";
 20.1256 +	return (fsig_init(fp, &ops));
 20.1257 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/tools/libfsimage/ufs/Makefile	Thu Nov 09 14:09:53 2006 +0000
    21.3 @@ -0,0 +1,13 @@
    21.4 +XEN_ROOT = ../../..
    21.5 +
    21.6 +LIB_SRCS-y = fsys_ufs.c
    21.7 +
    21.8 +FS = ufs
    21.9 +
   21.10 +.PHONY: all
   21.11 +all: fs-all
   21.12 +
   21.13 +.PHONY: install
   21.14 +install: fs-install
   21.15 +
   21.16 +include $(XEN_ROOT)/tools/libfsimage/Rules.mk
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/tools/libfsimage/ufs/fsys_ufs.c	Thu Nov 09 14:09:53 2006 +0000
    22.3 @@ -0,0 +1,276 @@
    22.4 +/*  
    22.5 + *  GRUB  --  GRand Unified Bootloader
    22.6 + *  Copyright (C) 2006 Free Software Foundation, Inc.
    22.7 + *
    22.8 + *  This program is free software; you can redistribute it and/or modify
    22.9 + *  it under the terms of the GNU General Public License as published by
   22.10 + *  the Free Software Foundation; either version 2 of the License, or
   22.11 + *  (at your option) any later version.
   22.12 + *
   22.13 + *  This program is distributed in the hope that it will be useful,
   22.14 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   22.15 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   22.16 + *  GNU General Public License for more details.
   22.17 + *
   22.18 + *  You should have received a copy of the GNU General Public License
   22.19 + *  along with this program; if not, write to the Free Software
   22.20 + *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   22.21 + */
   22.22 +/*
   22.23 + * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
   22.24 + * Use is subject to license terms.
   22.25 + */
   22.26 +
   22.27 +/* From Solaris usr/src/stand/lib/fs/ufs/ufsops.c */
   22.28 +
   22.29 +#include <fsimage_grub.h>
   22.30 +
   22.31 +#include "ufs.h"
   22.32 +
   22.33 +/* These are the pools of buffers, etc. */
   22.34 +
   22.35 +#define SUPERBLOCK ((struct fs *)(FSYS_BUF + 0x2000))
   22.36 +#define	INODE ((struct icommon *)(FSYS_BUF + 0x1000))
   22.37 +#define DIRENT (FSYS_BUF + 0x4000)
   22.38 +#define INDIRBLK1 ((grub_daddr32_t *)(FSYS_BUF + 0x4000)) /* 2+ indir blk */
   22.39 +#define	INDIRBLK0 ((grub_daddr32_t *)(FSYS_BUF+ 0x6000))  /* 1st indirect blk */
   22.40 +
   22.41 +#define	indirblk0 (*fsig_int1(ffi))
   22.42 +#define	indirblk1 (*fsig_int2(ffi))
   22.43 +
   22.44 +static int openi(fsi_file_t *, grub_ino_t);
   22.45 +static grub_ino_t dlook(fsi_file_t *, grub_ino_t, char *);
   22.46 +static grub_daddr32_t sbmap(fsi_file_t *, grub_daddr32_t);
   22.47 +
   22.48 +/* read superblock and check fs magic */
   22.49 +int
   22.50 +ufs_mount(fsi_file_t *ffi)
   22.51 +{
   22.52 +	if (/*! IS_PC_SLICE_TYPE_SOLARIS(current_slice) || */
   22.53 +	    !devread(ffi, UFS_SBLOCK, 0, UFS_SBSIZE, (char *)SUPERBLOCK) ||
   22.54 +	    SUPERBLOCK->fs_magic != UFS_MAGIC)
   22.55 +		return 0;
   22.56 +
   22.57 +	return 1;
   22.58 +}
   22.59 +
   22.60 +
   22.61 +/*
   22.62 + * searching for a file, if successful, inode will be loaded in INODE
   22.63 + * The entry point should really be named ufs_open(char *pathname).
   22.64 + * For now, keep it consistent with the rest of fsys modules.
   22.65 + */
   22.66 +int
   22.67 +ufs_dir(fsi_file_t *ffi, char *dirname)
   22.68 +{
   22.69 +	grub_ino_t inode = ROOTINO;	/* start from root */
   22.70 +	char *fname, ch;
   22.71 +
   22.72 +	indirblk0 = indirblk1 = 0;
   22.73 +
   22.74 +	/* skip leading slashes */
   22.75 +	while (*dirname == '/')
   22.76 +		dirname++;
   22.77 +
   22.78 +	while (inode && *dirname && !isspace(*dirname)) {
   22.79 +		if (!openi(ffi, inode))
   22.80 +			return 0;
   22.81 +
   22.82 +		/* parse for next path component */
   22.83 +		fname = dirname;
   22.84 +		while (*dirname && !isspace(*dirname) && *dirname != '/')
   22.85 +			dirname++;
   22.86 +		ch = *dirname;
   22.87 +		*dirname = 0;	/* ensure null termination */
   22.88 +
   22.89 +		inode = dlook(ffi, inode, fname);
   22.90 +		*dirname = ch;
   22.91 +		while (*dirname == '/')
   22.92 +			dirname++;
   22.93 +	}
   22.94 +
   22.95 +	/* return 1 only if inode exists and is a regular file */
   22.96 +	if  (! openi(ffi, inode))
   22.97 +		return (0);
   22.98 +	filepos = 0;
   22.99 +	filemax = INODE->ic_sizelo;
  22.100 +	return (inode && ((INODE->ic_smode & IFMT) == IFREG));
  22.101 +}
  22.102 +
  22.103 +/*
  22.104 + * This is the high-level read function.
  22.105 + */
  22.106 +int
  22.107 +ufs_read(fsi_file_t *ffi, char *buf, int len)
  22.108 +{
  22.109 +  	int off, size, ret = 0, ok;
  22.110 +	grub_daddr32_t lblk, dblk;
  22.111 +
  22.112 +  	while (len) {
  22.113 +	  	off = blkoff(SUPERBLOCK, filepos);
  22.114 +		lblk = lblkno(SUPERBLOCK, filepos);
  22.115 +		size = SUPERBLOCK->fs_bsize;
  22.116 +		size -= off;
  22.117 +		if (size > len)
  22.118 +		  	size = len;
  22.119 +
  22.120 +		if ((dblk = sbmap(ffi, lblk)) <= 0) {
  22.121 +			/* we are in a file hole, just zero the buf */
  22.122 +			grub_memset(buf, 0, size);
  22.123 +		} else {
  22.124 +			disk_read_func = disk_read_hook;
  22.125 +			ok = devread(ffi, fsbtodb(SUPERBLOCK, dblk),
  22.126 +				off, size, buf);
  22.127 +			disk_read_func = 0;
  22.128 +			if (!ok)
  22.129 +		  		return 0;
  22.130 +		}
  22.131 +		buf += size;
  22.132 +		len -= size;
  22.133 +		filepos += size;
  22.134 +		ret += size;
  22.135 +	}
  22.136 +
  22.137 +	return (ret);
  22.138 +}
  22.139 +
  22.140 +int
  22.141 +ufs_embed (int *start_sector, int needed_sectors)
  22.142 +{
  22.143 +	if (needed_sectors > 14)
  22.144 +        	return 0;
  22.145 +
  22.146 +	*start_sector = 2;
  22.147 +	return 1;
  22.148 +}
  22.149 +
  22.150 +/* read inode and place content in INODE */
  22.151 +static int
  22.152 +openi(fsi_file_t *ffi, grub_ino_t inode)
  22.153 +{
  22.154 +	grub_daddr32_t dblk;
  22.155 +	int off;
  22.156 +
  22.157 +	/* get block and byte offset into the block */
  22.158 +	dblk = fsbtodb(SUPERBLOCK, itod(SUPERBLOCK, inode));
  22.159 +	off = itoo(SUPERBLOCK, inode) * sizeof (struct icommon);
  22.160 +
  22.161 +	return (devread(ffi, dblk, off, sizeof (struct icommon), (char *)INODE));
  22.162 +}
  22.163 +
  22.164 +/*
  22.165 + * Performs fileblock mapping. Convert file block no. to disk block no.
  22.166 + * Returns 0 when block doesn't exist and <0 when block isn't initialized
  22.167 + * (i.e belongs to a hole in the file).
  22.168 + */
  22.169 +grub_daddr32_t
  22.170 +sbmap(fsi_file_t *ffi, grub_daddr32_t bn)
  22.171 +{
  22.172 +  	int level, bound, i, index;
  22.173 +	grub_daddr32_t nb, blkno;
  22.174 +	grub_daddr32_t *db = INODE->ic_db;
  22.175 +
  22.176 +	/* blocks 0..UFS_NDADDR are direct blocks */
  22.177 +	if (bn < UFS_NDADDR) {
  22.178 +		return db[bn];
  22.179 +	}
  22.180 +
  22.181 +	/* determine how many levels of indirection. */
  22.182 +	level = 0;
  22.183 +	bn -= UFS_NDADDR;
  22.184 +	bound = UFS_NINDIR(SUPERBLOCK);
  22.185 +	while (bn >= bound) {
  22.186 +		level++;
  22.187 +		bn -= bound;
  22.188 +		bound *= UFS_NINDIR(SUPERBLOCK);
  22.189 +	}
  22.190 +	if (level >= UFS_NIADDR)	/* bn too big */
  22.191 +		return ((grub_daddr32_t)0);
  22.192 +
  22.193 +	/* fetch the first indirect block */
  22.194 +	nb = INODE->ic_ib[level];
  22.195 +	if (nb == 0) {
  22.196 +		return ((grub_daddr32_t)0);
  22.197 +	}
  22.198 +	if (indirblk0 != nb) {
  22.199 +		indirblk0 = 0;
  22.200 +		blkno = fsbtodb(SUPERBLOCK, nb);
  22.201 +		if (!devread(ffi, blkno, 0, SUPERBLOCK->fs_bsize,
  22.202 +		    (char *)INDIRBLK0))
  22.203 +			return (0);
  22.204 +		indirblk0 = nb;
  22.205 +	}
  22.206 +	bound /= UFS_NINDIR(SUPERBLOCK);
  22.207 +	index = (bn / bound) % UFS_NINDIR(SUPERBLOCK);
  22.208 +	nb = INDIRBLK0[index];
  22.209 +
  22.210 +	/* fetch through the indirect blocks */
  22.211 +	for (i = 1; i <= level; i++) {
  22.212 +		if (indirblk1 != nb) {
  22.213 +			blkno = fsbtodb(SUPERBLOCK, nb);
  22.214 +			if (!devread(ffi, blkno, 0, SUPERBLOCK->fs_bsize,
  22.215 +			    (char *)INDIRBLK1))
  22.216 +				return (0);
  22.217 +			indirblk1 = nb;
  22.218 +		}
  22.219 +		bound /= UFS_NINDIR(SUPERBLOCK);
  22.220 +		index = (bn / bound) % UFS_NINDIR(SUPERBLOCK);
  22.221 +		nb = INDIRBLK1[index];
  22.222 +		if (nb == 0)
  22.223 +			return ((grub_daddr32_t)0);
  22.224 +	}
  22.225 +
  22.226 +	return (nb);
  22.227 +}
  22.228 +
  22.229 +/* search directory content for name, return inode number */
  22.230 +static grub_ino_t
  22.231 +dlook(fsi_file_t *ffi, grub_ino_t dir_ino, char *name)
  22.232 +{
  22.233 +	int loc, off;
  22.234 +	grub_daddr32_t lbn, dbn, dblk;
  22.235 +	struct direct *dp;
  22.236 +
  22.237 +	if ((INODE->ic_smode & IFMT) != IFDIR)
  22.238 +		return 0;
  22.239 +
  22.240 +	loc = 0;
  22.241 +	while (loc < INODE->ic_sizelo) {
  22.242 +	  	/* offset into block */
  22.243 +		off = blkoff(SUPERBLOCK, loc);
  22.244 +		if (off == 0) {		/* need to read in a new block */
  22.245 +		  	/* get logical block number */
  22.246 +			lbn = lblkno(SUPERBLOCK, loc);
  22.247 +			/* resolve indrect blocks */
  22.248 +			dbn = sbmap(ffi, lbn);
  22.249 +			if (dbn == 0)
  22.250 +				return (0);
  22.251 +
  22.252 +			dblk = fsbtodb(SUPERBLOCK, dbn);
  22.253 +			if (!devread(ffi, dblk, 0, SUPERBLOCK->fs_bsize,
  22.254 +			    (char *)DIRENT)) {
  22.255 +				return 0;
  22.256 +			}
  22.257 +		}
  22.258 +
  22.259 +		dp = (struct direct *)(DIRENT + off);
  22.260 +		if (dp->d_ino && substring(name, dp->d_name) == 0)
  22.261 +			return (dp->d_ino);
  22.262 +		loc += dp->d_reclen;
  22.263 +	}
  22.264 +	return (0);
  22.265 +}
  22.266 +
  22.267 +fsi_plugin_ops_t *
  22.268 +fsi_init_plugin(int version, fsi_plugin_t *fp, const char **name)
  22.269 +{
  22.270 +	static fsig_plugin_ops_t ops = {
  22.271 +		FSIMAGE_PLUGIN_VERSION,
  22.272 +		.fpo_mount = ufs_mount,
  22.273 +		.fpo_dir = ufs_dir,
  22.274 +		.fpo_read = ufs_read
  22.275 +	};
  22.276 +
  22.277 +	*name = "ufs";
  22.278 +	return (fsig_init(fp, &ops));
  22.279 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/tools/libfsimage/ufs/ufs.h	Thu Nov 09 14:09:53 2006 +0000
    23.3 @@ -0,0 +1,228 @@
    23.4 +/*
    23.5 + * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
    23.6 + * Use is subject to license terms.
    23.7 + */
    23.8 +
    23.9 +#ifndef _GRUB_UFS_H
   23.10 +#define _GRUB_UFS_H_
   23.11 +
   23.12 +/* ufs specific constants */
   23.13 +#define UFS_SBLOCK	16
   23.14 +#define UFS_SBSIZE	8192
   23.15 +#define	UFS_MAGIC	0x011954
   23.16 +#define	ROOTINO		2	/* i number of all roots */
   23.17 +#define UFS_NDADDR	12	/* direct blocks */
   23.18 +#define	UFS_NIADDR	3	/* indirect blocks */
   23.19 +#define	MAXMNTLEN	512
   23.20 +#define	MAXCSBUFS	32
   23.21 +#define	MAXNAMELEN	256
   23.22 +
   23.23 +/* file types */
   23.24 +#define	IFMT		0xf000
   23.25 +#define	IFREG		0x8000
   23.26 +#define	IFDIR		0x4000
   23.27 +
   23.28 +typedef unsigned char	grub_uchar_t;
   23.29 +typedef	unsigned short	grub_ushort_t;
   23.30 +typedef	unsigned short	grub_o_mode_t;
   23.31 +typedef	unsigned short	grub_o_uid_t;
   23.32 +typedef	unsigned short	grub_o_gid_t;
   23.33 +typedef	uint32_t	grub_ino_t;
   23.34 +typedef	int32_t		grub_int32_t;
   23.35 +typedef	int32_t		grub_uid_t;
   23.36 +typedef	int32_t		grub_gid_t;
   23.37 +typedef uint32_t	grub_uint32_t;
   23.38 +typedef uint32_t	grub_daddr32_t;
   23.39 +typedef	uint32_t	grub_time32_t;
   23.40 +typedef struct { int val[2]; } grub_quad_t;
   23.41 +
   23.42 +struct timeval32 {
   23.43 +  	grub_time32_t	tv_sec;
   23.44 +	grub_int32_t	tv_usec;
   23.45 +};
   23.46 +
   23.47 +/*
   23.48 + * Per cylinder group information; summarized in blocks allocated
   23.49 + * from first cylinder group data blocks.  These blocks have to be
   23.50 + * read in from fs_csaddr (size fs_cssize) in addition to the
   23.51 + * super block.
   23.52 + *
   23.53 + * N.B. sizeof (struct csum) must be a power of two in order for
   23.54 + * the ``fs_cs'' macro to work (see below).
   23.55 + */
   23.56 +struct csum {
   23.57 +	grub_int32_t	cs_ndir;	/* number of directories */
   23.58 +	grub_int32_t	cs_nbfree;	/* number of free blocks */
   23.59 +	grub_int32_t	cs_nifree;	/* number of free inodes */
   23.60 +	grub_int32_t	cs_nffree;	/* number of free frags */
   23.61 +};
   23.62 +
   23.63 +/* Ufs super block */
   23.64 +struct fs {
   23.65 +	grub_uint32_t	fs_link;	/* linked list of file systems */
   23.66 +	grub_uint32_t	fs_rolled;	/* logging only: fs fully rolled */
   23.67 +	grub_daddr32_t	fs_sblkno;	/* addr of super-block in filesys */
   23.68 +	grub_daddr32_t	fs_cblkno;	/* offset of cyl-block in filesys */
   23.69 +	grub_daddr32_t	fs_iblkno;	/* offset of inode-blocks in filesys */
   23.70 +	grub_daddr32_t	fs_dblkno;	/* offset of first data after cg */
   23.71 +	grub_int32_t	fs_cgoffset;	/* cylinder group offset in cylinder */
   23.72 +	grub_int32_t	fs_cgmask;	/* used to calc mod fs_ntrak */
   23.73 +	grub_time32_t	fs_time;	/* last time written */
   23.74 +	grub_int32_t	fs_size;	/* number of blocks in fs */
   23.75 +	grub_int32_t	fs_dsize;	/* number of data blocks in fs */
   23.76 +	grub_int32_t	fs_ncg;		/* number of cylinder groups */
   23.77 +	grub_int32_t	fs_bsize;	/* size of basic blocks in fs */
   23.78 +	grub_int32_t	fs_fsize;	/* size of frag blocks in fs */
   23.79 +	grub_int32_t	fs_frag;	/* number of frags in a block in fs */
   23.80 +	/* these are configuration parameters */
   23.81 +	grub_int32_t	fs_minfree;	/* minimum percentage of free blocks */
   23.82 +	grub_int32_t	fs_rotdelay;	/* num of ms for optimal next block */
   23.83 +	grub_int32_t	fs_rps;		/* disk revolutions per second */
   23.84 +	/* these fields can be computed from the others */
   23.85 +	grub_int32_t	fs_bmask;	/* ``blkoff'' calc of blk offsets */
   23.86 +	grub_int32_t	fs_fmask;	/* ``fragoff'' calc of frag offsets */
   23.87 +	grub_int32_t	fs_bshift;	/* ``lblkno'' calc of logical blkno */
   23.88 +	grub_int32_t	fs_fshift;	/* ``numfrags'' calc number of frags */
   23.89 +	/* these are configuration parameters */
   23.90 +	grub_int32_t	fs_maxcontig;	/* max number of contiguous blks */
   23.91 +	grub_int32_t	fs_maxbpg;	/* max number of blks per cyl group */
   23.92 +	/* these fields can be computed from the others */
   23.93 +	grub_int32_t	fs_fragshift;	/* block to frag shift */
   23.94 +	grub_int32_t	fs_fsbtodb;	/* fsbtodb and dbtofsb shift constant */
   23.95 +	grub_int32_t	fs_sbsize;	/* actual size of super block */
   23.96 +	grub_int32_t	fs_csmask;	/* csum block offset */
   23.97 +	grub_int32_t	fs_csshift;	/* csum block number */
   23.98 +	grub_int32_t	fs_nindir;	/* value of NINDIR */
   23.99 +	grub_int32_t	fs_inopb;	/* value of INOPB */
  23.100 +	grub_int32_t	fs_nspf;	/* value of NSPF */
  23.101 +	/* yet another configuration parameter */
  23.102 +	grub_int32_t	fs_optim;	/* optimization preference, see below */
  23.103 +	/* these fields are derived from the hardware */
  23.104 +	/* USL SVR4 compatibility */
  23.105 +	/*
  23.106 +	 *	* USL SVR4 compatibility
  23.107 +	 *
  23.108 +	 * There was a significant divergence here between Solaris and
  23.109 +	 * SVR4 for x86.	By swapping these two members in the superblock,
  23.110 +	 * we get read-only compatibility of SVR4 filesystems.	Otherwise
  23.111 +	 * there would be no compatibility.	This change was introduced
  23.112 +	 * during bootstrapping of Solaris on x86.	By making this ifdef'ed
  23.113 +	 * on byte order, we provide ongoing compatibility across all
  23.114 +	 * platforms with the same byte order, the highest compatibility
  23.115 +	 * that can be achieved.
  23.116 +	 */
  23.117 +	grub_int32_t	fs_state;	/* file system state time stamp */
  23.118 +	grub_int32_t	fs_si;		/* summary info state - lufs only */
  23.119 +	grub_int32_t	fs_trackskew;	/* sector 0 skew, per track */
  23.120 +	/* unique id for this filesystem (currently unused and unmaintained) */
  23.121 +	/* In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek */
  23.122 +	/* Neither of those fields is used in the Tahoe code right now but */
  23.123 +	/* there could be problems if they are.	*/
  23.124 +	grub_int32_t	fs_id[2];	/* file system id */
  23.125 +	/* sizes determined by number of cylinder groups and their sizes */
  23.126 +	grub_daddr32_t	fs_csaddr;	/* blk addr of cyl grp summary area */
  23.127 +	grub_int32_t	fs_cssize;	/* size of cyl grp summary area */
  23.128 +	grub_int32_t	fs_cgsize;	/* cylinder group size */
  23.129 +	/* these fields are derived from the hardware */
  23.130 +	grub_int32_t	fs_ntrak;	/* tracks per cylinder */
  23.131 +	grub_int32_t	fs_nsect;	/* sectors per track */
  23.132 +	grub_int32_t	fs_spc;		/* sectors per cylinder */
  23.133 +	/* this comes from the disk driver partitioning */
  23.134 +	grub_int32_t	fs_ncyl;	/* cylinders in file system */
  23.135 +	/* these fields can be computed from the others */
  23.136 +	grub_int32_t	fs_cpg;		/* cylinders per group */
  23.137 +	grub_int32_t	fs_ipg;		/* inodes per group */
  23.138 +	grub_int32_t	fs_fpg;		/* blocks per group * fs_frag */
  23.139 +	/* this data must be re-computed after crashes */
  23.140 +	struct csum	fs_cstotal;	/* cylinder summary information */
  23.141 +	/* these fields are cleared at mount time */
  23.142 +	char		fs_fmod;	/* super block modified flag */
  23.143 +	char		fs_clean;	/* file system state flag */
  23.144 +	char		fs_ronly;	/* mounted read-only flag */
  23.145 +	char		fs_flags;	/* largefiles flag, etc. */
  23.146 +	char		fs_fsmnt[MAXMNTLEN];	/* name mounted on */
  23.147 +	/* these fields retain the current block allocation info */
  23.148 +	grub_int32_t	fs_cgrotor;	/* last cg searched */
  23.149 +	/*
  23.150 +	 * The following used to be fs_csp[MAXCSBUFS]. It was not
  23.151 +	 * used anywhere except in old utilities.  We removed this
  23.152 +	 * in 5.6 and expect fs_u.fs_csp to be used instead.
  23.153 +	 * We no longer limit fs_cssize based on MAXCSBUFS.
  23.154 +	 */
  23.155 +	union {	/* fs_cs (csum) info */
  23.156 +		grub_uint32_t	fs_csp_pad[MAXCSBUFS];
  23.157 +		struct csum	*fs_csp;
  23.158 +	} fs_u;
  23.159 +	grub_int32_t	fs_cpc;		/* cyl per cycle in postbl */
  23.160 +	short		fs_opostbl[16][8];  /* old rotation block list head */
  23.161 +	grub_int32_t	fs_sparecon[51];    /* reserved for future constants */
  23.162 +	grub_int32_t	fs_version;	/* minor version of MTB ufs */
  23.163 +	grub_int32_t	fs_logbno;	/* block # of embedded log */
  23.164 +	grub_int32_t	fs_reclaim;	/* reclaim open, deleted files */
  23.165 +	grub_int32_t	fs_sparecon2;	/* reserved for future constant */
  23.166 +	/* USL SVR4 compatibility */
  23.167 +	grub_int32_t	fs_npsect;	/* # sectors/track including spares */
  23.168 +	grub_quad_t	fs_qbmask;	/* ~fs_bmask - for use with quad size */
  23.169 +	grub_quad_t	fs_qfmask;	/* ~fs_fmask - for use with quad size */
  23.170 +	grub_int32_t	fs_postblformat; /* fmt of positional layout tables */
  23.171 +	grub_int32_t	fs_nrpos;	/* number of rotaional positions */
  23.172 +	grub_int32_t	fs_postbloff;	/* (short) rotation block list head */
  23.173 +	grub_int32_t	fs_rotbloff;	/* (grub_uchar_t) blocks for each */
  23.174 +					/* rotation */
  23.175 +	grub_int32_t	fs_magic;	/* magic number */
  23.176 +	grub_uchar_t	fs_space[1];	/* list of blocks for each rotation */
  23.177 +	/* actually longer */
  23.178 +};
  23.179 +
  23.180 +struct icommon {
  23.181 +	grub_o_mode_t	ic_smode;	/* 0: mode and type of file */
  23.182 +	short		ic_nlink;	/* 2: number of links to file */
  23.183 +	grub_o_uid_t	ic_suid;	/* 4: owner's user id */
  23.184 +	grub_o_gid_t	ic_sgid;	/* 6: owner's group id */
  23.185 +	grub_uint32_t	ic_sizelo;	/* 8: number of bytes in file */
  23.186 +	grub_uint32_t	ic_sizehi;	/* 12: number of bytes in file */
  23.187 +	struct timeval32 ic_atime;	/* 16: time last accessed */
  23.188 +	struct timeval32 ic_mtime;	/* 24: time last modified */
  23.189 +	struct timeval32 ic_ctime;	/* 32: last time inode changed */
  23.190 +	grub_daddr32_t	ic_db[UFS_NDADDR];	/* 40: disk block addresses */
  23.191 +	grub_daddr32_t	ic_ib[UFS_NIADDR];	/* 88: indirect blocks */
  23.192 +	grub_int32_t	ic_flags;	/* 100: cflags */
  23.193 +	grub_int32_t	ic_blocks;	/* 104: 512 byte blocks actually held */
  23.194 +	grub_int32_t	ic_gen;		/* 108: generation number */
  23.195 +	grub_int32_t	ic_shadow;	/* 112: shadow inode */
  23.196 +	grub_uid_t	ic_uid;		/* 116: long EFT version of uid */
  23.197 +	grub_gid_t	ic_gid;		/* 120: long EFT version of gid */
  23.198 +	grub_uint32_t	ic_oeftflag;	/* 124: extended attr directory ino, */
  23.199 +					/*      0 = none */
  23.200 +};
  23.201 +
  23.202 +struct direct {
  23.203 +	grub_ino_t	d_ino;
  23.204 +	grub_ushort_t	d_reclen;
  23.205 +	grub_ushort_t	d_namelen;
  23.206 +	char		d_name[MAXNAMELEN + 1];
  23.207 +};
  23.208 +
  23.209 +/* inode macros */
  23.210 +#define INOPB(fs)       ((fs)->fs_inopb)
  23.211 +#define itoo(fs, x)	((x) % (grub_uint32_t)INOPB(fs))
  23.212 +#define	itog(fs, x)	((x) / (grub_uint32_t)(fs)->fs_ipg)
  23.213 +#define itod(fs, x)	((grub_daddr32_t)(cgimin(fs, itog(fs, x)) + \
  23.214 +  (blkstofrags((fs), \
  23.215 +  ((x) % (grub_uint32_t)(fs)->fs_ipg / (grub_uint32_t)INOPB(fs))))))
  23.216 +
  23.217 +/* block conversion macros */
  23.218 +#define	UFS_NINDIR(fs)	((fs)->fs_nindir)	/* # of indirects */
  23.219 +#define blkoff(fs, loc)	((int)((loc & ~(fs)->fs_bmask)))
  23.220 +#define lblkno(fs, loc) ((grub_int32_t)((loc) >> (fs)->fs_bshift))
  23.221 +/* frag to blk */
  23.222 +#define fsbtodb(fs, b)	(((grub_daddr32_t)(b)) << (fs)->fs_fsbtodb)
  23.223 +#define blkstofrags(fs, b) ((b) << (fs)->fs_fragshift)
  23.224 +
  23.225 +/* cynlinder group macros */
  23.226 +#define cgbase(fs, c)	((grub_daddr32_t)((fs)->fs_fpg * (c)))
  23.227 +#define	cgimin(fs, c)	(cgstart(fs, c) + (fs)->fs_iblkno) /* inode block */
  23.228 +#define cgstart(fs, c) \
  23.229 +  (cgbase(fs, c) + (fs)->fs_cgoffset * ((c) & ~((fs)->fs_cgmask)))
  23.230 +
  23.231 +#endif /* !_GRUB_UFS_H */