namei.c ( File view )

  • By 2010-08-31
  • View(s):24
  • Download(s):2
  • Point(s): 1
			/*
* 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;
	
}
// 否则继续在目录项数据块中比较下一个目录项。
      de++;
      i++;
    
}
// 若指定目录中的所有目录项都搜索完还没有找到相应的目录项,则释放目录项数据块,返回NULL。
  brelse (bh);
  return NULL;

}

/*
* add_entry()
*
* adds a file entry to the specified directory, using the same
* semantics as find_entry(). It returns NULL if it failed.
*
* NOTE!! The inode part of 'de' is left at 0 - which means you
* may not sleep between calling this and putting something into
* the entry, as someone else might have used it while you slept.
*/
/*
* add_entry()
* 使用与find_entry()同样的方法,往指定目录中添加
...
...
(Not finished, please download and read the complete file)
			
...
Expand> <Close

Want complete source code? Download it here

Point(s): 1

Download
0 lines left, continue to read
Sponsored links

File list

Tips: You can preview the content of files by clicking file names^_^
Name Size Date
linux0.00 B0% 04-10-07
<boot>0.00 B04-10-07 15:01
bootsect.s12.49 kB08-01-04 21:38
head.s13.22 kB08-01-04 21:38
setup.s12.42 kB08-01-04 21:38
<fs>0.00 B04-10-07 15:01
bitmap.c8.46 kB02-09-04 13:12
block_dev.c3.95 kB02-09-04 13:12
buffer.c17.71 kB02-09-04 13:12
char_dev.c4.09 kB02-09-04 13:12
exec.c18.90 kB02-09-04 13:12
fcntl.c3.33 kB02-09-04 13:12
file_dev.c4.82 kB02-09-04 13:12
file_table.c209.00 B02-09-04 13:12
inode.c14.92 kB02-09-04 13:12
ioctl.c1.94 kB02-09-04 13:12
Makefile6.80 kB08-01-04 21:45
namei.c37.20 kB02-09-04 13:12
open.c10.00 kB02-09-04 13:12
pipe.c5.42 kB02-09-04 13:12
read_write.c5.86 kB02-09-04 13:12
stat.c2.69 kB02-09-04 13:12
super.c13.57 kB02-09-04 13:12
truncate.c2.46 kB02-09-04 13:12
<include>0.00 B04-10-07 15:01
a.out.h8.22 kB02-09-04 13:14
<asm>0.00 B04-10-07 15:01
io.h772.00 B02-09-04 13:14
memory.h1.03 kB08-01-04 22:13
segment.h2.50 kB02-09-04 13:14
system.h4.08 kB02-09-04 13:14
const.h589.00 B02-09-04 13:14
ctype.h1.68 kB02-09-04 13:14
errno.h2.30 kB02-09-04 13:14
fcntl.h3.30 kB02-09-04 13:14
<linux>0.00 B04-10-07 15:01
config.h2.16 kB02-09-04 13:14
fs.h9.72 kB02-09-04 13:14
hdreg.h2.94 kB02-09-04 13:14
head.h760.00 B02-09-04 13:14
kernel.h1.44 kB02-09-04 13:14
mm.h473.00 B02-09-04 13:14
sched.h13.25 kB02-09-04 13:14
sys.h5.41 kB02-09-04 13:14
tty.h3.93 kB02-09-04 13:14
signal.h4.01 kB02-09-04 13:14
stdarg.h1.77 kB02-09-04 13:14
stddef.h378.00 B02-09-04 13:14
string.h21.75 kB02-09-04 13:14
<sys>0.00 B04-10-07 15:01
stat.h2.37 kB02-09-04 13:14
times.h377.00 B02-09-04 13:14
types.h1.10 kB02-09-04 13:14
utsname.h423.00 B02-09-04 13:14
wait.h1.48 kB02-09-04 13:14
termios.h13.58 kB02-09-04 13:14
time.h1.81 kB02-09-04 13:14
unistd.h9.21 kB02-09-04 13:14
utime.h392.00 B02-09-04 13:14
<init>0.00 B04-10-07 15:01
main.c12.52 kB02-09-04 13:12
<kernel>0.00 B04-10-07 15:01
asm.s5.10 kB08-01-04 22:48
<blk_drv>0.00 B04-10-07 15:01
blk.h5.69 kB02-09-04 13:14
floppy.c23.49 kB02-09-04 13:12
hd.c17.14 kB02-09-04 13:12
ll_rw_blk.c7.59 kB02-09-04 13:12
Makefile4.25 kB08-01-04 22:53
ramdisk.c6.13 kB02-09-04 13:12
<chr_drv>0.00 B04-10-07 15:01
console.c30.91 kB02-09-04 13:12
keyboard.S21.04 kB08-01-04 22:59
Makefile4.81 kB08-01-04 22:59
rs_io.s5.75 kB08-01-04 22:59
serial.c2.91 kB02-09-04 13:12
tty_io.c18.40 kB02-09-04 13:12
tty_ioctl.c10.70 kB02-09-04 13:12
exit.c8.08 kB02-09-04 13:12
fork.c6.78 kB15-07-07 22:10
<math>0.00 B04-10-07 15:01
Makefile3.21 kB08-01-04 23:01
math_emulate.c2.08 kB02-09-04 13:12
mktime.c2.72 kB02-09-04 13:12
panic.c952.00 B02-09-04 13:12
printk.c1.75 kB02-09-04 13:12
sched.c18.57 kB16-07-07 21:23
signal.c5.61 kB02-09-04 13:12
sys.c7.62 kB02-09-04 13:12
system_call.s12.53 kB08-01-04 22:48
traps.c8.29 kB04-10-07 14:57
vsprintf.c9.96 kB02-09-04 13:12
<lib>0.00 B04-10-07 15:01
close.c397.00 B02-09-04 13:12
ctype.c1.72 kB02-09-04 13:12
dup.c401.00 B02-09-04 13:12
errno.c66.00 B02-09-04 13:12
execve.c607.00 B02-09-04 13:12
Makefile4.83 kB08-01-04 22:30
malloc.c13.50 kB02-09-04 13:12
open.c1.22 kB02-09-04 13:12
setsid.c382.00 B02-09-04 13:12
string.c199.00 B02-09-04 13:12
wait.c774.00 B02-09-04 13:12
write.c545.00 B02-09-04 13:12
_exit.c616.00 B02-09-04 13:12
Makefile8.58 kB08-01-04 22:21
<mm>0.00 B04-10-07 15:01
Makefile2.91 kB08-01-04 22:34
memory.c25.10 kB02-09-04 13:12
page.s842.00 B08-01-04 22:34
<tools>0.00 B04-10-07 15:01
build.c8.12 kB02-09-04 13:12
...
Sponsored links

namei.c (286.77 kB)

Need 1 point
Your Point(s)

Your Point isn't enough.

Get point immediately by PayPal

More(Debit card / Credit card / PayPal Credit / Online Banking)

Submit your source codes. Get more point

LOGIN

Don't have an account? Register now
Need any help?
Mail to: support@codeforge.com

切换到中文版?

CodeForge Chinese Version
CodeForge English Version

Where are you going?

^_^"Oops ...

Sorry!This guy is mysterious, its blog hasn't been opened, try another, please!
OK

Warm tip!

CodeForge to FavoriteFavorite by Ctrl+D