blob: ef0bb7ca659fbcf596571e7484e82f217bd901b6 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef F2FS_DIR_H_
#define F2FS_DIR_H_
#include <dirent.h>
#include <sys/stat.h>
namespace f2fs {
static unsigned char filetype_table[F2FS_FT_MAX] = {
[F2FS_FT_UNKNOWN] = DT_UNKNOWN, [F2FS_FT_REG_FILE] = DT_REG, [F2FS_FT_DIR] = DT_DIR,
[F2FS_FT_CHRDEV] = DT_CHR, [F2FS_FT_BLKDEV] = DT_BLK, [F2FS_FT_FIFO] = DT_FIFO,
[F2FS_FT_SOCK] = DT_SOCK, [F2FS_FT_SYMLINK] = DT_LNK,
};
#define S_SHIFT 12
static unsigned char type_by_mode[S_IFMT >> S_SHIFT] = {
[S_IFREG >> S_SHIFT] = F2FS_FT_REG_FILE, [S_IFDIR >> S_SHIFT] = F2FS_FT_DIR,
[S_IFCHR >> S_SHIFT] = F2FS_FT_CHRDEV, [S_IFBLK >> S_SHIFT] = F2FS_FT_BLKDEV,
[S_IFIFO >> S_SHIFT] = F2FS_FT_FIFO, [S_IFSOCK >> S_SHIFT] = F2FS_FT_SOCK,
[S_IFLNK >> S_SHIFT] = F2FS_FT_SYMLINK,
};
class Dir : public VnodeF2fs {
public:
explicit Dir(F2fs *fs);
explicit Dir(F2fs *fs, ino_t ino);
~Dir() = default;
zx_status_t Lookup(fbl::StringPiece name, fbl::RefPtr<fs::Vnode> *out) final;
zx_status_t Readdir(fs::VdirCookie *cookie, void *dirents, size_t len, size_t *out_actual) final;
zx_status_t Create(fbl::StringPiece name, uint32_t mode, fbl::RefPtr<fs::Vnode> *out) final;
zx_status_t Link(fbl::StringPiece name, fbl::RefPtr<fs::Vnode> _target) final;
zx_status_t Unlink(fbl::StringPiece name, bool must_be_dir) final;
zx_status_t Rename(fbl::RefPtr<fs::Vnode> _newdir, fbl::StringPiece oldname,
fbl::StringPiece newname, bool src_must_be_dir, bool dst_must_be_dir);
uint64_t DirBlocks();
static unsigned int DirBuckets(unsigned int level);
static unsigned int BucketBlocks(unsigned int level);
void SetDeType(f2fs_dir_entry *de, VnodeF2fs *vnode);
static uint64_t DirBlockIndex(unsigned int level, unsigned int idx);
bool EarlyMatchName(const char *name, int namelen, f2fs_hash_t namehash,
f2fs_dir_entry *de);
f2fs_dir_entry *FindInBlock(Page *dentry_page, const char *name, int namelen,
int *max_slots, f2fs_hash_t namehash, Page **res_page);
f2fs_dir_entry *FindInLevel(unsigned int level, fbl::StringPiece name, int namelen,
f2fs_hash_t namehash, Page **res_page);
f2fs_dir_entry *F2fsFindEntry(fbl::StringPiece name, Page **res_page);
f2fs_dir_entry *F2fsParentDir(Page **p);
ino_t F2fsInodeByName(fbl::StringPiece name);
void F2fsSetLink(f2fs_dir_entry *de, Page *page, VnodeF2fs *inode);
void InitDentInode(VnodeF2fs *vnode, Page *ipage);
zx_status_t InitInodeMetadata(VnodeF2fs *vnode, dentry *dentry);
void UpdateParentMetadata(VnodeF2fs *inode, unsigned int current_depth);
int RoomForFilename(f2fs_dentry_block *dentry_blk, int slots);
zx_status_t F2fsAddLink(fbl::StringPiece name, VnodeF2fs *vnode);
void F2fsDeleteEntry(f2fs_dir_entry *dentry, Page *page, VnodeF2fs *vnode);
zx_status_t F2fsMakeEmpty(VnodeF2fs *vnode, VnodeF2fs *parent);
bool F2fsEmptyDir();
zx_status_t F2fsNewInode(uint32_t mode, fbl::RefPtr<VnodeF2fs> *out);
int IsMultimediaFile(const char *s, const char *sub);
void SetColdFile(const char *name);
zx_status_t F2fsCreate(fbl::StringPiece name, uint32_t mode, fbl::RefPtr<fs::Vnode> *out);
int F2fsLink(dentry *old_dentry, dentry *dentry);
#if 0 // porting needed
// dentry *F2fsGetParent(dentry *child);
#endif
zx_status_t F2fsUnlink(VnodeF2fs *vnode, fbl::StringPiece name);
#if 0 // porting needed
// int F2fsSymlink(dentry *dentry, const char *symname);
#endif
zx_status_t F2fsMkdir(fbl::StringPiece name, uint32_t mode, fbl::RefPtr<fs::Vnode> *out);
zx_status_t F2fsRmdir(Dir *vnode, fbl::StringPiece name);
#if 0 // porting needed
// int F2fsMknod(dentry *dentry, umode_t mode, dev_t rdev);
#endif
zx_status_t F2fsLookup(fbl::StringPiece name, fbl::RefPtr<fs::Vnode> *out);
};
} // namespace f2fs
#endif // F2FS_DIR_H_