/* xfs.c - XFS. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2005,2006,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+");
struct grub_xfs_sblock
{
} __attribute__ ((packed));
struct grub_xfs_dir_header
{
union
{
} __attribute__ ((packed));
struct grub_xfs_dir_entry
{
/* Inode number follows, 32 bits. */
} __attribute__ ((packed));
struct grub_xfs_dir2_entry
{
} __attribute__ ((packed));
struct grub_xfs_btree_node
{
} __attribute__ ((packed));
struct grub_xfs_btree_root
{
} __attribute__ ((packed));
struct grub_xfs_time
{
} __attribute__ ((packed));
struct grub_xfs_inode
{
union
{
struct dir
{
} dir;
} __attribute__ ((packed));
struct grub_xfs_dirblock_tail
{
} __attribute__ ((packed));
struct grub_fshelp_node
{
int inode_read;
};
struct grub_xfs_data
{
int pos;
int bsize;
};
/* Filetype information as used in inodes. */
static inline int
{
}
static inline grub_uint64_t
{
}
static inline grub_uint64_t
{
}
static inline grub_disk_addr_t
{
}
static inline grub_uint64_t
{
}
static inline grub_uint64_t
{
& (0x1ff)) << 43
}
static inline grub_uint64_t
{
}
static inline int
{
}
static inline int
{
}
static inline grub_uint64_t
{
long long block;
return block;
}
static inline int
{
}
static grub_err_t
struct grub_xfs_inode *inode)
{
/* Read the inode. */
return grub_errno;
return 0;
}
static grub_disk_addr_t
{
{
int recoffset;
if (leaf == 0)
return 0;
/ (2 * sizeof (grub_uint64_t));
else
/ (2 * sizeof (grub_uint64_t));
do
{
int i;
for (i = 0; i < nrec; i++)
{
break;
}
/* Sparse block. */
if (i == 0)
{
return 0;
}
GRUB_XFS_FSB_TO_BLOCK (node->data, grub_be_to_cpu64 (keys[i - 1 + recoffset])) << (node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS),
return 0;
{
return 0;
}
- (char *) leaf))
/ (2 * sizeof (grub_uint64_t)));
}
}
{
}
else
{
"XFS does not support inode format %d yet",
return 0;
}
/* Iterate over each extent to figure out which extent has
the block we are looking for. */
{
/* Sparse block. */
break;
{
break;
}
}
}
/* 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
{
}
static char *
{
{
case XFS_INODE_FORMAT_INO:
case XFS_INODE_FORMAT_EXT:
{
char *symlink;
if (!symlink)
return 0;
{
return 0;
}
return symlink;
}
}
return 0;
}
static enum grub_fshelp_filetype
{
if ((grub_be_to_cpu16 (mode)
return GRUB_FSHELP_DIR;
else if ((grub_be_to_cpu16 (mode)
return GRUB_FSHELP_SYMLINK;
else if ((grub_be_to_cpu16 (mode)
return GRUB_FSHELP_REG;
return GRUB_FSHELP_UNKNOWN;
}
static int
int NESTED_FUNC_ATTR
enum grub_fshelp_filetype filetype,
{
{
- sizeof (struct grub_xfs_inode)
if (!fdiro)
return 0;
/* The inode should be read, otherwise the filetype can
not be determined. */
fdiro);
}
{
case XFS_INODE_FORMAT_INO:
{
int i;
/* If small inode numbers are used to pack the direntry, the
parent inode number is small too. */
if (smallino)
{
/* The header is a bit smaller than usual. */
}
else
{
}
/* Synthesize the direntries for `.' and `..'. */
return 1;
return 1;
{
+ sizeof (struct grub_xfs_dir_entry)
/* inopos might be unaligned. */
if (smallino)
else
return 1;
de = ((struct grub_xfs_dir_entry *)
+ ((smallino ? sizeof (grub_uint32_t)
: sizeof (grub_uint64_t))) - 1));
}
break;
}
case XFS_INODE_FORMAT_BTREE:
case XFS_INODE_FORMAT_EXT:
{
char *dirblock;
if (! dirblock)
return 0;
/* Iterate over every block the directory has. */
for (blk = 0;
>> dirblk_log2);
blk++)
{
/* The header is skipped, the first direntry is stored
from byte 16. */
int entries;
- sizeof (struct grub_xfs_dirblock_tail));
blk << dirblk_log2,
if (numread != dirblk_size)
return 0;
/* Iterate over all entries within this block. */
while (pos < (dirblk_size
- (int) sizeof (struct grub_xfs_dir2_entry)))
{
char *filename;
{
/* This entry is not used, go to the next one. */
continue;
}
/* The byte after the filename is for the tag, which
is not used by GRUB. So it can be overwritten. */
{
return 1;
}
/* Check if last direntry in this block is
reached. */
entries--;
if (!entries)
break;
/* Select the next directory entry. */
}
}
break;
}
default:
"XFS does not support inode format %d yet",
}
return 0;
}
static struct grub_xfs_data *
{
if (!data)
return 0;
/* Read the superblock. */
if (grub_disk_read (disk, 0, 0,
goto fail;
{
goto fail;
}
sizeof (struct grub_xfs_data)
- sizeof (struct grub_xfs_inode)
if (! data)
goto fail;
return data;
fail:
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
return 0;
}
static grub_err_t
const struct grub_dirhook_info *info))
{
enum grub_fshelp_filetype filetype,
enum grub_fshelp_filetype filetype,
{
if (node->inode_read)
{
}
}
if (!data)
goto mount_fail;
if (grub_errno)
goto fail;
fail:
return grub_errno;
}
/* Open a file named NAME and initialize FILE. */
static grub_err_t
{
if (!data)
goto mount_fail;
if (grub_errno)
goto fail;
if (!fdiro->inode_read)
{
if (grub_errno)
goto fail;
}
{
sizeof (struct grub_fshelp_node)
- sizeof (struct grub_xfs_inode)
}
return 0;
fail:
return grub_errno;
}
static grub_ssize_t
{
}
static grub_err_t
{
return GRUB_ERR_NONE;
}
static grub_err_t
{
if (data)
else
*label = 0;
return grub_errno;
}
static grub_err_t
{
if (data)
{
}
else
return grub_errno;
}
{
.name = "xfs",
.dir = grub_xfs_dir,
.open = grub_xfs_open,
.read = grub_xfs_read,
.close = grub_xfs_close,
.label = grub_xfs_label,
.uuid = grub_xfs_uuid,
#ifdef GRUB_UTIL
.reserved_first_sector = 0,
#endif
.next = 0
};
{
}
{
}