linux 0.11 内核学习 -- namei.c。

文件可能比较长,呵呵。

 

/*

 *  linux/fs/namei.c

 *

 *  (C) 1991  Linus Torvalds

 */

 

/*

 * Some corrections by tytso.

 */

 

#include <linux/sched.h>

#include <linux/kernel.h>

#include <asm/segment.h>

 

#include <string.h>

#include <fcntl.h>

#include <errno.h>

#include <const.h>

#include <sys/stat.h>

 

#define ACC_MODE(x) ("/004/002/006/377"[(x)&O_ACCMODE])

 

/*

 * comment out this line if you want names > NAME_LEN chars to be

 * truncated. Else they will be disallowed.

 */

/* #define NO_TRUNCATE */

 

#define MAY_EXEC 1

#define MAY_WRITE 2

#define MAY_READ 4

 

/*

 * permission()

 *

 * is used to check for read/write/execute permissions on a file.

 * I don't know if we should look at just the euid or both euid and

 * uid, but that should be easily changed.

 */

/* 检测文件访问许可权限 */

static int permission(struct m_inode * inode,int mask)

{

int mode = inode->i_mode;

 

/* special case: not even root can read/write a deleted file */

if (inode->i_dev && !inode->i_nlinks)

return 0;

// 如果进程的有效用户id(euid)与i 节点的用户id 相同

else if (current->euid==inode->i_uid)

// 则取文件宿主的用户访问权限

mode >>= 6;

// 如果进程的有效组id(egid)与i 节点的组id 相同

else if (current->egid==inode->i_gid)

// 则取组用户的访问权限

mode >>= 3;

// 如果上面所取的的访问权限与屏蔽码相同,或者是超级用户

if (((mode & mask & 0007) == mask) || suser())

return 1;

return 0;

}

 

/*

 * ok, we cannot use strncmp, as the name is not in our data space.

 * Thus we'll have to use match. No big problem. Match also makes

 * some sanity tests.

 *

 * NOTE! unlike strncmp, match returns 1 for success, 0 for failure.

 */

/* 指定长度字符串比较函数,match()成功时返回1,失败时返回0 */

static int match(int len,const char * name,struct dir_entry * de)

{

register int same __asm__("ax");

 

if (!de || !de->inode || len > NAME_LEN)

return 0;

if (len < NAME_LEN && de->name[len])

return 0;

__asm__("cld/n/t"

"fs ; repe ; cmpsb/n/t"

"setz %%al"

:"=a" (same)

:"0" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)

:"cx","di","si");

return same;

}

 

/*

 * find_entry()

 *

 * finds an entry in the specified directory with the wanted name. It

 * returns the cache buffer in which the entry was found, and the entry

 * itself (as a parameter - res_dir). It does NOT read the inode of the

 * entry - you'll have to do that yourself if you want to.

 *

 * This also takes care of the few special cases due to '..'-traversal

 * over a pseudo-root and a mount point.

 */

/* 从一个目录中搜索制定的目录项,在指定的目录下,查找相应的文件inode */

/* 标志。例如在/etc/目录下,查找某个文件,返回的是该文件的inode标志 */

/* 函数的返回值放在参数res_dir中    */

static struct buffer_head * find_entry(struct m_inode ** dir,

const char * name, int namelen, struct dir_entry ** res_dir)

{

int entries;

int block,i;

struct buffer_head * bh;

struct dir_entry * de;

struct super_block * sb;

 

// 得到namelen

#ifdef NO_TRUNCATE

if (namelen > NAME_LEN)

return NULL;

#else

if (namelen > NAME_LEN)

namelen = NAME_LEN;

#endif

// linux中目录也是文件

// 计算本目录中目录项项数entries

entries = (*dir)->i_size / (sizeof (struct dir_entry));

*res_dir = NULL; // 返回目录项结构指针

if (!namelen)

return NULL;

/* check for '..', as we might have to do some "magic" for it */

/* /* 检查目录项'..' */

if (namelen==2 && get_fs_byte(name)=='.' && get_fs_byte(name+1)=='.') 

{

/* '..' in a pseudo-root results in a faked '.' (just change namelen) */

// 如果当前进程的根节点指针即是指定的目录,则将文件名修改为'.'

if ((*dir) == current->root)

namelen=1;

// 否则如果该目录的i 节点号等于ROOT_INO(1)的话, 说明是文件系统根节点

else if ((*dir)->i_num == ROOT_INO) 

{

/* '..' over a mount-point results in 'dir' being exchanged for the mounted

   directory-inode. NOTE! We set mounted, so that we can iput the new dir */

// 取文件系统的超级块

sb=get_super((*dir)->i_dev);

if (sb->s_imount) // 如果被安装到的i 节点存在

{

iput(*dir); // 释放原i 节点

// 让*dir 指向该被安装到的i 节点

(*dir)=sb->s_imount; // 对被安装到的i 节点进行处理

(*dir)->i_count++; // i_count加加

}

}

}

// 如果该i 节点所指向的第一个直接磁盘块号为0

if (!(block = (*dir)->i_zone[0]))

// 返回NULL,退出

return NULL;

// 从节点所在设备读取指定的目录项数据块

if (!(bh = bread((*dir)->i_dev,block)))

return NULL;

i = 0;

// 让de 指向数据块(de -- struct dir_entry)

de = (struct dir_entry *) bh->b_data;

while (i < entries) // 不超过目录中目录项数

{

// 如果当前目录项数据块已经搜索完

if ((char *)de >= BLOCK_SIZE+bh->b_data) 

{

brelse(bh); // 释放当前目录项数据块

bh = NULL;

// 在读入下一目录项数据块,首先是使用*dir来得到设备上的

// 逻辑块号,然后使用函数bread来读取设备上的数据

if (!(block = bmap(*dir,i/DIR_ENTRIES_PER_BLOCK)) ||

   !(bh = bread((*dir)->i_dev,block))) 

{

i += DIR_ENTRIES_PER_BLOCK;

continue;

}

de = (struct dir_entry *) bh->b_data; // 就让de 指向该目录项数据块

}

// 如果找到匹配的目录项的话,则返回该目录项结构指针和该目录项数据块指针

if (match(namelen,name,de))

{

*res_dir = de;

return bh;

}

// 否则继续在目录项数据块中比较下一个目录项

de++;

i++;

}

// 若指定目录中的所有目录项都搜索完还没有找到相应的目录项

brelse(bh); // 释放目录项数据块

 

return NULL;

}

 

/*

 * add_entry()

 *

 * adds a file entry to the specified dire

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值