📄 namei.cpp
字号:
#include "../jffs/jffstypes.h"
#include "../jffs/fcntl.h"
#include "../jffs/errno.h"
#include "../jffs/stat.h"
#include "../jffs/fs.h"
/*
* lookup() looks up one part of a pathname, using the fs-dependent
* routines (currently minix_lookup) for it. It also checks for
* fathers (pseudo-roots, mount-points)
*/
int lookup(struct inode * dir,const char * name, int len,
struct inode ** result)
{
struct super_block * sb;
int perm;
*result = (struct inode *)NULL;
if (!dir)
return -ENOENT;
if (!dir->i_op || !dir->i_op->lookup) {
iput(dir);
return -ENOTDIR;
}
if (!len) {
*result = dir;
return 0;
}
return dir->i_op->lookup(dir, name, len, result);
}
int follow_link(struct inode * dir, struct inode * inode,
int flag, int mode, struct inode ** res_inode)
{
if (!dir || !inode) {
/*iput(dir);
iput(inode);*/
*res_inode = (struct inode *)NULL;
return -ENOENT;
}
if (!inode->i_op || !inode->i_op->follow_link) {
/*iput(dir);*/
*res_inode = inode;
return 0;
}
return inode->i_op->follow_link(dir,inode,flag,mode,res_inode);
}
/*
* dir_namei()
*
* dir_namei() returns the inode of the directory of the
* specified name, and the name within that directory.
*/
/*pathname需以'\0'结尾, 要求绝对路径 */
static int dir_namei(const char *pathname, int *namelen, const char **name,
struct inode * base, struct inode **res_inode)
{
char c;
const char * thisname;
int len,error;
struct inode * inode;
//struct inode bbase;
//base = &bbase;
*res_inode = (struct inode *)NULL;
/*只处理绝对路径, fdk文件传送, 自己循环查询*/
if ((c = *pathname) == '/') {
/*iput(base); base为NULL*/
base = current_fs.root;
//memcpy(base, current_fs.root, sizeof(struct inode));
pathname++;
/*base->i_count++;*/
}
else
return -ENOTDIR;
while (1) {
thisname = pathname;
for(len=0;(c = *(pathname++))&&(c != '/');len++)
/* nothing */ ;
if (!c)
break;
/*base->i_count++;*/
error = lookup(base, thisname, len, &inode);
if (error) {
/*iput(base);*/
return error;
}
//memcpy(base, &inode, sizeof(
base = inode;
/*在follow_link中更新base, ?follow_link的意义*/
/*error = follow_link(base,inode,0,0,&base);
if (error)
return error;*/
}
if (!base->i_op || !base->i_op->lookup) {
/*iput(base);*/
return -ENOTDIR;
}
*name = thisname;
*namelen = len;
*res_inode = base;
return 0;
}
/*
* open_namei()
*
* namei for open - this is in fact almost the whole open-routine.
*
* Note that the low bits of "flag" aren't the same as in the open
* system call - they are 00 - no permissions needed
* 01 - read permission needed
* 10 - write permission needed
* 11 - read/write permissions needed
* which is a lot more logical, and also allows the "no perm" needed
* for symlinks (where the permissions are checked later).
*/
int open_namei(const char * pathname, int flag, int mode,
struct inode ** res_inode, struct inode * base)
{
const char * basename;
int namelen,error;
struct inode * dir, *inode;
error = dir_namei(pathname, &namelen, &basename, base, &dir);
if (error)
return error;
if (!namelen) { /* special case: '/usr/' etc */
if (flag & 2) {
iput(dir);
return -EISDIR;
}
*res_inode=dir;
return 0;
}
dir->i_count++; /* lookup eats the dir */
if (flag & O_CREAT) {
/*???down(&dir->i_sem);*/
error = lookup(dir, basename, namelen, &inode);
if (!error) {
if (flag & O_EXCL) {
iput(inode);
error = -EEXIST;
}
} else if (IS_RDONLY(dir))
error = -EROFS;
else if (!dir->i_op || !dir->i_op->create)
error = -EACCES;
else {
dir->i_count++; /* create eats the dir */
error = dir->i_op->create(dir, basename, namelen, mode, res_inode);
/*???up(&dir->i_sem);*/
iput(dir);
return error;
}
/*???up(&dir->i_sem);TODO*/
} else
error = lookup(dir, basename, namelen, &inode);
if (error) {
iput(dir);
return error;
}
if (S_ISDIR(inode->i_mode) && (flag & 2)) {
iput(inode);
return -EISDIR;
}
if (IS_RDONLY(inode) && (flag & 2)) {
iput(inode);
return -EROFS;
}
/*
* An append-only file must be opened in append mode for writing
* Additionally, we must disallow O_TRUNC -- cevans
*/
if (IS_APPEND(inode) && (((flag & FMODE_WRITE) && !(flag & O_APPEND)) || (flag & O_TRUNC))) {
iput(inode);
return -EPERM;
}
if (flag & O_TRUNC) {
/*error = do_truncate(inode, 0);
if (error) {
iput(inode);
return error;
}*/
}
*res_inode = inode;
return 0;
}
int mf_unlink(const char * name)
{
const char * basename;
int namelen, error;
struct inode * dir;
int fd;
fd = mf_open((char *)name, 0, 0); /*!!!修改current_fd,get_empty_inode*/
if(fd == 0) return -1;
error = dir_namei(name, &namelen, &basename, (struct inode *)NULL, &dir);
if (error)
return error;
if (!namelen) {
/*iput(dir);*/
return -EPERM;
}
/*if (IS_RDONLY(dir)) {
iput(dir);
return -EROFS;
}*/
/*if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) {
iput(dir);
return error;
}*/
/*
* A file cannot be removed from an append-only directory
*/
/*if (IS_APPEND(dir)) {
iput(dir);
return -EPERM;
}
if (!dir->i_op || !dir->i_op->unlink) {
iput(dir);
return -EPERM;
}*/
/*if (dir->i_sb && dir->i_sb->dq_op)
dir->i_sb->dq_op->initialize(dir, -1);*/
/*-down(&dir->i_sem);*/
error = dir->i_op->unlink(dir,basename,namelen);
/*-up(&dir->i_sem);*/
mf_close(fd);
return error;
}
int mf_mkdir(const char * pathname, int mode)
{
const char * basename;
int namelen, error;
struct inode * dir;
error = dir_namei(pathname, &namelen, &basename, (struct inode *)0, &dir);
if (error)
return error;
if (!namelen) {
iput(dir);
return -ENOENT;
}
if (IS_RDONLY(dir)) {
iput(dir);
return -EROFS;
}
/*m* if ((error = permission(dir,MAY_WRITE | MAY_EXEC)) != 0) {
iput(dir);
return error;
}*/
if (!dir->i_op || !dir->i_op->mkdir) {
iput(dir);
return -EPERM;
}
dir->i_count++;
/*m* if (dir->i_sb && dir->i_sb->dq_op)
dir->i_sb->dq_op->initialize(dir, -1);
down(&dir->i_sem);*/
/*m* error = dir->i_op->mkdir(dir, basename, namelen, mode & 01777 & ~current->fs->umask);*/
error = dir->i_op->mkdir(dir, basename, namelen, mode & 01777);
/*m* up(&dir->i_sem);*/
iput(dir);
return error;
}
int mf_rename(const char * oldname, const char * newname, int must_be_dir)
{
struct inode * old_dir, * new_dir;
const char * old_base, * new_base;
int old_len, new_len, error;
error = dir_namei(oldname, &old_len, &old_base, ( struct inode *)NULL, &old_dir);
if (error)
return error;
/*if ((error = permission(old_dir,MAY_WRITE | MAY_EXEC)) != 0) {
iput(old_dir);
return error;
}*/
if (!old_len || (old_base[0] == '.' &&
(old_len == 1 || (old_base[1] == '.' &&
old_len == 2)))) {
iput(old_dir);
return -EPERM;
}
error = dir_namei(newname, &new_len, &new_base, ( struct inode *)NULL, &new_dir);
if (error) {
iput(old_dir);
return error;
}
/*if ((error = permission(new_dir,MAY_WRITE | MAY_EXEC)) != 0){
iput(old_dir);
iput(new_dir);
return error;
}*/
if (!new_len || (new_base[0] == '.' &&
(new_len == 1 || (new_base[1] == '.' &&
new_len == 2)))) {
iput(old_dir);
iput(new_dir);
return -EPERM;
}
if (new_dir->i_dev != old_dir->i_dev) {
iput(old_dir);
iput(new_dir);
return -EXDEV;
}
if (IS_RDONLY(new_dir) || IS_RDONLY(old_dir)) {
iput(old_dir);
iput(new_dir);
return -EROFS;
}
/*
* A file cannot be removed from an append-only directory
*/
if (IS_APPEND(old_dir)) {
iput(old_dir);
iput(new_dir);
return -EPERM;
}
if (!old_dir->i_op || !old_dir->i_op->rename) {
iput(old_dir);
iput(new_dir);
return -EPERM;
}
new_dir->i_count++;
/*if (new_dir->i_sb && new_dir->i_sb->dq_op)
new_dir->i_sb->dq_op->initialize(new_dir, -1);
down(&new_dir->i_sem);*/
error = old_dir->i_op->rename(old_dir, old_base, old_len,
new_dir, new_base, new_len, must_be_dir);
/*up(&new_dir->i_sem);*/
iput(new_dir);
return error;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -