Import 2.1.81
[davej-history.git] / fs / open.c
blobe417119a95c0d67c97749443f08d06d763d9b661
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>
24 #include <asm/uaccess.h>
25 #include <asm/bitops.h>
27 asmlinkage int sys_statfs(const char * path, struct statfs * buf)
29 struct dentry * dentry;
30 int error;
32 lock_kernel();
33 dentry = namei(path);
34 error = PTR_ERR(dentry);
35 if (!IS_ERR(dentry)) {
36 struct inode * inode = dentry->d_inode;
38 error = -ENOSYS;
39 if (inode->i_sb->s_op->statfs)
40 error = inode->i_sb->s_op->statfs(inode->i_sb, buf, sizeof(struct statfs));
42 dput(dentry);
44 unlock_kernel();
45 return error;
48 asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf)
50 struct inode * inode;
51 struct dentry * dentry;
52 struct file * file;
53 int error;
55 lock_kernel();
56 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
57 error = -EBADF;
58 else if (!(dentry = file->f_dentry))
59 error = -ENOENT;
60 else if (!(inode = dentry->d_inode))
61 error = -ENOENT;
62 else if (!inode->i_sb)
63 error = -ENODEV;
64 else if (!inode->i_sb->s_op->statfs)
65 error = -ENOSYS;
66 else
67 error = inode->i_sb->s_op->statfs(inode->i_sb, buf, sizeof(struct statfs));
68 unlock_kernel();
69 return error;
72 int do_truncate(struct dentry *dentry, unsigned long length)
74 struct inode *inode = dentry->d_inode;
75 int error;
76 struct iattr newattrs;
78 down(&inode->i_sem);
79 newattrs.ia_size = length;
80 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
81 error = notify_change(dentry, &newattrs);
82 if (!error) {
83 /* truncate virtual mappings of this file */
84 vmtruncate(inode, length);
85 if (inode->i_op && inode->i_op->truncate)
86 inode->i_op->truncate(inode);
88 up(&inode->i_sem);
89 return error;
92 asmlinkage int sys_truncate(const char * path, unsigned long length)
94 struct dentry * dentry;
95 struct inode * inode;
96 int error;
98 lock_kernel();
99 dentry = namei(path);
101 error = PTR_ERR(dentry);
102 if (IS_ERR(dentry))
103 goto out;
104 inode = dentry->d_inode;
106 error = -EACCES;
107 if (S_ISDIR(inode->i_mode))
108 goto dput_and_out;
110 error = permission(inode,MAY_WRITE);
111 if (error)
112 goto dput_and_out;
114 error = -EROFS;
115 if (IS_RDONLY(inode))
116 goto dput_and_out;
118 error = -EPERM;
119 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
120 goto dput_and_out;
122 error = get_write_access(inode);
123 if (error)
124 goto dput_and_out;
126 error = locks_verify_area(FLOCK_VERIFY_WRITE, inode, NULL,
127 length < inode->i_size ? length : inode->i_size,
128 abs(inode->i_size - length));
129 if (!error) {
130 if (inode->i_sb && inode->i_sb->dq_op)
131 inode->i_sb->dq_op->initialize(inode, -1);
132 error = do_truncate(dentry, length);
134 put_write_access(inode);
135 dput_and_out:
136 dput(dentry);
137 out:
138 unlock_kernel();
139 return error;
142 asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length)
144 struct inode * inode;
145 struct dentry *dentry;
146 struct file * file;
147 int error;
149 lock_kernel();
150 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
151 error = -EBADF;
152 else if (!(dentry = file->f_dentry))
153 error = -ENOENT;
154 else if (!(inode = dentry->d_inode))
155 error = -ENOENT;
156 else if (S_ISDIR(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
157 error = -EACCES;
158 else if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
159 error = -EPERM;
160 else {
161 error = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file,
162 length<inode->i_size ? length : inode->i_size,
163 abs(inode->i_size - length));
164 if (!error)
165 error = do_truncate(dentry, length);
167 unlock_kernel();
168 return error;
171 #ifndef __alpha__
174 * sys_utime() can be implemented in user-level using sys_utimes().
175 * Is this for backwards compatibility? If so, why not move it
176 * into the appropriate arch directory (for those architectures that
177 * need it).
180 /* If times==NULL, set access and modification to current time,
181 * must be owner or have write permission.
182 * Else, update from *times, must be owner or super user.
184 asmlinkage int sys_utime(char * filename, struct utimbuf * times)
186 int error;
187 struct dentry * dentry;
188 struct inode * inode;
189 struct iattr newattrs;
191 lock_kernel();
192 dentry = namei(filename);
194 error = PTR_ERR(dentry);
195 if (IS_ERR(dentry))
196 goto out;
197 inode = dentry->d_inode;
199 error = -EROFS;
200 if (IS_RDONLY(inode))
201 goto dput_and_out;
203 /* Don't worry, the checks are done in inode_change_ok() */
204 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
205 if (times) {
206 error = get_user(newattrs.ia_atime, &times->actime);
207 if (!error)
208 error = get_user(newattrs.ia_mtime, &times->modtime);
209 if (error)
210 goto dput_and_out;
212 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
213 } else {
214 if (current->fsuid != inode->i_uid &&
215 (error = permission(inode,MAY_WRITE)) != 0)
216 goto dput_and_out;
218 error = notify_change(dentry, &newattrs);
219 dput_and_out:
220 dput(dentry);
221 out:
222 unlock_kernel();
223 return error;
226 #endif
228 /* If times==NULL, set access and modification to current time,
229 * must be owner or have write permission.
230 * Else, update from *times, must be owner or super user.
232 asmlinkage int sys_utimes(char * filename, struct timeval * utimes)
234 int error;
235 struct dentry * dentry;
236 struct inode * inode;
237 struct iattr newattrs;
239 lock_kernel();
240 dentry = namei(filename);
242 error = PTR_ERR(dentry);
243 if (IS_ERR(dentry))
244 goto out;
245 inode = dentry->d_inode;
247 error = -EROFS;
248 if (IS_RDONLY(inode))
249 goto dput_and_out;
251 /* Don't worry, the checks are done in inode_change_ok() */
252 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
253 if (utimes) {
254 struct timeval times[2];
255 error = -EFAULT;
256 if (copy_from_user(&times, utimes, sizeof(times)))
257 goto dput_and_out;
258 newattrs.ia_atime = times[0].tv_sec;
259 newattrs.ia_mtime = times[1].tv_sec;
260 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
261 } else {
262 if ((error = permission(inode,MAY_WRITE)) != 0)
263 goto dput_and_out;
265 error = notify_change(dentry, &newattrs);
266 dput_and_out:
267 dput(dentry);
268 out:
269 unlock_kernel();
270 return error;
274 * access() needs to use the real uid/gid, not the effective uid/gid.
275 * We do this by temporarily setting fsuid/fsgid to the wanted values
277 asmlinkage int sys_access(const char * filename, int mode)
279 struct dentry * dentry;
280 int old_fsuid, old_fsgid;
281 int res = -EINVAL;
283 lock_kernel();
284 if (mode != (mode & S_IRWXO)) /* where's F_OK, X_OK, W_OK, R_OK? */
285 goto out;
286 old_fsuid = current->fsuid;
287 old_fsgid = current->fsgid;
288 current->fsuid = current->uid;
289 current->fsgid = current->gid;
291 dentry = namei(filename);
292 res = PTR_ERR(dentry);
293 if (!IS_ERR(dentry)) {
294 res = permission(dentry->d_inode, mode);
295 dput(dentry);
298 current->fsuid = old_fsuid;
299 current->fsgid = old_fsgid;
300 out:
301 unlock_kernel();
302 return res;
305 asmlinkage int sys_chdir(const char * filename)
307 int error;
308 struct inode *inode;
309 struct dentry *dentry, *tmp;
311 lock_kernel();
313 dentry = namei(filename);
314 error = PTR_ERR(dentry);
315 if (IS_ERR(dentry))
316 goto out;
318 inode = dentry->d_inode;
320 error = -ENOTDIR;
321 if (!S_ISDIR(inode->i_mode))
322 goto dput_and_out;
324 error = permission(inode,MAY_EXEC);
325 if (error)
326 goto dput_and_out;
328 /* exchange dentries */
329 tmp = current->fs->pwd;
330 current->fs->pwd = dentry;
331 dentry = tmp;
333 dput_and_out:
334 dput(dentry);
335 out:
336 unlock_kernel();
337 return error;
340 asmlinkage int sys_fchdir(unsigned int fd)
342 struct file *file;
343 struct dentry *dentry;
344 struct inode *inode;
345 int error;
347 lock_kernel();
349 error = -EBADF;
350 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
351 goto out;
353 error = -ENOENT;
354 if (!(dentry = file->f_dentry))
355 goto out;
356 if (!(inode = dentry->d_inode))
357 goto out;
359 error = -ENOTDIR;
360 if (!S_ISDIR(inode->i_mode))
361 goto out;
363 error = permission(inode,MAY_EXEC);
364 if (error)
365 goto out;
368 struct dentry *tmp;
370 tmp = current->fs->pwd;
371 current->fs->pwd = dget(dentry);
372 dput(tmp);
374 out:
375 unlock_kernel();
376 return error;
379 asmlinkage int sys_chroot(const char * filename)
381 int error;
382 struct inode *inode;
383 struct dentry *dentry, *tmp;
385 lock_kernel();
387 dentry = namei(filename);
388 error = PTR_ERR(dentry);
389 if (IS_ERR(dentry))
390 goto out;
392 inode = dentry->d_inode;
394 error = -ENOTDIR;
395 if (!S_ISDIR(inode->i_mode))
396 goto dput_and_out;
398 error = permission(inode,MAY_EXEC);
399 if (error)
400 goto dput_and_out;
402 error = -EPERM;
403 if (!fsuser())
404 goto dput_and_out;
406 /* exchange dentries */
407 tmp = current->fs->root;
408 current->fs->root = dentry;
409 dentry = tmp;
410 error = 0;
412 dput_and_out:
413 dput(dentry);
414 out:
415 unlock_kernel();
416 return error;
419 asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
421 struct inode * inode;
422 struct dentry * dentry;
423 struct file * file;
424 struct iattr newattrs;
425 int err = -EBADF;
427 lock_kernel();
428 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
429 goto out;
430 err = -ENOENT;
431 if (!(dentry = file->f_dentry))
432 goto out;
433 if (!(inode = dentry->d_inode))
434 goto out;
435 err = -EROFS;
436 if (IS_RDONLY(inode))
437 goto out;
438 err = -EPERM;
439 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
440 goto out;
441 if (mode == (mode_t) -1)
442 mode = inode->i_mode;
443 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
444 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
445 err = notify_change(dentry, &newattrs);
446 out:
447 unlock_kernel();
448 return err;
451 asmlinkage int sys_chmod(const char * filename, mode_t mode)
453 struct dentry * dentry;
454 struct inode * inode;
455 int error;
456 struct iattr newattrs;
458 lock_kernel();
459 dentry = namei(filename);
461 error = PTR_ERR(dentry);
462 if (IS_ERR(dentry))
463 goto out;
464 inode = dentry->d_inode;
466 error = -EROFS;
467 if (IS_RDONLY(inode))
468 goto dput_and_out;
470 error = -EPERM;
471 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
472 goto dput_and_out;
474 if (mode == (mode_t) -1)
475 mode = inode->i_mode;
476 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
477 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
478 error = notify_change(dentry, &newattrs);
480 dput_and_out:
481 dput(dentry);
482 out:
483 unlock_kernel();
484 return error;
487 static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
489 struct inode * inode;
490 struct iattr newattrs;
491 int error;
493 error = -ENOENT;
494 if (!(inode = dentry->d_inode)) {
495 printk("chown_common: NULL inode\n");
496 goto out;
498 error = -EROFS;
499 if (IS_RDONLY(inode))
500 goto out;
501 error = -EPERM;
502 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
503 goto out;
504 if (user == (uid_t) -1)
505 user = inode->i_uid;
506 if (group == (gid_t) -1)
507 group = inode->i_gid;
508 newattrs.ia_mode = inode->i_mode;
509 newattrs.ia_uid = user;
510 newattrs.ia_gid = group;
511 newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
513 * If the owner has been changed, remove the setuid bit
515 if (inode->i_mode & S_ISUID) {
516 newattrs.ia_mode &= ~S_ISUID;
517 newattrs.ia_valid |= ATTR_MODE;
520 * If the group has been changed, remove the setgid bit
522 * Don't remove the setgid bit if no group execute bit.
523 * This is a file marked for mandatory locking.
525 if (((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) {
526 newattrs.ia_mode &= ~S_ISGID;
527 newattrs.ia_valid |= ATTR_MODE;
529 if (inode->i_sb && inode->i_sb->dq_op) {
530 inode->i_sb->dq_op->initialize(inode, -1);
531 error = -EDQUOT;
532 if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
533 goto out;
534 error = notify_change(dentry, &newattrs);
535 if (error)
536 inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
537 } else
538 error = notify_change(dentry, &newattrs);
539 out:
540 return error;
543 asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
545 struct dentry * dentry;
546 int error;
548 lock_kernel();
549 dentry = namei(filename);
551 error = PTR_ERR(dentry);
552 if (!IS_ERR(dentry)) {
553 error = chown_common(dentry, user, group);
554 dput(dentry);
556 unlock_kernel();
557 return error;
560 asmlinkage int sys_lchown(const char * filename, uid_t user, gid_t group)
562 struct dentry * dentry;
563 int error;
565 lock_kernel();
566 dentry = lnamei(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_fchown(unsigned int fd, uid_t user, gid_t group)
579 struct dentry * dentry;
580 struct file * file;
581 int error = -EBADF;
583 lock_kernel();
584 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
585 goto out;
586 error = -ENOENT;
587 if (!(dentry = file->f_dentry))
588 goto out;
590 error = chown_common(dentry, user, group);
592 out:
593 unlock_kernel();
594 return error;
598 * Note that while the flag value (low two bits) for sys_open means:
599 * 00 - read-only
600 * 01 - write-only
601 * 10 - read-write
602 * 11 - special
603 * it is changed into
604 * 00 - no permissions needed
605 * 01 - read-permission
606 * 10 - write-permission
607 * 11 - read-write
608 * for the internal routines (ie open_namei()/follow_link() etc). 00 is
609 * used by symlinks.
611 static int do_open(const char * filename,int flags,int mode, int fd)
613 struct inode * inode;
614 struct dentry * dentry;
615 struct file * f;
616 int flag,error;
618 f = get_empty_filp();
619 if (!f)
620 return -ENFILE;
621 f->f_flags = flag = flags;
622 f->f_mode = (flag+1) & O_ACCMODE;
623 if (f->f_mode)
624 flag++;
625 if (flag & O_TRUNC)
626 flag |= 2;
627 dentry = open_namei(filename,flag,mode);
628 error = PTR_ERR(dentry);
629 if (IS_ERR(dentry))
630 goto cleanup_file;
631 inode = dentry->d_inode;
632 if (f->f_mode & FMODE_WRITE) {
633 error = get_write_access(inode);
634 if (error)
635 goto cleanup_dentry;
638 f->f_dentry = dentry;
639 f->f_pos = 0;
640 f->f_reada = 0;
641 f->f_op = NULL;
642 if (inode->i_op)
643 f->f_op = inode->i_op->default_file_ops;
644 if (f->f_op && f->f_op->open) {
645 error = f->f_op->open(inode,f);
646 if (error)
647 goto cleanup_all;
649 f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
651 current->files->fd[fd] = f;
652 return 0;
654 cleanup_all:
655 if (f->f_mode & FMODE_WRITE)
656 put_write_access(inode);
657 cleanup_dentry:
658 dput(dentry);
659 cleanup_file:
660 put_filp(f);
661 return error;
665 * Find an empty file descriptor entry, and mark it busy
667 int get_unused_fd(void)
669 int fd;
670 struct files_struct * files = current->files;
672 fd = find_first_zero_bit(&files->open_fds, NR_OPEN);
673 if (fd < current->rlim[RLIMIT_NOFILE].rlim_cur) {
674 FD_SET(fd, &files->open_fds);
675 FD_CLR(fd, &files->close_on_exec);
676 return fd;
678 return -EMFILE;
681 inline void put_unused_fd(int fd)
683 FD_CLR(fd, &current->files->open_fds);
686 asmlinkage int sys_open(const char * filename,int flags,int mode)
688 char * tmp;
689 int fd, error;
691 lock_kernel();
692 error = get_unused_fd();
693 if (error < 0)
694 goto out;
696 fd = error;
697 tmp = getname(filename);
698 error = PTR_ERR(tmp);
699 if (!IS_ERR(tmp)) {
700 error = do_open(tmp,flags,mode,fd);
701 putname(tmp);
702 if (!error) {
703 error = fd;
704 goto out;
707 put_unused_fd(fd);
708 out:
709 unlock_kernel();
710 return error;
713 #ifndef __alpha__
716 * For backward compatibility? Maybe this should be moved
717 * into arch/i386 instead?
719 asmlinkage int sys_creat(const char * pathname, int mode)
721 int ret;
723 lock_kernel();
724 ret = sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
725 unlock_kernel();
726 return ret;
729 #endif
731 int __fput(struct file *filp)
733 int error = 0;
734 struct dentry * dentry = filp->f_dentry;
735 struct inode * inode = dentry->d_inode;
737 if (filp->f_op && filp->f_op->release)
738 error = filp->f_op->release(inode, filp);
739 filp->f_dentry = NULL;
740 if (filp->f_mode & FMODE_WRITE)
741 put_write_access(inode);
742 dput(dentry);
743 return error;
746 int close_fp(struct file *filp)
748 struct dentry *dentry;
749 struct inode *inode;
751 if (filp->f_count == 0) {
752 printk("VFS: Close: file count is 0\n");
753 return 0;
755 dentry = filp->f_dentry;
756 inode = dentry->d_inode;
757 if (inode)
758 locks_remove_locks(current, filp);
759 return fput(filp);
762 asmlinkage int sys_close(unsigned int fd)
764 int error;
765 struct file * filp;
766 struct files_struct * files;
768 lock_kernel();
769 files = current->files;
770 error = -EBADF;
771 if (fd < NR_OPEN && (filp = files->fd[fd]) != NULL) {
772 put_unused_fd(fd);
773 FD_CLR(fd, &files->close_on_exec);
774 files->fd[fd] = NULL;
775 error = close_fp(filp);
777 unlock_kernel();
778 return error;
782 * This routine simulates a hangup on the tty, to arrange that users
783 * are given clean terminals at login time.
785 asmlinkage int sys_vhangup(void)
787 int ret = -EPERM;
789 lock_kernel();
790 if (!suser())
791 goto out;
792 /* If there is a controlling tty, hang it up */
793 if (current->tty)
794 tty_vhangup(current->tty);
795 ret = 0;
796 out:
797 unlock_kernel();
798 return ret;