This source file includes following definitions.
- sys_ustat
- sys_statfs
- sys_fstatfs
- sys_truncate
- sys_ftruncate
- sys_utime
- sys_access
- sys_chdir
- sys_chroot
- sys_fchmod
- sys_chmod
- sys_fchown
- sys_chown
- sys_open
- sys_creat
- close_fp
- sys_close
- sys_vhangup
1
2
3
4
5
6
7 #include <linux/vfs.h>
8 #include <linux/types.h>
9 #include <linux/utime.h>
10 #include <linux/errno.h>
11 #include <linux/fcntl.h>
12 #include <linux/stat.h>
13 #include <linux/string.h>
14 #include <linux/sched.h>
15 #include <linux/kernel.h>
16 #include <linux/signal.h>
17 #include <linux/tty.h>
18 #include <linux/time.h>
19
20 #include <asm/segment.h>
21
22 extern void fcntl_remove_locks(struct task_struct *, struct file *);
23
24 int sys_ustat(int dev, struct ustat * ubuf)
25 {
26 return -ENOSYS;
27 }
28
29 int sys_statfs(const char * path, struct statfs * buf)
30 {
31 struct inode * inode;
32 int error;
33
34 verify_area(buf, sizeof(struct statfs));
35 error = namei(path,&inode);
36 if (error)
37 return error;
38 if (!inode->i_sb->s_op->statfs) {
39 iput(inode);
40 return -ENOSYS;
41 }
42 inode->i_sb->s_op->statfs(inode->i_sb, buf);
43 iput(inode);
44 return 0;
45 }
46
47 int sys_fstatfs(unsigned int fd, struct statfs * buf)
48 {
49 struct inode * inode;
50 struct file * file;
51
52 verify_area(buf, sizeof(struct statfs));
53 if (fd >= NR_OPEN || !(file = current->filp[fd]))
54 return -EBADF;
55 if (!(inode = file->f_inode))
56 return -ENOENT;
57 if (!inode->i_sb->s_op->statfs)
58 return -ENOSYS;
59 inode->i_sb->s_op->statfs(inode->i_sb, buf);
60 return 0;
61 }
62
63 int sys_truncate(const char * path, unsigned int length)
64 {
65 struct inode * inode;
66 int error;
67
68 error = namei(path,&inode);
69 if (error)
70 return error;
71 if (S_ISDIR(inode->i_mode) || !permission(inode,MAY_WRITE)) {
72 iput(inode);
73 return -EACCES;
74 }
75 if (IS_RDONLY(inode)) {
76 iput(inode);
77 return -EROFS;
78 }
79 inode->i_size = length;
80 if (inode->i_op && inode->i_op->truncate)
81 inode->i_op->truncate(inode);
82 inode->i_atime = inode->i_mtime = CURRENT_TIME;
83 inode->i_dirt = 1;
84 error = notify_change(NOTIFY_SIZE, inode);
85 iput(inode);
86 return error;
87 }
88
89 int sys_ftruncate(unsigned int fd, unsigned int length)
90 {
91 struct inode * inode;
92 struct file * file;
93
94 if (fd >= NR_OPEN || !(file = current->filp[fd]))
95 return -EBADF;
96 if (!(inode = file->f_inode))
97 return -ENOENT;
98 if (S_ISDIR(inode->i_mode) || !(file->f_mode & 2))
99 return -EACCES;
100 inode->i_size = length;
101 if (inode->i_op && inode->i_op->truncate)
102 inode->i_op->truncate(inode);
103 inode->i_atime = inode->i_mtime = CURRENT_TIME;
104 inode->i_dirt = 1;
105 return notify_change(NOTIFY_SIZE, inode);
106 }
107
108
109
110
111
112 int sys_utime(char * filename, struct utimbuf * times)
113 {
114 struct inode * inode;
115 long actime,modtime;
116 int error;
117
118 error = namei(filename,&inode);
119 if (error)
120 return error;
121 if (IS_RDONLY(inode)) {
122 iput(inode);
123 return -EROFS;
124 }
125 if (times) {
126 if ((current->euid != inode->i_uid) && !suser()) {
127 iput(inode);
128 return -EPERM;
129 }
130 actime = get_fs_long((unsigned long *) ×->actime);
131 modtime = get_fs_long((unsigned long *) ×->modtime);
132 } else {
133 if ((current->euid != inode->i_uid) &&
134 !permission(inode,MAY_WRITE)) {
135 iput(inode);
136 return -EACCES;
137 }
138 actime = modtime = CURRENT_TIME;
139 }
140 inode->i_atime = actime;
141 inode->i_mtime = modtime;
142 inode->i_ctime = CURRENT_TIME;
143 inode->i_dirt = 1;
144 error = notify_change(NOTIFY_TIME, inode);
145 iput(inode);
146 return error;
147 }
148
149
150
151
152
153 int sys_access(const char * filename,int mode)
154 {
155 struct inode * inode;
156 int res, i_mode;
157
158 mode &= 0007;
159 res = namei(filename,&inode);
160 if (res)
161 return res;
162 i_mode = res = inode->i_mode & 0777;
163 iput(inode);
164 if (current->uid == inode->i_uid)
165 res >>= 6;
166 else if (in_group_p(inode->i_gid))
167 res >>= 3;
168 if ((res & 0007 & mode) == mode)
169 return 0;
170
171
172
173
174
175
176 if ((!current->uid) &&
177 (!(mode & 1) || (i_mode & 0111)))
178 return 0;
179 return -EACCES;
180 }
181
182 int sys_chdir(const char * filename)
183 {
184 struct inode * inode;
185 int error;
186
187 error = namei(filename,&inode);
188 if (error)
189 return error;
190 if (!S_ISDIR(inode->i_mode)) {
191 iput(inode);
192 return -ENOTDIR;
193 }
194 if (!permission(inode,MAY_EXEC)) {
195 iput(inode);
196 return -EACCES;
197 }
198 iput(current->pwd);
199 current->pwd = inode;
200 return (0);
201 }
202
203 int sys_chroot(const char * filename)
204 {
205 struct inode * inode;
206 int error;
207
208 error = namei(filename,&inode);
209 if (error)
210 return error;
211 if (!S_ISDIR(inode->i_mode)) {
212 iput(inode);
213 return -ENOTDIR;
214 }
215 if (!suser()) {
216 iput(inode);
217 return -EPERM;
218 }
219 iput(current->root);
220 current->root = inode;
221 return (0);
222 }
223
224 int sys_fchmod(unsigned int fd, mode_t mode)
225 {
226 struct inode * inode;
227 struct file * file;
228
229 if (fd >= NR_OPEN || !(file = current->filp[fd]))
230 return -EBADF;
231 if (!(inode = file->f_inode))
232 return -ENOENT;
233 if ((current->euid != inode->i_uid) && !suser())
234 return -EPERM;
235 if (IS_RDONLY(inode))
236 return -EROFS;
237 inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
238 if (!suser() && !in_group_p(inode->i_gid))
239 inode->i_mode &= ~S_ISGID;
240 inode->i_ctime = CURRENT_TIME;
241 inode->i_dirt = 1;
242 return notify_change(NOTIFY_MODE, inode);
243 }
244
245 int sys_chmod(const char * filename, mode_t mode)
246 {
247 struct inode * inode;
248 int error;
249
250 error = namei(filename,&inode);
251 if (error)
252 return error;
253 if ((current->euid != inode->i_uid) && !suser()) {
254 iput(inode);
255 return -EPERM;
256 }
257 if (IS_RDONLY(inode)) {
258 iput(inode);
259 return -EROFS;
260 }
261 inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
262 if (!suser() && !in_group_p(inode->i_gid))
263 inode->i_mode &= ~S_ISGID;
264 inode->i_ctime = CURRENT_TIME;
265 inode->i_dirt = 1;
266 error = notify_change(NOTIFY_MODE, inode);
267 iput(inode);
268 return error;
269 }
270
271 int sys_fchown(unsigned int fd, uid_t user, gid_t group)
272 {
273 struct inode * inode;
274 struct file * file;
275
276 if (fd >= NR_OPEN || !(file = current->filp[fd]))
277 return -EBADF;
278 if (!(inode = file->f_inode))
279 return -ENOENT;
280 if (IS_RDONLY(inode))
281 return -EROFS;
282 if (user == (uid_t) -1)
283 user = inode->i_uid;
284 if (group == (gid_t) -1)
285 group = inode->i_gid;
286 if ((current->euid == inode->i_uid && user == inode->i_uid &&
287 (in_group_p(group) || group == inode->i_gid)) ||
288 suser()) {
289 inode->i_uid = user;
290 inode->i_gid = group;
291 inode->i_ctime = CURRENT_TIME;
292 inode->i_dirt = 1;
293 return notify_change(NOTIFY_UIDGID, inode);
294 }
295 return -EPERM;
296 }
297
298 int sys_chown(const char * filename, uid_t user, gid_t group)
299 {
300 struct inode * inode;
301 int error;
302
303 error = lnamei(filename,&inode);
304 if (error)
305 return error;
306 if (IS_RDONLY(inode)) {
307 iput(inode);
308 return -EROFS;
309 }
310 if (user == (uid_t) -1)
311 user = inode->i_uid;
312 if (group == (gid_t) -1)
313 group = inode->i_gid;
314 if ((current->euid == inode->i_uid && user == inode->i_uid &&
315 (in_group_p(group) || group == inode->i_gid)) ||
316 suser()) {
317 inode->i_uid = user;
318 inode->i_gid = group;
319 inode->i_ctime = CURRENT_TIME;
320 inode->i_dirt = 1;
321 error = notify_change(NOTIFY_UIDGID, inode);
322 iput(inode);
323 return error;
324 }
325 iput(inode);
326 return -EPERM;
327 }
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343 int sys_open(const char * filename,int flag,int mode)
344 {
345 struct inode * inode;
346 struct file * f;
347 int i,fd;
348
349 for(fd=0 ; fd<NR_OPEN ; fd++)
350 if (!current->filp[fd])
351 break;
352 if (fd>=NR_OPEN)
353 return -EMFILE;
354 FD_CLR(fd,¤t->close_on_exec);
355 f = get_empty_filp();
356 if (!f)
357 return -ENFILE;
358 current->filp[fd] = f;
359 f->f_flags = flag;
360 f->f_mode = (flag+1) & O_ACCMODE;
361 if (f->f_mode)
362 flag++;
363 if (flag & (O_TRUNC | O_CREAT))
364 flag |= 2;
365 i = open_namei(filename,flag,mode,&inode,NULL);
366 if (i) {
367 current->filp[fd]=NULL;
368 f->f_count--;
369 return i;
370 }
371 if (flag & O_TRUNC) {
372 inode->i_size = 0;
373 if (inode->i_op && inode->i_op->truncate)
374 inode->i_op->truncate(inode);
375 if ((i = notify_change(NOTIFY_SIZE, inode))) {
376 iput(inode);
377 current->filp[fd] = NULL;
378 f->f_count--;
379 return i;
380 }
381 }
382 if (!IS_RDONLY(inode)) {
383 inode->i_atime = CURRENT_TIME;
384 inode->i_dirt = 1;
385 }
386 f->f_inode = inode;
387 f->f_pos = 0;
388 f->f_reada = 0;
389 f->f_op = NULL;
390 if (inode->i_op)
391 f->f_op = inode->i_op->default_file_ops;
392 if (f->f_op && f->f_op->open) {
393 i = f->f_op->open(inode,f);
394 if (i) {
395 iput(inode);
396 f->f_count--;
397 current->filp[fd]=NULL;
398 return i;
399 }
400 }
401 f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
402 return (fd);
403 }
404
405 int sys_creat(const char * pathname, int mode)
406 {
407 return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
408 }
409
410 int close_fp(struct file *filp)
411 {
412 struct inode *inode;
413
414 if (filp->f_count == 0) {
415 printk("Close: file count is 0\n");
416 return 0;
417 }
418 inode = filp->f_inode;
419 if (inode && S_ISREG(inode->i_mode))
420 fcntl_remove_locks(current, filp);
421 if (filp->f_count > 1) {
422 filp->f_count--;
423 return 0;
424 }
425 if (filp->f_op && filp->f_op->release)
426 filp->f_op->release(inode,filp);
427 filp->f_count--;
428 filp->f_inode = NULL;
429 iput(inode);
430 return 0;
431 }
432
433 int sys_close(unsigned int fd)
434 {
435 struct file * filp;
436
437 if (fd >= NR_OPEN)
438 return -EINVAL;
439 FD_CLR(fd, ¤t->close_on_exec);
440 if (!(filp = current->filp[fd]))
441 return -EINVAL;
442 current->filp[fd] = NULL;
443 return (close_fp (filp));
444 }
445
446
447
448
449
450 int sys_vhangup(void)
451 {
452 struct tty_struct *tty;
453
454 if (!suser())
455 return -EPERM;
456
457 if (current->tty < 0)
458 return 0;
459 tty = TTY_TABLE(MINOR(current->tty));
460 tty_hangup(tty);
461 return 0;
462 }