����12-6 linux/fs/namei.c


  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 }

634

    //// ɾ��Ŀ¼��

    // ������ 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;

642

    // ���ȼ���������Ч�Բ�ȡ·�����ж���Ŀ¼��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 }

708

    //// ɾ�����ͷţ��ļ�����Ӧ��Ŀ¼�

    // ���ļ�ϵͳɾ��һ�����֡�������ļ������һ�����ӣ�����û�н������򿪸��ļ������

    // �ļ�Ҳ����ɾ�������ͷ���ռ�õ��豸�ռ䡣

    // ������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