1 /*
2 * linux/fs/namei.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /*
8 * Some corrections by tytso.
9 */
10
11 #include <linux/sched.h> // ���ȳ���ͷ�ļ�������������ṹtask_struct������0�����ݵȡ�
12 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
13 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
14
15 #include <string.h> // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ַ���������Ƕ�뺯����
16 #include <fcntl.h> // �ļ�����ͷ�ļ����ļ������������IJ������Ƴ������ŵĶ��塣
17 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
18 #include <const.h> // ��������ͷ�ļ���Ŀǰ������i�ڵ���i_mode�ֶεĸ���־λ��
19 #include <sys/stat.h> // �ļ�״̬ͷ�ļ��������ļ����ļ�ϵͳ״̬�ṹstat{}�ͳ�����
20
// ���ļ������Ҷ�Ӧi�ڵ���ڲ�������
21 static struct m_inode * _namei(const char * filename, struct m_inode * base,
22 int follow_links);
23
// ��������Ҳ����ʽ�Ƿ��������һ������ʹ�÷�����������������һ����ʵ��������������
// �����±�����ʾ�����������a[b]����ֵ��ͬ��ʹ��������ָ�루��ַ�����ϸ���ƫ�Ƶ�ַ
// ����ʽ��ֵ *(a + b)��ͬʱ��֪��a[b]Ҳ���Ա�ʾ��b[a]����ʽ����˶����ַ���������ʽ
// Ϊ "LoveYou"[2]������2["LoveYou"]���͵�ͬ��*("LoveYou" + 2)�����⣬�ַ���"LoveYou"
// ���ڴ��б��洢��λ�þ������ַ�����������"LoveYou"[2]��ֵ���Ǹ��ַ���������ֵΪ2
// ���ַ�"v"����Ӧ��ASCII��ֵ0x76�����ð˽��Ʊ�ʾ����0166����C�����У��ַ�Ҳ������
// ��ASCII��ֵ����ʾ�����������ַ���ASCII��ֵǰ���һ����б�ܡ������ַ� "v"���Ա�ʾ
// ��"\x76"����"\166"����˶��ڲ�����ʾ���ַ�������ASCII��ֵΪ0x00--0x1f�Ŀ����ַ���
// �Ϳ�����ASCII��ֵ����ʾ��
//
// �����Ƿ���ģʽ�ꡣx��ͷ�ļ�include/fcntl.h�е�7�п�ʼ������ļ����ʣ�����־��
// ���������ļ����ʱ�־x��ֵ������˫�����ж�Ӧ����ֵ��˫��������4���˽�����ֵ��ʵ
// �ʱ�ʾ4�������ַ�����"\004\002\006\377"���ֱ��ʾ����д��ִ�е�Ȩ��Ϊ: r��w��rw
// ��wxrwxrwx�����ҷֱ��Ӧx������ֵ0--3�� ���磬���xΪ2����ú귵�ذ˽���ֵ006��
// ��ʾ�ɶ���д��rw�������⣬����O_ACCMODE = 00003��������ֵx�������롣
24 #define ACC_MODE(x) ("\004\002\006\377"[(x)&O_ACCMODE])
25
26 /*
27 * comment out this line if you want names > NAME_LEN chars to be
28 * truncated. Else they will be disallowed.
29 */
/*
* ��������ļ������� > NAME_LEN�����ַ����ص����ͽ����涨��ע�͵���
*/
30 /* #define NO_TRUNCATE */
31
32 #define MAY_EXEC 1 // ��ִ��(�ɽ���)��
33 #define MAY_WRITE 2 // ���
34 #define MAY_READ 4 // �ɶ���
35
36 /*
37 * permission()
38 *
39 * is used to check for read/write/execute permissions on a file.
40 * I don't know if we should look at just the euid or both euid and
41 * uid, but that should be easily changed.
42 */
/*
* permission()
*
* �ú������ڼ��һ���ļ��Ķ�/д/ִ��Ȩ�ޡ��Ҳ�֪���Ƿ�ֻ����euid��
* ������Ҫ���euid��uid���ߣ�������������ġ�
*/
//// ����ļ���������Ȩ�ޡ�
// ������inode - �ļ���i�ڵ�ָ�룻mask - �������������롣
// ���أ��������ɷ���1������0��
43 static int permission(struct m_inode * inode,int mask)
44 {
45 int mode = inode->i_mode; // �ļ��������ԡ�
46
47 /* special case: not even root can read/write a deleted file */
/* �����������ʹ�dz����û���root��Ҳ���ܶ�/дһ���ѱ�ɾ�����ļ� */
// ���i�ڵ��ж�Ӧ���豸������i�ڵ�����Ӽ���ֵ����0����ʾ���ļ��ѱ�ɾ�����ء�
// ����������̵���Ч�û�id��euid����i�ڵ���û�id��ͬ����ȡ�ļ������ķ���Ȩ�ޡ�
// ����������̵���Ч��id��egid����i�ڵ����id��ͬ����ȡ���û��ķ���Ȩ�ޡ�
48 if (inode->i_dev && !inode->i_nlinks)
49 return 0;
50 else if (current->euid==inode->i_uid)
51 mode >>= 6;
52 else if (in_group_p(inode->i_gid))
53 mode >>= 3;
// ����ж������ȡ�ĵķ���Ȩ������������ͬ�������dz����û�����1������0��
54 if (((mode & mask & 0007) == mask) || suser())
55 return 1;
56 return 0;
57 }
58
59 /*
60 * ok, we cannot use strncmp, as the name is not in our data space.
61 * Thus we'll have to use match. No big problem. Match also makes
62 * some sanity tests.
63 *
64 * NOTE! unlike strncmp, match returns 1 for success, 0 for failure.
65 */
/*
* ok�����Dz���ʹ��strncmp�ַ����ȽϺ�������Ϊ���Ʋ������ǵ����ݿռ�
* �������ں˿ռ䣩�� �������ֻ��ʹ�� match()�����ⲻ��match()ͬ��
* Ҳ����һЩ�����IJ��ԡ�
*
* ע�⣡��strncmp��ͬ����match()�ɹ�ʱ����1��ʧ��ʱ����0��
*/
//// ָ�������ַ����ȽϺ�����
// ������len - �Ƚϵ��ַ������ȣ�name - �ļ���ָ�룻de - Ŀ¼��ṹ��
// ���أ���ͬ����1����ͬ����0��
// ��68���϶�����һ���ֲ��Ĵ�������same���ñ�������������eax�Ĵ����У��Ա��ڸ�Ч
// ���ʡ�
66 static int match(int len,const char * name,struct dir_entry * de)
67 {
68 register int same __asm__("ax");
69
// �����жϺ�����������Ч�ԡ����Ŀ¼��ָ��գ�����Ŀ¼��i�ڵ����0������Ҫ�Ƚϵ�
// �ַ������ȳ����ļ������ȣ���0����ƥ�䣩������Ƚϵij���len����0����Ŀ¼��
// ���ļ����ĵ�1���ַ��� '.'������ֻ����ôһ���ַ�����ô���Ǿ���Ϊ����ͬ�ģ���˷�
// ��1��ƥ�䣩�����Ҫ�Ƚϵij���lenС��NAME_LEN������Ŀ¼�����ļ������ȳ���len��
// ��Ҳ����0����ƥ�䣩��
// ��75���϶�Ŀ¼�����ļ��������Ƿ� len ���жϷ����Ǽ�� name[len] �Ƿ�ΪNULL��
// �����ȳ���len����name[len]������һ������NULL����ͨ�ַ��������ڳ���Ϊlen���ַ�
// ��name���ַ�name[len]��Ӧ����NULL��
70 if (!de || !de->inode || len > NAME_LEN)
71 return 0;
72 /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
/* "" ���� "." ������ ---> �������ܴ����� "/usr/lib//libc.a" ������·���� */
73 if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
74 return 1;
75 if (len < NAME_LEN && de->name[len])
76 return 0;
// Ȼ��ʹ��Ƕ���������п��ٱȽϲ������������û����ݿռ䣨fs�Σ�ִ���ַ����ıȽ�
// ������%0 - eax���ȽϽ��same����%1 - eax��eax��ֵ0����%2 - esi������ָ�룩��
// %3 - edi��Ŀ¼����ָ�룩��%4 - ecx(�Ƚϵ��ֽڳ���ֵlen)��
77 __asm__("cld\n\t" // �巽���־λ��
78 "fs ; repe ; cmpsb\n\t" // �û��ռ�ִ��ѭ���Ƚ�[esi++]��[edi++]������
79 "setz %%al" // ���ȽϽ��һ����zf=0������al=1��same=eax����
80 :"=a" (same)
81 :"" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
82 :"cx","di","si");
83 return same; // ���رȽϽ����
84 }
85
86 /*
87 * find_entry()
88 *
89 * finds an entry in the specified directory with the wanted name. It
90 * returns the cache buffer in which the entry was found, and the entry
91 * itself (as a parameter - res_dir). It does NOT read the inode of the
92 * entry - you'll have to do that yourself if you want to.
93 *
94 * This also takes care of the few special cases due to '..'-traversal
95 * over a pseudo-root and a mount point.
96 */
/*
* find_entry()
*
* ��ָ��Ŀ¼��Ѱ��һ��������ƥ���Ŀ¼�����һ�������ҵ�Ŀ¼��ĸ���
* ������Լ�Ŀ¼�������Ϊһ������ - res_dir�����ú���������ȡĿ¼��
* ��i�ڵ� - �����Ҫ�Ļ����Լ�������
*
* ������'..'Ŀ¼�����ڲ����ڼ�Ҳ��Լ�����������ֱ��� - �����Խ
* һ��α��Ŀ¼�Լ���װ�㡣
*/
//// ����ָ��Ŀ¼���ļ�����Ŀ¼�
// ������*dir - ָ��Ŀ¼i�ڵ��ָ�룻name - �ļ�����namelen - �ļ������ȣ�
// �ú�����ָ��Ŀ¼�����ݣ��ļ���������ָ���ļ�����Ŀ¼�����ָ���ļ�����'..'��
// ������ݵ�ǰ���е�������ý�������������ں�����������ָ���ָ������ã����
// ��linux/sched.c��151��ǰ��ע�͡�
// ���أ��ɹ��������ٻ�����ָ�룬����*res_dir�����ص�Ŀ¼��ṹָ�롣ʧ����
// ��ָ��NULL��
97 static struct buffer_head * find_entry(struct m_inode ** dir,
98 const char * name, int namelen, struct dir_entry ** res_dir)
99 {
100 int entries;
101 int block,i;
102 struct buffer_head * bh;
103 struct dir_entry * de;
104 struct super_block * sb;
105
// ͬ����������һ����Ҳ��Ҫ�Ժ�����������Ч�Խ����жϺ���֤�����������ǰ���30��
// �����˷��ų���NO_TRUNCATE����ô����ļ������ȳ������NAME_LEN�����账����
// ���û�ж����NO_TRUNCATE����ô���ļ������ȳ������NAME_LENʱ�ض�֮��
106 #ifdef NO_TRUNCATE
107 if (namelen > NAME_LEN)
108 return NULL;
109 #else
110 if (namelen > NAME_LEN)
111 namelen = NAME_LEN;
112 #endif
// ���ȼ��㱾Ŀ¼��Ŀ¼������entries�� Ŀ¼i�ڵ� i_size�ֶ��к��б�Ŀ¼����������
// ���ȣ���������һ��Ŀ¼��ij��ȣ�16�ֽڣ����ɵõ���Ŀ¼��Ŀ¼������Ȼ���ÿշ���
// Ŀ¼��ṹָ�롣
113 entries = (*dir)->i_size / (sizeof (struct dir_entry));
114 *res_dir = NULL;
// ���������Ƕ�Ŀ¼���ļ�����'..'���������������������ǰ����ָ���ĸ�i�ڵ����
// ��������ָ����Ŀ¼����˵�����ڱ�������˵�����Ŀ¼��������α��Ŀ¼��������ֻ�ܷ�
// �ʸ�Ŀ¼�е�������ܺ��˵��丸Ŀ¼��ȥ��Ҳ�����ڸý��̱�Ŀ¼����ͬ���ļ�ϵͳ�ĸ�
// Ŀ¼�����������Ҫ���ļ�����Ϊ'.'��
// ���������Ŀ¼��i�ڵ�ŵ���ROOT_INO��1�ţ��Ļ���˵��ȷʵ���ļ�ϵͳ�ĸ�i�ڵ㡣
// ��ȡ�ļ�ϵͳ�ij����顣�������װ����i�ڵ���ڣ����ȷŻ�ԭi�ڵ㣬Ȼ��Ա���װ��
// ��i�ڵ���д���������������*dirָ��ñ���װ����i�ڵ㣻���Ҹ�i�ڵ����������1��
// ���������������������ĵؽ����ˡ�͵������������:)
115 /* check for '..', as we might have to do some "magic" for it */
/* ���Ŀ¼�� '..'����Ϊ���ǿ�����Ҫ������������ */
116 if (namelen==2 && get_fs_byte(name)=='.' && get_fs_byte(name+1)=='.') {
117 /* '..' in a pseudo-root results in a faked '.' (just change namelen) */
/* α���е� '..' ��ͬһ���� '.'��ֻ��ı����ֳ��ȣ� */
118 if ((*dir) == current->root)
119 namelen=1;
120 else if ((*dir)->i_num == ROOT_INO) {
121 /* '..' over a mount-point results in 'dir' being exchanged for the mounted
122 directory-inode. NOTE! We set mounted, so that we can iput the new dir */
/* ��һ����װ���ϵ� '..' ������Ŀ¼����������װ�ļ�ϵͳ��Ŀ¼i�ڵ��ϡ�ע�⣡
��������������mounted��־����������ܹ��Żظ���Ŀ¼ */
123 sb=get_super((*dir)->i_dev);
124 if (sb->s_imount) {
125 iput(*dir);
126 (*dir)=sb->s_imount;
127 (*dir)->i_count++;
128 }
129 }
130 }
// �������ǿ�ʼ��������������ָ���ļ�����Ŀ¼����ʲô�ط������������Ҫ��ȡĿ¼����
// �ݣ���ȡ��Ŀ¼i�ڵ��Ӧ���豸�������е����ݿ飨���飩��Ϣ����Щ����Ŀ�ű�
// ����i�ڵ�ṹ�� i_zone[9]�����С�������ȡ���е�1����š����Ŀ¼i�ڵ�ָ��ĵ�
// һ��ֱ�Ӵ��̿��Ϊ0����˵����Ŀ¼��Ȼ�������ݣ��ⲻ���������Ƿ���NULL�˳�������
// ���Ǿʹӽڵ������豸��ȡָ����Ŀ¼�����ݿ顣��Ȼ��������ɹ�����Ҳ����NULL�˳���
131 if (!(block = (*dir)->i_zone[0]))
132 return NULL;
133 if (!(bh = bread((*dir)->i_dev,block)))
134 return NULL;
// ��ʱ���Ǿ��������ȡ��Ŀ¼i�ڵ����ݿ�������ƥ��ָ���ļ�����Ŀ¼�������deָ
// ����е����ݿ鲿�֣����ڲ�����Ŀ¼��Ŀ¼�����������£�ѭ��ִ������������i��
// Ŀ¼�е�Ŀ¼�������ţ���ѭ����ʼʱ��ʼ��Ϊ0��
135 i = 0;
136 de = (struct dir_entry *) bh->b_data;
137 while (i < entries) {
// �����ǰĿ¼�����ݿ��Ѿ������꣬��û���ҵ�ƥ���Ŀ¼����ͷŵ�ǰĿ¼�����ݿ顣
// �ٶ���Ŀ¼����һ�����顣�����Ϊ�գ���ֻҪ��û��������Ŀ¼�е�����Ŀ¼���
// �����ÿ飬������Ŀ¼����һ���顣���ÿ鲻�գ����� de ָ������ݿ飬Ȼ��������
// ��������������141����i/DIR_ENTRIES_PER_BLOCK�ɵõ���ǰ������Ŀ¼������Ŀ¼��
// ���еĿ�ţ���bmap()������inode.c����142�У���ɼ�������豸�϶�Ӧ������š�
138 if ((char *)de >= BLOCK_SIZE+bh->b_data) {
139 brelse(bh);
140 bh = NULL;
141 if (!(block = bmap(*dir,i/DIR_ENTRIES_PER_BLOCK)) ||
142 !(bh = bread((*dir)->i_dev,block))) {
143 i += DIR_ENTRIES_PER_BLOCK;
144 continue;
145 }
146 de = (struct dir_entry *) bh->b_data;
147 }
// ����ҵ�ƥ���Ŀ¼��Ļ����ظ�Ŀ¼��ṹָ��de��Ŀ¼��i�ڵ�ָ��*dir��
// ����Ŀ¼�����ݿ�ָ��bh�����˳����������������Ŀ¼�����ݿ��бȽ���һ��Ŀ¼�
148 if (match(namelen,name,de)) {
149 *res_dir = de;
150 return bh;
151 }
152 de++;
153 i++;
154 }
// ���ָ��Ŀ¼�е�����Ŀ¼��������û���ҵ���Ӧ��Ŀ¼����ͷ�Ŀ¼������
// �飬���NULL��ʧ�ܣ���
155 brelse(bh);
156 return NULL;
157 }
158
159 /*
160 * add_entry()
161 *
162 * adds a file entry to the specified directory, using the same
163 * semantics as find_entry(). It returns NULL if it failed.
164 *
165 * NOTE!! The inode part of 'de' is left at 0 - which means you
166 * may not sleep between calling this and putting something into
167 * the entry, as someone else might have used it while you slept.
168 */
/*
* add_entry()
* ʹ����find_entry()ͬ���ķ�������ָ��Ŀ¼������һָ���ļ�����Ŀ
* ¼����ʧ����NULL��
*
* ע�⣡��'de'��ָ��Ŀ¼��ṹָ�룩��i�ڵ㲿�ֱ�����Ϊ0 - ���
* ʾ�ڵ��øú�������Ŀ¼����������Ϣ֮�䲻��ȥ˯�ߡ� ��Ϊ���˯�ߣ�
* ��ô������(����)���ܻ�ʹ���˸�Ŀ¼�
*/
//// ����ָ����Ŀ¼���ļ�������Ŀ¼�
// ������dir - ָ��Ŀ¼��i�ڵ㣻name - �ļ�����namelen - �ļ������ȣ�
// ���أ����ٻ�����ָ�룻res_dir - ���ص�Ŀ¼��ṹָ�룻
169 static struct buffer_head * add_entry(struct m_inode * dir,
170 const char * name, int namelen, struct dir_entry ** res_dir)
171 {
172 int block,i;
173 struct buffer_head * bh;
174 struct dir_entry * de;
175
// ͬ����������һ����Ҳ��Ҫ�Ժ�����������Ч�Խ����жϺ���֤�����������ǰ���30��
// �����˷��ų���NO_TRUNCATE����ô����ļ������ȳ������NAME_LEN�����账����
// ���û�ж����NO_TRUNCATE����ô���ļ������ȳ������NAME_LENʱ�ض�֮��
176 *res_dir = NULL; // ���ڷ���Ŀ¼��ṹָ�롣
177 #ifdef NO_TRUNCATE
178 if (namelen > NAME_LEN)
179 return NULL;
180 #else
181 if (namelen > NAME_LEN)
182 namelen = NAME_LEN;
183 #endif
// �������ǿ�ʼ��������ָ��Ŀ¼������һ��ָ���ļ�����Ŀ¼����������Ҫ�ȶ�ȡĿ¼
// �����ݣ���ȡ��Ŀ¼i�ڵ��Ӧ���豸�������е����ݿ飨���飩��Ϣ����Щ����Ŀ�
// �ű�����i�ڵ�ṹ�� i_zone[9]�����С�������ȡ���е�1����š����Ŀ¼i�ڵ�ָ��
// �ĵ�һ��ֱ�Ӵ��̿��Ϊ0����˵����Ŀ¼��Ȼ�������ݣ��ⲻ���������Ƿ���NULL�˳���
// �������Ǿʹӽڵ������豸��ȡָ����Ŀ¼�����ݿ顣��Ȼ��������ɹ�����Ҳ����NULL
// �˳������⣬��������ṩ���ļ������ȵ���0����Ҳ����NULL�˳���
184 if (!namelen)
185 return NULL;
186 if (!(block = dir->i_zone[0]))
187 return NULL;
188 if (!(bh = bread(dir->i_dev,block)))
189 return NULL;
// ��ʱ���Ǿ������Ŀ¼i�ڵ����ݿ���ѭ���������δʹ�õĿ�Ŀ¼�������Ŀ¼��ṹ
// ָ��deָ����е����ݿ鲿�֣�����һ��Ŀ¼�������i��Ŀ¼�е�Ŀ¼�������ţ�
// ��ѭ����ʼʱ��ʼ��Ϊ0��
190 i = 0;
191 de = (struct dir_entry *) bh->b_data;
192 while (1) {
// �����ǰĿ¼�����ݿ��Ѿ�������ϣ�����û���ҵ���Ҫ�Ŀ�Ŀ¼����ͷŵ�ǰĿ¼����
// �ݿ飬�ٶ���Ŀ¼����һ�����顣�����Ӧ�����鲻���ھʹ���һ�顣����ȡ����
// ��ʧ���ؿա�����˴ζ�ȡ�Ĵ����������ݷ��صĻ����ָ��Ϊ�գ�˵���������
// ��������Ϊ�����ڶ��´����Ŀտ飬���Ŀ¼������ֵ����һ�������������ɵ�Ŀ¼����
// DIR_ENTRIES_PER_BLOCK�����������ÿ鲢��������������˵���¶���Ŀ�����Ŀ¼�����ݣ�
// ������Ŀ¼��ṹָ��deָ��ÿ�Ļ�������ݲ��֣�Ȼ�������м�������������196��
// �ϵ� i/DIR_ENTRIES_PER_BLOCK �ɼ���õ���ǰ������Ŀ¼��i ����Ŀ¼�ļ��еĿ�ţ�
// ��create_block()������inode.c����147�У���ɶ�ȡ�������豸�϶�Ӧ�����顣
193 if ((char *)de >= BLOCK_SIZE+bh->b_data) {
194 brelse(bh);
195 bh = NULL;
196 block = create_block(dir,i/DIR_ENTRIES_PER_BLOCK);
197 if (!block)
198 return NULL;
199 if (!(bh = bread(dir->i_dev,block))) { // �����������ÿ������
200 i += DIR_ENTRIES_PER_BLOCK;
201 continue;
202 }
203 de = (struct dir_entry *) bh->b_data;
204 }
// �����ǰ��������Ŀ¼�����i����Ŀ¼�ṹ��С���ij���ֵ�Ѿ������˸�Ŀ¼i�ڵ���Ϣ
// ��ָ����Ŀ¼���ݳ���ֵ i_size ����˵������Ŀ¼�ļ�������û������ɾ���ļ����µĿ�
// Ŀ¼��������ֻ�ܰ���Ҫ���ӵ���Ŀ¼��ӵ�Ŀ¼�ļ����ݵ�ĩ�˴������ǶԸô�Ŀ
// ¼��������ã��ø�Ŀ¼���i�ڵ�ָ��Ϊ�գ��������¸�Ŀ¼�ļ��ij���ֵ������һ��Ŀ
// ¼��ij��ȣ���Ȼ������Ŀ¼��i�ڵ����ı�־���ٸ��¸�Ŀ¼�ĸı�ʱ��Ϊ��ǰʱ�䡣
205 if (i*sizeof(struct dir_entry) >= dir->i_size) {
206 de->inode=0;
207 dir->i_size = (i+1)*sizeof(struct dir_entry);
208 dir->i_dirt = 1;
209 dir->i_ctime = CURRENT_TIME;
210 }
// ����ǰ������Ŀ¼�� de ��i�ڵ�Ϊ�գ����ʾ�ҵ�һ����δʹ�õĿ���Ŀ¼��������ӵ�
// ��Ŀ¼����Ǹ���Ŀ¼����ʱ��Ϊ��ǰʱ�䣬�����û������������ļ�������Ŀ¼���
// �ļ����ֶΣ��ú��б�Ŀ¼�����Ӧ���ٻ�������ı�־�����ظ�Ŀ¼���ָ���Լ��ø�
// �ٻ�����ָ�룬�˳���
211 if (!de->inode) {
212 dir->i_mtime = CURRENT_TIME;
213 for (i=0; i < NAME_LEN ; i++)
214 de->name[i]=(i<namelen)?get_fs_byte(name+i):0;
215 bh->b_dirt = 1;
216 *res_dir = de;
217 return bh;
218 }
219 de++; // �����Ŀ¼���Ѿ���ʹ�ã�����������һ��Ŀ¼�
220 i++;
221 }
// ������ִ�в��������Ҳ����Linus��д��δ���ʱ���ȸ���������find_entry()����
// �Ĵ��룬�����ijɱ�������J��
222 brelse(bh);
223 return NULL;
224 }
225
//// ���ҷ������ӵ�i�ڵ㡣
// ������dir - Ŀ¼i�ڵ㣻inode - Ŀ¼��i�ڵ㡣
// ���أ����ط������ӵ��ļ���i�ڵ�ָ�롣��������NULL��
226 static struct m_inode * follow_link(struct m_inode * dir, struct m_inode * inode)
227 {
228 unsigned short fs; // ������ʱ����fs�μĴ���ֵ��
229 struct buffer_head * bh;
230
// �����жϺ�����������Ч�ԡ����û�и���Ŀ¼i�ڵ㣬���Ǿ�ʹ�ý�������ṹ�����õ�
// ��i�ڵ㣬������������1�����û�и���Ŀ¼��i�ڵ㣬��Ż�Ŀ¼i�ڵ��NULL��
// ���ָ��Ŀ¼���һ���������ӣ���ֱ�ӷ���Ŀ¼���Ӧ��i�ڵ�inode��
231 if (!dir) {
232 dir = current->root;
233 dir->i_count++;
234 }
235 if (!inode) {
236 iput(dir);
237 return NULL;
238 }
239 if (!S_ISLNK(inode->i_mode)) {
240 iput(dir);
241 return inode;
242 }
// Ȼ��ȡfs�μĴ���ֵ��fsͨ��������ָ���������ݶε�ѡ���0x17�����fsû��ָ���û�
// ���ݶΣ����߸�����Ŀ¼��i�ڵ��1��ֱ�ӿ��ŵ���0�������Ƕ�ȡ��1��ֱ�ӿ������
// ��Ż�dir��inode����i�ڵ㲢����NULL�˳�������˵������fs��ָ���û����ݶΡ�����
// �����Ѿ��ɹ��ض�ȡ�������������Ŀ¼����ļ����ݣ������ļ������Ѿ��� bh ָ��Ļ���
// ���������С�ʵ���ϣ����������������н�����һ������ָ����ļ�·�����ַ�����
243 __asm__("mov %%fs,%0":"=r" (fs));
244 if (fs != 0x17 || !inode->i_zone[0] ||
245 !(bh = bread(inode->i_dev, inode->i_zone[0]))) {
246 iput(dir);
247 iput(inode);
248 return NULL;
249 }
// ��ʱ�����Ѿ�����Ҫ��������Ŀ¼���i�ڵ��ˣ����ǰ����Żء���������һ�����⣬�Ǿ�
// ���ں˺����������û����ݶ��Ǵ�����û����ݿռ��еģ���ʹ���� fs �μĴ��������û�
// �ռ䴫�����ݵ��ں˿ռ��С���������Ҫ����������ȴ���ں˿ռ��С����Ϊ����ȷ�ش���
// λ���ں��е��û����ݣ�������Ҫ��fs�μĴ�����ʱָ���ں˿ռ䣬����fs =0x10������
// ���ú�����������ٻָ�ԭfs��ֵ������ͷ���Ӧ����飬������ _namei()�����õ��ķ�
// ������ָ����ļ�i�ڵ㡣
250 iput(inode);
251 __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
252 inode = _namei(bh->b_data,dir,0);
253 __asm__("mov %0,%%fs"::"r" (fs));
254 brelse(bh);
255 return inode;
256 }
257
258 /*
259 * get_dir()
260 *
261 * Getdir traverses the pathname until it hits the topmost directory.
262 * It returns NULL on failure.
263 */
/*
* get_dir()
*
* �ú������ݸ�����·��������������ֱ���ﵽ��˵�Ŀ¼��
* ���ʧ����NULL��
*/
//// ��ָ��Ŀ¼��ʼ��Ѱָ��·������Ŀ¼�����ļ�������i�ڵ㡣
// ������pathname - ·������inode - ָ����ʼĿ¼��i�ڵ㡣
// ���أ�Ŀ¼���ļ���i�ڵ�ָ�롣ʧ��ʱ����NULL��
264 static struct m_inode * get_dir(const char * pathname, struct m_inode * inode)
265 {
266 char c;
267 const char * thisname;
268 struct buffer_head * bh;
269 int namelen,inr;
270 struct dir_entry * de;
271 struct m_inode * dir;
272
// �����жϲ�����Ч�ԡ����������ָ��Ŀ¼��i�ڵ�ָ��inodeΪ�գ���ʹ�õ�ǰ���̵ĵ�
// ǰ����Ŀ¼i�ڵ㡣����û�ָ��·�����ĵ�1���ַ���'/'����˵��·�����Ǿ���·������
// ��Ӧ�ôӵ�ǰ��������ṹ�����õĸ�����α����i�ڵ㿪ʼ����������������Ҫ�ȷŻز�
// ��ָ���Ļ����趨��Ŀ¼i�ڵ㣬��ȡ�ý���ʹ�õĸ�i�ڵ㡣Ȼ��Ѹ�i�ڵ�����ü���
// ��1����ɾ��·�����ĵ�1���ַ� '/'�������Ϳ��Ա�֤��ǰ����ֻ�������趨�ĸ�i�ڵ�
// ��Ϊ��������㡣
273 if (!inode) {
274 inode = current->pwd; // ���̵ĵ�ǰ����Ŀ¼i�ڵ㡣
275 inode->i_count++;
276 }
277 if ((c=get_fs_byte(pathname))=='/') {
278 iput(inode); // �Ż�ԭi�ڵ㡣
279 inode = current->root; // Ϊ����ָ���ĸ�i�ڵ㡣
280 pathname++;
281 inode->i_count++;
282 }
// Ȼ�����·�����еĸ���Ŀ¼�����ֺ��ļ�������ѭ����������ѭ�����������У�������Ҫ
// �Ե�ǰ���ڴ�����Ŀ¼�����ֵ� i�ڵ������Ч���жϣ����Ұѱ���thisname ָ��ǰ��
// �ڴ�����Ŀ¼�����֡������i�ڵ������ǰ������Ŀ¼�����ֲ���Ŀ¼���ͣ�����û�п�
// �����Ŀ¼�ķ������ɣ���Żظ�i�ڵ㣬������NULL�˳��� ��Ȼ�ڸս���ѭ��ʱ����ǰ
// Ŀ¼��i�ڵ�inode���ǽ��̸�i�ڵ�����ǵ�ǰ����Ŀ¼��i�ڵ㣬�����Dz���ָ����ij
// ��������ʼĿ¼��i�ڵ㡣
283 while (1) {
284 thisname = pathname;
285 if (!S_ISDIR(inode->i_mode) || !permission(inode,MAY_EXEC)) {
286 iput(inode);
287 return NULL;
288 }
// ÿ��ѭ�����Ǵ���·������һ��Ŀ¼�������ļ��������֡������ÿ��ѭ�������Ƕ�Ҫ��·
// �����ַ����з����һ��Ŀ¼�������ļ������������Ǵӵ�ǰ·����ָ�� pathname ��ʼ��
// ��������ַ���ֱ���ַ���һ����β����NULL��������һ��'/'�ַ�����ʱ���� namelen ��
// ���ǵ�ǰ����Ŀ¼�����ֵij��ȣ������� thisname ��ָ���Ŀ¼�����ֵĿ�ʼ������ʱ��
// ���ַ��ǽ�β��NULL��������Ѿ�������·����ĩβ�����ѵ������ָ��Ŀ¼�����ļ�����
// �ظ�i�ڵ�ָ���˳���
// ע�⣡���·���������һ������Ҳ��һ��Ŀ¼�����������û�м��� '/'�ַ���������
// �᷵�ظ����Ŀ¼����i�ڵ㣡���磺����·����/usr/src/linux���ú�����ֻ����src/Ŀ
// ¼����i�ڵ㡣
289 for(namelen=0;(c=get_fs_byte(pathname++))&&(c!='/');namelen++)
290 /* nothing */ ;
291 if (!c)
292 return inode;
// �ڵõ���ǰĿ¼�����֣����ļ����������ǵ��ò���Ŀ¼���find_entry()�ڵ�ǰ��
// ����Ŀ¼��Ѱ��ָ�����Ƶ�Ŀ¼����û���ҵ�����Żظ�i�ڵ㣬������NULL�˳���
// Ȼ�����ҵ���Ŀ¼����ȡ����i�ڵ��inr���豸��idev���ͷŰ�����Ŀ¼��ĸ��ٻ���
// �鲢�Żظ�i�ڵ㡣 Ȼ��ȡ�ڵ��inr��i�ڵ�inode�����Ը�Ŀ¼��Ϊ��ǰĿ¼����ѭ
// ������·�����е���һĿ¼�����֣����ļ������������ǰ������Ŀ¼����һ����������
// ������ʹ��follow_link()�Ϳ��Եõ���ָ���Ŀ¼������i�ڵ㡣
293 if (!(bh = find_entry(&inode,thisname,namelen,&de))) {
294 iput(inode);
295 return NULL;
296 }
297 inr = de->inode; // ��ǰĿ¼�����ֵ�i�ڵ�š�
298 brelse(bh);
299 dir = inode;
300 if (!(inode = iget(dir->i_dev,inr))) { // ȡi�ڵ����ݡ�
301 iput(dir);
302 return NULL;
303 }
304 if (!(inode = follow_link(dir,inode)))
305 return NULL;
306 }
307 }
308
309 /*
310 * dir_namei()
311 *
312 * dir_namei() returns the inode of the directory of the
313 * specified name, and the name within that directory.
314 */
/*
* dir_namei()
*
* dir_namei()��������ָ��Ŀ¼����i�ڵ�ָ�룬�Լ������
* Ŀ¼�����ơ�
*/
// ������pathname - Ŀ¼·������namelen - ·�������ȣ�name - ���ص����Ŀ¼����
// base - ������ʼĿ¼��i�ڵ㡣
// ���أ�ָ��Ŀ¼�����Ŀ¼��i�ڵ�ָ������Ŀ¼���Ƽ����ȡ�����ʱ����NULL��
// ע�⣡��������Ŀ¼����ָ·���������ĩ�˵�Ŀ¼��
315 static struct m_inode * dir_namei(const char * pathname,
316 int * namelen, const char ** name, struct m_inode * base)
317 {
318 char c;
319 const char * basename;
320 struct m_inode * dir;
321
// ����ȡ��ָ��·�������Ŀ¼��i�ڵ㡣Ȼ���·����pathname����������⣬������
// һ��'/'�ַ�����������ַ����������䳤�ȣ����ҷ������Ŀ¼��i�ڵ�ָ�롣ע�⣡��
// ��·�������һ���ַ���б���ַ�'/'����ô���ص�Ŀ¼��Ϊ�գ����ҳ���Ϊ0�������ص�i
// �ڵ�ָ����Ȼָ�����һ��'/'�ַ�ǰĿ¼����i�ڵ㡣�μ���289���ϵġ�ע�⡱˵����
322 if (!(dir = get_dir(pathname,base))) // base��ָ������ʼĿ¼i�ڵ㡣
323 return NULL;
324 basename = pathname;
325 while (c=get_fs_byte(pathname++))
326 if (c=='/')
327 basename=pathname;
328 *namelen = pathname-basename-1;
329 *name = basename;
330 return dir;
331 }
332
//// ȡָ��·������i�ڵ��ڲ�������
// ������pathname - ·������base - �������Ŀ¼i�ڵ㣻follow_links - �Ƿ����
// �������ӵı�־��1 - ��Ҫ��0����Ҫ��
// ���أ���Ӧ��i�ڵ㡣
333 struct m_inode * _namei(const char * pathname, struct m_inode * base,
334 int follow_links)
335 {
336 const char * basename;
337 int inr,namelen;
338 struct m_inode * inode;
339 struct buffer_head * bh;
340 struct dir_entry * de;
341
// ���Ȳ���ָ��·���������Ŀ¼��Ŀ¼�����õ���i�ڵ㡣�������ڣ���NULL�˳���
// ������ص�������ֵij�����0�����ʾ��·������һ��Ŀ¼��Ϊ���һ����˵����
// ���Ѿ��ҵ���ӦĿ¼��i�ڵ㣬����ֱ�ӷ��ظ�i�ڵ��˳���������ص����ֳ��Ȳ���0��
// ��������ָ������ʼĿ¼base���ٴε���dir_namei()��������������Ŀ¼���������ݷ���
// ����Ϣ�������жϡ�
311 if (!(dir = dir_namei(pathname,&namelen,&basename)))
312 return NULL;
313 if (!namelen) /* special case: '/usr/' etc */
314 return dir; /* ��Ӧ��'/usr/'����� */
342 if (!(base = dir_namei(pathname,&namelen,&basename,base)))
343 return NULL;
344 if (!namelen) /* special case: '/usr/' etc */
345 return base;
// Ȼ���ڷ��صĶ���Ŀ¼��Ѱ��ָ���ļ���Ŀ¼���i�ڵ㡣ע�⣡��Ϊ������Ҳ��һ��Ŀ
// ¼���������û�м�'/'���᷵�ظ����Ŀ¼��i�ڵ㣡 ���磺/usr/src/linux����ֻ
// ���� src/Ŀ¼����i�ڵ㡣��Ϊ����dir_namei() ������'/'���������һ�����ֵ���һ��
// �ļ��������������������Ҫ�������������ʹ��Ѱ��Ŀ¼��i�ڵ㺯��find_entry()����
// ��������ʱde�к���Ѱ�ҵ���Ŀ¼��ָ�룬��dir�ǰ�����Ŀ¼���Ŀ¼��i�ڵ�ָ�롣
346 bh = find_entry(&base,basename,namelen,&de);
347 if (!bh) {
348 iput(base);
349 return NULL;
350 }
// ����ȡ��Ŀ¼���i�ڵ�ţ����ͷŰ�����Ŀ¼��ĸ��ٻ���鲢�Ż�Ŀ¼i�ڵ㡣Ȼ��ȡ
// ��Ӧ�ڵ�ŵ�i�ڵ㣬���䱻����ʱ��Ϊ��ǰʱ�䣬�������ı�־����ظ�i�ڵ�
// ָ��inode�������ǰ������Ŀ¼����һ����������������ʹ��follow_link()�õ���ָ���
// Ŀ¼������i�ڵ㡣
351 inr = de->inode;
352 brelse(bh);
353 if (!(inode = iget(base->i_dev,inr))) {
354 iput(base);
355 return NULL;
356 }
357 if (follow_links)
358 inode = follow_link(base,inode);
359 else
360 iput(base);
361 inode->i_atime=CURRENT_TIME;
362 inode->i_dirt=1;
363 return inode;
364 }
365
//// ȡָ��·������i�ڵ㣬������������ӡ�
// ������pathname - ·������
// ���أ���Ӧ��i�ڵ㡣
366 struct m_inode * lnamei(const char * pathname)
367 {
368 return _namei(pathname, NULL, 0);
369 }
370
371 /*
372 * namei()
373 *
374 * is used by most simple commands to get the inode of a specified name.
375 * Open, link etc use their own routines, but this is enough for things
376 * like 'chmod' etc.
377 */
/*
* namei()
*
* �ú������������������ȡ��ָ��·�����Ƶ�i�ڵ㡣open��link����ʹ������
* �Լ�����Ӧ����������������ģʽ'chmod'������������ú������㹻���ˡ�
*/
//// ȡָ��·������i�ڵ㣬����������ӡ�
// ������pathname - ·������
// ���أ���Ӧ��i�ڵ㡣
378 struct m_inode * namei(const char * pathname)
379 {
380 return _namei(pathname,NULL,1);
381 }
382
383 /*
384 * open_namei()
385 *
386 * namei for open - this is in fact almost the whole open-routine.
387 */
/*
* open_namei()
*
* open()����ʹ�õ�namei���� - ����ʵ�����������Ĵ��ļ�����
*/
//// ���namei������
// ����filename���ļ�·������flag�Ǵ��ļ���־����ȡֵO_RDONLY��ֻ������O_WRONLY
// ��ֻд����O_RDWR����д�����Լ�O_CREAT����������O_EXCL���������ļ����벻���ڣ���
// O_APPEND�����ļ�β�������ݣ�������һЩ��־����ϡ���������ô�����һ�����ļ�����
// mode������ָ���ļ����������ԡ���Щ������S_IRWXU���ļ��������ж���д��ִ��Ȩ�ޣ���
// S_IRUSR���û����ж��ļ�Ȩ�ޣ���S_IRWXG�����Ա���ж���д��ִ��Ȩ�ޣ��ȵȡ�������
// �������ļ�����Щ����ֻӦ���ڽ������ļ��ķ��ʣ�������ֻ���ļ��Ĵ���Ҳ������һ
// ���ɶ�д���ļ�������μ������ļ�sys/stat.h��fcntl.h��
// ���أ��ɹ�����0�����س����룻res_inode - ���ض�Ӧ�ļ�·������i�ڵ�ָ�롣
388 int open_namei(const char * pathname, int flag, int mode,
389 struct m_inode ** res_inode)
390 {
391 const char * basename;
392 int inr,dev,namelen;
393 struct m_inode * dir, *inode;
394 struct buffer_head * bh;
395 struct dir_entry * de;
396
// ���ȶԺ����������к����Ĵ���������ļ�����ģʽ��־��ֻ����0���������ļ������־
// O_TRUNCȴ��λ�ˣ������ļ���־������ֻд��־O_WRONLY����������ԭ�������ڽ���
// ��־O_TRUNC�������ļ���д����²���Ч��Ȼ��ʹ�õ�ǰ���̵��ļ��������������룬��
// �ε�����ģʽ�е���Ӧλ����������ͨ�ļ���־I_REGULAR���ñ�־�����ڴ��ļ�����
// �ڶ���Ҫ�����ļ�ʱ����Ϊ���ļ���Ĭ�����ԡ��μ�����411���ϵ�ע�͡�
397 if ((flag & O_TRUNC) && !(flag & O_ACCMODE))
398 flag |= O_WRONLY;
399 mode &= 0777 & ~current->umask;
400 mode |= I_REGULAR; // �����ļ���־�����μ�include/const.h�ļ�����
// Ȼ�����ָ����·����Ѱ�ҵ���Ӧ��i�ڵ㣬�Լ����Ŀ¼�����䳤�ȡ���ʱ������
// Ŀ¼������Ϊ0�� ����'/usr/' ����·���������������ô���������Ƕ�д���������ļ���
// �Ƚ�0�����ʾ���ڴ�һ��Ŀ¼���ļ�����������ֱ�ӷ��ظ�Ŀ¼��i�ڵ㲢����0�˳���
// ����˵�����̲����Ƿ������ǷŻظ�i�ڵ㣬���س����롣
401 if (!(dir = dir_namei(pathname,&namelen,&basename,NULL)))
402 return -ENOENT;
403 if (!namelen) { /* special case: '/usr/' etc */
404 if (!(flag & (O_ACCMODE|O_CREAT|O_TRUNC))) {
405 *res_inode=dir;
406 return 0;
407 }
408 iput(dir);
409 return -EISDIR;
410 }
// ���Ÿ�������õ������Ŀ¼����i�ڵ�dir�������в���ȡ��·�����ַ�����������
// ������Ӧ��Ŀ¼��ṹde����ͬʱ�õ���Ŀ¼�����ڵĸ��ٻ�����ָ�롣 ����ø��ٻ���
// ָ��ΪNULL�����ʾû���ҵ���Ӧ�ļ�����Ŀ¼����ֻ�����Ǵ����ļ������� ��ʱ��
// �����Ǵ����ļ�����Żظ�Ŀ¼��i�ڵ㣬���س������˳�������û��ڸ�Ŀ¼û��д��Ȩ
// ������Żظ�Ŀ¼��i�ڵ㣬���س������˳���
411 bh = find_entry(&dir,basename,namelen,&de);
412 if (!bh) {
413 if (!(flag & O_CREAT)) {
414 iput(dir);
415 return -ENOENT;
416 }
417 if (!permission(dir,MAY_WRITE)) {
418 iput(dir);
419 return -EACCES;
420 }
// ��������ȷ�����Ǵ�������������д�������ɡ� ������Ǿ���Ŀ¼i�ڵ��Ӧ�豸������
// һ���µ�i�ڵ��·������ָ�����ļ�ʹ�á� ��ʧ����Ż�Ŀ¼��i�ڵ㣬������û�п�
// ������롣����ʹ�ø��� i�ڵ㣬������г�ʼ���ã��ýڵ���û�id����Ӧ�ڵ����ģ
// ʽ�������ı�־��Ȼ����ָ��Ŀ¼dir������һ����Ŀ¼�
421 inode = new_inode(dir->i_dev);
422 if (!inode) {
423 iput(dir);
424 return -ENOSPC;
425 }
426 inode->i_uid = current->euid;
427 inode->i_mode = mode;
428 inode->i_dirt = 1;
429 bh = add_entry(dir,basename,namelen,&de);
// ������ص�Ӧ�ú�����Ŀ¼��ĸ��ٻ�����ָ��ΪNULL�����ʾ����Ŀ¼�����ʧ�ܡ�����
// ������i�ڵ���������Ӽ�����1���Żظ�i�ڵ���Ŀ¼��i�ڵ㲢���س������˳��� ����
// ˵������Ŀ¼������ɹ��� �������������ø���Ŀ¼���һЩ��ʼֵ����i�ڵ��Ϊ������
// ����i�ڵ�ĺ��룻���ø��ٻ��������ı�־�� Ȼ���ͷŸø��ٻ��������Ż�Ŀ¼��i��
// �㡣������Ŀ¼���i�ڵ�ָ�룬���ɹ��˳���
430 if (!bh) {
431 inode->i_nlinks--;
432 iput(inode);
433 iput(dir);
434 return -ENOSPC;
435 }
436 de->inode = inode->i_num;
437 bh->b_dirt = 1;
438 brelse(bh);
439 iput(dir);
440 *res_inode = inode;
441 return 0;
442 }
// �����棨411�У���Ŀ¼��ȡ�ļ�����ӦĿ¼��ṹ�IJ����ɹ�����bh��ΪNULL������˵
// ��ָ�����ļ��Ѿ����ڡ�����ȡ����Ŀ¼���i�ڵ�ź��������豸�ţ����ͷŸø���
// �������Լ��Ż�Ŀ¼��i�ڵ㡣�����ʱ��ռ������־O_EXCL��λ���������ļ��Ѿ����ڣ�
// ���ļ��Ѵ��ڳ������˳���
443 inr = de->inode;
444 dev = dir->i_dev;
445 brelse(bh);
446 if (flag & O_EXCL) {
447 iput(dir);
448 return -EEXIST;
449 }
// Ȼ�����Ƕ�ȡ��Ŀ¼���i�ڵ����ݡ�����i�ڵ���һ��Ŀ¼��i�ڵ㲢�ҷ���ģʽ��ֻ
// д���д������û�з��ʵ�����Ȩ�ޣ���Żظ�i�ڵ㣬���ط���Ȩ�������˳���
450 if (!(inode = follow_link(dir,iget(dev,inr))))
451 return -EACCES;
452 if ((S_ISDIR(inode->i_mode) && (flag & O_ACCMODE)) ||
453 !permission(inode,ACC_MODE(flag))) {
454 iput(inode);
455 return -EPERM;
456 }
// �������Ǹ��¸�i�ڵ�ķ���ʱ���ֶ�ֵΪ��ǰʱ�䡣��������˽�0��־����i��
// ����ļ����Ƚ�Ϊ0����ظ�Ŀ¼��i�ڵ��ָ�룬������0���ɹ�����
457 inode->i_atime = CURRENT_TIME;
458 if (flag & O_TRUNC)
459 truncate(inode);
460 *res_inode = inode;
461 return 0;
462 }
463
//// ����һ���豸�����ļ�����ͨ�ļ��ڵ㣨node����
// �ú�����������Ϊfilename����mode��devָ�����ļ�ϵͳ�ڵ㣨��ͨ�ļ����豸������
// ���������ܵ�����
// ������filename - ·������mode - ָ��ʹ�������Լ��������ڵ�����ͣ�dev - �豸�š�
// ���أ��ɹ���0�����س����롣
464 int sys_mknod(const char * filename, int mode, int dev)
465 {
466 const char * basename;
467 int namelen;
468 struct m_inode * dir, * inode;
469 struct buffer_head * bh;
470 struct dir_entry * de;
471
// ���ȼ��������ɺͲ�������Ч�Բ�ȡ·�����ж���Ŀ¼��i�ڵ㡣������dz����û�����
// ���ط������ɳ����롣����Ҳ�����Ӧ·�����ж���Ŀ¼��i�ڵ㣬�س����롣�����
// ���˵��ļ�������Ϊ0����˵��������·�������û��ָ���ļ������Żظ�Ŀ¼i�ڵ㣬��
// �س������˳�������ڸ�Ŀ¼��û��д��Ȩ�ޣ���Żظ�Ŀ¼��i�ڵ㣬���ط������ɳ���
// ���˳���������dz����û����ط������ɳ����롣
472 if (!suser())
473 return -EPERM;
474 if (!(dir = dir_namei(filename,&namelen,&basename, NULL)))
475 return -ENOENT;
476 if (!namelen) {
477 iput(dir);
478 return -ENOENT;
479 }
480 if (!permission(dir,MAY_WRITE)) {
481 iput(dir);
482 return -EPERM;
483 }
// Ȼ����������һ��·����ָ�����ļ��Ƿ��Ѿ����ڡ����Ѿ��������ܴ���ͬ���ļ��ڵ㡣
// �����Ӧ·�����������ļ�����Ŀ¼���Ѿ����ڣ����ͷŰ�����Ŀ¼��Ļ������鲢�Ż�
// Ŀ¼��i�ڵ㣬�����ļ��Ѿ����ڵij������˳���
484 bh = find_entry(&dir,basename,namelen,&de);
485 if (bh) {
486 brelse(bh);
487 iput(dir);
488 return -EEXIST;
489 }
// �������Ǿ�����һ���µ�i�ڵ㣬�����ø�i�ڵ������ģʽ�����Ҫ�������ǿ��豸�ļ�
// �������ַ��豸�ļ�������i�ڵ��ֱ������ָ��0�����豸�š��������豸�ļ���˵��
// ��i�ڵ��i_zone[0]�д�ŵ��Ǹ��豸�ļ��������豸���豸�š�Ȼ�����ø�i�ڵ����
// ��ʱ�䡢����ʱ��Ϊ��ǰʱ�䣬������i�ڵ����ı�־��
490 inode = new_inode(dir->i_dev);
491 if (!inode) { // �����ɹ���Ż�Ŀ¼i�ڵ㣬�����ռ�������˳���
492 iput(dir);
493 return -ENOSPC;
494 }
495 inode->i_mode = mode;
496 if (S_ISBLK(mode) || S_ISCHR(mode))
497 inode->i_zone[0] = dev;
498 inode->i_mtime = inode->i_atime = CURRENT_TIME;
499 inode->i_dirt = 1;
// ����Ϊ����µ�i�ڵ���Ŀ¼��������һ��Ŀ¼����ʧ�ܣ�������Ŀ¼��ĸ��ٻ���
// ��ָ��ΪNULL������Ż�Ŀ¼��i�ڵ㣻���������i�ڵ��������Ӽ�����λ�����Żظ�
// i�ڵ㣬���س������˳���
500 bh = add_entry(dir,basename,namelen,&de);
501 if (!bh) {
502 iput(dir);
503 inode->i_nlinks=0;
504 iput(inode);
505 return -ENOSPC;
506 }
// ��������Ŀ¼�����Ҳ�ɹ��ˣ������������������Ŀ¼�����ݡ����Ŀ¼���i�ڵ���
// �ε�����i�ڵ�ţ����ø��ٻ��������ı�־���Ż�Ŀ¼���µ�i�ڵ㣬�ͷŸ��ٻ���
// �������0(�ɹ�)��
507 de->inode = inode->i_num;
508 bh->b_dirt = 1;
509 iput(dir);
510 iput(inode);
511 brelse(bh);
512 return 0;
513 }
514
//// ����һ��Ŀ¼��
// ������pathname - ·������mode - Ŀ¼ʹ�õ�Ȩ�����ԡ�
// ���أ��ɹ���0�����س����롣
515 int sys_mkdir(const char * pathname, int mode)
516 {
517 const char * basename;
518 int namelen;
519 struct m_inode * dir, * inode;
520 struct buffer_head * bh, *dir_block;
521 struct dir_entry * de;
522
// ���ȼ���������Ч�Բ�ȡ·�����ж���Ŀ¼��i�ڵ㡣����Ҳ�����Ӧ·�����ж���Ŀ¼
// ��i�ڵ㣬�س����롣�����˵��ļ�������Ϊ0����˵��������·�������û��ָ
// ���ļ������Żظ�Ŀ¼i�ڵ㣬���س������˳�������ڸ�Ŀ¼��û��д��Ȩ�ޣ���Żظ�
// Ŀ¼��i�ڵ㣬���ط������ɳ������˳���������dz����û����ط������ɳ����롣
523 if (!(dir = dir_namei(pathname,&namelen,&basename, NULL)))
524 return -ENOENT;
525 if (!namelen) {
526 iput(dir);
527 return -ENOENT;
528 }
529 if (!permission(dir,MAY_WRITE)) {
530 iput(dir);
531 return -EPERM;
532 }
// Ȼ����������һ��·����ָ����Ŀ¼���Ƿ��Ѿ����ڡ����Ѿ��������ܴ���ͬ��Ŀ¼�ڵ㡣
// �����Ӧ·����������Ŀ¼����Ŀ¼���Ѿ����ڣ����ͷŰ�����Ŀ¼��Ļ������鲢�Ż�
// Ŀ¼��i�ڵ㣬�����ļ��Ѿ����ڵij������˳����������Ǿ�����һ���µ�i�ڵ㣬������
// ��i�ڵ������ģʽ���ø���i�ڵ��Ӧ���ļ�����Ϊ32�ֽ� ��2��Ŀ¼��Ĵ�С������
// �ڵ����ı�־���Լ��ڵ����ʱ��ͷ���ʱ�䡣2��Ŀ¼��ֱ�����'.'��'..'Ŀ¼��
533 bh = find_entry(&dir,basename,namelen,&de);
534 if (bh) {
535 brelse(bh);
536 iput(dir);
537 return -EEXIST;
538 }
539 inode = new_inode(dir->i_dev);
540 if (!inode) { // �����ɹ���Ż�Ŀ¼��i�ڵ㣬�����ռ�����롣
541 iput(dir);
542 return -ENOSPC;
543 }
544 inode->i_size = 32;
545 inode->i_dirt = 1;
546 inode->i_mtime = inode->i_atime = CURRENT_TIME;
// ����Ϊ����i�ڵ�����һ���ڱ���Ŀ¼�����ݵĴ��̿飬����i�ڵ�ĵ�һ��ֱ�ӿ�ָ���
// �ڸÿ�š��������ʧ����Żض�ӦĿ¼��i�ڵ㣻��λ�������i�ڵ����Ӽ������Żظ�
// �µ�i�ڵ㣬����û�пռ�������˳��������ø��µ�i�ڵ����ı�־��
547 if (!(inode->i_zone[0]=new_block(inode->i_dev))) {
548 iput(dir);
549 inode->i_nlinks--;
550 iput(inode);
551 return -ENOSPC;
552 }
553 inode->i_dirt = 1;
// ���豸�϶�ȡ������Ĵ��̿飨Ŀ���ǰѶ�Ӧ��ŵ����ٻ������У�������������Żض�Ӧ
// Ŀ¼��i�ڵ㣻�ͷ�����Ĵ��̿飻��λ�������i�ڵ����Ӽ������Żظ��µ�i�ڵ㣬��
// ��û�пռ�������˳���
554 if (!(dir_block=bread(inode->i_dev,inode->i_zone[0]))) {
555 iput(dir);
556 inode->i_nlinks--;
557 iput(inode);
558 return -ERROR;
559 }
// Ȼ�������ڻ�����н�����������Ŀ¼�ļ��е�2��Ĭ�ϵ���Ŀ¼�'.'��'..'���ṹ��
// �ݡ�������deָ����Ŀ¼������ݿ飬Ȼ���ø�Ŀ¼���i�ڵ���ֶε����������i
// �ڵ�ţ������ֶε���"."�� Ȼ��deָ����һ��Ŀ¼��ṹ�����ڸýṹ�д���ϼ�Ŀ¼
// �� i�ڵ�ź�����".."��Ȼ�����øø��ٻ�������ı�־�����ͷŸû���顣�ٳ�ʼ��
// ������i�ڵ��ģʽ�ֶΣ����ø�i�ڵ����ı�־��
560 de = (struct dir_entry *) dir_block->b_data;
561 de->inode=inode->i_num; // ����'.'Ŀ¼�
562 strcpy(de->name,".");
563 de++;
564 de->inode = dir->i_num; // ����'..'Ŀ¼�
565 strcpy(de->name,"..");
566 inode->i_nlinks = 2;
567 dir_block->b_dirt = 1;
568 brelse(dir_block);
569 inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask);
570 inode->i_dirt = 1;
// ����������ָ��Ŀ¼��������һ��Ŀ¼����ڴ���½�Ŀ¼��i�ڵ��Ŀ¼�������ʧ
// �ܣ�������Ŀ¼��ĸ��ٻ�����ָ��ΪNULL������Ż�Ŀ¼��i�ڵ㣻�������i�ڵ���
// �����Ӽ�����λ�����Żظ�i�ڵ㡣���س������˳���
571 bh = add_entry(dir,basename,namelen,&de);
572 if (!bh) {
573 iput(dir);
574 inode->i_nlinks=0;
575 iput(inode);
576 return -ENOSPC;
577 }
// ��������Ŀ¼���i�ڵ��ֶε�����i�ڵ�ţ����ø��ٻ�������ı�־���Ż�Ŀ¼
// ���µ�i�ڵ㣬�ͷŸ��ٻ����������0���ɹ�����
578 de->inode = inode->i_num;
579 bh->b_dirt = 1;
580 dir->i_nlinks++;
581 dir->i_dirt = 1;
582 iput(dir);
583 iput(inode);
584 brelse(bh);
585 return 0;
586 }
587
588 /*
589 * routine to check that the specified directory is empty (for rmdir)
590 */
/*
* ���ڼ��ָ����Ŀ¼�Ƿ�Ϊ�յ��ӳ�������rmdirϵͳ���ã���
*/
//// ���ָ��Ŀ¼�Ƿ�ա�
// ������inode - ָ��Ŀ¼��i�ڵ�ָ�롣
// ���أ�1 �C Ŀ¼���ǿյģ�0 - ���ա�
591 static int empty_dir(struct m_inode * inode)
592 {
593 int nr,block;
594 int len;
595 struct buffer_head * bh;
596 struct dir_entry * de;
597
// ���ȼ���ָ��Ŀ¼������Ŀ¼���������鿪ʼ�����ض�Ŀ¼������Ϣ�Ƿ���ȷ��һ��Ŀ¼
// ��Ӧ��������2��Ŀ¼���"."��".."�� ���Ŀ¼���������2�����߸�Ŀ¼i�ڵ�ĵ�
// 1��ֱ�ӿ�û��ָ���κδ��̿�ţ����߸�ֱ�ӿ������������ʾ������Ϣ���豸dev ��Ŀ
// ¼����������0(ʧ��)��
598 len = inode->i_size / sizeof (struct dir_entry); // Ŀ¼��Ŀ¼�������
599 if (len<2 || !inode->i_zone[0] ||
600 !(bh=bread(inode->i_dev,inode->i_zone[0]))) {
601 printk("warning - bad directory on dev %04x\n",inode->i_dev);
602 return 0;
603 }
// ��ʱbh��ָ������к���Ŀ¼�����ݡ�������Ŀ¼��ָ��deָ����е�1��Ŀ¼�
// ���ڵ�1��Ŀ¼�"."��������i�ڵ���ֶ�inodeӦ�õ��ڵ�ǰĿ¼��i�ڵ�š�����
// ��2��Ŀ¼�".."��������i�ڵ���ֶ� inode Ӧ�õ�����һ��Ŀ¼��i�ڵ�ţ�����
// Ϊ0����������1��Ŀ¼���i�ڵ���ֶ�ֵ�����ڸ�Ŀ¼��i�ڵ�ţ����ߵ�2��Ŀ¼
// ���i�ڵ���ֶ�Ϊ�㣬��������Ŀ¼��������ֶβ��ֱ����"."��".."������ʾ������
// ����Ϣ���豸dev��Ŀ¼������������0��
604 de = (struct dir_entry *) bh->b_data;
605 if (de[0].inode != inode->i_num || !de[1].inode ||
606 strcmp(".",de[0].name) || strcmp("..",de[1].name)) {
607 printk("warning - bad directory on dev %04x\n",inode->i_dev);
608 return 0;
609 }
// Ȼ��������nr����Ŀ¼����ţ���0��ʼ�ƣ���deָ�������Ŀ¼���ѭ������Ŀ¼
// ���������еģ�len - 2����Ŀ¼�����û��Ŀ¼���i�ڵ���ֶβ�Ϊ0����ʹ�ã���
610 nr = 2;
611 de += 2;
612 while (nr<len) {
// ����ÿ���̿��е�Ŀ¼���Ѿ�ȫ�������ϣ����ͷŸô��̿�Ļ���飬����ȡĿ¼����
// �ļ�����һ�麬��Ŀ¼��Ĵ��̿顣��ȡ�ķ����Ǹ��ݵ�ǰ����Ŀ¼����� nr �������
// ӦĿ¼����Ŀ¼�����ļ��е����ݿ�ţ�nr/DIR_ENTRIES_PER_BLOCK����Ȼ��ʹ�� bmap()
// ����ȡ�ö�Ӧ���̿�� block����ʹ�ö��豸�̿麯��bread() ����Ӧ�̿���뻺����У�
// �����ظû�����ָ�롣������ȡ����Ӧ�̿�û��ʹ�ã����Ѿ����ã����ļ��Ѿ�ɾ���ȣ���
// ���������һ�飬�������������������0��������deָ����������Ŀ¼�
613 if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
614 brelse(bh);
615 block=bmap(inode,nr/DIR_ENTRIES_PER_BLOCK);
616 if (!block) {
617 nr += DIR_ENTRIES_PER_BLOCK;
618 continue;
619 }
620 if (!(bh=bread(inode->i_dev,block)))
621 return 0;
622 de = (struct dir_entry *) bh->b_data;
623 }
// ����deָ��ĵ�ǰĿ¼������Ŀ¼���i�ڵ���ֶβ�����0�����ʾ��Ŀ¼��Ŀǰ��
// ��ʹ�ã����ͷŸø��ٻ�����������0�˳�����������û�в�ѯ���Ŀ¼�е�����Ŀ¼�
// ���Ŀ¼�����nr��1��deָ����һ��Ŀ¼�������⡣
624 if (de->inode) {
625 brelse(bh);
626 return 0;
627 }
628 de++;
629 nr++;
630 }
// ִ�е�����˵����Ŀ¼��û���ҵ����õ�Ŀ¼��(��Ȼ����ͷ��������)�����ͷŻ���鷵��1��
631 brelse(bh);
632 return 1;
633 }
//// ɾ��Ŀ¼��
// ������ name - Ŀ¼����·��������
// ���أ�����0��ʾ�ɹ������س����š�
635 int sys_rmdir(const char * name)
636 {
637 const char * basename;
638 int namelen;
639 struct m_inode * dir, * inode;
640 struct buffer_head * bh;
641 struct dir_entry * de;
// ���ȼ���������Ч�Բ�ȡ·�����ж���Ŀ¼��i�ڵ㡣����Ҳ�����Ӧ·�����ж���Ŀ¼
// ��i�ڵ㣬�س����롣�����˵��ļ�������Ϊ0����˵��������·�������û��ָ
// ���ļ������Żظ�Ŀ¼i�ڵ㣬���س������˳�������ڸ�Ŀ¼��û��д��Ȩ�ޣ���Żظ�
// Ŀ¼��i�ڵ㣬���ط������ɳ������˳���������dz����û����ط������ɳ����롣
643 if (!(dir = dir_namei(name,&namelen,&basename, NULL)))
644 return -ENOENT;
645 if (!namelen) {
646 iput(dir);
647 return -ENOENT;
648 }
649 if (!permission(dir,MAY_WRITE)) {
650 iput(dir);
651 return -EPERM;
652 }
// Ȼ�����ָ��Ŀ¼��i�ڵ��Ŀ¼�����ú���find_entry()Ѱ�Ҷ�ӦĿ¼������ذ�����
// Ŀ¼��Ļ����ָ��bh��������Ŀ¼���Ŀ¼��i�ڵ�ָ��dir��Ŀ¼��ָ��de���ٸ���
// ��Ŀ¼��de �е�i�ڵ������ iget()�����õ���Ӧ��i�ڵ� inode�������Ӧ·��������
// ��Ŀ¼����Ŀ¼����ڣ����ͷŰ�����Ŀ¼��ĸ��ٻ��������Ż�Ŀ¼�� i�ڵ㣬������
// ���Ѿ����ڳ����룬���˳������ȡĿ¼���i�ڵ��������Ż�Ŀ¼�� i�ڵ㣬���ͷź�
// ��Ŀ¼��ĸ��ٻ����������س����š�
653 bh = find_entry(&dir,basename,namelen,&de);
654 if (!bh) {
655 iput(dir);
656 return -ENOENT;
657 }
658 if (!(inode = iget(dir->i_dev, de->inode))) {
659 iput(dir);
660 brelse(bh);
661 return -EPERM;
662 }
// ��ʱ�������а���Ҫ��ɾ��Ŀ¼���Ŀ¼i�ڵ�dir��Ҫ��ɾ��Ŀ¼���i�ڵ�inode��Ҫ
// ��ɾ��Ŀ¼��ָ��de����������ͨ������3����������Ϣ�ļ������֤ɾ�������Ŀ����ԡ�
// ����Ŀ¼����������ɾ����־���ҽ��̵���Ч�û�id��euid������root�����ҽ��̵���Ч
// �û�id��euid�������ڸ�i�ڵ���û�id�����ʾ��ǰ����û��Ȩ��ɾ����Ŀ¼�����Ƿ�
// �ذ���Ҫɾ��Ŀ¼����Ŀ¼ i�ڵ��Ҫɾ��Ŀ¼�� i�ڵ㣬Ȼ���ͷŸ��ٻ�����������
// �����롣
663 if ((dir->i_mode & S_ISVTX) && current->euid &&
664 inode->i_uid != current->euid) {
665 iput(dir);
666 iput(inode);
667 brelse(bh);
668 return -EPERM;
669 }
// ���Ҫ��ɾ����Ŀ¼��i�ڵ���豸�Ų����ڰ�����Ŀ¼���Ŀ¼���豸�ţ����߸ñ�ɾ��
// Ŀ¼���������Ӽ������� 1����ʾ�з������ӵȣ�������ɾ����Ŀ¼�������ͷŰ���Ҫɾ
// ��Ŀ¼����Ŀ¼i�ڵ��Ҫɾ��Ŀ¼��i�ڵ㣬�ͷŸ��ٻ���飬���س����롣
670 if (inode->i_dev != dir->i_dev || inode->i_count>1) {
671 iput(dir);
672 iput(inode);
673 brelse(bh);
674 return -EPERM;
675 }
// ���Ҫ��ɾ��Ŀ¼��Ŀ¼��i�ڵ�͵��ڰ�������ɾ��Ŀ¼��Ŀ¼i�ڵ㣬���ʾ��ͼɾ��
// "."Ŀ¼�����Dz������ġ����ǷŻذ���Ҫɾ��Ŀ¼����Ŀ¼i�ڵ��Ҫɾ��Ŀ¼��i�ڵ㣬
// �ͷŸ��ٻ���飬���س����롣
676 if (inode == dir) { /* we may not delete ".", but "../dir" is ok */
677 iput(inode);
678 iput(dir);
679 brelse(bh);
680 return -EPERM;
681 }
// ��Ҫ��ɾ��Ŀ¼i�ڵ�����Ա����ⲻ��һ��Ŀ¼����ɾ��������ǰ����ȫ�����ڡ�����
// �Żذ���ɾ��Ŀ¼����Ŀ¼i�ڵ��Ҫɾ��Ŀ¼��i�ڵ㣬�ͷŸ��ٻ���飬���س����롣
682 if (!S_ISDIR(inode->i_mode)) {
683 iput(inode);
684 iput(dir);
685 brelse(bh);
686 return -ENOTDIR;
687 }
// �����豻ɾ����Ŀ¼���գ���Ҳ����ɾ�������ǷŻذ���Ҫɾ��Ŀ¼����Ŀ¼i�ڵ��Ҫ
// ɾ��Ŀ¼��i�ڵ㣬�ͷŸ��ٻ���飬���س����롣
688 if (!empty_dir(inode)) {
689 iput(inode);
690 iput(dir);
691 brelse(bh);
692 return -ENOTEMPTY;
693 }
// ����һ����Ŀ¼����Ŀ¼��������Ӧ��Ϊ2�����ӵ��ϲ�Ŀ¼�ͱ�Ŀ¼���������豻ɾ��Ŀ
// ¼��i�ڵ��������������2������ʾ������Ϣ����ɾ��������Ȼ����ִ�С������ø��豻
// ɾ��Ŀ¼��Ŀ¼���i�ڵ���ֶ�Ϊ0����ʾ��Ŀ¼���ʹ�ã����ú��и�Ŀ¼��ĸ���
// ��������ı�־�����ͷŸû���顣Ȼ�����ñ�ɾ��Ŀ¼i�ڵ��������Ϊ0����ʾ���У���
// ����i�ڵ����ı�־��
694 if (inode->i_nlinks != 2)
695 printk("empty directory has nlink!=2 (%d)",inode->i_nlinks);
696 de->inode = 0;
697 bh->b_dirt = 1;
698 brelse(bh);
699 inode->i_nlinks=0;
700 inode->i_dirt=1;
// �ٽ�������ɾ��Ŀ¼����Ŀ¼��i�ڵ����Ӽ�����1������ı�ʱ�����ʱ��Ϊ��ǰʱ
// �䣬���øýڵ����ı�־�����Żذ���Ҫɾ��Ŀ¼����Ŀ¼i�ڵ��Ҫɾ��Ŀ¼��i
// �ڵ㣬����0��ɾ�������ɹ�����
701 dir->i_nlinks--;
702 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
703 dir->i_dirt=1;
704 iput(dir);
705 iput(inode);
706 return 0;
707 }
//// ɾ�����ͷţ��ļ�����Ӧ��Ŀ¼�
// ���ļ�ϵͳɾ��һ�����֡�������ļ������һ�����ӣ�����û�н��������ļ������
// �ļ�Ҳ����ɾ�������ͷ���ռ�õ��豸�ռ䡣
// ������name - �ļ�����·��������
// ���أ��ɹ���0�����س����š�
709 int sys_unlink(const char * name)
710 {
711 const char * basename;
712 int namelen;
713 struct m_inode * dir, * inode;
714 struct buffer_head * bh;
715 struct dir_entry * de;
716
// ���ȼ���������Ч�Բ�ȡ·�����ж���Ŀ¼��i�ڵ㡣����Ҳ�����Ӧ·�����ж���Ŀ¼
// �� i�ڵ㣬�س����롣�����˵��ļ�������Ϊ0����˵��������·�������û��ָ
// ���ļ������Żظ�Ŀ¼i�ڵ㣬���س������˳�������ڸ�Ŀ¼��û��д��Ȩ�ޣ���Żظ�
// Ŀ¼��i�ڵ㣬���ط������ɳ������˳�������Ҳ�����Ӧ·��������Ŀ¼��i�ڵ㣬��
// �س����롣
717 if (!(dir = dir_namei(name,&namelen,&basename, NULL)))
718 return -ENOENT;
719 if (!namelen) {
720 iput(dir);
721 return -ENOENT;
722 }
723 if (!permission(dir,MAY_WRITE)) {
724 iput(dir);
725 return -EPERM;
726 }
// Ȼ�����ָ��Ŀ¼��i�ڵ��Ŀ¼�����ú���find_entry()Ѱ�Ҷ�ӦĿ¼������ذ�����
// Ŀ¼��Ļ����ָ��bh��������Ŀ¼���Ŀ¼��i�ڵ�ָ��dir��Ŀ¼��ָ��de���ٸ���
// ��Ŀ¼��de �е�i�ڵ������ iget()�����õ���Ӧ��i�ڵ� inode�������Ӧ·��������
// ��Ŀ¼����Ŀ¼����ڣ����ͷŰ�����Ŀ¼��ĸ��ٻ��������Ż�Ŀ¼�� i�ڵ㣬������
// ���Ѿ����ڳ����룬���˳������ȡĿ¼���i�ڵ��������Ż�Ŀ¼�� i�ڵ㣬���ͷź�
// ��Ŀ¼��ĸ��ٻ����������س����š�
727 bh = find_entry(&dir,basename,namelen,&de);
728 if (!bh) {
729 iput(dir);
730 return -ENOENT;
731 }
732 if (!(inode = iget(dir->i_dev, de->inode))) {
733 iput(dir);
734 brelse(bh);
735 return -ENOENT;
736 }
// ��ʱ�������а���Ҫ��ɾ��Ŀ¼���Ŀ¼i�ڵ�dir��Ҫ��ɾ��Ŀ¼���i�ڵ�inode��Ҫ
// ��ɾ��Ŀ¼��ָ��de����������ͨ������3����������Ϣ�ļ������֤ɾ�������Ŀ����ԡ�
// ����Ŀ¼����������ɾ����־���ҽ��̵���Ч�û�id��euid������root�����ҽ��̵�euid
// �����ڸ�i�ڵ���û�id�����ҽ��̵�euidҲ������Ŀ¼i�ڵ���û�id�����ʾ��ǰ��
// ��û��Ȩ��ɾ����Ŀ¼�����ǷŻذ���Ҫɾ��Ŀ¼����Ŀ¼i�ڵ��Ҫɾ��Ŀ¼��i�ڵ㣬
// Ȼ���ͷŸ��ٻ���飬���س����롣
737 if ((dir->i_mode & S_ISVTX) && !suser() &&
738 current->euid != inode->i_uid &&
739 current->euid != dir->i_uid) {
740 iput(dir);
741 iput(inode);
742 brelse(bh);
743 return -EPERM;
744 }
// �����ָ���ļ�����һ��Ŀ¼����Ҳ����ɾ�����Żظ�Ŀ¼i�ڵ���ļ���Ŀ¼���i��
// �㣬�ͷŰ�����Ŀ¼��Ļ���飬���س����š�
745 if (S_ISDIR(inode->i_mode)) {
746 iput(inode);
747 iput(dir);
748 brelse(bh);
749 return -EPERM;
750 }
// �����i�ڵ�����Ӽ���ֵ�Ѿ�Ϊ0������ʾ������Ϣ����������Ϊ1��
751 if (!inode->i_nlinks) {
752 printk("Deleting nonexistent file (%04x:%d), %d\n",
753 inode->i_dev,inode->i_num,inode->i_nlinks);
754 inode->i_nlinks=1;
755 }
// �������ǿ���ɾ���ļ�����Ӧ��Ŀ¼���ˡ����ǽ����ļ���Ŀ¼���е�i�ڵ���ֶ���Ϊ0��
// ��ʾ�ͷŸ�Ŀ¼������ð�����Ŀ¼��Ļ�������ı�־���ͷŸø��ٻ���顣
756 de->inode = 0;
757 bh->b_dirt = 1;
758 brelse(bh);
// Ȼ����ļ�����Ӧi�ڵ����������1�������ı�־�����¸ı�ʱ��Ϊ��ǰʱ�䡣����
// �ظ�i�ڵ��Ŀ¼��i�ڵ㣬����0���ɹ�����������ļ������һ�����ӣ���i�ڵ�����
// ����1�����0�����Ҵ�ʱû�н��������ļ�����ô�ڵ���iput()�Ż�i�ڵ�ʱ������
// ��Ҳ����ɾ�������ͷ���ռ�õ��豸�ռ䡣�μ�fs/inode.c����183�С�
759 inode->i_nlinks--;
760 inode->i_dirt = 1;
761 inode->i_ctime = CURRENT_TIME;
762 iput(inode);
763 iput(dir);
764 return 0;
765 }
766
//// �����������ӡ�
// Ϊһ���Ѵ����ļ�����һ���������ӣ�Ҳ��Ϊ������ - hard link����
// ������oldname - ԭ·������newname - �µ�·������
// ���أ����ɹ���0�����س����š�
767 int sys_symlink(const char * oldname, const char * newname)
768 {
769 struct dir_entry * de;
770 struct m_inode * dir, * inode;
771 struct buffer_head * bh, * name_block;
772 const char * basename;
773 int namelen, i;
774 char c;
775
// ���Ȳ�����·���������Ŀ¼��i�ڵ�dir�������������ļ������䳤�ȡ����Ŀ¼��
// i�ڵ�û���ҵ����س����š������·�����в������ļ�������Ż���·����Ŀ¼��i
// �ڵ㣬���س����š����⣬����û�û������Ŀ¼��д��Ȩ�ޣ���Ҳ���ܽ������ӣ����Ƿ�
// ����·����Ŀ¼��i�ڵ㣬���س����š�
776 dir = dir_namei(newname,&namelen,&basename, NULL);
777 if (!dir)
778 return -EACCES;
779 if (!namelen) {
780 iput(dir);
781 return -EPERM;
782 }
783 if (!permission(dir,MAY_WRITE)) {
784 iput(dir);
785 return -EACCES;
786 }
// ����������Ŀ¼ָ���豸������һ���µ�i�ڵ㣬�����ø�i�ڵ�ģʽΪ�������������Լ�
// ���̹涨��ģʽ�����롣�������ø�i�ڵ����ı�־��
787 if (!(inode = new_inode(dir->i_dev))) {
788 iput(dir);
789 return -ENOSPC;
790 }
791 inode->i_mode = S_IFLNK | (0777 & ~current->umask);
792 inode->i_dirt = 1;
// Ϊ�˱����������·�����ַ�����Ϣ��������ҪΪ��i�ڵ�����һ�����̿飬����i�ڵ��
// ��1��ֱ�ӿ��i_zone[0]���ڵõ�������š�Ȼ����i�ڵ����ı�־���������ʧ��
// ��Żض�ӦĿ¼��i�ڵ㣻��λ�������i�ڵ����Ӽ������Żظ��µ�i�ڵ㣬����û�п�
// ��������˳���
793 if (!(inode->i_zone[0]=new_block(inode->i_dev))) {
794 iput(dir);
795 inode->i_nlinks--;
796 iput(inode);
797 return -ENOSPC;
798 }
799 inode->i_dirt = 1;
// Ȼ����豸�϶�ȡ������Ĵ��̿飨Ŀ���ǰѶ�Ӧ��ŵ����ٻ������У�������������Ż�
// ��ӦĿ¼��i�ڵ㣻��λ�������i�ڵ����Ӽ������Żظ��µ�i�ڵ㣬����û�пռ����
// ���˳���
800 if (!(name_block=bread(inode->i_dev,inode->i_zone[0]))) {
801 iput(dir);
802 inode->i_nlinks--;
803 iput(inode);
804 return -ERROR;
805 }
// �������ǿ��ѷ����������ַ�����������̿����ˡ��̿鳤��Ϊ1024�ֽڣ����Ĭ�Ϸ���
// �������������Ҳֻ����1024�ֽڡ����ǰ��û��ռ��еķ����������ַ������Ƶ��̿�����
// �Ļ�����У����û�������ı�־��Ϊ��ֹ�û��ṩ���ַ���û����null��β�������ڻ�
// ������������һ���ֽڴ�����һ��NULL��Ȼ���ͷŸû���飬������i�ڵ��Ӧ�ļ�����
// �ݳ��ȵ��ڷ����������ַ������ȣ�����i�ڵ����ı�־��
806 i = 0;
807 while (i < 1023 && (c=get_fs_byte(oldname++)))
808 name_block->b_data[i++] = c;
809 name_block->b_data[i] = 0;
810 name_block->b_dirt = 1;
811 brelse(name_block);
812 inode->i_size = i;
813 inode->i_dirt = 1;
// Ȼ����������һ��·����ָ���ķ��������ļ����Ƿ��Ѿ����ڡ����Ѿ��������ܴ���ͬ��
// Ŀ¼��i�ڵ㡣�����Ӧ���������ļ����Ѿ����ڣ����ͷŰ�����Ŀ¼��Ļ������飬��λ
// �������i�ڵ����Ӽ��������Ż�Ŀ¼��i�ڵ㣬�����ļ��Ѿ����ڵij������˳���
814 bh = find_entry(&dir,basename,namelen,&de);
815 if (bh) {
816 inode->i_nlinks--;
817 iput(inode);
818 brelse(bh);
819 iput(dir);
820 return -EEXIST;
821 }
// ����������ָ��Ŀ¼��������һ��Ŀ¼����ڴ���½����������ļ�����i�ڵ�ź�Ŀ¼
// �������ʧ�ܣ�������Ŀ¼��ĸ��ٻ�����ָ��ΪNULL������Ż�Ŀ¼��i�ڵ㣻�������
// i�ڵ��������Ӽ�����λ�����Żظ�i�ڵ㡣���س������˳���
822 bh = add_entry(dir,basename,namelen,&de);
823 if (!bh) {
824 inode->i_nlinks--;
825 iput(inode);
826 iput(dir);
827 return -ENOSPC;
828 }
// ��������Ŀ¼���i�ڵ��ֶε�����i�ڵ�ţ����ø��ٻ�������ı�־���ͷŸ��ٻ�
// ��飬�Ż�Ŀ¼���µ�i�ڵ㣬���0���ɹ�����
829 de->inode = inode->i_num;
830 bh->b_dirt = 1;
831 brelse(bh);
832 iput(dir);
833 iput(inode);
834 return 0;
835 }
836
//// Ϊ�ļ�����һ���ļ���Ŀ¼�
// Ϊһ���Ѵ��ڵ��ļ�����һ�������ӣ�Ҳ��ΪӲ���� - hard link����
// ������oldname - ԭ·������newname - �µ�·������
// ���أ����ɹ���0�����س����š�
837 int sys_link(const char * oldname, const char * newname)
838 {
839 struct dir_entry * de;
840 struct m_inode * oldinode, * dir;
841 struct buffer_head * bh;
842 const char * basename;
843 int namelen;
844
// ���ȶ�ԭ�ļ���������Ч����֤����Ӧ�ô��ڲ��Ҳ���һ��Ŀ¼��������������ȡԭ�ļ�·
// ������Ӧ��i�ڵ�oldinode�����Ϊ0�����ʾ���������س����š����ԭ·������Ӧ����
// һ��Ŀ¼������Żظ�i�ڵ㣬Ҳ���س����š�
845 oldinode=namei(oldname);
846 if (!oldinode)
847 return -ENOENT;
848 if (S_ISDIR(oldinode->i_mode)) {
849 iput(oldinode);
850 return -EPERM;
851 }
// Ȼ�������·���������Ŀ¼��i�ڵ�dir�������������ļ������䳤�ȡ����Ŀ¼��
// i�ڵ�û���ҵ�����Ż�ԭ·������i�ڵ㣬���س����š������·�����в������ļ�����
// ��Ż�ԭ·����i�ڵ����·����Ŀ¼��i�ڵ㣬���س����š�
852 dir = dir_namei(newname,&namelen,&basename, NULL);
853 if (!dir) {
854 iput(oldinode);
855 return -EACCES;
856 }
857 if (!namelen) {
858 iput(oldinode);
859 iput(dir);
860 return -EPERM;
861 }
// ���Dz��ܿ��豸����Ӳ���ӡ���������·��������Ŀ¼���豸����ԭ·�������豸��
// ��һ������Ż���·����Ŀ¼��i�ڵ��ԭ·������i�ڵ㣬���س����š����⣬����û�
// û������Ŀ¼��д��Ȩ�ޣ���Ҳ���ܽ������ӣ����ǷŻ���·����Ŀ¼��i�ڵ��ԭ·����
// ��i�ڵ㣬���س����š�
862 if (dir->i_dev != oldinode->i_dev) {
863 iput(dir);
864 iput(oldinode);
865 return -EXDEV;
866 }
867 if (!permission(dir,MAY_WRITE)) {
868 iput(dir);
869 iput(oldinode);
870 return -EACCES;
871 }
// ���ڲ�ѯ����·�����Ƿ��Ѿ����ڣ����������Ҳ���ܽ������ӡ������ͷŰ������Ѵ���Ŀ
// ¼��ĸ��ٻ���飬�Ż���·����Ŀ¼��i�ڵ��ԭ·������i�ڵ㣬���س����š�
872 bh = find_entry(&dir,basename,namelen,&de);
873 if (bh) {
874 brelse(bh);
875 iput(dir);
876 iput(oldinode);
877 return -EEXIST;
878 }
// �������������������ˣ�������������Ŀ¼������һ��Ŀ¼���ʧ����Żظ�Ŀ¼��i��
// ���ԭ·������i�ڵ㣬���س����š������ʼ���ø�Ŀ¼���i�ڵ�ŵ���ԭ·������i
// �ڵ�ţ����ð���������Ŀ¼��Ļ�������ı�־���ͷŸû���飬�Ż�Ŀ¼��i�ڵ㡣
879 bh = add_entry(dir,basename,namelen,&de);
880 if (!bh) {
881 iput(dir);
882 iput(oldinode);
883 return -ENOSPC;
884 }
885 de->inode = oldinode->i_num;
886 bh->b_dirt = 1;
887 brelse(bh);
888 iput(dir);
// �ٽ�ԭ�ڵ�����Ӽ�����1������ı�ʱ��Ϊ��ǰʱ�䣬������i�ڵ����ı�־�����
// �Ż�ԭ·������i�ڵ㣬������0���ɹ�����
889 oldinode->i_nlinks++;
890 oldinode->i_ctime = CURRENT_TIME;
891 oldinode->i_dirt = 1;
892 iput(oldinode);
893 return 0;
894 }
895