From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by monty-python.gnu.org with archive (Exim 4.34) id 1BQvz8-0003WV-RF for mharc-grub-devel@gnu.org; Thu, 20 May 2004 18:25:55 -0400 Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.34) id 1BQvyz-0003Sl-3j for grub-devel@gnu.org; Thu, 20 May 2004 18:25:45 -0400 Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.34) id 1BQvyR-0003IL-63 for grub-devel@gnu.org; Thu, 20 May 2004 18:25:43 -0400 Received: from [145.74.66.11] (helo=mail-cn.han.nl) by monty-python.gnu.org with esmtp (Exim 4.34) id 1BQvuS-00029W-Na for grub-devel@gnu.org; Thu, 20 May 2004 18:21:05 -0400 Received: from localhost (charlie.han.nl [145.74.66.9]) by mail-cn.han.nl (Postfix) with ESMTP id A384B8926 for ; Fri, 21 May 2004 00:16:44 +0200 (CEST) Received: from mail-cn.han.nl ([145.74.66.11]) by localhost (charlie.han.nl [145.74.66.9]) (amavisd-new, port 10024) with ESMTP id 24616-06; Fri, 21 May 2004 00:16:39 +0200 (CEST) Received: from mail1.han.nl (mail1.han.nl [145.74.103.11]) by mail-cn.han.nl (Postfix) with ESMTP id EAEE288C6; Fri, 21 May 2004 00:15:58 +0200 (CEST) Received: from marco.marco-g.com (a82-92-27-129.adsl.xs4all.nl [82.92.27.129]) by mail1.han.nl (Postfix) with ESMTP id 36D70C048; Thu, 20 May 2004 23:15:56 +0200 (CEST) Mail-Copies-To: metgerards@student.han.nl To: The development of GRUB 2 References: <87ekpoe3qx.fsf@marco.marco-g.com> From: Marco Gerards Date: Fri, 21 May 2004 00:18:20 +0200 In-Reply-To: <87ekpoe3qx.fsf@marco.marco-g.com> (Marco Gerards's message of "Thu, 13 May 2004 17:38:46 +0200") Message-ID: <877jv63fpv.fsf@marco.marco-g.com> User-Agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Virus-Scanned: by amavisd-new@vscan-cn.han.nl Cc: Subject: Re: UFS support X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.4 Precedence: list Reply-To: The development of GRUB 2 List-Id: The development of GRUB 2 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 20 May 2004 22:25:46 -0000 Marco Gerards writes: > I am working on UFS/UFS2 support for GRUB 2 (and it is almost > finished). After that I will work on some other filesystems: Here it is. It supports both UFS and UFS2. I will commit it on Sunday, so please review it before Sunday if you want to check it. Thanks, Marco 2004-05-21 Marco Gerards * conf/i386-pc.rmk (grub_setup_SOURCES): Add fs/ufs.c (grub_emu_SOURCES): Likewise. (pkgdata_MODULES): Add ufs.mod. (ufs_mod_SOURCES): New variable. (ufs_mod_CFLAGS): Likewise. * fs/ufs.c: New file. * include/grub/fs.h (grub_ufs_init): New prototype. (grub_ufs_fini): Likewise. * util/grub-emu.c (main): Initialize and deinitialize UFS. Index: conf/i386-pc.rmk =================================================================== RCS file: /cvsroot/grub/grub2/conf/i386-pc.rmk,v retrieving revision 1.13 diff -u -p -u -p -r1.13 i386-pc.rmk --- conf/i386-pc.rmk 4 Apr 2004 13:46:00 -0000 1.13 +++ conf/i386-pc.rmk 20 May 2004 22:09:47 -0000 @@ -56,7 +56,7 @@ grub_mkimage_LDFLAGS = -llzo grub_setup_SOURCES = util/i386/pc/grub-setup.c util/i386/pc/biosdisk.c \ util/misc.c util/i386/pc/getroot.c kern/device.c kern/disk.c \ kern/err.c kern/misc.c disk/i386/pc/partition.c fs/fat.c fs/ext2.c \ - kern/file.c kern/fs.c kern/env.c + fs/ufs.c kern/file.c kern/fs.c kern/env.c # For grub grub_emu_SOURCES = kern/main.c kern/device.c \ @@ -64,7 +64,7 @@ grub_emu_SOURCES = kern/main.c kern/devi kern/misc.c kern/loader.c kern/rescue.c kern/term.c \ disk/i386/pc/partition.c kern/env.c commands/ls.c \ commands/terminal.c commands/boot.c commands/cmp.c commands/cat.c \ - util/i386/pc/biosdisk.c fs/fat.c fs/ext2.c \ + util/i386/pc/biosdisk.c fs/fat.c fs/ext2.c fs/ufs.c \ normal/cmdline.c normal/command.c normal/main.c normal/menu.c normal/arg.c \ util/console.c util/grub-emu.c util/misc.c util/i386/pc/getroot.c grub_emu_LDFLAGS = -lncurses @@ -73,7 +73,7 @@ grub_emu_LDFLAGS = -lncurses genmoddep_SOURCES = util/genmoddep.c # Modules. -pkgdata_MODULES = _chain.mod _linux.mod fat.mod ext2.mod normal.mod hello.mod \ +pkgdata_MODULES = _chain.mod _linux.mod fat.mod ufs.mod ext2.mod normal.mod hello.mod \ vga.mod font.mod _multiboot.mod ls.mod boot.mod cmp.mod cat.mod terminal.mod # For _chain.mod. @@ -87,6 +87,10 @@ fat_mod_CFLAGS = $(COMMON_CFLAGS) # For ext2.mod. ext2_mod_SOURCES = fs/ext2.c ext2_mod_CFLAGS = $(COMMON_CFLAGS) + +# For ufs.mod. +ufs_mod_SOURCES = fs/ufs.c +ufs_mod_CFLAGS = $(COMMON_CFLAGS) # For _linux.mod. _linux_mod_SOURCES = loader/i386/pc/linux.c Index: fs/ufs.c =================================================================== RCS file: fs/ufs.c diff -N fs/ufs.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ fs/ufs.c 20 May 2004 22:09:47 -0000 @@ -0,0 +1,690 @@ +/* ufs.c - Unix File System */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2004 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + + +#define GRUB_UFS_MAGIC 0x11954 +#define GRUB_UFS2_MAGIC 0x19540119 +#define GRUB_UFS_INODE 2 +#define GRUB_UFS_FILETYPE_DIR 4 +#define GRUB_UFS_FILETYPE_LNK 10 +#define GRUB_UFS_MAX_SYMLNK_CNT 8 + +#define GRUB_UFS_DIRBLKS 12 +#define GRUB_UFS_INDIRBLKS 3 + +#define GRUB_UFS_ATTR_DIR 040000 + +/* Calculate in which group the inode can be found. */ +#define inode_group(inode,sblock) () + +#define UFS_BLKSZ(sblock) (grub_le_to_cpu32 (sblock->bsize)) + +#define INODE(data,field) (data->ufs_type == UFS1 ? \ + data->inode. field : data->inode2. field) +#define INODE_ENDIAN(data,field,bits1,bits2) (data->ufs_type == UFS1 ? \ + grub_le_to_cpu##bits1 (data->inode.field) : \ + grub_le_to_cpu##bits2 (data->inode2.field)) +#define INODE_SIZE(data) INODE_ENDIAN (data,size,32,64) +#define INODE_MODE(data) INODE_ENDIAN (data,mode,16,16) +#define INODE_BLKSZ(data) (data->ufs_type == UFS1 ? 32 : 64) +#define INODE_DIRBLOCKS(data,blk) INODE_ENDIAN \ + (data,blocks.dir_blocks[blk],32,64) +#define INODE_INDIRBLOCKS(data,blk) INODE_ENDIAN \ + (data,blocks.indir_blocks[blk],32,64) + +/* The blocks on which the superblock can be found. */ +static int sblocklist[] = { 128, 16, 0, 512, -1 }; + +struct grub_ufs_sblock +{ + grub_uint8_t unused[16]; + /* The offset of the inodes in the cylinder group. */ + grub_uint32_t inoblk_offs; + + grub_uint8_t unused2[4]; + + /* The start of the cylinder group. */ + grub_uint32_t cylg_offset; + + grub_uint8_t unused3[20]; + + /* The size of a block in bytes. */ + grub_int32_t bsize; + grub_uint8_t unused4[48]; + + /* The size of filesystem blocks to disk blocks. */ + grub_uint32_t log2_blksz; + grub_uint8_t unused5[80]; + + /* Inodes stored per cylinder group. */ + grub_uint32_t ino_per_group; + + /* The frags per cylinder group. */ + grub_uint32_t frags_per_group; + + grub_uint8_t unused7[1180]; + + /* Magic value to check if this is really a UFS filesystem. */ + grub_uint32_t magic; +}; + +/* UFS inode. */ +struct grub_ufs_inode +{ + grub_uint16_t mode; + grub_uint16_t nlinks; + grub_uint16_t uid; + grub_uint16_t gid; + grub_int64_t size; + grub_uint64_t atime; + grub_uint64_t mtime; + grub_uint64_t ctime; + union + { + struct + { + grub_uint32_t dir_blocks[GRUB_UFS_DIRBLKS]; + grub_uint32_t indir_blocks[GRUB_UFS_INDIRBLKS]; + } blocks; + grub_uint8_t symlink[(GRUB_UFS_DIRBLKS + GRUB_UFS_INDIRBLKS) * 4]; + }; + grub_uint32_t flags; + grub_uint32_t nblocks; + grub_uint32_t gen; + grub_uint32_t unused; + grub_uint8_t pad[12]; +}; + +/* UFS inode. */ +struct grub_ufs2_inode +{ + grub_uint16_t mode; + grub_uint16_t nlinks; + grub_uint32_t uid; + grub_uint32_t gid; + grub_uint32_t blocksize; + grub_int64_t size; + grub_int64_t nblocks; + grub_uint64_t atime; + grub_uint64_t mtime; + grub_uint64_t ctime; + grub_uint64_t create_time; + grub_uint32_t atime_sec; + grub_uint32_t mtime_sec; + grub_uint32_t ctime_sec; + grub_uint32_t create_time_sec; + grub_uint32_t gen; + grub_uint32_t kernel_flags; + grub_uint32_t flags; + grub_uint32_t extsz; + grub_uint64_t ext[2]; + union + { + struct + { + grub_uint64_t dir_blocks[GRUB_UFS_DIRBLKS]; + grub_uint64_t indir_blocks[GRUB_UFS_INDIRBLKS]; + } blocks; + grub_uint8_t symlink[(GRUB_UFS_DIRBLKS + GRUB_UFS_INDIRBLKS) * 8]; + }; + + grub_uint8_t unused[24]; +}; + +/* Directory entry. */ +struct grub_ufs_dirent +{ + grub_uint32_t ino; + grub_uint16_t direntlen; + grub_uint8_t filetype; + grub_uint8_t namelen; +}; + +/* Information about a "mounted" ufs filesystem. */ +struct grub_ufs_data +{ + struct grub_ufs_sblock sblock; + grub_disk_t disk; + union + { + struct grub_ufs_inode inode; + struct grub_ufs2_inode inode2; + }; + enum + { + UFS1, + UFS2, + UNKNOWN + } ufs_type; + int ino; + int linknest; +}; + +#ifndef GRUB_UTIL +static grub_dl_t my_mod; +#endif + +/* Forward declaration. */ +static grub_err_t grub_ufs_find_file (struct grub_ufs_data *data, + const char *path); + + +static int +grub_ufs_get_file_block (struct grub_ufs_data *data, unsigned int blk) +{ + struct grub_ufs_sblock *sblock = &data->sblock; + unsigned int indirsz; + + /* Direct. */ + if (blk < GRUB_UFS_DIRBLKS) + return INODE_DIRBLOCKS (data, blk); + + blk -= GRUB_UFS_DIRBLKS; + + indirsz = UFS_BLKSZ (sblock) / INODE_BLKSZ (data); + /* Single indirect block. */ + if (blk < indirsz) + { + grub_uint32_t indir[UFS_BLKSZ (sblock)]; + grub_disk_read (data->disk, INODE_INDIRBLOCKS (data, 0), + 0, sizeof (indir), (char *) indir); + return indir[blk]; + } + blk -= indirsz; + + /* Double indirect block. */ + if (blk < UFS_BLKSZ (sblock) / indirsz) + { + grub_uint32_t indir[UFS_BLKSZ (sblock)]; + + grub_disk_read (data->disk, INODE_INDIRBLOCKS (data, 1), + 0, sizeof (indir), (char *) indir); + grub_disk_read (data->disk, indir[blk / indirsz], + 0, sizeof (indir), (char *) indir); + + return indir[blk % indirsz]; + } + + + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "ufs does not support tripple indirect blocks"); + return 0; +} + + +/* Read LEN bytes from the file described by DATA starting with byte + POS. Return the amount of read bytes in READ. */ +static grub_ssize_t +grub_ufs_read_file (struct grub_ufs_data *data, + void (*read_hook) (unsigned long sector, + unsigned offset, unsigned length), + int pos, unsigned int len, char *buf) +{ + struct grub_ufs_sblock *sblock = &data->sblock; + int i; + int blockcnt; + + /* Adjust len so it we can't read past the end of the file. */ + if (len > INODE_SIZE (data)) + len = INODE_SIZE (data); + + blockcnt = (len + pos + UFS_BLKSZ (sblock) - 1) / UFS_BLKSZ (sblock); + + for (i = pos / UFS_BLKSZ (sblock); i < blockcnt; i++) + { + int blknr; + int blockoff = pos % UFS_BLKSZ (sblock); + int blockend = UFS_BLKSZ (sblock); + + int skipfirst = 0; + + blknr = grub_ufs_get_file_block (data, i); + if (grub_errno) + return -1; + + /* Last block. */ + if (i == blockcnt - 1) + { + blockend = (len + pos) % UFS_BLKSZ (sblock); + + if (!blockend) + blockend = UFS_BLKSZ (sblock); + } + + /* First block. */ + if (i == (pos / (int) UFS_BLKSZ (sblock))) + { + skipfirst = blockoff; + blockend -= skipfirst; + } + + /* XXX: If the block number is 0 this block is not stored on + disk but is zero filled instead. */ + if (blknr) + { + data->disk->read_hook = read_hook; + grub_disk_read (data->disk, + blknr << grub_le_to_cpu32 (data->sblock.log2_blksz), + skipfirst, blockend, buf); + data->disk->read_hook = 0; + if (grub_errno) + return -1; + } + else + grub_memset (buf, UFS_BLKSZ (sblock) - skipfirst, 0); + + buf += UFS_BLKSZ (sblock) - skipfirst; + } + + return len; +} + + +/* Read inode INO from the mounted filesystem described by DATA. This + inode is used by default now. */ +static grub_err_t +grub_ufs_read_inode (struct grub_ufs_data *data, int ino) +{ + struct grub_ufs_sblock *sblock = &data->sblock; + + /* Determine the group the inode is in. */ + int group = ino / grub_le_to_cpu32 (sblock->ino_per_group); + + /* Determine the inode within the group. */ + int grpino = ino % grub_le_to_cpu32 (sblock->ino_per_group); + + /* The first block of the group. */ + int grpblk = group * (grub_le_to_cpu32 (sblock->frags_per_group)); + + if (data->ufs_type == UFS1) + { + struct grub_ufs_inode *inode = &data->inode; + + grub_disk_read (data->disk, + (((grub_le_to_cpu32 (sblock->inoblk_offs) + grpblk) + << grub_le_to_cpu32 (data->sblock.log2_blksz))) + + grpino / 4, + (grpino % 4) * sizeof (struct grub_ufs_inode), + sizeof (struct grub_ufs_inode), + (char *) inode); + } + else + { + struct grub_ufs2_inode *inode = &data->inode2; + + grub_disk_read (data->disk, + (((grub_le_to_cpu32 (sblock->inoblk_offs) + grpblk) + << grub_le_to_cpu32 (data->sblock.log2_blksz))) + + grpino / 2, + (grpino % 2) * sizeof (struct grub_ufs2_inode), + sizeof (struct grub_ufs2_inode), + (char *) inode); + } + + data->ino = ino; + return grub_errno; +} + + +/* Lookup the symlink the current inode points to. INO is the inode + number of the directory the symlink is relative to. */ +static grub_err_t +grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino) +{ + char symlink[INODE_SIZE (data)]; + + if (++data->linknest > GRUB_UFS_MAX_SYMLNK_CNT) + return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks"); + + if (INODE_SIZE (data) < (GRUB_UFS_DIRBLKS + GRUB_UFS_INDIRBLKS + * INODE_BLKSZ (data))) + grub_strcpy (symlink, INODE (data, symlink)); + else + { + grub_disk_read (data->disk, + (INODE_DIRBLOCKS (data, 0) + << grub_le_to_cpu32 (data->sblock.log2_blksz)), + 0, INODE_SIZE (data), symlink); + symlink[INODE_SIZE (data)] = '\0'; + } + + /* The symlink is an absolute path, go back to the root inode. */ + if (symlink[0] == '/') + ino = GRUB_UFS_INODE; + + /* Now load in the old inode. */ + if (grub_ufs_read_inode (data, ino)) + return grub_errno; + + grub_ufs_find_file (data, symlink); + if (grub_errno) + grub_error (grub_errno, "Can not follow symlink `%s'.", symlink); + + return grub_errno; +} + + +/* Find the file with the pathname PATH on the filesystem described by + DATA. */ +static grub_err_t +grub_ufs_find_file (struct grub_ufs_data *data, const char *path) +{ + char fpath[grub_strlen (path)]; + char *name = fpath; + char *next; + unsigned int pos = 0; + int dirino; + + grub_strncpy (fpath, path, grub_strlen (path)); + + /* Skip the first slash. */ + if (name[0] == '/') + { + name++; + if (!*name) + return 0; + } + + /* Extract the actual part from the pathname. */ + next = grub_strchr (name, '/'); + if (next) + { + next[0] = '\0'; + next++; + } + + do + { + struct grub_ufs_dirent dirent; + + if (grub_strlen (name) == 0) + return GRUB_ERR_NONE; + + if (grub_ufs_read_file (data, 0, pos, sizeof (dirent), + (char *) &dirent) < 0) + return grub_errno; + + { + char filename[dirent.namelen + 1]; + + if (grub_ufs_read_file (data, 0, pos + sizeof (dirent), + dirent.namelen, filename) < 0) + return grub_errno; + + filename[dirent.namelen] = '\0'; + + if (!grub_strcmp (name, filename)) + { + dirino = data->ino; + grub_ufs_read_inode (data, grub_le_to_cpu32 (dirent.ino)); + + if (dirent.filetype == GRUB_UFS_FILETYPE_LNK) + { + grub_ufs_lookup_symlink (data, dirino); + if (grub_errno) + return grub_errno; + } + + if (!next) + return 0; + + pos = 0; + + name = next; + next = grub_strchr (name, '/'); + if (next) + { + next[0] = '\0'; + next++; + } + + if (!(dirent.filetype & GRUB_UFS_FILETYPE_DIR)) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + + continue; + } + } + + pos += grub_le_to_cpu16 (dirent.direntlen); + } while (pos < grub_le_to_cpu32 (INODE_SIZE (data))); + + grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + return grub_errno; +} + + +/* Mount the filesystem on the disk DISK. */ +static struct grub_ufs_data * +grub_ufs_mount (grub_disk_t disk) +{ + struct grub_ufs_data *data; + int *sblklist = sblocklist; + + data = grub_malloc (sizeof (struct grub_ufs_data)); + if (!data) + return 0; + + /* Find a UFS1 or UFS2 sblock. */ + data->ufs_type = UNKNOWN; + while (*sblklist != -1) + { + grub_disk_read (disk, *sblklist, 0, sizeof (struct grub_ufs_sblock), + (char *) &data->sblock); + if (grub_errno) + goto fail; + + if (grub_le_to_cpu32 (data->sblock.magic) == GRUB_UFS_MAGIC) + { + data->ufs_type = UFS1; + break; + } + else if (grub_le_to_cpu32 (data->sblock.magic) == GRUB_UFS2_MAGIC) + { + data->ufs_type = UFS2; + break; + } + sblklist++; + } + if (data->ufs_type == UNKNOWN) + { + grub_error (GRUB_ERR_BAD_FS, "not an ufs filesystem"); + goto fail; + } + + data->disk = disk; + data->linknest = 0; + return data; + + fail: + grub_free (data); + return 0; +} + + +static grub_err_t +grub_ufs_dir (grub_device_t device, const char *path, + int (*hook) (const char *filename, int dir)) +{ + struct grub_ufs_data *data; + struct grub_ufs_sblock *sblock; + unsigned int pos = 0; + + data = grub_ufs_mount (device->disk); + if (!data) + return grub_errno; + + grub_ufs_read_inode (data, GRUB_UFS_INODE); + if (grub_errno) + return grub_errno; + + sblock = &data->sblock; + + if (!path || path[0] != '/') + { + grub_error (GRUB_ERR_BAD_FILENAME, "bad filename"); + return grub_errno; + } + + grub_ufs_find_file (data, path); + if (grub_errno) + goto fail; + + if (!(INODE_MODE (data) & GRUB_UFS_ATTR_DIR)) + { + grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + goto fail; + } + + while (pos < INODE_SIZE (data)) + { + struct grub_ufs_dirent dirent; + + if (grub_ufs_read_file (data, 0, pos, sizeof (dirent), + (char *) &dirent) < 0) + break; + + { + char filename[dirent.namelen + 1]; + + if (grub_ufs_read_file (data, 0, pos + sizeof (dirent), + dirent.namelen, filename) < 0) + break; + + filename[dirent.namelen] = '\0'; + if (hook (filename, dirent.filetype == GRUB_UFS_FILETYPE_DIR)) + break; + } + + pos += grub_le_to_cpu16 (dirent.direntlen); + } + + fail: + grub_free (data); + + return grub_errno; +} + + +/* Open a file named NAME and initialize FILE. */ +static grub_err_t +grub_ufs_open (struct grub_file *file, const char *name) +{ + struct grub_ufs_data *data; + data = grub_ufs_mount (file->device->disk); + if (!data) + return grub_errno; + + grub_ufs_read_inode (data, 2); + if (grub_errno) + { + grub_free (data); + return grub_errno; + } + + if (!name || name[0] != '/') + { + grub_error (GRUB_ERR_BAD_FILENAME, "bad filename"); + return grub_errno; + } + + grub_ufs_find_file (data, name); + if (grub_errno) + { + grub_free (data); + return grub_errno; + } + + file->data = data; + file->size = INODE_SIZE (data); + + return GRUB_ERR_NONE; +} + + +static grub_ssize_t +grub_ufs_read (grub_file_t file, char *buf, grub_ssize_t len) +{ + struct grub_ufs_data *data = + (struct grub_ufs_data *) file->data; + + return grub_ufs_read_file (data, file->read_hook, file->offset, len, buf); +} + + +static grub_err_t +grub_ufs_close (grub_file_t file) +{ + grub_free (file->data); + + return GRUB_ERR_NONE; +} + + +static grub_err_t +grub_ufs_label (grub_device_t device __attribute ((unused)), + char **label __attribute ((unused))) +{ + return GRUB_ERR_NONE; +} + + +static struct grub_fs grub_ufs_fs = + { + .name = "ufs", + .dir = grub_ufs_dir, + .open = grub_ufs_open, + .read = grub_ufs_read, + .close = grub_ufs_close, + .label = grub_ufs_label, + .next = 0 + }; + +#ifdef GRUB_UTIL +void +grub_ufs_init (void) +{ + grub_fs_register (&grub_ufs_fs); +} + +void +grub_ufs_fini (void) +{ + grub_fs_unregister (&grub_ufs_fs); +} +#else /* ! GRUB_UTIL */ +GRUB_MOD_INIT +{ + grub_fs_register (&grub_ufs_fs); + my_mod = mod; +} + +GRUB_MOD_FINI +{ + grub_fs_unregister (&grub_ufs_fs); +} +#endif /* ! GRUB_UTIL */ Index: include/grub/fs.h =================================================================== RCS file: /cvsroot/grub/grub2/include/grub/fs.h,v retrieving revision 1.6 diff -u -p -u -p -r1.6 fs.h --- include/grub/fs.h 4 Apr 2004 13:46:00 -0000 1.6 +++ include/grub/fs.h 20 May 2004 22:09:47 -0000 @@ -1,7 +1,7 @@ /* fs.h - filesystem manager */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003 Free Software Foundation, Inc. + * Copyright (C) 2002,2003,2004 Free Software Foundation, Inc. * * GRUB is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -70,6 +70,8 @@ void grub_fat_init (void); void grub_fat_fini (void); void grub_ext2_init (void); void grub_ext2_fini (void); +void grub_ufs_init (void); +void grub_ufs_fini (void); #endif /* GRUB_UTIL */ #endif /* ! GRUB_FS_HEADER */ Index: util/grub-emu.c =================================================================== RCS file: /cvsroot/grub/grub2/util/grub-emu.c,v retrieving revision 1.4 diff -u -p -u -p -r1.4 grub-emu.c --- util/grub-emu.c 4 Apr 2004 13:46:03 -0000 1.4 +++ util/grub-emu.c 20 May 2004 22:09:49 -0000 @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004 Free Software Foundation, Inc. * * GRUB is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -158,6 +158,7 @@ main (int argc, char *argv[]) /* Initialize the default modules. */ grub_fat_init (); grub_ext2_init (); + grub_ufs_init (); grub_ls_init (); grub_boot_init (); grub_cmp_init (); @@ -173,6 +174,7 @@ main (int argc, char *argv[]) grub_util_biosdisk_fini (); grub_normal_fini (); grub_ext2_fini (); + grub_ufs_fini (); grub_fat_fini (); grub_boot_fini (); grub_cmp_fini ();