ia64/xen-unstable
changeset 12338: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>
Initial support is provided for Solaris UFS, ext2 (both using libext2fs
and not), and reiserfs.
Signed-off-by: John Levon <john.levon@sun.com>
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 */