diff options
author | Paulo Alcantara <pcacjr@zytor.com> | 2012-07-28 17:03:58 -0300 |
---|---|---|
committer | Paulo Alcantara <pcacjr@zytor.com> | 2012-07-28 17:03:58 -0300 |
commit | 7f421798ce904cba41a04aa29a05ae8b35c90172 (patch) | |
tree | 25a7c6df57c0937cb71513284cc03934bb686b6f | |
parent | 9f463254bed88abe242adc62ce30f0bbf9ccf825 (diff) | |
download | syslinux-7f421798ce904cba41a04aa29a05ae8b35c90172.tar.gz syslinux-7f421798ce904cba41a04aa29a05ae8b35c90172.tar.xz syslinux-7f421798ce904cba41a04aa29a05ae8b35c90172.zip |
xfs: Move readdir functions to another source file
All readdir functions get bigger in size when lookup functions are added
to xfs_dir2.c accordingly, so we need to move them out to another source
file.
Signed-off-by: Paulo Alcantara <pcacjr@zytor.com>
-rw-r--r-- | core/fs/xfs/xfs.c | 270 | ||||
-rw-r--r-- | core/fs/xfs/xfs_readdir.c | 291 | ||||
-rw-r--r-- | core/fs/xfs/xfs_readdir.h | 30 |
3 files changed, 326 insertions, 265 deletions
diff --git a/core/fs/xfs/xfs.c b/core/fs/xfs/xfs.c index 873e84d4..9bd278dd 100644 --- a/core/fs/xfs/xfs.c +++ b/core/fs/xfs/xfs.c @@ -35,267 +35,7 @@ #include "xfs.h" #include "xfs_dinode.h" #include "xfs_dir2.h" - -static int fill_dirent(struct fs_info *fs, struct dirent *dirent, - uint32_t offset, xfs_ino_t ino, char *name, - size_t namelen) -{ - xfs_dinode_t *core; - - dirent->d_ino = ino; - dirent->d_off = offset; - dirent->d_reclen = offsetof(struct dirent, d_name) + namelen + 1; - - core = xfs_dinode_get_core(fs, ino); - if (!core) { - xfs_error("Failed to get dinode from disk (ino 0x%llx)", ino); - return -1; - } - - if (be16_to_cpu(core->di_mode) & S_IFDIR) - dirent->d_type = DT_DIR; - else if (be16_to_cpu(core->di_mode) & S_IFREG) - dirent->d_type = DT_REG; - - memcpy(dirent->d_name, name, namelen + 1); - - return 0; -} - -static int xfs_fmt_local_readdir(struct file *file, struct dirent *dirent, - xfs_dinode_t *core) -{ - xfs_dir2_sf_t *sf = (xfs_dir2_sf_t *)&core->di_literal_area[0]; - xfs_dir2_sf_entry_t *sf_entry; - uint8_t count = sf->hdr.i8count ? sf->hdr.i8count : sf->hdr.count; - uint32_t offset = file->offset; - uint8_t *start_name; - uint8_t *end_name; - char *name; - xfs_ino_t ino; - struct fs_info *fs = file->fs; - int retval = 0; - - xfs_debug("count %hhu i8count %hhu", sf->hdr.count, sf->hdr.i8count); - - if (file->offset + 1 > count) - return -1; - - file->offset++; - - sf_entry = (xfs_dir2_sf_entry_t *)((uint8_t *)&sf->list[0] - - (!sf->hdr.i8count ? 4 : 0)); - - if (file->offset - 1) { - offset = file->offset; - while (--offset) { - sf_entry = (xfs_dir2_sf_entry_t *)( - (uint8_t *)sf_entry + - offsetof(struct xfs_dir2_sf_entry, - name[0]) + - sf_entry->namelen + - (sf->hdr.i8count ? 8 : 4)); - } - } - - start_name = &sf_entry->name[0]; - end_name = start_name + sf_entry->namelen; - - name = xfs_dir2_get_entry_name(start_name, end_name); - - ino = xfs_dir2_sf_get_inumber(sf, (xfs_dir2_inou_t *)( - (uint8_t *)sf_entry + - offsetof(struct xfs_dir2_sf_entry, - name[0]) + - sf_entry->namelen)); - - retval = fill_dirent(fs, dirent, file->offset, ino, (char *)name, - end_name - start_name); - if (retval) - xfs_error("Failed to fill in dirent structure"); - - free(name); - - return retval; -} - -static int xfs_dir2_block_readdir(struct file *file, struct dirent *dirent, - xfs_dinode_t *core) -{ - xfs_bmbt_irec_t r; - block_t dir_blk; - struct fs_info *fs = file->fs; - uint8_t *dirblk_buf; - uint8_t *p; - uint32_t offset; - xfs_dir2_data_hdr_t *hdr; - xfs_dir2_block_tail_t *btp; - xfs_dir2_data_unused_t *dup; - xfs_dir2_data_entry_t *dep; - uint8_t *start_name; - uint8_t *end_name; - char *name; - xfs_ino_t ino; - int retval = 0; - - bmbt_irec_get(&r, (xfs_bmbt_rec_t *)&core->di_literal_area[0]); - dir_blk = fsblock_to_bytes(fs, r.br_startblock) >> BLOCK_SHIFT(fs); - - dirblk_buf = xfs_dir2_get_dirblks(fs, dir_blk, r.br_blockcount); - hdr = (xfs_dir2_data_hdr_t *)dirblk_buf; - if (be32_to_cpu(hdr->magic) != XFS_DIR2_BLOCK_MAGIC) { - xfs_error("Block directory header's magic number does not match!"); - xfs_debug("hdr->magic: 0x%lx", be32_to_cpu(hdr->magic)); - - free(dirblk_buf); - - return -1; - } - - btp = xfs_dir2_block_tail_p(XFS_INFO(fs), hdr); - - if (file->offset + 1 > be32_to_cpu(btp->count)) - return -1; - - file->offset++; - - p = (uint8_t *)(hdr + 1); - - if (file->offset - 1) { - offset = file->offset; - while (--offset) { - dep = (xfs_dir2_data_entry_t *)p; - - dup = (xfs_dir2_data_unused_t *)p; - if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { - p += be16_to_cpu(dup->length); - continue; - } - - p += xfs_dir2_data_entsize(dep->namelen); - } - } - - dep = (xfs_dir2_data_entry_t *)p; - - start_name = &dep->name[0]; - end_name = start_name + dep->namelen; - name = xfs_dir2_get_entry_name(start_name, end_name); - - ino = be64_to_cpu(dep->inumber); - - retval = fill_dirent(fs, dirent, file->offset, ino, name, - end_name - start_name); - if (retval) - xfs_error("Failed to fill in dirent structure"); - - free(dirblk_buf); - free(name); - - return retval; -} - -static int xfs_dir2_leaf_readdir(struct file *file, struct dirent *dirent, - xfs_dinode_t *core) -{ - xfs_bmbt_irec_t irec; - struct fs_info *fs = file->fs; - xfs_dir2_leaf_t *leaf; - block_t leaf_blk, dir_blk; - xfs_dir2_leaf_entry_t *lep; - uint32_t newdb; - uint32_t curdb = -1; - xfs_dir2_data_entry_t *dep; - xfs_dir2_data_hdr_t *data_hdr; - uint8_t *start_name; - uint8_t *end_name; - char *name; - xfs_intino_t ino; - uint8_t *buf = NULL; - int retval = 0; - - bmbt_irec_get(&irec, ((xfs_bmbt_rec_t *)&core->di_literal_area[0]) + - be32_to_cpu(core->di_nextents) - 1); - leaf_blk = fsblock_to_bytes(fs, irec.br_startblock) >> - BLOCK_SHIFT(file->fs); - - leaf = (xfs_dir2_leaf_t *)xfs_dir2_get_dirblks(fs, leaf_blk, - irec.br_blockcount); - if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR2_LEAF1_MAGIC) { - xfs_error("Single leaf block header's magic number does not match!"); - goto out; - } - - if (!leaf->hdr.count) - goto out; - - if (file->offset + 1 > be16_to_cpu(leaf->hdr.count)) - goto out; - - lep = &leaf->ents[file->offset++]; - - /* Skip over stale leaf entries */ - for ( ; be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR; - lep++, file->offset++); - - newdb = xfs_dir2_dataptr_to_db(fs, be32_to_cpu(lep->address)); - if (newdb != curdb) { - if (buf) - free(buf); - - bmbt_irec_get(&irec, - ((xfs_bmbt_rec_t *)&core->di_literal_area[0]) + newdb); - dir_blk = fsblock_to_bytes(fs, irec.br_startblock) >> - BLOCK_SHIFT(fs); - buf = xfs_dir2_get_dirblks(fs, dir_blk, irec.br_blockcount); - data_hdr = (xfs_dir2_data_hdr_t *)buf; - if (be32_to_cpu(data_hdr->magic) != XFS_DIR2_DATA_MAGIC) { - xfs_error("Leaf directory's data magic number does not match!"); - goto out1; - } - - curdb = newdb; - } - - dep = (xfs_dir2_data_entry_t *)( - (char *)buf + xfs_dir2_dataptr_to_off(fs, - be32_to_cpu(lep->address))); - - start_name = &dep->name[0]; - end_name = start_name + dep->namelen; - name = xfs_dir2_get_entry_name(start_name, end_name); - - ino = be64_to_cpu(dep->inumber); - - retval = fill_dirent(fs, dirent, file->offset, ino, name, - end_name - start_name); - if (retval) - xfs_error("Failed to fill in dirent structure"); - - free(name); - free(buf); - free(leaf); - - return retval; - -out1: - free(buf); - -out: - free(leaf); - - return -1; -} - -static int xfs_dir2_node_readdir(struct file *file, struct dirent *dirent, - xfs_dinode_t *core) -{ - (void)file; - (void)dirent; - (void)core; - - return -1; -} +#include "xfs_readdir.h" static int xfs_fmt_extents_readdir(struct file *file, struct dirent *dirent, xfs_dinode_t *core) @@ -304,13 +44,13 @@ static int xfs_fmt_extents_readdir(struct file *file, struct dirent *dirent, if (be32_to_cpu(core->di_nextents) <= 1) { /* Single-block Directories */ - retval = xfs_dir2_block_readdir(file, dirent, core); + retval = xfs_readdir_dir2_block(file, dirent, core); } else if (xfs_dir2_isleaf(file->fs, core)) { /* Leaf Directory */ - retval = xfs_dir2_leaf_readdir(file, dirent, core); + retval = xfs_readdir_dir2_leaf(file, dirent, core); } else { /* Node Directory */ - retval = xfs_dir2_node_readdir(file, dirent, core); + retval = xfs_readdir_dir2_node(file, dirent, core); } return retval; @@ -330,7 +70,7 @@ static int xfs_readdir(struct file *file, struct dirent *dirent) } if (core->di_format == XFS_DINODE_FMT_LOCAL) - retval = xfs_fmt_local_readdir(file, dirent, core); + retval = xfs_readdir_dir2_local(file, dirent, core); else if (core->di_format == XFS_DINODE_FMT_EXTENTS) retval = xfs_fmt_extents_readdir(file, dirent, core); diff --git a/core/fs/xfs/xfs_readdir.c b/core/fs/xfs/xfs_readdir.c new file mode 100644 index 00000000..4eaeae36 --- /dev/null +++ b/core/fs/xfs/xfs_readdir.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2012 Paulo Alcantara <pcacjr@zytor.com> + * + * 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. + * + * This program is distributed in the hope that it would 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 the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <cache.h> +#include <core.h> +#include <fs.h> + +#include "xfs_types.h" +#include "xfs_sb.h" +#include "xfs_ag.h" +#include "misc.h" +#include "xfs.h" +#include "xfs_dinode.h" +#include "xfs_dir2.h" + +#include "xfs_readdir.h" + +static int fill_dirent(struct fs_info *fs, struct dirent *dirent, + uint32_t offset, xfs_ino_t ino, char *name, + size_t namelen) +{ + xfs_dinode_t *core; + + dirent->d_ino = ino; + dirent->d_off = offset; + dirent->d_reclen = offsetof(struct dirent, d_name) + namelen + 1; + + core = xfs_dinode_get_core(fs, ino); + if (!core) { + xfs_error("Failed to get dinode from disk (ino 0x%llx)", ino); + return -1; + } + + if (be16_to_cpu(core->di_mode) & S_IFDIR) + dirent->d_type = DT_DIR; + else if (be16_to_cpu(core->di_mode) & S_IFREG) + dirent->d_type = DT_REG; + + memcpy(dirent->d_name, name, namelen + 1); + + return 0; +} + +int xfs_readdir_dir2_local(struct file *file, struct dirent *dirent, + xfs_dinode_t *core) +{ + xfs_dir2_sf_t *sf = (xfs_dir2_sf_t *)&core->di_literal_area[0]; + xfs_dir2_sf_entry_t *sf_entry; + uint8_t count = sf->hdr.i8count ? sf->hdr.i8count : sf->hdr.count; + uint32_t offset = file->offset; + uint8_t *start_name; + uint8_t *end_name; + char *name; + xfs_ino_t ino; + struct fs_info *fs = file->fs; + int retval = 0; + + xfs_debug("count %hhu i8count %hhu", sf->hdr.count, sf->hdr.i8count); + + if (file->offset + 1 > count) + return -1; + + file->offset++; + + sf_entry = (xfs_dir2_sf_entry_t *)((uint8_t *)&sf->list[0] - + (!sf->hdr.i8count ? 4 : 0)); + + if (file->offset - 1) { + offset = file->offset; + while (--offset) { + sf_entry = (xfs_dir2_sf_entry_t *)( + (uint8_t *)sf_entry + + offsetof(struct xfs_dir2_sf_entry, + name[0]) + + sf_entry->namelen + + (sf->hdr.i8count ? 8 : 4)); + } + } + + start_name = &sf_entry->name[0]; + end_name = start_name + sf_entry->namelen; + + name = xfs_dir2_get_entry_name(start_name, end_name); + + ino = xfs_dir2_sf_get_inumber(sf, (xfs_dir2_inou_t *)( + (uint8_t *)sf_entry + + offsetof(struct xfs_dir2_sf_entry, + name[0]) + + sf_entry->namelen)); + + retval = fill_dirent(fs, dirent, file->offset, ino, (char *)name, + end_name - start_name); + if (retval) + xfs_error("Failed to fill in dirent structure"); + + free(name); + + return retval; +} + +int xfs_readdir_dir2_block(struct file *file, struct dirent *dirent, + xfs_dinode_t *core) +{ + xfs_bmbt_irec_t r; + block_t dir_blk; + struct fs_info *fs = file->fs; + uint8_t *dirblk_buf; + uint8_t *p; + uint32_t offset; + xfs_dir2_data_hdr_t *hdr; + xfs_dir2_block_tail_t *btp; + xfs_dir2_data_unused_t *dup; + xfs_dir2_data_entry_t *dep; + uint8_t *start_name; + uint8_t *end_name; + char *name; + xfs_ino_t ino; + int retval = 0; + + bmbt_irec_get(&r, (xfs_bmbt_rec_t *)&core->di_literal_area[0]); + dir_blk = fsblock_to_bytes(fs, r.br_startblock) >> BLOCK_SHIFT(fs); + + dirblk_buf = xfs_dir2_get_dirblks(fs, dir_blk, r.br_blockcount); + hdr = (xfs_dir2_data_hdr_t *)dirblk_buf; + if (be32_to_cpu(hdr->magic) != XFS_DIR2_BLOCK_MAGIC) { + xfs_error("Block directory header's magic number does not match!"); + xfs_debug("hdr->magic: 0x%lx", be32_to_cpu(hdr->magic)); + + free(dirblk_buf); + + return -1; + } + + btp = xfs_dir2_block_tail_p(XFS_INFO(fs), hdr); + + if (file->offset + 1 > be32_to_cpu(btp->count)) + return -1; + + file->offset++; + + p = (uint8_t *)(hdr + 1); + + if (file->offset - 1) { + offset = file->offset; + while (--offset) { + dep = (xfs_dir2_data_entry_t *)p; + + dup = (xfs_dir2_data_unused_t *)p; + if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) { + p += be16_to_cpu(dup->length); + continue; + } + + p += xfs_dir2_data_entsize(dep->namelen); + } + } + + dep = (xfs_dir2_data_entry_t *)p; + + start_name = &dep->name[0]; + end_name = start_name + dep->namelen; + name = xfs_dir2_get_entry_name(start_name, end_name); + + ino = be64_to_cpu(dep->inumber); + + retval = fill_dirent(fs, dirent, file->offset, ino, name, + end_name - start_name); + if (retval) + xfs_error("Failed to fill in dirent structure"); + + free(dirblk_buf); + free(name); + + return retval; +} + +int xfs_readdir_dir2_leaf(struct file *file, struct dirent *dirent, + xfs_dinode_t *core) +{ + xfs_bmbt_irec_t irec; + struct fs_info *fs = file->fs; + xfs_dir2_leaf_t *leaf; + block_t leaf_blk, dir_blk; + xfs_dir2_leaf_entry_t *lep; + uint32_t newdb; + uint32_t curdb = -1; + xfs_dir2_data_entry_t *dep; + xfs_dir2_data_hdr_t *data_hdr; + uint8_t *start_name; + uint8_t *end_name; + char *name; + xfs_intino_t ino; + uint8_t *buf = NULL; + int retval = 0; + + bmbt_irec_get(&irec, ((xfs_bmbt_rec_t *)&core->di_literal_area[0]) + + be32_to_cpu(core->di_nextents) - 1); + leaf_blk = fsblock_to_bytes(fs, irec.br_startblock) >> + BLOCK_SHIFT(file->fs); + + leaf = (xfs_dir2_leaf_t *)xfs_dir2_get_dirblks(fs, leaf_blk, + irec.br_blockcount); + if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR2_LEAF1_MAGIC) { + xfs_error("Single leaf block header's magic number does not match!"); + goto out; + } + + if (!leaf->hdr.count) + goto out; + + if (file->offset + 1 > be16_to_cpu(leaf->hdr.count)) + goto out; + + lep = &leaf->ents[file->offset++]; + + /* Skip over stale leaf entries */ + for ( ; be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR; + lep++, file->offset++); + + newdb = xfs_dir2_dataptr_to_db(fs, be32_to_cpu(lep->address)); + if (newdb != curdb) { + if (buf) + free(buf); + + bmbt_irec_get(&irec, + ((xfs_bmbt_rec_t *)&core->di_literal_area[0]) + newdb); + dir_blk = fsblock_to_bytes(fs, irec.br_startblock) >> + BLOCK_SHIFT(fs); + buf = xfs_dir2_get_dirblks(fs, dir_blk, irec.br_blockcount); + data_hdr = (xfs_dir2_data_hdr_t *)buf; + if (be32_to_cpu(data_hdr->magic) != XFS_DIR2_DATA_MAGIC) { + xfs_error("Leaf directory's data magic number does not match!"); + goto out1; + } + + curdb = newdb; + } + + dep = (xfs_dir2_data_entry_t *)( + (char *)buf + xfs_dir2_dataptr_to_off(fs, + be32_to_cpu(lep->address))); + + start_name = &dep->name[0]; + end_name = start_name + dep->namelen; + name = xfs_dir2_get_entry_name(start_name, end_name); + + ino = be64_to_cpu(dep->inumber); + + retval = fill_dirent(fs, dirent, file->offset, ino, name, + end_name - start_name); + if (retval) + xfs_error("Failed to fill in dirent structure"); + + free(name); + free(buf); + free(leaf); + + return retval; + +out1: + free(buf); + +out: + free(leaf); + + return -1; +} + +int xfs_readdir_dir2_node(struct file *file, struct dirent *dirent, + xfs_dinode_t *core) +{ + (void)file; + (void)dirent; + (void)core; + + return -1; +} diff --git a/core/fs/xfs/xfs_readdir.h b/core/fs/xfs/xfs_readdir.h new file mode 100644 index 00000000..2e564ec8 --- /dev/null +++ b/core/fs/xfs/xfs_readdir.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012 Paulo Alcantara <pcacjr@zytor.com> + * + * 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. + * + * This program is distributed in the hope that it would 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 the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef XFS_READDIR_H_ +#define XFS_READDIR_H_ + +int xfs_readdir_dir2_local(struct file *file, struct dirent *dirent, + xfs_dinode_t *core); +int xfs_readdir_dir2_block(struct file *file, struct dirent *dirent, + xfs_dinode_t *core); +int xfs_readdir_dir2_leaf(struct file *file, struct dirent *dirent, + xfs_dinode_t *core); +int xfs_readdir_dir2_node(struct file *file, struct dirent *dirent, + xfs_dinode_t *core); + +#endif /* XFS_READDIR_H_ */ |