diff options
Diffstat (limited to 'src/fs/open.c')
-rw-r--r-- | src/fs/open.c | 209 |
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 | |||
19 | int sys_ustat(int dev, struct ustat * ubuf) | ||
20 | { | ||
21 | return -ENOSYS; | ||
22 | } | ||
23 | |||
24 | int 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 *) ×->actime); | ||
33 | modtime = get_fs_long((unsigned long *) ×->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 | */ | ||
47 | int 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 | |||
75 | int 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 | |||
90 | int 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 | |||
105 | int 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 | |||
121 | int 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 | |||
138 | int 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 | |||
188 | int sys_creat(const char * pathname, int mode) | ||
189 | { | ||
190 | return sys_open(pathname, O_CREAT | O_TRUNC, mode); | ||
191 | } | ||
192 | |||
193 | int 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 | } | ||