1 /*
2 * linux/fs/open.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 #include <string.h> // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ַ���������Ƕ�뺯����
8 #include <errno.h> // �����ͷ�ļ�������ϵͳ�и��ֳ����š�
9 #include <fcntl.h> // �ļ�����ͷ�ļ��������ļ������������������Ƴ������Ŷ��塣
10 #include <sys/types.h> // ����ͷ�ļ������������ϵͳ���ļ�ϵͳͳ����Ϣ�ṹ�����͡�
11 #include <utime.h> // �û�ʱ��ͷ�ļ���������ʺ���ʱ��ṹ�Լ�utime()ԭ�͡�
12 #include <sys/stat.h> // �ļ�״̬ͷ�ļ��������ļ�״̬�ṹstat{}�ͷ��ų����ȡ�
13
14 #include <linux/sched.h> // ���ȳ���ͷ�ļ�����������ṹtask_struct������0���ݵȡ�
15 #include <linux/tty.h> // ttyͷ�ļ����������й�tty_io������ͨ�ŷ���IJ�����������
16 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣
17
18 #include <asm/segment.h> // �β���ͷ�ļ����������йضμĴ���������Ƕ��ʽ��ຯ����
19
//// ȡ�ļ�ϵͳ��Ϣ��
// ����dev�Ǻ����Ѱ�װ�ļ�ϵͳ���豸�š�ubuf��һ��ustat�ṹ������ָ�룬���ڴ��
// ϵͳ���ص��ļ�ϵͳ��Ϣ����ϵͳ�������ڷ����Ѱ�װ��mounted���ļ�ϵͳ��ͳ����Ϣ��
// �ɹ�ʱ����0������ubufָ���ustate�ṹ�������ļ�ϵͳ�ܿ��п����Ϳ���i�ڵ�����
// ustat�ṹ������include/sys/types.h�С�
20 int sys_ustat(int dev, struct ustat * ubuf)
21 {
22 return -ENOSYS; // �����룺���ܻ�δʵ�֡�
23 }
24
//// �����ļ����ʺ���ʱ�䡣
// ����filename���ļ�����times�Ƿ��ʺ���ʱ��ṹָ�롣
// ���timesָ�벻ΪNULL����ȡutimbuf�ṹ�е�ʱ����Ϣ�������ļ��ķ��ʺ���ʱ�䡣
// ���timesָ����NULL����ȡϵͳ��ǰʱ��������ָ���ļ��ķ��ʺ���ʱ����
25 int sys_utime(char * filename, struct utimbuf * times)
26 {
27 struct m_inode * inode;
28 long actime,modtime;
29
// �ļ���ʱ����Ϣ��������i�ڵ��ӡ�����������ȸ����ļ���ȡ�ö�Ӧi�ڵ㡣���û����
// �����س����롣����ṩ�ķ��ʺ���ʱ��ṹָ��times��ΪNULL����ӽṹ�ж�ȡ
// �û����õ�ʱ��ֵ���������ϵͳ��ǰʱ���������ļ��ķ��ʺ���ʱ�䡣
30 if (!(inode=namei(filename)))
31 return -ENOENT;
32 if (times) {
33 actime = get_fs_long((unsigned long *) ×->actime);
34 modtime = get_fs_long((unsigned long *) ×->modtime);
35 } else
36 actime = modtime = CURRENT_TIME;
// Ȼ����i�ڵ��еķ���ʱ���ֶκ���ʱ���ֶΡ�������i�ڵ����ı�־���Żظ�i��
// �㣬������0��
37 inode->i_atime = actime;
38 inode->i_mtime = modtime;
39 inode->i_dirt = 1;
40 iput(inode);
41 return 0;
42 }
43
44 /*
45 * XXX should we use the real or effective uid? BSD uses the real uid,
46 * so as to make this call useful to setuid programs.
47 */
/*
* XXX ���Ǹ�����ʵ�û�id��ruid��������Ч�û�id��euid����BSDϵͳʹ����
* ��ʵ�û�id����ʹ�õ��ÿ��Թ�setuid����ʹ�á�
* ��ע��POSIX������ʹ����ʵ�û�ID����
* ��ע1��Ӣ��ע�Ϳ�ʼ�� 'XXX' ��ʾ��Ҫ��ʾ����
*/
//// ����ļ��ķ���Ȩ�ޡ�
// ����filename���ļ�����mode�Ǽ��ķ������ԣ�����3����Ч����λ��ɣ�R_OK(ֵ4)��
// W_OK(2)��X_OK(1) ��F_OK(0) ��ɣ��ֱ��ʾ����ļ��Ƿ�ɶ�����д����ִ�к��ļ���
// ����ڡ�������������Ļ�����0�����س����롣
48 int sys_access(const char * filename,int mode)
49 {
50 struct m_inode * inode;
51 int res, i_mode;
52
// �ļ��ķ���Ȩ����ϢҲͬ���������ļ���i�ڵ�ṹ�У��������Ҫ��ȡ�ö�Ӧ�ļ�����i
// �ڵ㡣���ķ�������mode�ɵ�3λ��ɣ������Ҫ���ϰ˽���0007��������и߱���λ��
// ����ļ�����Ӧ��i�ڵ㲻���ڣ���û������Ȩ�����롣��i�ڵ���ڣ���ȡi�ڵ�
// ���ļ������룬���Żظ�i�ڵ㡣���⣬57������䡰iput(inode);��������61��֮��
53 mode &= 0007;
54 if (!(inode=namei(filename)))
55 return -EACCES; // �����룺����Ȩ�ޡ�
56 i_mode = res = inode->i_mode & 0777;
57 iput(inode);
// �����ǰ�����û��Ǹ��ļ�����������ȡ�ļ��������ԡ����������ǰ�����û�����ļ���
// ��ͬ��һ�飬��ȡ�ļ������ԡ�����ʱres���3�����������˷��ʸ��ļ����������ԡ�
// [[?? ����Ӧres >>3 ??]
58 if (current->uid == inode->i_uid)
59 res >>= 6;
60 else if (current->gid == inode->i_gid)
61 res >>= 6;
// ��ʱres�����3�����Ǹ��ݵ�ǰ�����û����ļ��Ĺ�ϵѡ������ķ�������λ����������
// ���ж���3���ء�����ļ����Ծ��в�������ѯ������λmode����������ɣ�����0
62 if ((res & 0007 & mode) == mode)
63 return 0;
64 /*
65 * XXX we are doing this test last because we really should be
66 * swapping the effective with the real user id (temporarily),
67 * and then calling suser() routine. If we do call the
68 * suser() routine, it needs to be called last.
69 */
/*
* XXX ��������������IJ��ԣ���Ϊ����ʵ������Ҫ������Ч�û�ID��
* ��ʵ�û�ID����ʱ�أ���Ȼ��ŵ���suser()�������������ȷʵҪ����
* suser()����������Ҫ���ű����á�
*/
// �����ǰ�û�IDΪ0�������û�������������ִ��λ��0�����ļ����Ա��κ���ִ�С���
// ������0�����س����롣
70 if ((!current->uid) &&
71 (!(mode & 1) || (i_mode & 0111)))
72 return 0;
73 return -EACCES; // �����룺����Ȩ�ޡ�
74 }
75
//// �ı䵱ǰ����Ŀ¼ϵͳ���á�
// ����filename��Ŀ¼����
// �����ɹ���0�����س����롣
76 int sys_chdir(const char * filename)
77 {
78 struct m_inode * inode;
79
// �ı䵱ǰ����Ŀ¼����Ҫ��ѽ�������ṹ�ĵ�ǰ����Ŀ¼�ֶ�ָ�����Ŀ¼����i�ڵ㡣
// �����������ȡĿ¼����i�ڵ㡣���Ŀ¼����Ӧ��i�ڵ㲻���ڣ��س����롣�����
// i�ڵ㲻��һ��Ŀ¼i�ڵ㣬��Żظ�i�ڵ㣬�����س����롣
80 if (!(inode = namei(filename)))
81 return -ENOENT; // �����룺�ļ���Ŀ¼�����ڡ�
82 if (!S_ISDIR(inode->i_mode)) {
83 iput(inode);
84 return -ENOTDIR; // �����룺����Ŀ¼����
85 }
// Ȼ���ͷŽ���ԭ����Ŀ¼i�ڵ㣬��ʹ��ָ�������õĹ���Ŀ¼i�ڵ㡣����0��
86 iput(current->pwd);
87 current->pwd = inode;
88 return (0);
89 }
90
//// �ı��Ŀ¼ϵͳ���á�
// ��ָ����Ŀ¼�����ó�Ϊ��ǰ���̵ĸ�Ŀ¼'/'��
// ��������ɹ���0�����س����롣
91 int sys_chroot(const char * filename)
92 {
93 struct m_inode * inode;
94
// �õ������ڸı䵱ǰ��������ṹ�еĸ�Ŀ¼�ֶ�root������ָ���������Ŀ¼����i�ڵ㡣
// ���Ŀ¼����Ӧ��i�ڵ㲻���ڣ��س����롣�����i�ڵ㲻��Ŀ¼i�ڵ㣬��Żظ�
// i�ڵ㣬Ҳ���س����롣
95 if (!(inode=namei(filename)))
96 return -ENOENT;
97 if (!S_ISDIR(inode->i_mode)) {
98 iput(inode);
99 return -ENOTDIR;
100 }
// Ȼ���ͷŵ�ǰ���̵ĸ�Ŀ¼i�ڵ㣬����������Ϊָ��Ŀ¼����i�ڵ㣬����0��
101 iput(current->root);
102 current->root = inode;
103 return (0);
104 }
105
//// ���ļ�����ϵͳ���á�
// ����filename���ļ�����mode���µ��ļ����ԡ�
// �������ɹ���0�����س����롣
106 int sys_chmod(const char * filename,int mode)
107 {
108 struct m_inode * inode;
109
// �õ���Ϊָ���ļ������µķ�������mode���ļ��ķ����������ļ�����Ӧ��i�ڵ��У����
// ��������ȡ�ļ�����Ӧ��i�ڵ㡣���i�ڵ㲻���ڣ��س����루�ļ���Ŀ¼�����ڣ���
// �����ǰ���̵���Ч�û�id���ļ�i�ڵ���û�id��ͬ������Ҳ���dz����û�����Żظ�
// �ļ�i�ڵ㣬���س����루û�з���Ȩ�ޣ���
110 if (!(inode=namei(filename)))
111 return -ENOENT;
112 if ((current->euid != inode->i_uid) && !suser()) {
113 iput(inode);
114 return -EACCES;
115 }
// ������������ø�i�ڵ���ļ����ԣ����ø�i�ڵ����ı�־���Żظ�i�ڵ㣬����0��
116 inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
117 inode->i_dirt = 1;
118 iput(inode);
119 return 0;
120 }
121
//// ���ļ�����ϵͳ���á�
// ����filename���ļ�����uid���û���ʶ��(�û�ID)��gid����ID��
// �������ɹ���0�����س����롣
122 int sys_chown(const char * filename,int uid,int gid)
123 {
124 struct m_inode * inode;
125
// �õ������������ļ�i�ڵ��е��û�����ID���������Ҫȡ�ø����ļ�����i�ڵ㡣�����
// ������i�ڵ㲻���ڣ��س����루�ļ���Ŀ¼�����ڣ��������ǰ���̲��dz����û���
// ��Żظ�i�ڵ㣬�����س����루û�з���Ȩ�ޣ���
126 if (!(inode=namei(filename)))
127 return -ENOENT;
128 if (!suser()) {
129 iput(inode);
130 return -EACCES;
131 }
// �������Ǿ��ò����ṩ��ֵ�������ļ�i�ڵ���û�ID����ID������i�ڵ��Ѿ��ı�־��
// �Żظ�i�ڵ㣬����0��
132 inode->i_uid=uid;
133 inode->i_gid=gid;
134 inode->i_dirt=1;
135 iput(inode);
136 return 0;
137 }
138
//// ����ַ��豸���͡�
// �ú��������������ļ���ϵͳ����sys_open()�����ڼ�������ļ���tty�ն��ַ���
// ��ʱ����Ҫ�Ե�ǰ���̵����úͶ�tty�������á�
// ����0�����ɹ�������-1��ʾʧ�ܣ���Ӧ�ַ��豸���ܴ�
139 static int check_char_dev(struct m_inode * inode, int dev, int flag)
140 {
141 struct tty_struct *tty;
142 int min; // ���豸�š�
143
// ֻ�������豸����4��/dev/ttyxx�ļ�����5��/dev/tty�ļ����������/dev/tty�����豸
// ����0�����һ�������п����նˣ������ǽ��̿����ն��豸��ͬ��������/dev/tty�豸��
// һ�������豸������Ӧ������ʵ��ʹ�õ�/dev/ttyxx�豸֮һ������һ��������˵��������
// �����նˣ���ô��������ṹ�е�tty�ֶν���4���豸��ijһ�����豸�š�
// ����������ļ��� /dev/tty����MAJOR(dev) = 5������ô������min = ��������ṹ
// �е�tty�ֶΣ���ȡ4���豸�����豸�š������������ij��4���豸����ֱ��ȡ����
// �豸�š�����õ��� 4���豸���豸��С��0����ô˵������û�п����նˣ������豸�Ŵ�
// ���� -1����ʾ���ڽ���û�п����նˣ����߲��ܴ�����豸��
144 if (MAJOR(dev) == 4 || MAJOR(dev) == 5) {
145 if (MAJOR(dev) == 5)
146 min = current->tty;
147 else
148 min = MINOR(dev);
149 if (min < 0)
150 return -1;
// ��α�ն��豸�ļ�ֻ�ܱ����̶�ռʹ�á�������豸�ű�����һ����α�նˣ����Ҹô��ļ�
// i �ڵ����ü������� 1����˵�����豸�ѱ���������ʹ�á���˲����ٴ��ַ��豸�ļ���
// ���Ƿ��� -1������������tty�ṹָ��ttyָ��tty���ж�Ӧ�ṹ������ļ�������
// ־flag�в�����������ն˱�־O_NOCTTY�����ҽ����ǽ��������죬���ҵ�ǰ����û�п���
// �նˣ�����tty�ṹ��session�ֶ�Ϊ0����ʾ���ն˻������κν�����Ŀ����նˣ�����ô
// ������Ϊ������������ն��豸 min Ϊ������նˡ��������ý�������ṹ�ն��豸���ֶ�
// ttyֵ����min���������ö�Ӧtty�ṹ�ĻỰ��session�ͽ������pgrp�ֱ���ڽ��̵Ļ�
// ���źͽ�����š�
151 if ((IS_A_PTY_MASTER(min)) && (inode->i_count>1))
152 return -1;
153 tty = TTY_TABLE(min);
154 if (!(flag & O_NOCTTY) &&
155 current->leader &&
156 current->tty<0 &&
157 tty->session==0) {
158 current->tty = min;
159 tty->session= current->session;
160 tty->pgrp = current->pgrp;
161 }
// ������ļ�������־flag�к���O_NONBLOCK������������־����������Ҫ�Ը��ַ��ն�
// �豸����������ã�����Ϊ�����������Ҫ��ȡ�������ַ���Ϊ0�����ó�ʱ��ʱֵΪ0��
// �����ն��豸���óɷǹ淶ģʽ����������ʽֻ�ܹ����ڷǹ淶ģʽ���ڴ�ģʽ�µ�VMIN
// ��VTIME������Ϊ0ʱ�������������ж���֧�����̾Ͷ�ȡ�����ַ��������̷��ء��μ�
// include/termios.h�ļ����˵����
162 if (flag & O_NONBLOCK) {
163 TTY_TABLE(min)->termios.c_cc[VMIN] =0;
164 TTY_TABLE(min)->termios.c_cc[VTIME] =0;
165 TTY_TABLE(min)->termios.c_lflag &= ~ICANON;
166 }
167 }
168 return 0;
169 }
170
//// �������ļ�ϵͳ���á�
// ����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��
171 int sys_open(const char * filename,int flag,int mode)
172 {
173 struct m_inode * inode;
174 struct file * f;
175 int i,fd;
176
// ���ȶԲ������д��������û����õ��ļ�ģʽ�ͽ���ģʽ���������룬�������ɵ��ļ�ģʽ��
// Ϊ��Ϊ���ļ�����һ���ļ��������Ҫ�������̽ṹ���ļ��ṹָ�����飬�Բ���һ����
// ����������������fd���Ǿ��ֵ�����Ѿ�û�п�����س����루������Ч����
177 mode &= 0777 & ~current->umask;
178 for(fd=0 ; fd<NR_OPEN ; fd++)
179 if (!current->filp[fd]) // �ҵ������
180 break;
181 if (fd>=NR_OPEN)
182 return -EINVAL;
// Ȼ���������õ�ǰ���̵�ִ��ʱ�ر��ļ������close_on_exec��λͼ����λ��Ӧ�ı���λ��
// close_on_exec ��һ�����������ļ������λͼ��־��ÿ������λ����һ�����ŵ��ļ���
// ����������ȷ���ڵ���ϵͳ���� execve()ʱ��Ҫ�رյ��ļ������������ʹ�� fork()����
// ������һ���ӽ���ʱ��ͨ�����ڸ��ӽ����е���execve()��������ִ����һ���³���ʱ
// �ӽ����п�ʼִ���³�����һ���ļ������close_on_exec�еĶ�Ӧ����λ����λ����ô
// ��ִ��execve()ʱ�ö�Ӧ�ļ���������رգ�������ļ������ʼ�մ��ڴ�״̬������
// һ���ļ�ʱ��Ĭ��������ļ�������ӽ�����Ҳ���ڴ�״̬���������Ҫ��λ��Ӧ����λ��
// Ȼ��Ϊ���ļ����ļ�����Ѱ��һ�����нṹ�������fָ���ļ������鿪ʼ����������
// ���ļ��ṹ����ü���Ϊ0��������Ѿ�û�п����ļ����ṹ��س����롣���⣬
// ��184���ϵ�ָ�븳ֵ "0+file_table " ��ͬ�� "file_table" �� "&file_table[0]"��
// ��������д���ܸ�������һЩ��
183 current->close_on_exec &= ~(1<<fd);
184 f=0+file_table;
185 for (i=0 ; i<NR_FILE ; i++,f++)
186 if (!f->f_count) break;
187 if (i>=NR_FILE)
188 return -EINVAL;
// ��ʱ�����ý��̶�Ӧ�ļ����fd���ļ��ṹָ��ָ�����������ļ��ṹ�������ļ����ü���
// ����1��Ȼ����ú���open_namei()ִ�д�����������ֵС��0����˵�������������ͷ�
// �����뵽���ļ��ṹ�����س�����i�����ļ������ɹ�����inode���Ѵ��ļ���i�ڵ�
// ָ�롣
189 (current->filp[fd]=f)->f_count++;
190 if ((i=open_namei(filename,flag,mode,&inode))<0) {
191 current->filp[fd]=NULL;
192 f->f_count=0;
193 return i;
194 }
// �����Ѵ��ļ�i�ڵ�������ֶΣ����ǿ���֪���ļ������͡����ڲ�ͬ���͵��ļ�������
// ��Ҫ��һЩ�ر����� ��������ַ��豸�ļ�����ô���Ǿ�Ҫ����check_char_dev()
// ��������鵱ǰ�����Ƿ��ܴ�����ַ��豸�ļ��������������������0������ô��
// check_char_dev()�л���ݾ����ļ���־Ϊ�������ÿ����նˡ� �����������
// ʹ�ø��ַ��豸�ļ�����ô����ֻ���ͷ�����������ļ���;����Դ�����س����롣
195 /* ttys are somewhat special (ttyxx major==4, tty major==5) */
/* ttys��Щ���⣨ttyxx�����豸��==4��tty�����豸��==5��*/
196 if (S_ISCHR(inode->i_mode))
197 if (check_char_dev(inode,inode->i_zone[0],flag)) {
198 iput(inode);
199 current->filp[fd]=NULL;
200 f->f_count=0;
201 return -EAGAIN; // �����ţ���Դ��ʱ�����á�
202 }
// ������ǿ��豸�ļ���������Ƭ�Ƿ��������������������Ҫ�ø��ٻ������и��豸
// �����л����ʧЧ��
203 /* Likewise with block-devices: check for floppy_change */
/* ͬ�����ڿ��豸�ļ�����Ҫ�����Ƭ�Ƿ��� */
204 if (S_ISBLK(inode->i_mode))
205 check_disk_change(inode->i_zone[0]);
// �������dz�ʼ�����ļ����ļ��ṹ�������ļ��ṹ���Ժͱ�־���þ�����ü���Ϊ1����
// ����i�ڵ��ֶ�Ϊ���ļ���i�ڵ㣬��ʼ���ļ���дָ��Ϊ0������ļ�����š�
206 f->f_mode = inode->i_mode;
207 f->f_flags = flag;
208 f->f_count = 1;
209 f->f_inode = inode;
210 f->f_pos = 0;
211 return (fd);
212 }
213
//// �����ļ�ϵͳ���á�
// ����pathname��·������mode�������sys_open()������ͬ��
// �ɹ����ļ���������س����롣
214 int sys_creat(const char * pathname, int mode)
215 {
216 return sys_open(pathname, O_CREAT | O_TRUNC, mode);
217 }
218
// �ر��ļ�ϵͳ���á�
// ����fd��������
// �ɹ���0�����س����롣
219 int sys_close(unsigned int fd)
220 {
221 struct file * filp;
222
// ���ȼ�������Ч�ԡ����������ļ����ֵ���ڳ���ͬʱ�ܴ��ļ���NR_OPEN����
// �����루������Ч����Ȼ��λ���̵�ִ��ʱ�ر��ļ����λͼ��Ӧλ�������ļ������Ӧ
// ���ļ��ṹָ����NULL���س����롣
223 if (fd >= NR_OPEN)
224 return -EINVAL;
225 current->close_on_exec &= ~(1<<fd);
226 if (!(filp = current->filp[fd]))
227 return -EINVAL;
// �����ø��ļ�������ļ��ṹָ��ΪNULL�����ڹر��ļ�֮ǰ����Ӧ�ļ��ṹ�еľ������
// �����Ѿ�Ϊ0����˵���ں˳�����ͣ��������Ӧ�ļ��ṹ�����ü�����1����ʱ�������
// ��Ϊ0����˵����������������ʹ�ø��ļ������Ƿ���0���ɹ�����������ü����ѵ���0��
// ˵�����ļ��Ѿ�û�н������ã����ļ��ṹ�ѱ�Ϊ���С����ͷŸ��ļ�i�ڵ㣬����0��
228 current->filp[fd] = NULL;
229 if (filp->f_count == 0)
230 panic("Close: file count is 0");
231 if (--filp->f_count)
232 return (0);
233 iput(filp->f_inode);
234 return (0);
235 }
236