summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorAlek Du <alek.du@intel.com>2010-03-09 13:34:03 +0800
committerH. Peter Anvin <hpa@zytor.com>2010-03-08 22:21:31 -0800
commitc928c768b17da550ed99150bbcef08d13e5521dd (patch)
tree56d8be16c881ffad68d65e2bbfd98276153642a7 /core
parent2a95944f8d7536868ca51ddf09514f78309af52a (diff)
downloadsyslinux-c928c768b17da550ed99150bbcef08d13e5521dd.tar.gz
btrfs: Implement readdir operation
Tested with dir.c32. Also use the new IFTODT macro to convert fs inode mode to internal dirent mode. Signed-off-by: Alek Du <alek.du@intel.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'core')
-rw-r--r--core/fs/btrfs/btrfs.c54
1 files changed, 42 insertions, 12 deletions
diff --git a/core/fs/btrfs/btrfs.c b/core/fs/btrfs/btrfs.c
index d055dda1..72dcbe92 100644
--- a/core/fs/btrfs/btrfs.c
+++ b/core/fs/btrfs/btrfs.c
@@ -17,7 +17,7 @@
#include <core.h>
#include <disk.h>
#include <fs.h>
-#include <sys/stat.h>
+#include <dirent.h>
#include "btrfs.h"
/* compare function used for bin_search */
@@ -424,15 +424,6 @@ static inline u64 btrfs_name_hash(const char *name, int len)
return btrfs_crc32c((u32)~1, name, len);
}
-static inline int get_inode_mode(int mode)
-{
- if (S_ISLNK(mode))
- return I_SYMLINK;
- if (S_ISDIR(mode))
- return I_DIR;
- return I_FILE;
-}
-
static struct inode *btrfs_iget_by_inr(struct fs_info *fs, u64 inr)
{
struct inode *inode;
@@ -455,9 +446,9 @@ static struct inode *btrfs_iget_by_inr(struct fs_info *fs, u64 inr)
return NULL;
inode->ino = inr;
inode->size = inode_item.size;
- inode->mode = get_inode_mode(inode_item.mode);
+ inode->mode = IFTODT(inode_item.mode);
- if (inode->mode == I_FILE || inode->mode == I_SYMLINK) {
+ if (inode->mode == DT_REG || inode->mode == DT_LNK) {
struct btrfs_file_extent_item extent_item;
u64 offset;
@@ -513,6 +504,44 @@ static int btrfs_readlink(struct inode *inode, char *buf)
return inode->size;
}
+static int btrfs_readdir(struct file *file, struct dirent *dirent)
+{
+ struct fs_info *fs = file->fs;
+ struct inode *inode = file->inode;
+ struct btrfs_disk_key search_key;
+ struct btrfs_path path;
+ struct btrfs_dir_item *dir_item;
+ int ret;
+
+ /*
+ * we use file->offset to store last search key.offset, will will search
+ * key that lower that offset, 0 means first search and we will search
+ * -1UL, which is the biggest possible key
+ */
+ search_key.objectid = inode->ino;
+ search_key.type = BTRFS_DIR_ITEM_KEY;
+ search_key.offset = file->offset - 1;
+ clear_path(&path);
+ ret = search_tree(fs, fs_tree, &search_key, &path);
+
+ if (ret) {
+ if (btrfs_comp_keys_type(&search_key, &path.item.key))
+ return -1;
+ }
+
+ dir_item = (struct btrfs_dir_item *)path.data;
+ file->offset = path.item.key.offset;
+ dirent->d_ino = dir_item->location.objectid;
+ dirent->d_off = file->offset;
+ dirent->d_reclen = offsetof(struct dirent, d_name)
+ + dir_item->name_len + 1;
+ dirent->d_type = IFTODT(dir_item->type);
+ memcpy(dirent->d_name, dir_item + 1, dir_item->name_len);
+ dirent->d_name[dir_item->name_len] = '\0';
+
+ return 0;
+}
+
static int btrfs_next_extent(struct inode *inode, uint32_t lstart)
{
struct btrfs_disk_key search_key;
@@ -662,5 +691,6 @@ const struct fs_ops btrfs_fs_ops = {
.close_file = generic_close_file,
.mangle_name = generic_mangle_name,
.next_extent = btrfs_next_extent,
+ .readdir = btrfs_readdir,
.load_config = generic_load_config
};