summaryrefslogtreecommitdiffstats
path: root/src/fs/open.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs/open.c')
-rw-r--r--src/fs/open.c209
1 files changed, 209 insertions, 0 deletions
diff --git a/src/fs/open.c b/src/fs/open.c
new file mode 100644
index 0000000..cac0082
--- /dev/null
+++ b/src/fs/open.c
@@ -0,0 +1,209 @@
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>
12#include <sys/stat.h>
13
14#include <linux/sched.h>
15#include <linux/tty.h>
16#include <linux/kernel.h>
17#include <asm/segment.h>
18
19int sys_ustat(int dev, struct ustat * ubuf)
20{
21 return -ENOSYS;
22}
23
24int sys_utime(char * filename, struct utimbuf * times)
25{
26 struct m_inode * inode;
27 long actime,modtime;
28
29 if (!(inode=namei(filename)))
30 return -ENOENT;
31 if (times) {
32 actime = get_fs_long((unsigned long *) &times->actime);
33 modtime = get_fs_long((unsigned long *) &times->modtime);
34 } else
35 actime = modtime = CURRENT_TIME;
36 inode->i_atime = actime;
37 inode->i_mtime = modtime;
38 inode->i_dirt = 1;
39 iput(inode);
40 return 0;
41}
42
43/*
44 * XXX should we use the real or effective uid? BSD uses the real uid,
45 * so as to make this call useful to setuid programs.
46 */
47int sys_access(const char * filename,int mode)
48{
49 struct m_inode * inode;
50 int res, i_mode;
51
52 mode &= 0007;
53 if (!(inode=namei(filename)))
54 return -EACCES;
55 i_mode = res = inode->i_mode & 0777;
56 iput(inode);
57 if (current->uid == inode->i_uid)
58 res >>= 6;
59 else if (current->gid == inode->i_gid)
60 res >>= 6;
61 if ((res & 0007 & mode) == mode)
62 return 0;
63 /*
64 * XXX we are doing this test last because we really should be
65 * swapping the effective with the real user id (temporarily),
66 * and then calling suser() routine. If we do call the
67 * suser() routine, it needs to be called last.
68 */
69 if ((!current->uid) &&
70 (!(mode & 1) || (i_mode & 0111)))
71 return 0;
72 return -EACCES;
73}
74
75int sys_chdir(const char * filename)
76{
77 struct m_inode * inode;
78
79 if (!(inode = namei(filename)))
80 return -ENOENT;
81 if (!S_ISDIR(inode->i_mode)) {
82 iput(inode);
83 return -ENOTDIR;
84 }
85 iput(current->pwd);
86 current->pwd = inode;
87 return (0);
88}
89
90int sys_chroot(const char * filename)
91{
92 struct m_inode * inode;
93
94 if (!(inode=namei(filename)))
95 return -ENOENT;
96 if (!S_ISDIR(inode->i_mode)) {
97 iput(inode);
98 return -ENOTDIR;
99 }
100 iput(current->root);
101 current->root = inode;
102 return (0);
103}
104
105int sys_chmod(const char * filename,int mode)
106{
107 struct m_inode * inode;
108
109 if (!(inode=namei(filename)))
110 return -ENOENT;
111 if ((current->euid != inode->i_uid) && !suser()) {
112 iput(inode);
113 return -EACCES;
114 }
115 inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
116 inode->i_dirt = 1;
117 iput(inode);
118 return 0;
119}
120
121int sys_chown(const char * filename,int uid,int gid)
122{
123 struct m_inode * inode;
124
125 if (!(inode=namei(filename)))
126 return -ENOENT;
127 if (!suser()) {
128 iput(inode);
129 return -EACCES;
130 }
131 inode->i_uid=uid;
132 inode->i_gid=gid;
133 inode->i_dirt=1;
134 iput(inode);
135 return 0;
136}
137
138int sys_open(const char * filename,int flag,int mode)
139{
140 struct m_inode * inode;
141 struct file * f;
142 int i,fd;
143
144 mode &= 0777 & ~current->umask;
145 for(fd=0 ; fd<NR_OPEN ; fd++)
146 if (!current->filp[fd])
147 break;
148 if (fd>=NR_OPEN)
149 return -EINVAL;
150 current->close_on_exec &= ~(1<<fd);
151 f=0+file_table;
152 for (i=0 ; i<NR_FILE ; i++,f++)
153 if (!f->f_count) break;
154 if (i>=NR_FILE)
155 return -EINVAL;
156 (current->filp[fd]=f)->f_count++;
157 if ((i=open_namei(filename,flag,mode,&inode))<0) {
158 current->filp[fd]=NULL;
159 f->f_count=0;
160 return i;
161 }
162/* ttys are somewhat special (ttyxx major==4, tty major==5) */
163 if (S_ISCHR(inode->i_mode)) {
164 if (MAJOR(inode->i_zone[0])==4) {
165 if (current->leader && current->tty<0) {
166 current->tty = MINOR(inode->i_zone[0]);
167 tty_table[current->tty].pgrp = current->pgrp;
168 }
169 } else if (MAJOR(inode->i_zone[0])==5)
170 if (current->tty<0) {
171 iput(inode);
172 current->filp[fd]=NULL;
173 f->f_count=0;
174 return -EPERM;
175 }
176 }
177/* Likewise with block-devices: check for floppy_change */
178 if (S_ISBLK(inode->i_mode))
179 check_disk_change(inode->i_zone[0]);
180 f->f_mode = inode->i_mode;
181 f->f_flags = flag;
182 f->f_count = 1;
183 f->f_inode = inode;
184 f->f_pos = 0;
185 return (fd);
186}
187
188int sys_creat(const char * pathname, int mode)
189{
190 return sys_open(pathname, O_CREAT | O_TRUNC, mode);
191}
192
193int sys_close(unsigned int fd)
194{
195 struct file * filp;
196
197 if (fd >= NR_OPEN)
198 return -EINVAL;
199 current->close_on_exec &= ~(1<<fd);
200 if (!(filp = current->filp[fd]))
201 return -EINVAL;
202 current->filp[fd] = NULL;
203 if (filp->f_count == 0)
204 panic("Close: file count is 0");
205 if (--filp->f_count)
206 return (0);
207 iput(filp->f_inode);
208 return (0);
209}