Import 2.1.116pre1
[davej-history.git] / fs / open.c
blob0bade427b0842e39325d87a65309c3addbd23851
1 /*
2 * linux/fs/open.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
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 #include <linux/file.h>
21 #include <linux/smp.h>
22 #include <linux/smp_lock.h>
23 #include <linux/quotaops.h>
25 #include <asm/uaccess.h>
26 #include <asm/bitops.h>
28 asmlinkage int sys_statfs(const char * path, struct statfs * buf)
30 struct dentry * dentry;
31 int error;
33 lock_kernel();
34 dentry = namei(path);
35 error = PTR_ERR(dentry);
36 if (!IS_ERR(dentry)) {
37 struct inode * inode = dentry->d_inode;
39 error = -ENOSYS;
40 if (inode->i_sb->s_op->statfs)
41 error = inode->i_sb->s_op->statfs(inode->i_sb, buf, sizeof(struct statfs));
43 dput(dentry);
45 unlock_kernel();
46 return error;
49 asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf)
51 struct file * file;
52 struct inode * inode;
53 struct dentry * dentry;
54 struct super_block * sb;
55 int error;
57 lock_kernel();
58 error = -EBADF;
59 file = fget(fd);
60 if (!file)
61 goto out;
62 error = -ENOENT;
63 if (!(dentry = file->f_dentry))
64 goto out_putf;
65 if (!(inode = dentry->d_inode))
66 goto out_putf;
67 error = -ENODEV;
68 if (!(sb = inode->i_sb))
69 goto out_putf;
70 error = -ENOSYS;
71 if (sb->s_op->statfs)
72 error = sb->s_op->statfs(sb, buf, sizeof(struct statfs));
73 out_putf:
74 fput(file);
75 out:
76 unlock_kernel();
77 return error;
80 int do_truncate(struct dentry *dentry, unsigned long length)
82 struct inode *inode = dentry->d_inode;
83 int error;
84 struct iattr newattrs;
86 down(&inode->i_sem);
87 newattrs.ia_size = length;
88 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
89 error = notify_change(dentry, &newattrs);
90 if (!error) {
91 /* truncate virtual mappings of this file */
92 vmtruncate(inode, length);
93 if (inode->i_op && inode->i_op->truncate)
94 inode->i_op->truncate(inode);
96 up(&inode->i_sem);
97 return error;
100 asmlinkage int sys_truncate(const char * path, unsigned long length)
102 struct dentry * dentry;
103 struct inode * inode;
104 int error;
106 lock_kernel();
107 dentry = namei(path);
109 error = PTR_ERR(dentry);
110 if (IS_ERR(dentry))
111 goto out;
112 inode = dentry->d_inode;
114 error = -EACCES;
115 if (S_ISDIR(inode->i_mode))
116 goto dput_and_out;
118 error = permission(inode,MAY_WRITE);
119 if (error)
120 goto dput_and_out;
122 error = -EROFS;
123 if (IS_RDONLY(inode))
124 goto dput_and_out;
126 error = -EPERM;
127 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
128 goto dput_and_out;
130 error = get_write_access(inode);
131 if (error)
132 goto dput_and_out;
134 error = locks_verify_area(FLOCK_VERIFY_WRITE, inode, NULL,
135 length < inode->i_size ? length : inode->i_size,
136 abs(inode->i_size - length));
137 if (!error) {
138 DQUOT_INIT(inode);
139 error = do_truncate(dentry, length);
141 put_write_access(inode);
142 dput_and_out:
143 dput(dentry);
144 out:
145 unlock_kernel();
146 return error;
149 asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length)
151 struct inode * inode;
152 struct dentry *dentry;
153 struct file * file;
154 int error;
156 lock_kernel();
157 error = -EBADF;
158 file = fget(fd);
159 if (!file)
160 goto out;
161 error = -ENOENT;
162 if (!(dentry = file->f_dentry))
163 goto out_putf;
164 if (!(inode = dentry->d_inode))
165 goto out_putf;
166 error = -EACCES;
167 if (S_ISDIR(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
168 goto out_putf;
169 error = -EPERM;
170 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
171 goto out_putf;
172 error = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file,
173 length<inode->i_size ? length : inode->i_size,
174 abs(inode->i_size - length));
175 if (!error)
176 error = do_truncate(dentry, length);
177 out_putf:
178 fput(file);
179 out:
180 unlock_kernel();
181 return error;
184 #ifndef __alpha__
187 * sys_utime() can be implemented in user-level using sys_utimes().
188 * Is this for backwards compatibility? If so, why not move it
189 * into the appropriate arch directory (for those architectures that
190 * need it).
193 /* If times==NULL, set access and modification to current time,
194 * must be owner or have write permission.
195 * Else, update from *times, must be owner or super user.
197 asmlinkage int sys_utime(char * filename, struct utimbuf * times)
199 int error;
200 struct dentry * dentry;
201 struct inode * inode;
202 struct iattr newattrs;
204 lock_kernel();
205 dentry = namei(filename);
207 error = PTR_ERR(dentry);
208 if (IS_ERR(dentry))
209 goto out;
210 inode = dentry->d_inode;
212 error = -EROFS;
213 if (IS_RDONLY(inode))
214 goto dput_and_out;
216 /* Don't worry, the checks are done in inode_change_ok() */
217 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
218 if (times) {
219 error = get_user(newattrs.ia_atime, &times->actime);
220 if (!error)
221 error = get_user(newattrs.ia_mtime, &times->modtime);
222 if (error)
223 goto dput_and_out;
225 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
226 } else {
227 if (current->fsuid != inode->i_uid &&
228 (error = permission(inode,MAY_WRITE)) != 0)
229 goto dput_and_out;
231 error = notify_change(dentry, &newattrs);
232 dput_and_out:
233 dput(dentry);
234 out:
235 unlock_kernel();
236 return error;
239 #endif
241 /* If times==NULL, set access and modification to current time,
242 * must be owner or have write permission.
243 * Else, update from *times, must be owner or super user.
245 asmlinkage int sys_utimes(char * filename, struct timeval * utimes)
247 int error;
248 struct dentry * dentry;
249 struct inode * inode;
250 struct iattr newattrs;
252 lock_kernel();
253 dentry = namei(filename);
255 error = PTR_ERR(dentry);
256 if (IS_ERR(dentry))
257 goto out;
258 inode = dentry->d_inode;
260 error = -EROFS;
261 if (IS_RDONLY(inode))
262 goto dput_and_out;
264 /* Don't worry, the checks are done in inode_change_ok() */
265 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
266 if (utimes) {
267 struct timeval times[2];
268 error = -EFAULT;
269 if (copy_from_user(&times, utimes, sizeof(times)))
270 goto dput_and_out;
271 newattrs.ia_atime = times[0].tv_sec;
272 newattrs.ia_mtime = times[1].tv_sec;
273 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
274 } else {
275 if ((error = permission(inode,MAY_WRITE)) != 0)
276 goto dput_and_out;
278 error = notify_change(dentry, &newattrs);
279 dput_and_out:
280 dput(dentry);
281 out:
282 unlock_kernel();
283 return error;
287 * access() needs to use the real uid/gid, not the effective uid/gid.
288 * We do this by temporarily clearing all FS-related capabilities and
289 * switching the fsuid/fsgid around to the real ones.
291 asmlinkage int sys_access(const char * filename, int mode)
293 struct dentry * dentry;
294 int old_fsuid, old_fsgid;
295 kernel_cap_t old_cap;
296 int res = -EINVAL;
298 lock_kernel();
299 if (mode != (mode & S_IRWXO)) /* where's F_OK, X_OK, W_OK, R_OK? */
300 goto out;
301 old_fsuid = current->fsuid;
302 old_fsgid = current->fsgid;
303 old_cap = current->cap_effective;
305 current->fsuid = current->uid;
306 current->fsgid = current->gid;
308 /* Clear the capabilities if we switch to a non-root user */
309 if (current->uid)
310 cap_clear(current->cap_effective);
312 dentry = namei(filename);
313 res = PTR_ERR(dentry);
314 if (!IS_ERR(dentry)) {
315 res = permission(dentry->d_inode, mode);
316 dput(dentry);
319 current->fsuid = old_fsuid;
320 current->fsgid = old_fsgid;
321 current->cap_effective = old_cap;
322 out:
323 unlock_kernel();
324 return res;
327 asmlinkage int sys_chdir(const char * filename)
329 int error;
330 struct inode *inode;
331 struct dentry *dentry, *tmp;
333 lock_kernel();
335 dentry = namei(filename);
336 error = PTR_ERR(dentry);
337 if (IS_ERR(dentry))
338 goto out;
340 inode = dentry->d_inode;
342 error = -ENOTDIR;
343 if (!S_ISDIR(inode->i_mode))
344 goto dput_and_out;
346 error = permission(inode,MAY_EXEC);
347 if (error)
348 goto dput_and_out;
350 /* exchange dentries */
351 tmp = current->fs->pwd;
352 current->fs->pwd = dentry;
353 dentry = tmp;
355 dput_and_out:
356 dput(dentry);
357 out:
358 unlock_kernel();
359 return error;
362 asmlinkage int sys_fchdir(unsigned int fd)
364 struct file *file;
365 struct dentry *dentry;
366 struct inode *inode;
367 int error;
369 lock_kernel();
371 error = -EBADF;
372 file = fget(fd);
373 if (!file)
374 goto out;
376 error = -ENOENT;
377 if (!(dentry = file->f_dentry))
378 goto out_putf;
379 if (!(inode = dentry->d_inode))
380 goto out_putf;
382 error = -ENOTDIR;
383 if (!S_ISDIR(inode->i_mode))
384 goto out_putf;
386 error = permission(inode, MAY_EXEC);
387 if (!error) {
388 struct dentry *tmp = current->fs->pwd;
389 current->fs->pwd = dget(dentry);
390 dput(tmp);
392 out_putf:
393 fput(file);
394 out:
395 unlock_kernel();
396 return error;
399 asmlinkage int sys_chroot(const char * filename)
401 int error;
402 struct inode *inode;
403 struct dentry *dentry, *tmp;
405 lock_kernel();
407 dentry = namei(filename);
408 error = PTR_ERR(dentry);
409 if (IS_ERR(dentry))
410 goto out;
412 inode = dentry->d_inode;
414 error = -ENOTDIR;
415 if (!S_ISDIR(inode->i_mode))
416 goto dput_and_out;
418 error = permission(inode,MAY_EXEC);
419 if (error)
420 goto dput_and_out;
422 error = -EPERM;
423 if (!capable(CAP_SYS_CHROOT))
424 goto dput_and_out;
426 /* exchange dentries */
427 tmp = current->fs->root;
428 current->fs->root = dentry;
429 dentry = tmp;
430 error = 0;
432 dput_and_out:
433 dput(dentry);
434 out:
435 unlock_kernel();
436 return error;
439 asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
441 struct inode * inode;
442 struct dentry * dentry;
443 struct file * file;
444 int err = -EBADF;
445 struct iattr newattrs;
447 lock_kernel();
448 file = fget(fd);
449 if (!file)
450 goto out;
452 err = -ENOENT;
453 if (!(dentry = file->f_dentry))
454 goto out_putf;
455 if (!(inode = dentry->d_inode))
456 goto out_putf;
458 err = -EROFS;
459 if (IS_RDONLY(inode))
460 goto out_putf;
461 err = -EPERM;
462 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
463 goto out_putf;
464 if (mode == (mode_t) -1)
465 mode = inode->i_mode;
466 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
467 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
468 err = notify_change(dentry, &newattrs);
470 out_putf:
471 fput(file);
472 out:
473 unlock_kernel();
474 return err;
477 asmlinkage int sys_chmod(const char * filename, mode_t mode)
479 struct dentry * dentry;
480 struct inode * inode;
481 int error;
482 struct iattr newattrs;
484 lock_kernel();
485 dentry = namei(filename);
487 error = PTR_ERR(dentry);
488 if (IS_ERR(dentry))
489 goto out;
490 inode = dentry->d_inode;
492 error = -EROFS;
493 if (IS_RDONLY(inode))
494 goto dput_and_out;
496 error = -EPERM;
497 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
498 goto dput_and_out;
500 if (mode == (mode_t) -1)
501 mode = inode->i_mode;
502 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
503 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
504 error = notify_change(dentry, &newattrs);
506 dput_and_out:
507 dput(dentry);
508 out:
509 unlock_kernel();
510 return error;
513 static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
515 struct inode * inode;
516 int error;
517 struct iattr newattrs;
519 error = -ENOENT;
520 if (!(inode = dentry->d_inode)) {
521 printk("chown_common: NULL inode\n");
522 goto out;
524 error = -EROFS;
525 if (IS_RDONLY(inode))
526 goto out;
527 error = -EPERM;
528 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
529 goto out;
530 if (user == (uid_t) -1)
531 user = inode->i_uid;
532 if (group == (gid_t) -1)
533 group = inode->i_gid;
534 newattrs.ia_mode = inode->i_mode;
535 newattrs.ia_uid = user;
536 newattrs.ia_gid = group;
537 newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
539 * If the owner has been changed, remove the setuid bit
541 if (inode->i_mode & S_ISUID) {
542 newattrs.ia_mode &= ~S_ISUID;
543 newattrs.ia_valid |= ATTR_MODE;
546 * If the group has been changed, remove the setgid bit
548 * Don't remove the setgid bit if no group execute bit.
549 * This is a file marked for mandatory locking.
551 if (((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) {
552 newattrs.ia_mode &= ~S_ISGID;
553 newattrs.ia_valid |= ATTR_MODE;
555 error = DQUOT_TRANSFER(dentry, &newattrs);
556 out:
557 return error;
560 asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
562 struct dentry * dentry;
563 int error;
565 lock_kernel();
566 dentry = namei(filename);
568 error = PTR_ERR(dentry);
569 if (!IS_ERR(dentry)) {
570 error = chown_common(dentry, user, group);
571 dput(dentry);
573 unlock_kernel();
574 return error;
577 asmlinkage int sys_lchown(const char * filename, uid_t user, gid_t group)
579 struct dentry * dentry;
580 int error;
582 lock_kernel();
583 dentry = lnamei(filename);
585 error = PTR_ERR(dentry);
586 if (!IS_ERR(dentry)) {
587 error = chown_common(dentry, user, group);
588 dput(dentry);
590 unlock_kernel();
591 return error;
595 asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
597 struct dentry * dentry;
598 struct file * file;
599 int error = -EBADF;
601 lock_kernel();
602 file = fget(fd);
603 if (!file)
604 goto out;
605 error = -ENOENT;
606 if ((dentry = file->f_dentry) != NULL)
607 error = chown_common(dentry, user, group);
608 fput(file);
610 out:
611 unlock_kernel();
612 return error;
616 * Note that while the flag value (low two bits) for sys_open means:
617 * 00 - read-only
618 * 01 - write-only
619 * 10 - read-write
620 * 11 - special
621 * it is changed into
622 * 00 - no permissions needed
623 * 01 - read-permission
624 * 10 - write-permission
625 * 11 - read-write
626 * for the internal routines (ie open_namei()/follow_link() etc). 00 is
627 * used by symlinks.
629 static int do_open(const char * filename, int flags, int mode, int fd)
631 struct inode * inode;
632 struct dentry * dentry;
633 struct file * f;
634 int flag,error;
636 error = -ENFILE;
637 f = get_empty_filp();
638 if (!f)
639 goto out;
640 f->f_flags = flag = flags;
641 f->f_mode = (flag+1) & O_ACCMODE;
642 if (f->f_mode)
643 flag++;
644 if (flag & O_TRUNC)
645 flag |= 2;
646 dentry = open_namei(filename,flag,mode);
647 error = PTR_ERR(dentry);
648 if (IS_ERR(dentry))
649 goto cleanup_file;
650 inode = dentry->d_inode;
651 if (f->f_mode & FMODE_WRITE) {
652 error = get_write_access(inode);
653 if (error)
654 goto cleanup_dentry;
657 f->f_dentry = dentry;
658 f->f_pos = 0;
659 f->f_reada = 0;
660 f->f_op = NULL;
661 if (inode->i_op)
662 f->f_op = inode->i_op->default_file_ops;
663 if (f->f_op && f->f_op->open) {
664 error = f->f_op->open(inode,f);
665 if (error)
666 goto cleanup_all;
668 f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
670 fd_install(fd, f);
671 return 0;
673 cleanup_all:
674 if (f->f_mode & FMODE_WRITE)
675 put_write_access(inode);
676 cleanup_dentry:
677 f->f_dentry = NULL;
678 dput(dentry);
679 cleanup_file:
680 put_filp(f);
681 out:
682 return error;
686 * Find an empty file descriptor entry, and mark it busy.
688 int get_unused_fd(void)
690 struct files_struct * files = current->files;
691 int fd, error;
693 error = -EMFILE;
694 fd = find_first_zero_bit(&files->open_fds, NR_OPEN);
696 * N.B. For clone tasks sharing a files structure, this test
697 * will limit the total number of files that can be opened.
699 if (fd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
700 goto out;
702 /* Check here for fd > files->max_fds to do dynamic expansion */
704 FD_SET(fd, &files->open_fds);
705 FD_CLR(fd, &files->close_on_exec);
706 #if 1
707 /* Sanity check */
708 if (files->fd[fd] != NULL) {
709 printk("get_unused_fd: slot %d not NULL!\n", fd);
710 files->fd[fd] = NULL;
712 #endif
713 error = fd;
715 out:
716 return error;
719 inline void put_unused_fd(unsigned int fd)
721 FD_CLR(fd, &current->files->open_fds);
724 asmlinkage int sys_open(const char * filename, int flags, int mode)
726 char * tmp;
727 int fd, error;
729 lock_kernel();
730 fd = get_unused_fd();
731 if (fd < 0)
732 goto out;
734 tmp = getname(filename);
735 error = PTR_ERR(tmp);
736 if (IS_ERR(tmp))
737 goto out_fail;
738 error = do_open(tmp, flags, mode, fd);
739 putname(tmp);
740 if (error)
741 goto out_fail;
742 out:
743 unlock_kernel();
744 return fd;
746 out_fail:
747 put_unused_fd(fd);
748 fd = error;
749 goto out;
752 #ifndef __alpha__
755 * For backward compatibility? Maybe this should be moved
756 * into arch/i386 instead?
758 asmlinkage int sys_creat(const char * pathname, int mode)
760 int ret;
762 lock_kernel();
763 ret = sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
764 unlock_kernel();
765 return ret;
768 #endif
771 * Called when retiring the last use of a file pointer.
773 int __fput(struct file *filp)
775 struct dentry * dentry = filp->f_dentry;
776 struct inode * inode = dentry->d_inode;
777 int error = 0;
779 if (filp->f_op && filp->f_op->release)
780 error = filp->f_op->release(inode, filp);
781 filp->f_dentry = NULL;
782 if (filp->f_mode & FMODE_WRITE)
783 put_write_access(inode);
784 dput(dentry);
785 return error;
789 * "id" is the POSIX thread ID. We use the
790 * files pointer for this..
792 int close_fp(struct file *filp, fl_owner_t id)
794 struct dentry *dentry = filp->f_dentry;
796 if (filp->f_count == 0) {
797 printk("VFS: Close: file count is 0\n");
798 return 0;
800 if (dentry->d_inode)
801 locks_remove_posix(filp, id);
802 return fput(filp);
806 * Careful here! We test whether the file pointer is NULL before
807 * releasing the fd. This ensures that one clone task can't release
808 * an fd while another clone is opening it.
810 asmlinkage int sys_close(unsigned int fd)
812 int error;
813 struct file * filp;
815 lock_kernel();
816 error = -EBADF;
817 filp = fcheck(fd);
818 if (filp) {
819 struct files_struct * files = current->files;
820 files->fd[fd] = NULL;
821 put_unused_fd(fd);
822 FD_CLR(fd, &files->close_on_exec);
823 error = close_fp(filp, files);
825 unlock_kernel();
826 return error;
830 * This routine simulates a hangup on the tty, to arrange that users
831 * are given clean terminals at login time.
833 asmlinkage int sys_vhangup(void)
835 int ret = -EPERM;
837 lock_kernel();
838 if (!capable(CAP_SYS_TTY_CONFIG))
839 goto out;
840 /* If there is a controlling tty, hang it up */
841 if (current->tty)
842 tty_vhangup(current->tty);
843 ret = 0;
844 out:
845 unlock_kernel();
846 return ret;