Skip to content

Commit

Permalink
✨ 089 文件系统 namei
Browse files Browse the repository at this point in the history
  • Loading branch information
StevenBaby committed Oct 26, 2022
1 parent 3e29888 commit fdfe396
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 37 deletions.
11 changes: 11 additions & 0 deletions docs/11 文件系统/089 文件系统 namei.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# 文件系统 namei

主要完成以下函数:

```c++
// 获取 pathname 对应的父目录 inode
static inode_t *named(char *pathname, char **next);

// 获取 pathname 对应的 inode
static inode_t *namei(char *pathname);
```
181 changes: 144 additions & 37 deletions src/fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,73 @@
#include <onix/stat.h>
#include <onix/syscall.h>
#include <onix/string.h>
#include <onix/task.h>
#include <onix/assert.h>
#include <onix/debug.h>
#include <onix/stat.h>

#define LOGK(fmt, args...) DEBUGK(fmt, ##args)

#define P_EXEC IXOTH
#define P_READ IROTH
#define P_WRITE IWOTH

static bool permission(inode_t *inode, u16 mask)
{
u16 mode = inode->desc->mode;

if (!inode->desc->nlinks)
return false;

task_t *task = running_task();
if (task->uid == KERNEL_USER)
return true;

if (task->uid == inode->desc->uid)
mode >>= 6;
else if (task->gid == inode->desc->gid)
mode >>= 3;

if ((mode & mask & 0b111) == mask)
return true;
return false;
}

// 获取第一个分隔符
char *strsep(const char *str)
{
char *ptr = (char *)str;
while (true)
{
if (IS_SEPARATOR(*ptr))
{
return ptr;
}
if (*ptr++ == EOS)
{
return NULL;
}
}
}

// 获取最后一个分隔符
char *strrsep(const char *str)
{
char *last = NULL;
char *ptr = (char *)str;
while (true)
{
if (IS_SEPARATOR(*ptr))
{
last = ptr;
}
if (*ptr++ == EOS)
{
return last;
}
}
}

// 判断文件名是否相等
static bool match_name(const char *name, const char *entry_name, char **next)
{
Expand Down Expand Up @@ -121,58 +183,103 @@ static buffer_t *add_entry(inode_t *dir, const char *name, dentry_t **result)
};
}

#include <onix/task.h>

void dir_test()
// 获取 pathname 对应的父目录 inode
inode_t *named(char *pathname, char **next)
{
inode_t *inode = NULL;
task_t *task = running_task();
inode_t *inode = task->iroot;
char *left = pathname;
if (IS_SEPARATOR(left[0]))
{
inode = task->iroot;
left++;
}
else if (left[0])
inode = task->ipwd;
else
return NULL;

inode->count++;
char *next = NULL;
*next = left;

if (!*left)
{
return inode;
}

char *right = strrsep(left);
if (!right || right < left)
{
return inode;
}

right++;

*next = left;
dentry_t *entry = NULL;
buffer_t *buf = NULL;
while (true)
{
buf = find_entry(&inode, left, next, &entry);
if (!buf)
goto failure;

buf = find_entry(&inode, "hello.txt", &next, &entry);
idx_t nr = entry->nr;
brelse(buf);
dev_t dev = inode->dev;
iput(inode);
inode = iget(dev, entry->nr);
if (!ISDIR(inode->desc->mode) || !permission(inode, P_EXEC))
goto failure;

buf = add_entry(inode, "world.txt", &entry);
entry->nr = nr;
if (right == *next)
goto success;

inode_t *hello = iget(inode->dev, nr);
hello->desc->nlinks++;
hello->buf->dirty = true;
left = *next;
}

iput(inode);
iput(hello);
success:
brelse(buf);
return inode;

// char pathname[] = "d1/d2/d3/d4";

// dev_t dev = inode->dev;
// char *name = pathname;
// buf = find_entry(&inode, name, &next, &entry);
// brelse(buf);
failure:
brelse(buf);
iput(inode);
return NULL;
}

// iput(inode);
// inode = iget(dev, entry->nr);
// 获取 pathname 对应的 inode
inode_t *namei(char *pathname)
{
char *next = NULL;
inode_t *dir = named(pathname, &next);
if (!dir)
return NULL;
if (!(*next))
return dir;

// name = next;
// buf = find_entry(&inode, name, &next, &entry);
// brelse(buf);
char *name = next;
dentry_t *entry = NULL;
buffer_t *buf = find_entry(&dir, name, &next, &entry);
if (!buf)
{
iput(dir);
return NULL;
}

// iput(inode);
// inode = iget(dev, entry->nr);
inode_t *inode = iget(dir->dev, entry->nr);

// name = next;
// buf = find_entry(&inode, name, &next, &entry);
// brelse(buf);
iput(dir);
brelse(buf);
return inode;
}

// iput(inode);
// inode = iget(dev, entry->nr);
void dir_test()
{
char pathname[] = "/";
char *name = NULL;
inode_t *inode = named(pathname, &name);
iput(inode);

// name = next;
// buf = find_entry(&inode, name, &next, &entry);
// brelse(buf);
// iput(inode);
inode = namei("/home/hello.txt");
LOGK("get inode %d\n", inode->nr);
iput(inode);
}
3 changes: 3 additions & 0 deletions src/include/onix/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,7 @@ inode_t *get_root_inode(); // 获取根目录 inode
inode_t *iget(dev_t dev, idx_t nr); // 获得设备 dev 的 nr inode
void iput(inode_t *inode); // 释放 inode

inode_t *named(char *pathname, char **next); // 获取 pathname 对应的父目录 inode
inode_t *namei(char *pathname); // 获取 pathname 对应的 inode

#endif

0 comments on commit fdfe396

Please sign in to comment.