This should hopefully fix the warnings reported.
[linux-2.6/linux-mips.git] / fs / open.c
blob7896b0a2e58890eddb6cc7e5ff7ce13a62dfaa24
1 /*
2 * linux/fs/open.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
7 #include <linux/mm.h>
8 #include <linux/utime.h>
9 #include <linux/file.h>
10 #include <linux/smp_lock.h>
11 #include <linux/quotaops.h>
13 #include <asm/uaccess.h>
15 asmlinkage long sys_statfs(const char * path, struct statfs * buf)
17 struct dentry * dentry;
18 int error;
20 lock_kernel();
21 dentry = namei(path);
22 error = PTR_ERR(dentry);
23 if (!IS_ERR(dentry)) {
24 struct inode * inode = dentry->d_inode;
25 struct super_block * sb = inode->i_sb;
27 error = -ENODEV;
28 if (sb && sb->s_op && sb->s_op->statfs)
29 error = sb->s_op->statfs(sb, buf, sizeof(struct statfs));
31 dput(dentry);
33 unlock_kernel();
34 return error;
37 asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf)
39 struct file * file;
40 struct super_block * sb;
41 int error;
43 error = -EBADF;
44 file = fget(fd);
45 if (!file)
46 goto out;
47 error = -ENODEV;
48 sb = file->f_dentry->d_inode->i_sb;
49 lock_kernel();
50 if (sb && sb->s_op && sb->s_op->statfs)
51 error = sb->s_op->statfs(sb, buf, sizeof(struct statfs));
52 unlock_kernel();
53 fput(file);
54 out:
55 return error;
58 int do_truncate(struct dentry *dentry, loff_t length)
60 struct inode *inode = dentry->d_inode;
61 int error;
62 struct iattr newattrs;
64 /* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */
65 if (length < 0)
66 return -EINVAL;
68 down(&inode->i_sem);
69 newattrs.ia_size = length;
70 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
71 error = notify_change(dentry, &newattrs);
72 up(&inode->i_sem);
73 return error;
76 static inline long do_sys_truncate(const char * path, loff_t length)
78 struct dentry * dentry;
79 struct inode * inode;
80 int error;
82 lock_kernel();
84 error = -EINVAL;
85 if (length < 0) /* sorry, but loff_t says... */
86 goto out;
88 dentry = namei(path);
90 error = PTR_ERR(dentry);
91 if (IS_ERR(dentry))
92 goto out;
93 inode = dentry->d_inode;
95 error = -EACCES;
96 if (S_ISDIR(inode->i_mode))
97 goto dput_and_out;
99 error = permission(inode,MAY_WRITE);
100 if (error)
101 goto dput_and_out;
103 error = -EROFS;
104 if (IS_RDONLY(inode))
105 goto dput_and_out;
107 error = -EPERM;
108 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
109 goto dput_and_out;
111 error = get_write_access(inode);
112 if (error)
113 goto dput_and_out;
115 error = locks_verify_truncate(inode, NULL, length);
116 if (!error) {
117 DQUOT_INIT(inode);
118 error = do_truncate(dentry, length);
120 put_write_access(inode);
121 dput_and_out:
122 dput(dentry);
123 out:
124 unlock_kernel();
125 return error;
128 asmlinkage long sys_truncate(const char * path, unsigned long length)
130 return do_sys_truncate(path, length);
133 static inline long do_sys_ftruncate(unsigned int fd, loff_t length)
135 struct inode * inode;
136 struct dentry *dentry;
137 struct file * file;
138 int error;
140 error = -EINVAL;
141 if (length < 0)
142 goto out;
143 error = -EBADF;
144 file = fget(fd);
145 if (!file)
146 goto out;
147 error = -ENOENT;
148 if (!(dentry = file->f_dentry))
149 goto out_putf;
150 if (!(inode = dentry->d_inode))
151 goto out_putf;
152 error = -EACCES;
153 if (S_ISDIR(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
154 goto out_putf;
155 error = -EPERM;
156 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
157 goto out_putf;
158 error = locks_verify_truncate(inode, file, length);
159 lock_kernel();
160 if (!error)
161 error = do_truncate(dentry, length);
162 unlock_kernel();
163 out_putf:
164 fput(file);
165 out:
166 return error;
169 asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length)
171 return do_sys_ftruncate(fd, length);
174 /* LFS versions of truncate are only needed on 32 bit machines */
175 #if BITS_PER_LONG == 32
176 asmlinkage long sys_truncate64(const char * path, loff_t length)
178 return do_sys_truncate(path, length);
181 asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length)
183 return do_sys_ftruncate(fd, length);
185 #endif
187 #if !(defined(__alpha__) || defined(__ia64__))
190 * sys_utime() can be implemented in user-level using sys_utimes().
191 * Is this for backwards compatibility? If so, why not move it
192 * into the appropriate arch directory (for those architectures that
193 * need it).
196 /* If times==NULL, set access and modification to current time,
197 * must be owner or have write permission.
198 * Else, update from *times, must be owner or super user.
200 asmlinkage long sys_utime(char * filename, struct utimbuf * times)
202 int error;
203 struct dentry * dentry;
204 struct inode * inode;
205 struct iattr newattrs;
207 lock_kernel();
208 dentry = namei(filename);
210 error = PTR_ERR(dentry);
211 if (IS_ERR(dentry))
212 goto out;
213 inode = dentry->d_inode;
215 error = -EROFS;
216 if (IS_RDONLY(inode))
217 goto dput_and_out;
219 /* Don't worry, the checks are done in inode_change_ok() */
220 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
221 if (times) {
222 error = get_user(newattrs.ia_atime, &times->actime);
223 if (!error)
224 error = get_user(newattrs.ia_mtime, &times->modtime);
225 if (error)
226 goto dput_and_out;
228 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
229 } else {
230 if (current->fsuid != inode->i_uid &&
231 (error = permission(inode,MAY_WRITE)) != 0)
232 goto dput_and_out;
234 error = notify_change(dentry, &newattrs);
235 dput_and_out:
236 dput(dentry);
237 out:
238 unlock_kernel();
239 return error;
242 #endif
244 /* If times==NULL, set access and modification to current time,
245 * must be owner or have write permission.
246 * Else, update from *times, must be owner or super user.
248 asmlinkage long sys_utimes(char * filename, struct timeval * utimes)
250 int error;
251 struct dentry * dentry;
252 struct inode * inode;
253 struct iattr newattrs;
255 lock_kernel();
256 dentry = namei(filename);
258 error = PTR_ERR(dentry);
259 if (IS_ERR(dentry))
260 goto out;
261 inode = dentry->d_inode;
263 error = -EROFS;
264 if (IS_RDONLY(inode))
265 goto dput_and_out;
267 /* Don't worry, the checks are done in inode_change_ok() */
268 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
269 if (utimes) {
270 struct timeval times[2];
271 error = -EFAULT;
272 if (copy_from_user(&times, utimes, sizeof(times)))
273 goto dput_and_out;
274 newattrs.ia_atime = times[0].tv_sec;
275 newattrs.ia_mtime = times[1].tv_sec;
276 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
277 } else {
278 if ((error = permission(inode,MAY_WRITE)) != 0)
279 goto dput_and_out;
281 error = notify_change(dentry, &newattrs);
282 dput_and_out:
283 dput(dentry);
284 out:
285 unlock_kernel();
286 return error;
290 * access() needs to use the real uid/gid, not the effective uid/gid.
291 * We do this by temporarily clearing all FS-related capabilities and
292 * switching the fsuid/fsgid around to the real ones.
294 asmlinkage long sys_access(const char * filename, int mode)
296 struct dentry * dentry;
297 int old_fsuid, old_fsgid;
298 kernel_cap_t old_cap;
299 int res;
301 if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
302 return -EINVAL;
304 lock_kernel();
305 old_fsuid = current->fsuid;
306 old_fsgid = current->fsgid;
307 old_cap = current->cap_effective;
309 current->fsuid = current->uid;
310 current->fsgid = current->gid;
312 /* Clear the capabilities if we switch to a non-root user */
313 if (current->uid)
314 cap_clear(current->cap_effective);
315 else
316 current->cap_effective = current->cap_permitted;
318 dentry = namei(filename);
319 res = PTR_ERR(dentry);
320 if (!IS_ERR(dentry)) {
321 res = permission(dentry->d_inode, mode);
322 /* SuS v2 requires we report a read only fs too */
323 if(!res && (mode & S_IWOTH) && IS_RDONLY(dentry->d_inode))
324 res = -EROFS;
325 dput(dentry);
328 current->fsuid = old_fsuid;
329 current->fsgid = old_fsgid;
330 current->cap_effective = old_cap;
332 unlock_kernel();
333 return res;
336 asmlinkage long sys_chdir(const char * filename)
338 int error;
339 struct inode *inode;
340 struct dentry *dentry, *tmp;
342 lock_kernel();
344 dentry = namei(filename);
345 error = PTR_ERR(dentry);
346 if (IS_ERR(dentry))
347 goto out;
349 inode = dentry->d_inode;
351 error = -ENOTDIR;
352 if (!S_ISDIR(inode->i_mode))
353 goto dput_and_out;
355 error = permission(inode,MAY_EXEC);
356 if (error)
357 goto dput_and_out;
359 /* exchange dentries */
360 tmp = current->fs->pwd;
361 current->fs->pwd = dentry;
362 dentry = tmp;
364 dput_and_out:
365 dput(dentry);
366 out:
367 unlock_kernel();
368 return error;
371 asmlinkage long sys_fchdir(unsigned int fd)
373 struct file *file;
374 struct dentry *dentry;
375 struct inode *inode;
376 int error;
378 error = -EBADF;
379 file = fget(fd);
380 if (!file)
381 goto out;
383 error = -ENOENT;
384 if (!(dentry = file->f_dentry))
385 goto out_putf;
386 if (!(inode = dentry->d_inode))
387 goto out_putf;
389 error = -ENOTDIR;
390 if (!S_ISDIR(inode->i_mode))
391 goto out_putf;
393 lock_kernel();
394 error = permission(inode, MAY_EXEC);
395 if (!error) {
396 struct dentry *tmp = current->fs->pwd;
397 current->fs->pwd = dget(dentry);
398 dput(tmp);
400 unlock_kernel();
401 out_putf:
402 fput(file);
403 out:
404 return error;
407 asmlinkage long sys_chroot(const char * filename)
409 int error;
410 struct inode *inode;
411 struct dentry *dentry, *tmp;
413 lock_kernel();
415 dentry = namei(filename);
416 error = PTR_ERR(dentry);
417 if (IS_ERR(dentry))
418 goto out;
420 inode = dentry->d_inode;
422 error = -ENOTDIR;
423 if (!S_ISDIR(inode->i_mode))
424 goto dput_and_out;
426 error = permission(inode,MAY_EXEC);
427 if (error)
428 goto dput_and_out;
430 error = -EPERM;
431 if (!capable(CAP_SYS_CHROOT))
432 goto dput_and_out;
434 /* exchange dentries */
435 tmp = current->fs->root;
436 current->fs->root = dentry;
437 dentry = tmp;
438 error = 0;
440 dput_and_out:
441 dput(dentry);
442 out:
443 unlock_kernel();
444 return error;
447 asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
449 struct inode * inode;
450 struct dentry * dentry;
451 struct file * file;
452 int err = -EBADF;
453 struct iattr newattrs;
455 file = fget(fd);
456 if (!file)
457 goto out;
459 err = -ENOENT;
460 if (!(dentry = file->f_dentry))
461 goto out_putf;
462 if (!(inode = dentry->d_inode))
463 goto out_putf;
465 err = -EROFS;
466 if (IS_RDONLY(inode))
467 goto out_putf;
468 err = -EPERM;
469 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
470 goto out_putf;
471 if (mode == (mode_t) -1)
472 mode = inode->i_mode;
473 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
474 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
475 lock_kernel();
476 err = notify_change(dentry, &newattrs);
477 unlock_kernel();
479 out_putf:
480 fput(file);
481 out:
482 return err;
485 asmlinkage long sys_chmod(const char * filename, mode_t mode)
487 struct dentry * dentry;
488 struct inode * inode;
489 int error;
490 struct iattr newattrs;
492 lock_kernel();
493 dentry = namei(filename);
495 error = PTR_ERR(dentry);
496 if (IS_ERR(dentry))
497 goto out;
498 inode = dentry->d_inode;
500 error = -EROFS;
501 if (IS_RDONLY(inode))
502 goto dput_and_out;
504 error = -EPERM;
505 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
506 goto dput_and_out;
508 if (mode == (mode_t) -1)
509 mode = inode->i_mode;
510 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
511 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
512 error = notify_change(dentry, &newattrs);
514 dput_and_out:
515 dput(dentry);
516 out:
517 unlock_kernel();
518 return error;
521 static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
523 struct inode * inode;
524 int error;
525 struct iattr newattrs;
527 error = -ENOENT;
528 if (!(inode = dentry->d_inode)) {
529 printk("chown_common: NULL inode\n");
530 goto out;
532 error = -EROFS;
533 if (IS_RDONLY(inode))
534 goto out;
535 error = -EPERM;
536 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
537 goto out;
538 if (user == (uid_t) -1)
539 user = inode->i_uid;
540 if (group == (gid_t) -1)
541 group = inode->i_gid;
542 newattrs.ia_mode = inode->i_mode;
543 newattrs.ia_uid = user;
544 newattrs.ia_gid = group;
545 newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
547 * If the user or group of a non-directory has been changed by a
548 * non-root user, remove the setuid bit.
549 * 19981026 David C Niemi <niemi@tux.org>
551 * Changed this to apply to all users, including root, to avoid
552 * some races. This is the behavior we had in 2.0. The check for
553 * non-root was definitely wrong for 2.2 anyway, as it should
554 * have been using CAP_FSETID rather than fsuid -- 19990830 SD.
556 if ((inode->i_mode & S_ISUID) == S_ISUID &&
557 !S_ISDIR(inode->i_mode))
559 newattrs.ia_mode &= ~S_ISUID;
560 newattrs.ia_valid |= ATTR_MODE;
563 * Likewise, if the user or group of a non-directory has been changed
564 * by a non-root user, remove the setgid bit UNLESS there is no group
565 * execute bit (this would be a file marked for mandatory locking).
566 * 19981026 David C Niemi <niemi@tux.org>
568 * Removed the fsuid check (see the comment above) -- 19990830 SD.
570 if (((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))
571 && !S_ISDIR(inode->i_mode))
573 newattrs.ia_mode &= ~S_ISGID;
574 newattrs.ia_valid |= ATTR_MODE;
576 error = DQUOT_TRANSFER(dentry, &newattrs);
577 out:
578 return error;
581 asmlinkage long sys_chown(const char * filename, uid_t user, gid_t group)
583 struct dentry * dentry;
584 int error;
586 lock_kernel();
587 dentry = namei(filename);
589 error = PTR_ERR(dentry);
590 if (!IS_ERR(dentry)) {
591 error = chown_common(dentry, user, group);
592 dput(dentry);
594 unlock_kernel();
595 return error;
598 asmlinkage long sys_lchown(const char * filename, uid_t user, gid_t group)
600 struct dentry * dentry;
601 int error;
603 lock_kernel();
604 dentry = lnamei(filename);
606 error = PTR_ERR(dentry);
607 if (!IS_ERR(dentry)) {
608 error = chown_common(dentry, user, group);
609 dput(dentry);
611 unlock_kernel();
612 return error;
616 asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
618 struct dentry * dentry;
619 struct file * file;
620 int error = -EBADF;
622 file = fget(fd);
623 if (!file)
624 goto out;
625 error = -ENOENT;
626 lock_kernel();
627 if ((dentry = file->f_dentry) != NULL)
628 error = chown_common(dentry, user, group);
629 unlock_kernel();
630 fput(file);
632 out:
633 return error;
637 * Note that while the flag value (low two bits) for sys_open means:
638 * 00 - read-only
639 * 01 - write-only
640 * 10 - read-write
641 * 11 - special
642 * it is changed into
643 * 00 - no permissions needed
644 * 01 - read-permission
645 * 10 - write-permission
646 * 11 - read-write
647 * for the internal routines (ie open_namei()/follow_link() etc). 00 is
648 * used by symlinks.
650 struct file *filp_open(const char * filename, int flags, int mode)
652 struct inode * inode;
653 struct dentry * dentry;
654 struct file * f;
655 int flag,error;
657 error = -ENFILE;
658 f = get_empty_filp();
659 if (!f)
660 goto out;
661 f->f_flags = flag = flags;
662 f->f_mode = (flag+1) & O_ACCMODE;
663 if (f->f_mode)
664 flag++;
665 if (flag & O_TRUNC)
666 flag |= 2;
667 dentry = open_namei(filename,flag,mode);
668 error = PTR_ERR(dentry);
669 if (IS_ERR(dentry))
670 goto cleanup_file;
671 inode = dentry->d_inode;
672 if (f->f_mode & FMODE_WRITE) {
673 error = get_write_access(inode);
674 if (error)
675 goto cleanup_dentry;
678 f->f_dentry = dentry;
679 f->f_pos = 0;
680 f->f_reada = 0;
681 f->f_op = NULL;
682 if (inode->i_op)
683 f->f_op = inode->i_op->default_file_ops;
684 if (inode->i_sb)
685 file_move(f, &inode->i_sb->s_files);
686 if (f->f_op && f->f_op->open) {
687 error = f->f_op->open(inode,f);
688 if (error)
689 goto cleanup_all;
691 f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
693 return f;
695 cleanup_all:
696 if (f->f_mode & FMODE_WRITE)
697 put_write_access(inode);
698 cleanup_dentry:
699 f->f_dentry = NULL;
700 dput(dentry);
701 cleanup_file:
702 put_filp(f);
703 out:
704 return ERR_PTR(error);
708 * Find an empty file descriptor entry, and mark it busy.
710 int get_unused_fd(void)
712 struct files_struct * files = current->files;
713 int fd, error;
715 error = -EMFILE;
716 write_lock(&files->file_lock);
718 repeat:
719 fd = find_next_zero_bit(files->open_fds,
720 current->files->max_fdset,
721 files->next_fd);
724 * N.B. For clone tasks sharing a files structure, this test
725 * will limit the total number of files that can be opened.
727 if (fd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
728 goto out;
730 /* Do we need to expand the fdset array? */
731 if (fd >= current->files->max_fdset) {
732 error = expand_fdset(files, fd);
733 if (!error) {
734 error = -EMFILE;
735 goto repeat;
737 goto out;
741 * Check whether we need to expand the fd array.
743 if (fd >= files->max_fds) {
744 error = expand_fd_array(files, fd);
745 if (!error) {
746 error = -EMFILE;
747 goto repeat;
749 goto out;
752 FD_SET(fd, files->open_fds);
753 FD_CLR(fd, files->close_on_exec);
754 files->next_fd = fd + 1;
755 #if 1
756 /* Sanity check */
757 if (files->fd[fd] != NULL) {
758 printk("get_unused_fd: slot %d not NULL!\n", fd);
759 files->fd[fd] = NULL;
761 #endif
762 error = fd;
764 out:
765 write_unlock(&files->file_lock);
766 return error;
769 inline void put_unused_fd(unsigned int fd)
771 write_lock(&current->files->file_lock);
772 FD_CLR(fd, current->files->open_fds);
773 if (fd < current->files->next_fd)
774 current->files->next_fd = fd;
775 write_unlock(&current->files->file_lock);
778 asmlinkage long sys_open(const char * filename, int flags, int mode)
780 char * tmp;
781 int fd, error;
783 #if BITS_PER_LONG != 32
784 flags |= O_LARGEFILE;
785 #endif
786 tmp = getname(filename);
787 fd = PTR_ERR(tmp);
788 if (!IS_ERR(tmp)) {
789 fd = get_unused_fd();
790 if (fd >= 0) {
791 struct file * f;
792 lock_kernel();
793 f = filp_open(tmp, flags, mode);
794 unlock_kernel();
795 error = PTR_ERR(f);
796 if (IS_ERR(f))
797 goto out_error;
798 fd_install(fd, f);
800 out:
801 putname(tmp);
803 return fd;
805 out_error:
806 put_unused_fd(fd);
807 fd = error;
808 goto out;
811 #ifndef __alpha__
814 * For backward compatibility? Maybe this should be moved
815 * into arch/i386 instead?
817 asmlinkage long sys_creat(const char * pathname, int mode)
819 return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
822 #endif
825 * "id" is the POSIX thread ID. We use the
826 * files pointer for this..
828 int filp_close(struct file *filp, fl_owner_t id)
830 int retval;
831 struct dentry *dentry = filp->f_dentry;
833 if (!file_count(filp)) {
834 printk("VFS: Close: file count is 0\n");
835 return 0;
837 retval = 0;
838 if (filp->f_op && filp->f_op->flush)
839 retval = filp->f_op->flush(filp);
840 if (dentry->d_inode)
841 locks_remove_posix(filp, id);
842 fput(filp);
843 return retval;
847 * Careful here! We test whether the file pointer is NULL before
848 * releasing the fd. This ensures that one clone task can't release
849 * an fd while another clone is opening it.
851 * The "release" argument tells us whether or not to mark the fd as free
852 * or not in the open-files bitmap. dup2 uses this to retain the fd
853 * without races.
855 int do_close(unsigned int fd, int release)
857 int error;
858 struct file * filp;
859 struct files_struct * files = current->files;
861 error = -EBADF;
862 write_lock(&files->file_lock);
863 filp = frip(fd);
864 if (!filp)
865 goto out_unlock;
866 FD_CLR(fd, files->close_on_exec);
867 write_unlock(&files->file_lock);
868 if (release)
869 put_unused_fd(fd);
870 lock_kernel();
871 error = filp_close(filp, files);
872 unlock_kernel();
873 out:
874 return error;
875 out_unlock:
876 write_unlock(&files->file_lock);
877 goto out;
880 asmlinkage long sys_close(unsigned int fd)
882 return do_close(fd, 1);
886 * This routine simulates a hangup on the tty, to arrange that users
887 * are given clean terminals at login time.
889 asmlinkage long sys_vhangup(void)
891 if (capable(CAP_SYS_TTY_CONFIG)) {
892 tty_vhangup(current->tty);
893 return 0;
895 return -EPERM;