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
)
41 struct dentry
* dentry
;
42 struct super_block
* sb
;
51 if (!(dentry
= file
->f_dentry
))
53 if (!(inode
= dentry
->d_inode
))
57 if (sb
&& sb
->s_op
&& sb
->s_op
->statfs
)
58 error
= sb
->s_op
->statfs(sb
, buf
, sizeof(struct statfs
));
66 int do_truncate(struct dentry
*dentry
, unsigned long length
)
68 struct inode
*inode
= dentry
->d_inode
;
70 struct iattr newattrs
;
72 /* Not pretty: "inode->i_size" shouldn't really be "off_t". But it is. */
73 if ((off_t
) length
< 0)
77 newattrs
.ia_size
= length
;
78 newattrs
.ia_valid
= ATTR_SIZE
| ATTR_CTIME
;
79 error
= notify_change(dentry
, &newattrs
);
81 /* truncate virtual mappings of this file */
82 vmtruncate(inode
, length
);
83 if (inode
->i_op
&& inode
->i_op
->truncate
)
84 inode
->i_op
->truncate(inode
);
90 asmlinkage
int sys_truncate(const char * path
, unsigned long length
)
92 struct dentry
* dentry
;
99 error
= PTR_ERR(dentry
);
102 inode
= dentry
->d_inode
;
105 if (S_ISDIR(inode
->i_mode
))
108 error
= permission(inode
,MAY_WRITE
);
113 if (IS_RDONLY(inode
))
117 if (IS_IMMUTABLE(inode
) || IS_APPEND(inode
))
120 error
= get_write_access(inode
);
124 error
= locks_verify_area(FLOCK_VERIFY_WRITE
, inode
, NULL
,
125 length
< inode
->i_size
? length
: inode
->i_size
,
126 abs(inode
->i_size
- length
));
129 error
= do_truncate(dentry
, length
);
131 put_write_access(inode
);
139 asmlinkage
int sys_ftruncate(unsigned int fd
, unsigned long length
)
141 struct inode
* inode
;
142 struct dentry
*dentry
;
152 if (!(dentry
= file
->f_dentry
))
154 if (!(inode
= dentry
->d_inode
))
157 if (S_ISDIR(inode
->i_mode
) || !(file
->f_mode
& FMODE_WRITE
))
160 if (IS_IMMUTABLE(inode
) || IS_APPEND(inode
))
162 error
= locks_verify_area(FLOCK_VERIFY_WRITE
, inode
, file
,
163 length
<inode
->i_size
? length
: inode
->i_size
,
164 abs(inode
->i_size
- length
));
166 error
= do_truncate(dentry
, length
);
174 #if !(defined(__alpha__) || defined(__ia64__))
177 * sys_utime() can be implemented in user-level using sys_utimes().
178 * Is this for backwards compatibility? If so, why not move it
179 * into the appropriate arch directory (for those architectures that
183 /* If times==NULL, set access and modification to current time,
184 * must be owner or have write permission.
185 * Else, update from *times, must be owner or super user.
187 asmlinkage
int sys_utime(char * filename
, struct utimbuf
* times
)
190 struct dentry
* dentry
;
191 struct inode
* inode
;
192 struct iattr newattrs
;
195 dentry
= namei(filename
);
197 error
= PTR_ERR(dentry
);
200 inode
= dentry
->d_inode
;
203 if (IS_RDONLY(inode
))
206 /* Don't worry, the checks are done in inode_change_ok() */
207 newattrs
.ia_valid
= ATTR_CTIME
| ATTR_MTIME
| ATTR_ATIME
;
209 error
= get_user(newattrs
.ia_atime
, ×
->actime
);
211 error
= get_user(newattrs
.ia_mtime
, ×
->modtime
);
215 newattrs
.ia_valid
|= ATTR_ATIME_SET
| ATTR_MTIME_SET
;
217 if (current
->fsuid
!= inode
->i_uid
&&
218 (error
= permission(inode
,MAY_WRITE
)) != 0)
221 error
= notify_change(dentry
, &newattrs
);
231 /* If times==NULL, set access and modification to current time,
232 * must be owner or have write permission.
233 * Else, update from *times, must be owner or super user.
235 asmlinkage
int sys_utimes(char * filename
, struct timeval
* utimes
)
238 struct dentry
* dentry
;
239 struct inode
* inode
;
240 struct iattr newattrs
;
243 dentry
= namei(filename
);
245 error
= PTR_ERR(dentry
);
248 inode
= dentry
->d_inode
;
251 if (IS_RDONLY(inode
))
254 /* Don't worry, the checks are done in inode_change_ok() */
255 newattrs
.ia_valid
= ATTR_CTIME
| ATTR_MTIME
| ATTR_ATIME
;
257 struct timeval times
[2];
259 if (copy_from_user(×
, utimes
, sizeof(times
)))
261 newattrs
.ia_atime
= times
[0].tv_sec
;
262 newattrs
.ia_mtime
= times
[1].tv_sec
;
263 newattrs
.ia_valid
|= ATTR_ATIME_SET
| ATTR_MTIME_SET
;
265 if ((error
= permission(inode
,MAY_WRITE
)) != 0)
268 error
= notify_change(dentry
, &newattrs
);
277 * access() needs to use the real uid/gid, not the effective uid/gid.
278 * We do this by temporarily clearing all FS-related capabilities and
279 * switching the fsuid/fsgid around to the real ones.
281 asmlinkage
int sys_access(const char * filename
, int mode
)
283 struct dentry
* dentry
;
284 int old_fsuid
, old_fsgid
;
285 kernel_cap_t old_cap
;
289 if (mode
!= (mode
& S_IRWXO
)) /* where's F_OK, X_OK, W_OK, R_OK? */
291 old_fsuid
= current
->fsuid
;
292 old_fsgid
= current
->fsgid
;
293 old_cap
= current
->cap_effective
;
295 current
->fsuid
= current
->uid
;
296 current
->fsgid
= current
->gid
;
298 /* Clear the capabilities if we switch to a non-root user */
300 cap_clear(current
->cap_effective
);
302 current
->cap_effective
= current
->cap_permitted
;
304 dentry
= namei(filename
);
305 res
= PTR_ERR(dentry
);
306 if (!IS_ERR(dentry
)) {
307 res
= permission(dentry
->d_inode
, mode
);
308 /* SuS v2 requires we report a read only fs too */
309 if(!res
&& (mode
& S_IWOTH
) && IS_RDONLY(dentry
->d_inode
))
314 current
->fsuid
= old_fsuid
;
315 current
->fsgid
= old_fsgid
;
316 current
->cap_effective
= old_cap
;
322 asmlinkage
int sys_chdir(const char * filename
)
326 struct dentry
*dentry
, *tmp
;
330 dentry
= namei(filename
);
331 error
= PTR_ERR(dentry
);
335 inode
= dentry
->d_inode
;
338 if (!S_ISDIR(inode
->i_mode
))
341 error
= permission(inode
,MAY_EXEC
);
345 /* exchange dentries */
346 tmp
= current
->fs
->pwd
;
347 current
->fs
->pwd
= dentry
;
357 asmlinkage
int sys_fchdir(unsigned int fd
)
360 struct dentry
*dentry
;
372 if (!(dentry
= file
->f_dentry
))
374 if (!(inode
= dentry
->d_inode
))
378 if (!S_ISDIR(inode
->i_mode
))
381 error
= permission(inode
, MAY_EXEC
);
383 struct dentry
*tmp
= current
->fs
->pwd
;
384 current
->fs
->pwd
= dget(dentry
);
394 asmlinkage
int sys_chroot(const char * filename
)
398 struct dentry
*dentry
, *tmp
;
402 dentry
= namei(filename
);
403 error
= PTR_ERR(dentry
);
407 inode
= dentry
->d_inode
;
410 if (!S_ISDIR(inode
->i_mode
))
413 error
= permission(inode
,MAY_EXEC
);
418 if (!capable(CAP_SYS_CHROOT
))
421 /* exchange dentries */
422 tmp
= current
->fs
->root
;
423 current
->fs
->root
= dentry
;
434 asmlinkage
int sys_fchmod(unsigned int fd
, mode_t mode
)
436 struct inode
* inode
;
437 struct dentry
* dentry
;
440 struct iattr newattrs
;
448 if (!(dentry
= file
->f_dentry
))
450 if (!(inode
= dentry
->d_inode
))
454 if (IS_RDONLY(inode
))
457 if (IS_IMMUTABLE(inode
) || IS_APPEND(inode
))
459 if (mode
== (mode_t
) -1)
460 mode
= inode
->i_mode
;
461 newattrs
.ia_mode
= (mode
& S_IALLUGO
) | (inode
->i_mode
& ~S_IALLUGO
);
462 newattrs
.ia_valid
= ATTR_MODE
| ATTR_CTIME
;
463 err
= notify_change(dentry
, &newattrs
);
472 asmlinkage
int sys_chmod(const char * filename
, mode_t mode
)
474 struct dentry
* dentry
;
475 struct inode
* inode
;
477 struct iattr newattrs
;
480 dentry
= namei(filename
);
482 error
= PTR_ERR(dentry
);
485 inode
= dentry
->d_inode
;
488 if (IS_RDONLY(inode
))
492 if (IS_IMMUTABLE(inode
) || IS_APPEND(inode
))
495 if (mode
== (mode_t
) -1)
496 mode
= inode
->i_mode
;
497 newattrs
.ia_mode
= (mode
& S_IALLUGO
) | (inode
->i_mode
& ~S_IALLUGO
);
498 newattrs
.ia_valid
= ATTR_MODE
| ATTR_CTIME
;
499 error
= notify_change(dentry
, &newattrs
);
508 static int chown_common(struct dentry
* dentry
, uid_t user
, gid_t group
)
510 struct inode
* inode
;
512 struct iattr newattrs
;
515 if (!(inode
= dentry
->d_inode
)) {
516 printk("chown_common: NULL inode\n");
520 if (IS_RDONLY(inode
))
523 if (IS_IMMUTABLE(inode
) || IS_APPEND(inode
))
525 if (user
== (uid_t
) -1)
527 if (group
== (gid_t
) -1)
528 group
= inode
->i_gid
;
529 newattrs
.ia_mode
= inode
->i_mode
;
530 newattrs
.ia_uid
= user
;
531 newattrs
.ia_gid
= group
;
532 newattrs
.ia_valid
= ATTR_UID
| ATTR_GID
| ATTR_CTIME
;
534 * If the user or group of a non-directory has been changed by a
535 * non-root user, remove the setuid bit.
536 * 19981026 David C Niemi <niemi@tux.org>
539 if ((inode
->i_mode
& S_ISUID
) == S_ISUID
&&
540 !S_ISDIR(inode
->i_mode
)
543 newattrs
.ia_mode
&= ~S_ISUID
;
544 newattrs
.ia_valid
|= ATTR_MODE
;
547 * Likewise, if the user or group of a non-directory has been changed
548 * by a non-root user, remove the setgid bit UNLESS there is no group
549 * execute bit (this would be a file marked for mandatory locking).
550 * 19981026 David C Niemi <niemi@tux.org>
552 if (((inode
->i_mode
& (S_ISGID
| S_IXGRP
)) == (S_ISGID
| S_IXGRP
))
553 && !S_ISDIR(inode
->i_mode
) && current
->fsuid
)
555 newattrs
.ia_mode
&= ~S_ISGID
;
556 newattrs
.ia_valid
|= ATTR_MODE
;
558 error
= DQUOT_TRANSFER(dentry
, &newattrs
);
563 asmlinkage
int sys_chown(const char * filename
, uid_t user
, gid_t group
)
565 struct dentry
* dentry
;
569 dentry
= namei(filename
);
571 error
= PTR_ERR(dentry
);
572 if (!IS_ERR(dentry
)) {
573 error
= chown_common(dentry
, user
, group
);
580 asmlinkage
int sys_lchown(const char * filename
, uid_t user
, gid_t group
)
582 struct dentry
* dentry
;
586 dentry
= lnamei(filename
);
588 error
= PTR_ERR(dentry
);
589 if (!IS_ERR(dentry
)) {
590 error
= chown_common(dentry
, user
, group
);
598 asmlinkage
int sys_fchown(unsigned int fd
, uid_t user
, gid_t group
)
600 struct dentry
* dentry
;
609 if ((dentry
= file
->f_dentry
) != NULL
)
610 error
= chown_common(dentry
, user
, group
);
619 * Note that while the flag value (low two bits) for sys_open means:
625 * 00 - no permissions needed
626 * 01 - read-permission
627 * 10 - write-permission
629 * for the internal routines (ie open_namei()/follow_link() etc). 00 is
632 struct file
*filp_open(const char * filename
, int flags
, int mode
)
634 struct inode
* inode
;
635 struct dentry
* dentry
;
640 f
= get_empty_filp();
643 f
->f_flags
= flag
= flags
;
644 f
->f_mode
= (flag
+1) & O_ACCMODE
;
649 dentry
= open_namei(filename
,flag
,mode
);
650 error
= PTR_ERR(dentry
);
653 inode
= dentry
->d_inode
;
654 if (f
->f_mode
& FMODE_WRITE
) {
655 error
= get_write_access(inode
);
660 f
->f_dentry
= dentry
;
665 f
->f_op
= inode
->i_op
->default_file_ops
;
666 if (f
->f_op
&& f
->f_op
->open
) {
667 error
= f
->f_op
->open(inode
,f
);
671 f
->f_flags
&= ~(O_CREAT
| O_EXCL
| O_NOCTTY
| O_TRUNC
);
676 if (f
->f_mode
& FMODE_WRITE
)
677 put_write_access(inode
);
684 return ERR_PTR(error
);
688 * Find an empty file descriptor entry, and mark it busy.
690 int get_unused_fd(void)
692 struct files_struct
* files
= current
->files
;
696 fd
= find_first_zero_bit(&files
->open_fds
, NR_OPEN
);
698 * N.B. For clone tasks sharing a files structure, this test
699 * will limit the total number of files that can be opened.
701 if (fd
>= current
->rlim
[RLIMIT_NOFILE
].rlim_cur
)
704 /* Check here for fd > files->max_fds to do dynamic expansion */
706 FD_SET(fd
, &files
->open_fds
);
707 FD_CLR(fd
, &files
->close_on_exec
);
710 if (files
->fd
[fd
] != NULL
) {
711 printk("get_unused_fd: slot %d not NULL!\n", fd
);
712 files
->fd
[fd
] = NULL
;
721 inline void put_unused_fd(unsigned int fd
)
723 FD_CLR(fd
, ¤t
->files
->open_fds
);
726 asmlinkage
int sys_open(const char * filename
, int flags
, int mode
)
731 tmp
= getname(filename
);
735 fd
= get_unused_fd();
737 struct file
* f
= filp_open(tmp
, flags
, mode
);
758 * For backward compatibility? Maybe this should be moved
759 * into arch/i386 instead?
761 asmlinkage
int sys_creat(const char * pathname
, int mode
)
763 return sys_open(pathname
, O_CREAT
| O_WRONLY
| O_TRUNC
, mode
);
769 * Called when retiring the last use of a file pointer.
771 void __fput(struct file
*filp
)
773 struct dentry
* dentry
= filp
->f_dentry
;
774 struct inode
* inode
= dentry
->d_inode
;
776 if (filp
->f_op
&& filp
->f_op
->release
)
777 filp
->f_op
->release(inode
, filp
);
778 filp
->f_dentry
= NULL
;
779 if (filp
->f_mode
& FMODE_WRITE
)
780 put_write_access(inode
);
785 * "id" is the POSIX thread ID. We use the
786 * files pointer for this..
788 int filp_close(struct file
*filp
, fl_owner_t id
)
791 struct dentry
*dentry
= filp
->f_dentry
;
793 if (filp
->f_count
== 0) {
794 printk("VFS: Close: file count is 0\n");
798 if (filp
->f_op
&& filp
->f_op
->flush
)
799 retval
= filp
->f_op
->flush(filp
);
801 locks_remove_posix(filp
, id
);
807 * Careful here! We test whether the file pointer is NULL before
808 * releasing the fd. This ensures that one clone task can't release
809 * an fd while another clone is opening it.
811 asmlinkage
int sys_close(unsigned int fd
)
820 struct files_struct
* files
= current
->files
;
821 files
->fd
[fd
] = NULL
;
823 FD_CLR(fd
, &files
->close_on_exec
);
824 error
= filp_close(filp
, files
);
831 * This routine simulates a hangup on the tty, to arrange that users
832 * are given clean terminals at login time.
834 asmlinkage
int sys_vhangup(void)
839 if (!capable(CAP_SYS_TTY_CONFIG
))
841 /* If there is a controlling tty, hang it up */
843 tty_vhangup(current
->tty
);