/* ufs.c - Unix File System */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2004,2005,2007,2008,2009 Free Software Foundation, Inc.
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB 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 GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
GRUB_MOD_LICENSE ("GPLv3+");
#ifdef MODE_UFS2
#else
#endif
/* Calculate in which group the inode can be found. */
#ifdef MODE_UFS2
#else
#endif
#ifdef MODE_UFS2
#else
#endif
#ifdef MODE_UFS2
#else
#endif
/* The blocks on which the superblock can be found. */
struct grub_ufs_sblock
{
/* The offset of the inodes in the cylinder group. */
/* The start of the cylinder group. */
/* The size of a block in bytes. */
/* The size of filesystem blocks to disk blocks. */
/* Inodes stored per cylinder group. */
/* The frags per cylinder group. */
/* Volume name for UFS2. */
/* Magic value to check if this is really a UFS filesystem. */
};
#ifdef MODE_UFS2
/* UFS inode. */
struct grub_ufs_inode
{
union
{
struct
{
} blocks;
};
} __attribute__ ((packed));
#else
/* UFS inode. */
struct grub_ufs_inode
{
union
{
struct
{
} blocks;
};
} __attribute__ ((packed));
#endif
/* Directory entry. */
struct grub_ufs_dirent
{
union
{
struct
{
};
};
} __attribute__ ((packed));
/* Information about a "mounted" ufs filesystem. */
struct grub_ufs_data
{
int ino;
int linknest;
int log2_blksz;
};
/* Forward declaration. */
const char *path);
static grub_disk_addr_t
{
unsigned int indirsz;
int log2_blksz;
/* Direct. */
if (blk < GRUB_UFS_DIRBLKS)
blk -= GRUB_UFS_DIRBLKS;
/* Single indirect block. */
{
#ifdef MODE_UFS2
#else
#endif
}
/* Double indirect block. */
{
#ifdef MODE_UFS2
#else
#endif
<< log2_blksz,
}
"ufs does not support triple 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_off_t i;
/* Adjust len so it we can't read past the end of the file. */
{
int skipfirst = 0;
if (grub_errno)
return -1;
/* Last block. */
if (i == blockcnt - 1)
{
if (!blockend)
}
/* First block. */
{
}
/* XXX: If the block number is 0 this block is not stored on
disk but is zero filled instead. */
if (blknr)
{
if (grub_errno)
return -1;
}
else
}
return len;
}
/* Read inode INO from the mounted filesystem described by DATA. This
inode is used by default now. */
static grub_err_t
{
/* Determine the group the inode is in. */
/* Determine the inode within the group. */
/* The first block of the group. */
#ifndef MODE_UFS2
#endif
if (!inode)
{
}
* sizeof (struct grub_ufs_inode),
sizeof (struct grub_ufs_inode),
inode);
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
{
else
/* The symlink is an absolute path, go back to the root inode. */
if (symlink[0] == '/')
/* Now load in the old inode. */
return grub_errno;
if (grub_errno)
return grub_errno;
}
/* Find the file with the pathname PATH on the filesystem described by
DATA. */
static grub_err_t
{
char *next;
unsigned int pos = 0;
int dirino;
/* Skip the first slash. */
if (name[0] == '/')
{
name++;
if (!*name)
return 0;
}
/* Extract the actual part from the pathname. */
if (next)
{
next[0] = '\0';
next++;
}
do
{
int namelen;
if (grub_strlen (name) == 0)
return GRUB_ERR_NONE;
(char *) &dirent) < 0)
return grub_errno;
#ifdef MODE_UFS2
#else
#endif
{
return grub_errno;
{
{
if (grub_errno)
return grub_errno;
}
if (!next)
return 0;
pos = 0;
if (next)
{
next[0] = '\0';
next++;
}
continue;
}
}
return grub_errno;
}
/* Mount the filesystem on the disk DISK. */
static struct grub_ufs_data *
{
if (!data)
return 0;
/* Find a UFS sblock. */
while (*sblklist != -1)
{
if (grub_errno)
goto fail;
/* No need to byteswap bsize in this check. It works the same on both
endiannesses. */
{
for (data->log2_blksz = 0;
data->log2_blksz++);
return data;
}
sblklist++;
}
fail:
{
#ifdef MODE_UFS2
#else
#endif
}
return 0;
}
static grub_err_t
const struct grub_dirhook_info *info))
{
unsigned int pos = 0;
if (!data)
return grub_errno;
if (grub_errno)
return grub_errno;
{
return grub_errno;
}
if (grub_errno)
goto fail;
{
goto fail;
}
{
int namelen;
(char *) &dirent) < 0)
break;
#ifdef MODE_UFS2
#else
#endif
{
break;
== GRUB_UFS_ATTR_DIR);
break;
}
}
fail:
return grub_errno;
}
/* Open a file named NAME and initialize FILE. */
static grub_err_t
{
if (!data)
return grub_errno;
if (grub_errno)
{
return grub_errno;
}
{
return grub_errno;
}
if (grub_errno)
{
return grub_errno;
}
return GRUB_ERR_NONE;
}
static grub_ssize_t
{
}
static grub_err_t
{
return GRUB_ERR_NONE;
}
static grub_err_t
{
*label = 0;
if (data)
return grub_errno;
}
static grub_err_t
{
else
return grub_errno;
}
/* Get mtime. */
static grub_err_t
{
if (!data)
*tm = 0;
else
{
#ifdef MODE_UFS2
#endif
}
return grub_errno;
}
{
#ifdef MODE_UFS2
.name = "ufs2",
#else
.name = "ufs1",
#endif
.dir = grub_ufs_dir,
.open = grub_ufs_open,
.read = grub_ufs_read,
.close = grub_ufs_close,
.label = grub_ufs_label,
.uuid = grub_ufs_uuid,
.mtime = grub_ufs_mtime,
.next = 0
};
#ifdef MODE_UFS2
#else
#endif
{
}
#ifdef MODE_UFS2
#else
#endif
{
}