4 * Copyright (C) 1991, 1992 Linus Torvalds
7 #include <linux/string.h>
9 #include <linux/utime.h>
10 #include <linux/file.h>
11 #include <linux/smp_lock.h>
12 #include <linux/quotaops.h>
13 #include <linux/module.h>
15 #include <asm/uaccess.h>
17 int vfs_statfs(struct super_block
*sb
, struct statfs
*buf
)
23 if (sb
->s_op
&& sb
->s_op
->statfs
) {
24 memset(buf
, 0, sizeof(struct statfs
));
26 retval
= sb
->s_op
->statfs(sb
, buf
);
34 asmlinkage
long sys_statfs(const char * path
, struct statfs
* buf
)
39 error
= user_path_walk(path
, &nd
);
42 error
= vfs_statfs(nd
.dentry
->d_inode
->i_sb
, &tmp
);
43 if (!error
&& copy_to_user(buf
, &tmp
, sizeof(struct statfs
)))
50 asmlinkage
long sys_fstatfs(unsigned int fd
, struct statfs
* buf
)
60 error
= vfs_statfs(file
->f_dentry
->d_inode
->i_sb
, &tmp
);
61 if (!error
&& copy_to_user(buf
, &tmp
, sizeof(struct statfs
)))
68 int do_truncate(struct dentry
*dentry
, loff_t length
)
70 struct inode
*inode
= dentry
->d_inode
;
72 struct iattr newattrs
;
74 /* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */
79 newattrs
.ia_size
= length
;
80 newattrs
.ia_valid
= ATTR_SIZE
| ATTR_CTIME
;
81 error
= notify_change(dentry
, &newattrs
);
86 static inline long do_sys_truncate(const char * path
, loff_t length
)
93 if (length
< 0) /* sorry, but loff_t says... */
96 error
= user_path_walk(path
, &nd
);
99 inode
= nd
.dentry
->d_inode
;
102 if (S_ISDIR(inode
->i_mode
))
105 error
= permission(inode
,MAY_WRITE
);
110 if (IS_RDONLY(inode
))
114 if (IS_IMMUTABLE(inode
) || IS_APPEND(inode
))
118 error
= get_write_access(inode
);
122 error
= locks_verify_truncate(inode
, NULL
, length
);
125 error
= do_truncate(nd
.dentry
, length
);
127 put_write_access(inode
);
136 asmlinkage
long sys_truncate(const char * path
, unsigned long length
)
138 return do_sys_truncate(path
, length
);
141 static inline long do_sys_ftruncate(unsigned int fd
, loff_t length
)
143 struct inode
* inode
;
144 struct dentry
*dentry
;
155 dentry
= file
->f_dentry
;
156 inode
= dentry
->d_inode
;
158 if (S_ISDIR(inode
->i_mode
) || !(file
->f_mode
& FMODE_WRITE
))
161 if (IS_IMMUTABLE(inode
) || IS_APPEND(inode
))
165 error
= locks_verify_truncate(inode
, file
, length
);
167 error
= do_truncate(dentry
, length
);
175 asmlinkage
long sys_ftruncate(unsigned int fd
, unsigned long length
)
177 return do_sys_ftruncate(fd
, length
);
180 /* LFS versions of truncate are only needed on 32 bit machines */
181 #if BITS_PER_LONG == 32
182 asmlinkage
long sys_truncate64(const char * path
, loff_t length
)
184 return do_sys_truncate(path
, length
);
187 asmlinkage
long sys_ftruncate64(unsigned int fd
, loff_t length
)
189 return do_sys_ftruncate(fd
, length
);
193 #if !(defined(__alpha__) || defined(__ia64__))
196 * sys_utime() can be implemented in user-level using sys_utimes().
197 * Is this for backwards compatibility? If so, why not move it
198 * into the appropriate arch directory (for those architectures that
202 /* If times==NULL, set access and modification to current time,
203 * must be owner or have write permission.
204 * Else, update from *times, must be owner or super user.
206 asmlinkage
long sys_utime(char * filename
, struct utimbuf
* times
)
210 struct inode
* inode
;
211 struct iattr newattrs
;
213 error
= user_path_walk(filename
, &nd
);
216 inode
= nd
.dentry
->d_inode
;
219 if (IS_RDONLY(inode
))
222 /* Don't worry, the checks are done in inode_change_ok() */
223 newattrs
.ia_valid
= ATTR_CTIME
| ATTR_MTIME
| ATTR_ATIME
;
225 error
= get_user(newattrs
.ia_atime
, ×
->actime
);
227 error
= get_user(newattrs
.ia_mtime
, ×
->modtime
);
231 newattrs
.ia_valid
|= ATTR_ATIME_SET
| ATTR_MTIME_SET
;
233 if (current
->fsuid
!= inode
->i_uid
&&
234 (error
= permission(inode
,MAY_WRITE
)) != 0)
237 error
= notify_change(nd
.dentry
, &newattrs
);
246 /* If times==NULL, set access and modification to current time,
247 * must be owner or have write permission.
248 * Else, update from *times, must be owner or super user.
250 asmlinkage
long sys_utimes(char * filename
, struct timeval
* utimes
)
254 struct inode
* inode
;
255 struct iattr newattrs
;
257 error
= user_path_walk(filename
, &nd
);
261 inode
= nd
.dentry
->d_inode
;
264 if (IS_RDONLY(inode
))
267 /* Don't worry, the checks are done in inode_change_ok() */
268 newattrs
.ia_valid
= ATTR_CTIME
| ATTR_MTIME
| ATTR_ATIME
;
270 struct timeval times
[2];
272 if (copy_from_user(×
, utimes
, sizeof(times
)))
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
;
278 if ((error
= permission(inode
,MAY_WRITE
)) != 0)
281 error
= notify_change(nd
.dentry
, &newattrs
);
289 * access() needs to use the real uid/gid, not the effective uid/gid.
290 * We do this by temporarily clearing all FS-related capabilities and
291 * switching the fsuid/fsgid around to the real ones.
293 asmlinkage
long sys_access(const char * filename
, int mode
)
296 int old_fsuid
, old_fsgid
;
297 kernel_cap_t old_cap
;
300 if (mode
& ~S_IRWXO
) /* where's F_OK, X_OK, W_OK, R_OK? */
303 old_fsuid
= current
->fsuid
;
304 old_fsgid
= current
->fsgid
;
305 old_cap
= current
->cap_effective
;
307 current
->fsuid
= current
->uid
;
308 current
->fsgid
= current
->gid
;
310 /* Clear the capabilities if we switch to a non-root user */
312 cap_clear(current
->cap_effective
);
314 current
->cap_effective
= current
->cap_permitted
;
316 res
= user_path_walk(filename
, &nd
);
318 res
= permission(nd
.dentry
->d_inode
, mode
);
319 /* SuS v2 requires we report a read only fs too */
320 if(!res
&& (mode
& S_IWOTH
) && IS_RDONLY(nd
.dentry
->d_inode
))
325 current
->fsuid
= old_fsuid
;
326 current
->fsgid
= old_fsgid
;
327 current
->cap_effective
= old_cap
;
332 asmlinkage
long sys_chdir(const char * filename
)
340 name
= getname(filename
);
341 error
= PTR_ERR(name
);
346 if (path_init(name
,LOOKUP_POSITIVE
|LOOKUP_FOLLOW
|LOOKUP_DIRECTORY
,&nd
))
347 error
= path_walk(name
, &nd
);
352 error
= permission(nd
.dentry
->d_inode
,MAY_EXEC
);
356 set_fs_pwd(current
->fs
, nd
.mnt
, nd
.dentry
);
365 asmlinkage
long sys_fchdir(unsigned int fd
)
368 struct dentry
*dentry
;
370 struct vfsmount
*mnt
;
378 dentry
= file
->f_dentry
;
379 mnt
= file
->f_vfsmnt
;
380 inode
= dentry
->d_inode
;
383 if (!S_ISDIR(inode
->i_mode
))
387 error
= permission(inode
, MAY_EXEC
);
389 set_fs_pwd(current
->fs
, mnt
, dentry
);
397 asmlinkage
long sys_chroot(const char * filename
)
405 name
= getname(filename
);
406 error
= PTR_ERR(name
);
410 path_init(name
, LOOKUP_POSITIVE
| LOOKUP_FOLLOW
|
411 LOOKUP_DIRECTORY
| LOOKUP_NOALT
, &nd
);
412 error
= path_walk(name
, &nd
);
417 error
= permission(nd
.dentry
->d_inode
,MAY_EXEC
);
422 if (!capable(CAP_SYS_CHROOT
))
425 set_fs_root(current
->fs
, nd
.mnt
, nd
.dentry
);
435 asmlinkage
long sys_fchmod(unsigned int fd
, mode_t mode
)
437 struct inode
* inode
;
438 struct dentry
* dentry
;
441 struct iattr newattrs
;
447 dentry
= file
->f_dentry
;
448 inode
= dentry
->d_inode
;
451 if (IS_RDONLY(inode
))
454 if (IS_IMMUTABLE(inode
) || IS_APPEND(inode
))
456 if (mode
== (mode_t
) -1)
457 mode
= inode
->i_mode
;
458 newattrs
.ia_mode
= (mode
& S_IALLUGO
) | (inode
->i_mode
& ~S_IALLUGO
);
459 newattrs
.ia_valid
= ATTR_MODE
| ATTR_CTIME
;
461 err
= notify_change(dentry
, &newattrs
);
470 asmlinkage
long sys_chmod(const char * filename
, mode_t mode
)
473 struct inode
* inode
;
475 struct iattr newattrs
;
477 error
= user_path_walk(filename
, &nd
);
480 inode
= nd
.dentry
->d_inode
;
483 if (IS_RDONLY(inode
))
487 if (IS_IMMUTABLE(inode
) || IS_APPEND(inode
))
490 if (mode
== (mode_t
) -1)
491 mode
= inode
->i_mode
;
492 newattrs
.ia_mode
= (mode
& S_IALLUGO
) | (inode
->i_mode
& ~S_IALLUGO
);
493 newattrs
.ia_valid
= ATTR_MODE
| ATTR_CTIME
;
494 error
= notify_change(nd
.dentry
, &newattrs
);
502 static int chown_common(struct dentry
* dentry
, uid_t user
, gid_t group
)
504 struct inode
* inode
;
506 struct iattr newattrs
;
509 if (!(inode
= dentry
->d_inode
)) {
510 printk("chown_common: NULL inode\n");
514 if (IS_RDONLY(inode
))
517 if (IS_IMMUTABLE(inode
) || IS_APPEND(inode
))
519 if (user
== (uid_t
) -1)
521 if (group
== (gid_t
) -1)
522 group
= inode
->i_gid
;
523 newattrs
.ia_mode
= inode
->i_mode
;
524 newattrs
.ia_uid
= user
;
525 newattrs
.ia_gid
= group
;
526 newattrs
.ia_valid
= ATTR_UID
| ATTR_GID
| ATTR_CTIME
;
528 * If the user or group of a non-directory has been changed by a
529 * non-root user, remove the setuid bit.
530 * 19981026 David C Niemi <niemi@tux.org>
532 * Changed this to apply to all users, including root, to avoid
533 * some races. This is the behavior we had in 2.0. The check for
534 * non-root was definitely wrong for 2.2 anyway, as it should
535 * have been using CAP_FSETID rather than fsuid -- 19990830 SD.
537 if ((inode
->i_mode
& S_ISUID
) == S_ISUID
&&
538 !S_ISDIR(inode
->i_mode
))
540 newattrs
.ia_mode
&= ~S_ISUID
;
541 newattrs
.ia_valid
|= ATTR_MODE
;
544 * Likewise, if the user or group of a non-directory has been changed
545 * by a non-root user, remove the setgid bit UNLESS there is no group
546 * execute bit (this would be a file marked for mandatory locking).
547 * 19981026 David C Niemi <niemi@tux.org>
549 * Removed the fsuid check (see the comment above) -- 19990830 SD.
551 if (((inode
->i_mode
& (S_ISGID
| S_IXGRP
)) == (S_ISGID
| S_IXGRP
))
552 && !S_ISDIR(inode
->i_mode
))
554 newattrs
.ia_mode
&= ~S_ISGID
;
555 newattrs
.ia_valid
|= ATTR_MODE
;
557 error
= DQUOT_TRANSFER(dentry
, &newattrs
);
562 asmlinkage
long sys_chown(const char * filename
, uid_t user
, gid_t group
)
567 error
= user_path_walk(filename
, &nd
);
569 error
= chown_common(nd
.dentry
, user
, group
);
575 asmlinkage
long sys_lchown(const char * filename
, uid_t user
, gid_t group
)
580 error
= user_path_walk_link(filename
, &nd
);
582 error
= chown_common(nd
.dentry
, user
, group
);
589 asmlinkage
long sys_fchown(unsigned int fd
, uid_t user
, gid_t group
)
596 error
= chown_common(file
->f_dentry
, user
, group
);
603 * Note that while the flag value (low two bits) for sys_open means:
609 * 00 - no permissions needed
610 * 01 - read-permission
611 * 10 - write-permission
613 * for the internal routines (ie open_namei()/follow_link() etc). 00 is
616 struct file
*filp_open(const char * filename
, int flags
, int mode
)
618 int namei_flags
, error
;
622 if ((namei_flags
+1) & O_ACCMODE
)
624 if (namei_flags
& O_TRUNC
)
627 error
= open_namei(filename
, namei_flags
, mode
, &nd
);
629 return dentry_open(nd
.dentry
, nd
.mnt
, flags
);
631 return ERR_PTR(error
);
634 struct file
*dentry_open(struct dentry
*dentry
, struct vfsmount
*mnt
, int flags
)
641 f
= get_empty_filp();
645 f
->f_mode
= (flags
+1) & O_ACCMODE
;
646 inode
= dentry
->d_inode
;
647 if (f
->f_mode
& FMODE_WRITE
) {
648 error
= get_write_access(inode
);
653 f
->f_dentry
= dentry
;
657 f
->f_op
= fops_get(inode
->i_fop
);
659 file_move(f
, &inode
->i_sb
->s_files
);
660 if (f
->f_op
&& f
->f_op
->open
) {
661 error
= f
->f_op
->open(inode
,f
);
665 f
->f_flags
&= ~(O_CREAT
| O_EXCL
| O_NOCTTY
| O_TRUNC
);
671 if (f
->f_mode
& FMODE_WRITE
)
672 put_write_access(inode
);
680 return ERR_PTR(error
);
684 * Find an empty file descriptor entry, and mark it busy.
686 int get_unused_fd(void)
688 struct files_struct
* files
= current
->files
;
692 write_lock(&files
->file_lock
);
695 fd
= find_next_zero_bit(files
->open_fds
,
696 current
->files
->max_fdset
,
700 * N.B. For clone tasks sharing a files structure, this test
701 * will limit the total number of files that can be opened.
703 if (fd
>= current
->rlim
[RLIMIT_NOFILE
].rlim_cur
)
706 /* Do we need to expand the fdset array? */
707 if (fd
>= current
->files
->max_fdset
) {
708 error
= expand_fdset(files
, fd
);
717 * Check whether we need to expand the fd array.
719 if (fd
>= files
->max_fds
) {
720 error
= expand_fd_array(files
, fd
);
728 FD_SET(fd
, files
->open_fds
);
729 FD_CLR(fd
, files
->close_on_exec
);
730 files
->next_fd
= fd
+ 1;
733 if (files
->fd
[fd
] != NULL
) {
734 printk("get_unused_fd: slot %d not NULL!\n", fd
);
735 files
->fd
[fd
] = NULL
;
741 write_unlock(&files
->file_lock
);
745 asmlinkage
long sys_open(const char * filename
, int flags
, int mode
)
750 #if BITS_PER_LONG != 32
751 flags
|= O_LARGEFILE
;
753 tmp
= getname(filename
);
756 fd
= get_unused_fd();
760 f
= filp_open(tmp
, flags
, mode
);
781 * For backward compatibility? Maybe this should be moved
782 * into arch/i386 instead?
784 asmlinkage
long sys_creat(const char * pathname
, int mode
)
786 return sys_open(pathname
, O_CREAT
| O_WRONLY
| O_TRUNC
, mode
);
792 * "id" is the POSIX thread ID. We use the
793 * files pointer for this..
795 int filp_close(struct file
*filp
, fl_owner_t id
)
799 if (!file_count(filp
)) {
800 printk("VFS: Close: file count is 0\n");
804 if (filp
->f_op
&& filp
->f_op
->flush
)
805 retval
= filp
->f_op
->flush(filp
);
806 locks_remove_posix(filp
, id
);
812 * Careful here! We test whether the file pointer is NULL before
813 * releasing the fd. This ensures that one clone task can't release
814 * an fd while another clone is opening it.
816 * The "release" argument tells us whether or not to mark the fd as free
817 * or not in the open-files bitmap. dup2 uses this to retain the fd
820 int do_close(unsigned int fd
, int release
)
824 struct files_struct
* files
= current
->files
;
827 write_lock(&files
->file_lock
);
828 filp
= frip(files
, fd
);
831 FD_CLR(fd
, files
->close_on_exec
);
833 __put_unused_fd(files
, fd
);
834 write_unlock(&files
->file_lock
);
836 error
= filp_close(filp
, files
);
841 write_unlock(&files
->file_lock
);
845 asmlinkage
long sys_close(unsigned int fd
)
847 return do_close(fd
, 1);
851 * This routine simulates a hangup on the tty, to arrange that users
852 * are given clean terminals at login time.
854 asmlinkage
long sys_vhangup(void)
856 if (capable(CAP_SYS_TTY_CONFIG
)) {
857 tty_vhangup(current
->tty
);