4 * Copyright (C) 1991, 1992 Linus Torvalds
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
int sys_statfs(const char * path
, struct statfs
* buf
)
17 struct dentry
* dentry
;
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
;
28 if (sb
&& sb
->s_op
&& sb
->s_op
->statfs
)
29 error
= sb
->s_op
->statfs(sb
, buf
, sizeof(struct statfs
));
37 asmlinkage
int sys_fstatfs(unsigned int fd
, struct statfs
* buf
)
40 struct super_block
* sb
;
48 sb
= file
->f_dentry
->d_inode
->i_sb
;
50 if (sb
&& sb
->s_op
&& sb
->s_op
->statfs
)
51 error
= sb
->s_op
->statfs(sb
, buf
, sizeof(struct statfs
));
58 int do_truncate(struct dentry
*dentry
, unsigned long length
)
60 struct inode
*inode
= dentry
->d_inode
;
62 struct iattr newattrs
;
64 /* Not pretty: "inode->i_size" shouldn't really be "off_t". But it is. */
65 if ((off_t
) length
< 0)
69 newattrs
.ia_size
= length
;
70 newattrs
.ia_valid
= ATTR_SIZE
| ATTR_CTIME
;
71 error
= notify_change(dentry
, &newattrs
);
73 /* truncate virtual mappings of this file */
74 vmtruncate(inode
, length
);
75 if (inode
->i_op
&& inode
->i_op
->truncate
)
76 inode
->i_op
->truncate(inode
);
82 asmlinkage
int sys_truncate(const char * path
, unsigned long length
)
84 struct dentry
* dentry
;
91 error
= PTR_ERR(dentry
);
94 inode
= dentry
->d_inode
;
97 if (S_ISDIR(inode
->i_mode
))
100 error
= permission(inode
,MAY_WRITE
);
105 if (IS_RDONLY(inode
))
109 if (IS_IMMUTABLE(inode
) || IS_APPEND(inode
))
112 error
= get_write_access(inode
);
116 error
= locks_verify_area(FLOCK_VERIFY_WRITE
, inode
, NULL
,
117 length
< inode
->i_size
? length
: inode
->i_size
,
118 abs(inode
->i_size
- length
));
121 error
= do_truncate(dentry
, length
);
123 put_write_access(inode
);
131 asmlinkage
int sys_ftruncate(unsigned int fd
, unsigned long length
)
133 struct inode
* inode
;
134 struct dentry
*dentry
;
143 if (!(dentry
= file
->f_dentry
))
145 if (!(inode
= dentry
->d_inode
))
148 if (S_ISDIR(inode
->i_mode
) || !(file
->f_mode
& FMODE_WRITE
))
151 if (IS_IMMUTABLE(inode
) || IS_APPEND(inode
))
153 error
= locks_verify_area(FLOCK_VERIFY_WRITE
, inode
, file
,
154 length
<inode
->i_size
? length
: inode
->i_size
,
155 abs(inode
->i_size
- length
));
158 error
= do_truncate(dentry
, length
);
166 #if !(defined(__alpha__) || defined(__ia64__))
169 * sys_utime() can be implemented in user-level using sys_utimes().
170 * Is this for backwards compatibility? If so, why not move it
171 * into the appropriate arch directory (for those architectures that
175 /* If times==NULL, set access and modification to current time,
176 * must be owner or have write permission.
177 * Else, update from *times, must be owner or super user.
179 asmlinkage
int sys_utime(char * filename
, struct utimbuf
* times
)
182 struct dentry
* dentry
;
183 struct inode
* inode
;
184 struct iattr newattrs
;
187 dentry
= namei(filename
);
189 error
= PTR_ERR(dentry
);
192 inode
= dentry
->d_inode
;
195 if (IS_RDONLY(inode
))
198 /* Don't worry, the checks are done in inode_change_ok() */
199 newattrs
.ia_valid
= ATTR_CTIME
| ATTR_MTIME
| ATTR_ATIME
;
201 error
= get_user(newattrs
.ia_atime
, ×
->actime
);
203 error
= get_user(newattrs
.ia_mtime
, ×
->modtime
);
207 newattrs
.ia_valid
|= ATTR_ATIME_SET
| ATTR_MTIME_SET
;
209 if (current
->fsuid
!= inode
->i_uid
&&
210 (error
= permission(inode
,MAY_WRITE
)) != 0)
213 error
= notify_change(dentry
, &newattrs
);
223 /* If times==NULL, set access and modification to current time,
224 * must be owner or have write permission.
225 * Else, update from *times, must be owner or super user.
227 asmlinkage
int sys_utimes(char * filename
, struct timeval
* utimes
)
230 struct dentry
* dentry
;
231 struct inode
* inode
;
232 struct iattr newattrs
;
235 dentry
= namei(filename
);
237 error
= PTR_ERR(dentry
);
240 inode
= dentry
->d_inode
;
243 if (IS_RDONLY(inode
))
246 /* Don't worry, the checks are done in inode_change_ok() */
247 newattrs
.ia_valid
= ATTR_CTIME
| ATTR_MTIME
| ATTR_ATIME
;
249 struct timeval times
[2];
251 if (copy_from_user(×
, utimes
, sizeof(times
)))
253 newattrs
.ia_atime
= times
[0].tv_sec
;
254 newattrs
.ia_mtime
= times
[1].tv_sec
;
255 newattrs
.ia_valid
|= ATTR_ATIME_SET
| ATTR_MTIME_SET
;
257 if ((error
= permission(inode
,MAY_WRITE
)) != 0)
260 error
= notify_change(dentry
, &newattrs
);
269 * access() needs to use the real uid/gid, not the effective uid/gid.
270 * We do this by temporarily clearing all FS-related capabilities and
271 * switching the fsuid/fsgid around to the real ones.
273 asmlinkage
int sys_access(const char * filename
, int mode
)
275 struct dentry
* dentry
;
276 int old_fsuid
, old_fsgid
;
277 kernel_cap_t old_cap
;
281 if (mode
!= (mode
& S_IRWXO
)) /* where's F_OK, X_OK, W_OK, R_OK? */
283 old_fsuid
= current
->fsuid
;
284 old_fsgid
= current
->fsgid
;
285 old_cap
= current
->cap_effective
;
287 current
->fsuid
= current
->uid
;
288 current
->fsgid
= current
->gid
;
290 /* Clear the capabilities if we switch to a non-root user */
292 cap_clear(current
->cap_effective
);
294 current
->cap_effective
= current
->cap_permitted
;
296 dentry
= namei(filename
);
297 res
= PTR_ERR(dentry
);
298 if (!IS_ERR(dentry
)) {
299 res
= permission(dentry
->d_inode
, mode
);
300 /* SuS v2 requires we report a read only fs too */
301 if(!res
&& (mode
& S_IWOTH
) && IS_RDONLY(dentry
->d_inode
))
306 current
->fsuid
= old_fsuid
;
307 current
->fsgid
= old_fsgid
;
308 current
->cap_effective
= old_cap
;
314 asmlinkage
int sys_chdir(const char * filename
)
318 struct dentry
*dentry
, *tmp
;
322 dentry
= namei(filename
);
323 error
= PTR_ERR(dentry
);
327 inode
= dentry
->d_inode
;
330 if (!S_ISDIR(inode
->i_mode
))
333 error
= permission(inode
,MAY_EXEC
);
337 /* exchange dentries */
338 tmp
= current
->fs
->pwd
;
339 current
->fs
->pwd
= dentry
;
349 asmlinkage
int sys_fchdir(unsigned int fd
)
352 struct dentry
*dentry
;
362 if (!(dentry
= file
->f_dentry
))
364 if (!(inode
= dentry
->d_inode
))
368 if (!S_ISDIR(inode
->i_mode
))
372 error
= permission(inode
, MAY_EXEC
);
374 struct dentry
*tmp
= current
->fs
->pwd
;
375 current
->fs
->pwd
= dget(dentry
);
385 asmlinkage
int sys_chroot(const char * filename
)
389 struct dentry
*dentry
, *tmp
;
393 dentry
= namei(filename
);
394 error
= PTR_ERR(dentry
);
398 inode
= dentry
->d_inode
;
401 if (!S_ISDIR(inode
->i_mode
))
404 error
= permission(inode
,MAY_EXEC
);
409 if (!capable(CAP_SYS_CHROOT
))
412 /* exchange dentries */
413 tmp
= current
->fs
->root
;
414 current
->fs
->root
= dentry
;
425 asmlinkage
int sys_fchmod(unsigned int fd
, mode_t mode
)
427 struct inode
* inode
;
428 struct dentry
* dentry
;
431 struct iattr newattrs
;
438 if (!(dentry
= file
->f_dentry
))
440 if (!(inode
= dentry
->d_inode
))
444 if (IS_RDONLY(inode
))
447 if (IS_IMMUTABLE(inode
) || IS_APPEND(inode
))
449 if (mode
== (mode_t
) -1)
450 mode
= inode
->i_mode
;
451 newattrs
.ia_mode
= (mode
& S_IALLUGO
) | (inode
->i_mode
& ~S_IALLUGO
);
452 newattrs
.ia_valid
= ATTR_MODE
| ATTR_CTIME
;
454 err
= notify_change(dentry
, &newattrs
);
463 asmlinkage
int sys_chmod(const char * filename
, mode_t mode
)
465 struct dentry
* dentry
;
466 struct inode
* inode
;
468 struct iattr newattrs
;
471 dentry
= namei(filename
);
473 error
= PTR_ERR(dentry
);
476 inode
= dentry
->d_inode
;
479 if (IS_RDONLY(inode
))
483 if (IS_IMMUTABLE(inode
) || IS_APPEND(inode
))
486 if (mode
== (mode_t
) -1)
487 mode
= inode
->i_mode
;
488 newattrs
.ia_mode
= (mode
& S_IALLUGO
) | (inode
->i_mode
& ~S_IALLUGO
);
489 newattrs
.ia_valid
= ATTR_MODE
| ATTR_CTIME
;
490 error
= notify_change(dentry
, &newattrs
);
499 static int chown_common(struct dentry
* dentry
, uid_t user
, gid_t group
)
501 struct inode
* inode
;
503 struct iattr newattrs
;
506 if (!(inode
= dentry
->d_inode
)) {
507 printk("chown_common: NULL inode\n");
511 if (IS_RDONLY(inode
))
514 if (IS_IMMUTABLE(inode
) || IS_APPEND(inode
))
516 if (user
== (uid_t
) -1)
518 if (group
== (gid_t
) -1)
519 group
= inode
->i_gid
;
520 newattrs
.ia_mode
= inode
->i_mode
;
521 newattrs
.ia_uid
= user
;
522 newattrs
.ia_gid
= group
;
523 newattrs
.ia_valid
= ATTR_UID
| ATTR_GID
| ATTR_CTIME
;
525 * If the user or group of a non-directory has been changed by a
526 * non-root user, remove the setuid bit.
527 * 19981026 David C Niemi <niemi@tux.org>
530 if ((inode
->i_mode
& S_ISUID
) == S_ISUID
&&
531 !S_ISDIR(inode
->i_mode
)
534 newattrs
.ia_mode
&= ~S_ISUID
;
535 newattrs
.ia_valid
|= ATTR_MODE
;
538 * Likewise, if the user or group of a non-directory has been changed
539 * by a non-root user, remove the setgid bit UNLESS there is no group
540 * execute bit (this would be a file marked for mandatory locking).
541 * 19981026 David C Niemi <niemi@tux.org>
543 if (((inode
->i_mode
& (S_ISGID
| S_IXGRP
)) == (S_ISGID
| S_IXGRP
))
544 && !S_ISDIR(inode
->i_mode
) && current
->fsuid
)
546 newattrs
.ia_mode
&= ~S_ISGID
;
547 newattrs
.ia_valid
|= ATTR_MODE
;
549 error
= DQUOT_TRANSFER(dentry
, &newattrs
);
554 asmlinkage
int sys_chown(const char * filename
, uid_t user
, gid_t group
)
556 struct dentry
* dentry
;
560 dentry
= namei(filename
);
562 error
= PTR_ERR(dentry
);
563 if (!IS_ERR(dentry
)) {
564 error
= chown_common(dentry
, user
, group
);
571 asmlinkage
int sys_lchown(const char * filename
, uid_t user
, gid_t group
)
573 struct dentry
* dentry
;
577 dentry
= lnamei(filename
);
579 error
= PTR_ERR(dentry
);
580 if (!IS_ERR(dentry
)) {
581 error
= chown_common(dentry
, user
, group
);
589 asmlinkage
int sys_fchown(unsigned int fd
, uid_t user
, gid_t group
)
591 struct dentry
* dentry
;
600 if ((dentry
= file
->f_dentry
) != NULL
)
601 error
= chown_common(dentry
, user
, group
);
610 * Note that while the flag value (low two bits) for sys_open means:
616 * 00 - no permissions needed
617 * 01 - read-permission
618 * 10 - write-permission
620 * for the internal routines (ie open_namei()/follow_link() etc). 00 is
623 struct file
*filp_open(const char * filename
, int flags
, int mode
)
625 struct inode
* inode
;
626 struct dentry
* dentry
;
631 f
= get_empty_filp();
634 f
->f_flags
= flag
= flags
;
635 f
->f_mode
= (flag
+1) & O_ACCMODE
;
640 dentry
= open_namei(filename
,flag
,mode
);
641 error
= PTR_ERR(dentry
);
644 inode
= dentry
->d_inode
;
645 if (f
->f_mode
& FMODE_WRITE
) {
646 error
= get_write_access(inode
);
651 f
->f_dentry
= dentry
;
656 f
->f_op
= inode
->i_op
->default_file_ops
;
658 file_move(f
, &inode
->i_sb
->s_files
);
659 if (f
->f_op
&& f
->f_op
->open
) {
660 error
= f
->f_op
->open(inode
,f
);
664 f
->f_flags
&= ~(O_CREAT
| O_EXCL
| O_NOCTTY
| O_TRUNC
);
669 if (f
->f_mode
& FMODE_WRITE
)
670 put_write_access(inode
);
677 return ERR_PTR(error
);
681 * Find an empty file descriptor entry, and mark it busy.
683 int get_unused_fd(void)
685 struct files_struct
* files
= current
->files
;
690 write_lock(&files
->file_lock
);
691 fd
= find_first_zero_bit(&files
->open_fds
, NR_OPEN
);
693 * N.B. For clone tasks sharing a files structure, this test
694 * will limit the total number of files that can be opened.
696 if (fd
>= current
->rlim
[RLIMIT_NOFILE
].rlim_cur
)
699 /* Check here for fd > files->max_fds to do dynamic expansion */
701 FD_SET(fd
, &files
->open_fds
);
702 FD_CLR(fd
, &files
->close_on_exec
);
705 if (files
->fd
[fd
] != NULL
) {
706 printk("get_unused_fd: slot %d not NULL!\n", fd
);
707 files
->fd
[fd
] = NULL
;
713 write_unlock(&files
->file_lock
);
717 inline void put_unused_fd(unsigned int fd
)
719 write_lock(¤t
->files
->file_lock
);
720 FD_CLR(fd
, ¤t
->files
->open_fds
);
721 write_unlock(¤t
->files
->file_lock
);
724 asmlinkage
int sys_open(const char * filename
, int flags
, int mode
)
729 tmp
= getname(filename
);
732 fd
= get_unused_fd();
736 f
= filp_open(tmp
, flags
, mode
);
757 * For backward compatibility? Maybe this should be moved
758 * into arch/i386 instead?
760 asmlinkage
int sys_creat(const char * pathname
, int mode
)
762 return sys_open(pathname
, O_CREAT
| O_WRONLY
| O_TRUNC
, mode
);
768 * "id" is the POSIX thread ID. We use the
769 * files pointer for this..
771 int filp_close(struct file
*filp
, fl_owner_t id
)
774 struct dentry
*dentry
= filp
->f_dentry
;
776 if (!file_count(filp
)) {
777 printk("VFS: Close: file count is 0\n");
781 if (filp
->f_op
&& filp
->f_op
->flush
)
782 retval
= filp
->f_op
->flush(filp
);
784 locks_remove_posix(filp
, id
);
790 * Careful here! We test whether the file pointer is NULL before
791 * releasing the fd. This ensures that one clone task can't release
792 * an fd while another clone is opening it.
794 asmlinkage
int sys_close(unsigned int fd
)
798 struct files_struct
* files
= current
->files
;
801 write_lock(&files
->file_lock
);
805 FD_CLR(fd
, &files
->close_on_exec
);
806 write_unlock(&files
->file_lock
);
809 error
= filp_close(filp
, files
);
814 write_unlock(&files
->file_lock
);
819 * This routine simulates a hangup on the tty, to arrange that users
820 * are given clean terminals at login time.
822 asmlinkage
int sys_vhangup(void)
826 if (!capable(CAP_SYS_TTY_CONFIG
))
828 /* If there is a controlling tty, hang it up */
831 tty_vhangup(current
->tty
);