/*
* linux/fs/namei.c
*
* (C) 1991 Linus Torvalds
*/
/*
* Some corrections by tytso.
*/
/*
* tytso 作了一些纠正。
*/
#include <linux/sched.h> // 调度程序头文件,定义了任务结构task_struct、初始任务0 的数据,
// 还有一些有关描述符参数设置和获取的嵌入式汇编函数宏语句。
#include <linux/kernel.h> // 内核头文件。含有一些内核常用函数的原形定义。
#include <asm/segment.h> // 段操作头文件。定义了有关段寄存器操作的嵌入式汇编函数。
#include <string.h> // 字符串头文件。主要定义了一些有关字符串操作的嵌入函数。
#include <fcntl.h> // 文件控制头文件。用于文件及其描述符的操作控制常数符号的定义。
#include <errno.h> // 错误号头文件。包含系统中各种出错号。(Linus 从minix 中引进的)。
#include <const.h> // 常数符号头文件。目前仅定义了i 节点中i_mode 字段的各标志位。
#include <sys/stat.h> // 文件状态头文件。含有文件或文件系统状态结构stat{}和常量。
// 访问模式宏。x 是include/fcntl.h 第7 行开始定义的文件访问标志。
// 根据x 值索引对应数值(数值表示rwx 权限: r, w, rw, wxrwxrwx)(数值是8 进制)。
#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.
*/
/*
* 如果想让文件名长度>NAME_LEN 的字符被截掉,就将下面定义注释掉。
*/
/* #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.
*/
/*
* permission()
* 该函数用于检测一个文件的读/写/执行权限。我不知道是否只需检查euid,还是
* 需要检查euid 和uid 两者,不过这很容易修改。
*/
//// 检测文件访问许可权限。
// 参数:inode - 文件对应的i 节点;mask - 访问属性屏蔽码。
// 返回:访问许可返回1,否则返回0。
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 */
/* 特殊情况:即使是超级用户(root)也不能读/写一个已被删除的文件 */
// 如果i 节点有对应的设备,但该i 节点的连接数等于0,则返回。
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;
// 如果上面所取的的访问权限与屏蔽码相同,或者是超级用户,则返回1,否则返回0。
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.
*/
/*
* ok,我们不能使用strncmp 字符串比较函数,因为名称不在我们的数据空间(不在内核空间)。
* 因而我们只能使用match()。问题不大。match()同样也处理一些完整的测试。
*
* 注意!与strncmp 不同的是match()成功时返回1,失败时返回0。
*/
//// 指定长度字符串比较函数。
// 参数:len - 比较的字符串长度;name - 文件名指针;de - 目录项结构。
// 返回:相同返回1,不同返回0。
static int
match (int len, const char *name, struct dir_entry *de)
{
register int same __asm__ ("ax");
// 如果目录项指针空,或者目录项i 节点等于0,或者要比较的字符串长度超过文件名长度,则返回0。
if (!de || !de->inode || len > NAME_LEN)
return 0;
// 如果要比较的长度len 小于NAME_LEN,但是目录项中文件名长度超过len,则返回0。
if (len < NAME_LEN && de->name[len])
return 0;
// 下面嵌入汇编语句,在用户数据空间(fs)执行字符串的比较操作。
// %0 - eax(比较结果same);%1 - eax(eax 初值0);%2 - esi(名字指针);%3 - edi(目录项名指针);
// %4 - ecx(比较的字节长度值len)。
__asm__ ("cld\n\t" // 清方向位。
"fs ; repe ; cmpsb\n\t" // 用户空间执行循环比较[esi++]和[edi++]操作,
"setz %%al" // 若比较结果一样(z=0)则设置al=1(same=eax)。
: "=a" (same): "" (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.
*/
/*
* find_entry()
* 在指定的目录中寻找一个与名字匹配的目录项。返回一个含有找到目录项的高速
* 缓冲区以及目录项本身(作为一个参数 - res_dir)。并不读目录项的i 节点 - 如
* 果需要的话需自己操作。
*
* '..'目录项,操作期间也会对几种特殊情况分别处理 - 比如横越一个伪根目录以
* 及安装点。
*/
//// 查找指定目录和文件名的目录项。
// 参数:dir - 指定目录i 节点的指针;name - 文件名;namelen - 文件名长度;
// 返回:高速缓冲区指针;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;
// 如果定义了NO_TRUNCATE,则若文件名长度超过最大长度NAME_LEN,则返回。
#ifdef NO_TRUNCATE
if (namelen > NAME_LEN)
return NULL;
//如果没有定义NO_TRUNCATE,则若文件名长度超过最大长度NAME_LEN,则截短之。
#else
if (namelen > NAME_LEN)
namelen = NAME_LEN;
#endif
// 计算本目录中目录项项数entries。置空返回目录项结构指针。
entries = (*dir)->i_size / (sizeof (struct dir_entry));
*res_dir = NULL;
// 如果文件名长度等于0,则返回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 */
/* 在一个安装点上的'..'将导致目录交换到安装到文件系统的目录i 节点。
注意!由于设置了mounted 标志,因而我们能够取出该新目录 */
sb = get_super ((*dir)->i_dev);
// 如果被安装到的i 节点存在,则先释放原i 节点,然后对被安装到的i 节点进行处理。
// 让*dir 指向该被安装到的i 节点;该i 节点的引用数加1。
if (sb->s_imount)
{
iput (*dir);
(*dir) = sb->s_imount;
(*dir)->i_count++;
}
}
}
// 如果该i 节点所指向的第一个直接磁盘块号为0,则返回NULL,退出。
if (!(block = (*dir)->i_zone[0]))
return NULL;
// 从节点所在设备读取指定的目录项数据块,如果不成功,则返回NULL,退出。
if (!(bh = bread ((*dir)->i_dev, block)))
return NULL;
// 在目录项数据块中搜索匹配指定文件名的目录项,首先让de 指向数据块,并在不超过目录中目录项数
// 的条件下,循环执行搜索。
i = 0;
de = (struct dir_entry *) bh->b_data;
while (i < entries)
{
// 如果当前目录项数据块已经搜索完,还没有找到匹配的目录项,则释放当前目录项数据块。
if ((char *) de >= BLOCK_SIZE + bh->b_data)
{
brelse (bh);
bh = NULL;
// 在读入下一目录项数据块。若这块为空,则只要还没有搜索完目录中的所有目录项,就跳过该块,
// 继续读下一目录项数据块。若该块不空,就让de 指向该目录项数据块,继续搜索。
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;
}
// 如果找到匹配的目录项的话,则返回该目录项结构指针和该目录项数据块指针,退出。
if (match (namelen, name, de))
{
*res_dir = de;
return bh;
}
// 否则继续在目录项数据块中比较下一个目录项。
没有合适的资源?快使用搜索试试~ 我知道了~
Liunx0.rar
共98个文件
c:50个
h:32个
s:8个
需积分: 10 2 下载量 148 浏览量
2008-10-17
23:43:43
上传
评论
收藏 279KB RAR 举报
温馨提示
Liunx0.1源码,有详细的中文注释,是初学的好源码
资源详情
资源评论
资源推荐
收起资源包目录
linux 0.11 源代码0.11.rar (98个子文件)
www.pudn.com.txt 218B
linux
init
main.c 13KB
tools
build.c 8KB
boot
head.s 13KB
bootsect.s 12KB
setup.s 12KB
mm
page.s 842B
memory.c 25KB
Makefile 3KB
include
stdarg.h 2KB
string.h 22KB
const.h 589B
utime.h 392B
ctype.h 2KB
unistd.h 9KB
termios.h 14KB
stddef.h 378B
signal.h 4KB
asm
memory.h 1KB
segment.h 2KB
system.h 4KB
io.h 772B
linux
config.h 2KB
kernel.h 1KB
fs.h 10KB
sys.h 5KB
head.h 760B
tty.h 4KB
hdreg.h 3KB
sched.h 13KB
mm.h 473B
fcntl.h 3KB
errno.h 2KB
a.out.h 8KB
sys
utsname.h 423B
types.h 1KB
wait.h 1KB
times.h 377B
stat.h 2KB
time.h 2KB
fs
buffer.c 18KB
stat.c 3KB
inode.c 15KB
open.c 10KB
block_dev.c 4KB
truncate.c 2KB
file_dev.c 5KB
bitmap.c 8KB
ioctl.c 2KB
read_write.c 6KB
pipe.c 5KB
exec.c 19KB
fcntl.c 3KB
file_table.c 209B
super.c 14KB
namei.c 37KB
Makefile 7KB
char_dev.c 4KB
lib
write.c 545B
errno.c 66B
open.c 1KB
_exit.c 616B
malloc.c 14KB
dup.c 401B
string.c 199B
close.c 397B
setsid.c 382B
Makefile 5KB
execve.c 607B
ctype.c 2KB
wait.c 774B
Makefile 9KB
kernel
mktime.c 3KB
sys.c 8KB
asm.s 5KB
exit.c 8KB
system_call.s 13KB
fork.c 7KB
printk.c 2KB
sched.c 19KB
signal.c 6KB
vsprintf.c 10KB
blk_drv
hd.c 17KB
blk.h 6KB
floppy.c 23KB
ramdisk.c 6KB
ll_rw_blk.c 8KB
Makefile 4KB
math
math_emulate.c 2KB
Makefile 3KB
chr_drv
keyboard.S 21KB
tty_ioctl.c 11KB
console.c 31KB
Makefile 5KB
serial.c 3KB
rs_io.s 6KB
tty_io.c 18KB
panic.c 952B
共 98 条
- 1
匠心码农
- 粉丝: 1074
- 资源: 53
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0