This source file includes following definitions.
- sys_statfs
- sys_fstatfs
- do_truncate
- sys_truncate
- sys_ftruncate
- sys_utime
- sys_utimes
- 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 #include <linux/mm.h>
20
21 #include <asm/segment.h>
22
23 extern void locks_remove_locks(struct task_struct *, struct file *);
24
25 asmlinkage int sys_statfs(const char * path, struct statfs * buf)
26 {
27 struct inode * inode;
28 int error;
29
30 error = verify_area(VERIFY_WRITE, buf, sizeof(struct statfs));
31 if (error)
32 return error;
33 error = namei(path,&inode);
34 if (error)
35 return error;
36 if (!inode->i_sb->s_op->statfs) {
37 iput(inode);
38 return -ENOSYS;
39 }
40 inode->i_sb->s_op->statfs(inode->i_sb, buf, sizeof(struct statfs));
41 iput(inode);
42 return 0;
43 }
44
45 asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf)
46 {
47 struct inode * inode;
48 struct file * file;
49 int error;
50
51 error = verify_area(VERIFY_WRITE, buf, sizeof(struct statfs));
52 if (error)
53 return error;
54 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
55 return -EBADF;
56 if (!(inode = file->f_inode))
57 return -ENOENT;
58 if (!inode->i_sb->s_op->statfs)
59 return -ENOSYS;
60 inode->i_sb->s_op->statfs(inode->i_sb, buf, sizeof(struct statfs));
61 return 0;
62 }
63
64 static int do_truncate(struct inode *inode, unsigned long length)
65 {
66 struct iattr newattrs;
67
68
69 down(&inode->i_sem);
70 vmtruncate(inode, length);
71 inode->i_size = newattrs.ia_size = length;
72 if (inode->i_op && inode->i_op->truncate)
73 inode->i_op->truncate(inode);
74 up(&inode->i_sem);
75 newattrs.ia_ctime = newattrs.ia_mtime = CURRENT_TIME;
76 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME | ATTR_MTIME;
77 inode->i_dirt = 1;
78 return notify_change(inode, &newattrs);
79 }
80
81 asmlinkage int sys_truncate(const char * path, unsigned long length)
82 {
83 struct inode * inode;
84 int error;
85
86 error = namei(path,&inode);
87 if (error)
88 return error;
89 if (S_ISDIR(inode->i_mode)) {
90 iput(inode);
91 return -EACCES;
92 }
93 if ((error = permission(inode,MAY_WRITE)) != 0) {
94 iput(inode);
95 return error;
96 }
97 if (IS_RDONLY(inode)) {
98 iput(inode);
99 return -EROFS;
100 }
101 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
102 iput(inode);
103 return -EPERM;
104 }
105 error = get_write_access(inode);
106 if (error) {
107 iput(inode);
108 return error;
109 }
110 error = do_truncate(inode, length);
111 put_write_access(inode);
112 iput(inode);
113 return error;
114 }
115
116 asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length)
117 {
118 struct inode * inode;
119 struct file * file;
120
121 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
122 return -EBADF;
123 if (!(inode = file->f_inode))
124 return -ENOENT;
125 if (S_ISDIR(inode->i_mode) || !(file->f_mode & 2))
126 return -EACCES;
127 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
128 return -EPERM;
129 return do_truncate(inode, length);
130 }
131
132
133
134
135
136 asmlinkage int sys_utime(char * filename, struct utimbuf * times)
137 {
138 struct inode * inode;
139 long actime,modtime;
140 int error;
141 unsigned int flags = 0;
142 struct iattr newattrs;
143
144 error = namei(filename,&inode);
145 if (error)
146 return error;
147 if (IS_RDONLY(inode)) {
148 iput(inode);
149 return -EROFS;
150 }
151
152 if (times) {
153 error = verify_area(VERIFY_READ, times, sizeof(*times));
154 if (error) {
155 iput(inode);
156 return error;
157 }
158 actime = get_user(×->actime);
159 modtime = get_user(×->modtime);
160 newattrs.ia_ctime = CURRENT_TIME;
161 flags = ATTR_ATIME_SET | ATTR_MTIME_SET;
162 } else {
163 if ((error = permission(inode,MAY_WRITE)) != 0) {
164 iput(inode);
165 return error;
166 }
167 actime = modtime = newattrs.ia_ctime = CURRENT_TIME;
168 }
169 newattrs.ia_atime = actime;
170 newattrs.ia_mtime = modtime;
171 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME | flags;
172 inode->i_dirt = 1;
173 error = notify_change(inode, &newattrs);
174 iput(inode);
175 return error;
176 }
177
178
179
180
181
182 asmlinkage int sys_utimes(char * filename, struct timeval * utimes)
183 {
184 struct inode * inode;
185 long actime,modtime;
186 int error;
187 unsigned int flags = 0;
188 struct iattr newattrs;
189
190 error = namei(filename,&inode);
191 if (error)
192 return error;
193 if (IS_RDONLY(inode)) {
194 iput(inode);
195 return -EROFS;
196 }
197
198 if (utimes) {
199 struct timeval times[2];
200 error = verify_area(VERIFY_READ, utimes, sizeof(times));
201 if (error) {
202 iput(inode);
203 return error;
204 }
205 memcpy_fromfs(×, utimes, sizeof(times));
206 actime = times[0].tv_sec;
207 modtime = times[1].tv_sec;
208 newattrs.ia_ctime = CURRENT_TIME;
209 flags = ATTR_ATIME_SET | ATTR_MTIME_SET;
210 } else {
211 if ((error = permission(inode,MAY_WRITE)) != 0) {
212 iput(inode);
213 return error;
214 }
215 actime = modtime = newattrs.ia_ctime = CURRENT_TIME;
216 }
217 newattrs.ia_atime = actime;
218 newattrs.ia_mtime = modtime;
219 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME | flags;
220 inode->i_dirt = 1;
221 error = notify_change(inode, &newattrs);
222 iput(inode);
223 return error;
224 }
225
226
227
228
229
230 asmlinkage int sys_access(const char * filename, int mode)
231 {
232 struct inode * inode;
233 int old_fsuid, old_fsgid;
234 int res;
235
236 if (mode != (mode & S_IRWXO))
237 return -EINVAL;
238 old_fsuid = current->fsuid;
239 old_fsgid = current->fsgid;
240 current->fsuid = current->uid;
241 current->fsgid = current->gid;
242 res = namei(filename,&inode);
243 if (!res) {
244 res = permission(inode, mode);
245 iput(inode);
246 }
247 current->fsuid = old_fsuid;
248 current->fsgid = old_fsgid;
249 return res;
250 }
251
252 asmlinkage int sys_chdir(const char * filename)
253 {
254 struct inode * inode;
255 int error;
256
257 error = namei(filename,&inode);
258 if (error)
259 return error;
260 if (!S_ISDIR(inode->i_mode)) {
261 iput(inode);
262 return -ENOTDIR;
263 }
264 if ((error = permission(inode,MAY_EXEC)) != 0) {
265 iput(inode);
266 return error;
267 }
268 iput(current->fs->pwd);
269 current->fs->pwd = inode;
270 return (0);
271 }
272
273 asmlinkage int sys_fchdir(unsigned int fd)
274 {
275 struct inode * inode;
276 struct file * file;
277 int error;
278
279 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
280 return -EBADF;
281 if (!(inode = file->f_inode))
282 return -ENOENT;
283 if (!S_ISDIR(inode->i_mode))
284 return -ENOTDIR;
285 if ((error = permission(inode,MAY_EXEC)) != 0)
286 return error;
287 iput(current->fs->pwd);
288 current->fs->pwd = inode;
289 inode->i_count++;
290 return (0);
291 }
292
293 asmlinkage int sys_chroot(const char * filename)
294 {
295 struct inode * inode;
296 int error;
297
298 error = namei(filename,&inode);
299 if (error)
300 return error;
301 if (!S_ISDIR(inode->i_mode)) {
302 iput(inode);
303 return -ENOTDIR;
304 }
305 if (!fsuser()) {
306 iput(inode);
307 return -EPERM;
308 }
309 iput(current->fs->root);
310 current->fs->root = inode;
311 return (0);
312 }
313
314 asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
315 {
316 struct inode * inode;
317 struct file * file;
318 struct iattr newattrs;
319
320 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
321 return -EBADF;
322 if (!(inode = file->f_inode))
323 return -ENOENT;
324 if (IS_RDONLY(inode))
325 return -EROFS;
326 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
327 return -EPERM;
328 if (mode == (mode_t) -1)
329 mode = inode->i_mode;
330 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
331 newattrs.ia_ctime = CURRENT_TIME;
332 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
333 inode->i_dirt = 1;
334 return notify_change(inode, &newattrs);
335 }
336
337 asmlinkage int sys_chmod(const char * filename, mode_t mode)
338 {
339 struct inode * inode;
340 int error;
341 struct iattr newattrs;
342
343 error = namei(filename,&inode);
344 if (error)
345 return error;
346 if (IS_RDONLY(inode)) {
347 iput(inode);
348 return -EROFS;
349 }
350 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
351 iput(inode);
352 return -EPERM;
353 }
354 if (mode == (mode_t) -1)
355 mode = inode->i_mode;
356 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
357 newattrs.ia_ctime = CURRENT_TIME;
358 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
359 inode->i_dirt = 1;
360 error = notify_change(inode, &newattrs);
361 iput(inode);
362 return error;
363 }
364
365 asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
366 {
367 struct inode * inode;
368 struct file * file;
369 struct iattr newattrs;
370
371 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
372 return -EBADF;
373 if (!(inode = file->f_inode))
374 return -ENOENT;
375 if (IS_RDONLY(inode))
376 return -EROFS;
377 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
378 return -EPERM;
379 if (user == (uid_t) -1)
380 user = inode->i_uid;
381 if (group == (gid_t) -1)
382 group = inode->i_gid;
383 newattrs.ia_mode = inode->i_mode;
384 newattrs.ia_uid = user;
385 newattrs.ia_gid = group;
386 newattrs.ia_ctime = CURRENT_TIME;
387 newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
388
389
390
391 if (user != inode->i_uid && (inode->i_mode & S_ISUID)) {
392 newattrs.ia_mode &= ~S_ISUID;
393 newattrs.ia_valid |= ATTR_MODE;
394 }
395
396
397
398 if (group != inode->i_gid && (inode->i_mode & S_ISGID)) {
399 newattrs.ia_mode &= ~S_ISGID;
400 newattrs.ia_valid |= ATTR_MODE;
401 }
402 inode->i_dirt = 1;
403 return notify_change(inode, &newattrs);
404 }
405
406 asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
407 {
408 struct inode * inode;
409 int error;
410 struct iattr newattrs;
411
412 error = lnamei(filename,&inode);
413 if (error)
414 return error;
415 if (IS_RDONLY(inode)) {
416 iput(inode);
417 return -EROFS;
418 }
419 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
420 iput(inode);
421 return -EPERM;
422 }
423 if (user == (uid_t) -1)
424 user = inode->i_uid;
425 if (group == (gid_t) -1)
426 group = inode->i_gid;
427 newattrs.ia_mode = inode->i_mode;
428 newattrs.ia_uid = user;
429 newattrs.ia_gid = group;
430 newattrs.ia_ctime = CURRENT_TIME;
431 newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
432
433
434
435 if (user != inode->i_uid && (inode->i_mode & S_ISUID)) {
436 newattrs.ia_mode &= ~S_ISUID;
437 newattrs.ia_valid |= ATTR_MODE;
438 }
439
440
441
442 if (group != inode->i_gid && (inode->i_mode & S_ISGID)) {
443 newattrs.ia_mode &= ~S_ISGID;
444 newattrs.ia_valid |= ATTR_MODE;
445 }
446 inode->i_dirt = 1;
447 error = notify_change(inode, &newattrs);
448 iput(inode);
449 return(error);
450 }
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466 int do_open(const char * filename,int flags,int mode)
467 {
468 struct inode * inode;
469 struct file * f;
470 int flag,error,fd;
471
472 f = get_empty_filp();
473 if (!f)
474 return -ENFILE;
475 f->f_flags = flag = flags;
476 f->f_mode = (flag+1) & O_ACCMODE;
477 if (f->f_mode)
478 flag++;
479 if (flag & (O_TRUNC | O_CREAT))
480 flag |= 2;
481 error = open_namei(filename,flag,mode,&inode,NULL);
482 if (error)
483 goto cleanup_file;
484 if (f->f_mode & 2) {
485 error = get_write_access(inode);
486 if (error)
487 goto cleanup_inode;
488 }
489
490 f->f_inode = inode;
491 f->f_pos = 0;
492 f->f_reada = 0;
493 f->f_op = NULL;
494 if (inode->i_op)
495 f->f_op = inode->i_op->default_file_ops;
496 if (f->f_op && f->f_op->open) {
497 error = f->f_op->open(inode,f);
498 if (error)
499 goto cleanup_all;
500 }
501 f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
502
503
504
505
506
507
508 for(fd = 0; fd < NR_OPEN && fd < current->rlim[RLIMIT_NOFILE].rlim_cur; fd++) {
509 if (!current->files->fd[fd]) {
510 current->files->fd[fd] = f;
511 FD_CLR(fd,¤t->files->close_on_exec);
512 return fd;
513 }
514 }
515 error = -EMFILE;
516 if (f->f_op && f->f_op->release)
517 f->f_op->release(inode,f);
518 cleanup_all:
519 if (f->f_mode & 2)
520 put_write_access(inode);
521 cleanup_inode:
522 iput(inode);
523 cleanup_file:
524 f->f_count--;
525 return error;
526 }
527
528 asmlinkage int sys_open(const char * filename,int flags,int mode)
529 {
530 char * tmp;
531 int error;
532
533 error = getname(filename, &tmp);
534 if (error)
535 return error;
536 error = do_open(tmp,flags,mode);
537 putname(tmp);
538 return error;
539 }
540
541 asmlinkage int sys_creat(const char * pathname, int mode)
542 {
543 return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
544 }
545
546 int close_fp(struct file *filp)
547 {
548 struct inode *inode;
549
550 if (filp->f_count == 0) {
551 printk("VFS: Close: file count is 0\n");
552 return 0;
553 }
554 inode = filp->f_inode;
555 if (inode)
556 locks_remove_locks(current, filp);
557 if (filp->f_count > 1) {
558 filp->f_count--;
559 return 0;
560 }
561 if (filp->f_op && filp->f_op->release)
562 filp->f_op->release(inode,filp);
563 filp->f_count--;
564 filp->f_inode = NULL;
565 if (filp->f_mode & 2) put_write_access(inode);
566 iput(inode);
567 return 0;
568 }
569
570 asmlinkage int sys_close(unsigned int fd)
571 {
572 struct file * filp;
573
574 if (fd >= NR_OPEN)
575 return -EBADF;
576 FD_CLR(fd, ¤t->files->close_on_exec);
577 if (!(filp = current->files->fd[fd]))
578 return -EBADF;
579 current->files->fd[fd] = NULL;
580 return (close_fp (filp));
581 }
582
583
584
585
586
587 asmlinkage int sys_vhangup(void)
588 {
589 if (!suser())
590 return -EPERM;
591
592 if (current->tty)
593 tty_vhangup(current->tty);
594 return 0;
595 }