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