diff options
Diffstat (limited to 'fs/open.c')
| -rw-r--r-- | fs/open.c | 40 |
1 files changed, 21 insertions, 19 deletions
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/tty.h> | 16 | #include <linux/tty.h> |
| 17 | #include <linux/namei.h> | 17 | #include <linux/namei.h> |
| 18 | #include <linux/backing-dev.h> | 18 | #include <linux/backing-dev.h> |
| 19 | #include <linux/capability.h> | ||
| 19 | #include <linux/security.h> | 20 | #include <linux/security.h> |
| 20 | #include <linux/mount.h> | 21 | #include <linux/mount.h> |
| 21 | #include <linux/vfs.h> | 22 | #include <linux/vfs.h> |
| @@ -194,7 +195,8 @@ out: | |||
| 194 | return error; | 195 | return error; |
| 195 | } | 196 | } |
| 196 | 197 | ||
| 197 | int do_truncate(struct dentry *dentry, loff_t length, struct file *filp) | 198 | int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, |
| 199 | struct file *filp) | ||
| 198 | { | 200 | { |
| 199 | int err; | 201 | int err; |
| 200 | struct iattr newattrs; | 202 | struct iattr newattrs; |
| @@ -204,19 +206,19 @@ int do_truncate(struct dentry *dentry, loff_t length, struct file *filp) | |||
| 204 | return -EINVAL; | 206 | return -EINVAL; |
| 205 | 207 | ||
| 206 | newattrs.ia_size = length; | 208 | newattrs.ia_size = length; |
| 207 | newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; | 209 | newattrs.ia_valid = ATTR_SIZE | time_attrs; |
| 208 | if (filp) { | 210 | if (filp) { |
| 209 | newattrs.ia_file = filp; | 211 | newattrs.ia_file = filp; |
| 210 | newattrs.ia_valid |= ATTR_FILE; | 212 | newattrs.ia_valid |= ATTR_FILE; |
| 211 | } | 213 | } |
| 212 | 214 | ||
| 213 | down(&dentry->d_inode->i_sem); | 215 | mutex_lock(&dentry->d_inode->i_mutex); |
| 214 | err = notify_change(dentry, &newattrs); | 216 | err = notify_change(dentry, &newattrs); |
| 215 | up(&dentry->d_inode->i_sem); | 217 | mutex_unlock(&dentry->d_inode->i_mutex); |
| 216 | return err; | 218 | return err; |
| 217 | } | 219 | } |
| 218 | 220 | ||
| 219 | static inline long do_sys_truncate(const char __user * path, loff_t length) | 221 | static long do_sys_truncate(const char __user * path, loff_t length) |
| 220 | { | 222 | { |
| 221 | struct nameidata nd; | 223 | struct nameidata nd; |
| 222 | struct inode * inode; | 224 | struct inode * inode; |
| @@ -266,7 +268,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length) | |||
| 266 | error = locks_verify_truncate(inode, NULL, length); | 268 | error = locks_verify_truncate(inode, NULL, length); |
| 267 | if (!error) { | 269 | if (!error) { |
| 268 | DQUOT_INIT(inode); | 270 | DQUOT_INIT(inode); |
| 269 | error = do_truncate(nd.dentry, length, NULL); | 271 | error = do_truncate(nd.dentry, length, 0, NULL); |
| 270 | } | 272 | } |
| 271 | put_write_access(inode); | 273 | put_write_access(inode); |
| 272 | 274 | ||
| @@ -282,7 +284,7 @@ asmlinkage long sys_truncate(const char __user * path, unsigned long length) | |||
| 282 | return do_sys_truncate(path, (long)length); | 284 | return do_sys_truncate(path, (long)length); |
| 283 | } | 285 | } |
| 284 | 286 | ||
| 285 | static inline long do_sys_ftruncate(unsigned int fd, loff_t length, int small) | 287 | static long do_sys_ftruncate(unsigned int fd, loff_t length, int small) |
| 286 | { | 288 | { |
| 287 | struct inode * inode; | 289 | struct inode * inode; |
| 288 | struct dentry *dentry; | 290 | struct dentry *dentry; |
| @@ -318,7 +320,7 @@ static inline long do_sys_ftruncate(unsigned int fd, loff_t length, int small) | |||
| 318 | 320 | ||
| 319 | error = locks_verify_truncate(inode, file, length); | 321 | error = locks_verify_truncate(inode, file, length); |
| 320 | if (!error) | 322 | if (!error) |
| 321 | error = do_truncate(dentry, length, file); | 323 | error = do_truncate(dentry, length, 0, file); |
| 322 | out_putf: | 324 | out_putf: |
| 323 | fput(file); | 325 | fput(file); |
| 324 | out: | 326 | out: |
| @@ -397,9 +399,9 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times) | |||
| 397 | (error = vfs_permission(&nd, MAY_WRITE)) != 0) | 399 | (error = vfs_permission(&nd, MAY_WRITE)) != 0) |
| 398 | goto dput_and_out; | 400 | goto dput_and_out; |
| 399 | } | 401 | } |
| 400 | down(&inode->i_sem); | 402 | mutex_lock(&inode->i_mutex); |
| 401 | error = notify_change(nd.dentry, &newattrs); | 403 | error = notify_change(nd.dentry, &newattrs); |
| 402 | up(&inode->i_sem); | 404 | mutex_unlock(&inode->i_mutex); |
| 403 | dput_and_out: | 405 | dput_and_out: |
| 404 | path_release(&nd); | 406 | path_release(&nd); |
| 405 | out: | 407 | out: |
| @@ -450,9 +452,9 @@ long do_utimes(char __user * filename, struct timeval * times) | |||
| 450 | (error = vfs_permission(&nd, MAY_WRITE)) != 0) | 452 | (error = vfs_permission(&nd, MAY_WRITE)) != 0) |
| 451 | goto dput_and_out; | 453 | goto dput_and_out; |
| 452 | } | 454 | } |
| 453 | down(&inode->i_sem); | 455 | mutex_lock(&inode->i_mutex); |
| 454 | error = notify_change(nd.dentry, &newattrs); | 456 | error = notify_change(nd.dentry, &newattrs); |
| 455 | up(&inode->i_sem); | 457 | mutex_unlock(&inode->i_mutex); |
| 456 | dput_and_out: | 458 | dput_and_out: |
| 457 | path_release(&nd); | 459 | path_release(&nd); |
| 458 | out: | 460 | out: |
| @@ -619,13 +621,13 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) | |||
| 619 | err = -EPERM; | 621 | err = -EPERM; |
| 620 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 622 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
| 621 | goto out_putf; | 623 | goto out_putf; |
| 622 | down(&inode->i_sem); | 624 | mutex_lock(&inode->i_mutex); |
| 623 | if (mode == (mode_t) -1) | 625 | if (mode == (mode_t) -1) |
| 624 | mode = inode->i_mode; | 626 | mode = inode->i_mode; |
| 625 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); | 627 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); |
| 626 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; | 628 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
| 627 | err = notify_change(dentry, &newattrs); | 629 | err = notify_change(dentry, &newattrs); |
| 628 | up(&inode->i_sem); | 630 | mutex_unlock(&inode->i_mutex); |
| 629 | 631 | ||
| 630 | out_putf: | 632 | out_putf: |
| 631 | fput(file); | 633 | fput(file); |
| @@ -653,13 +655,13 @@ asmlinkage long sys_chmod(const char __user * filename, mode_t mode) | |||
| 653 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 655 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) |
| 654 | goto dput_and_out; | 656 | goto dput_and_out; |
| 655 | 657 | ||
| 656 | down(&inode->i_sem); | 658 | mutex_lock(&inode->i_mutex); |
| 657 | if (mode == (mode_t) -1) | 659 | if (mode == (mode_t) -1) |
| 658 | mode = inode->i_mode; | 660 | mode = inode->i_mode; |
| 659 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); | 661 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); |
| 660 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; | 662 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
| 661 | error = notify_change(nd.dentry, &newattrs); | 663 | error = notify_change(nd.dentry, &newattrs); |
| 662 | up(&inode->i_sem); | 664 | mutex_unlock(&inode->i_mutex); |
| 663 | 665 | ||
| 664 | dput_and_out: | 666 | dput_and_out: |
| 665 | path_release(&nd); | 667 | path_release(&nd); |
| @@ -695,9 +697,9 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group) | |||
| 695 | } | 697 | } |
| 696 | if (!S_ISDIR(inode->i_mode)) | 698 | if (!S_ISDIR(inode->i_mode)) |
| 697 | newattrs.ia_valid |= ATTR_KILL_SUID|ATTR_KILL_SGID; | 699 | newattrs.ia_valid |= ATTR_KILL_SUID|ATTR_KILL_SGID; |
| 698 | down(&inode->i_sem); | 700 | mutex_lock(&inode->i_mutex); |
| 699 | error = notify_change(dentry, &newattrs); | 701 | error = notify_change(dentry, &newattrs); |
| 700 | up(&inode->i_sem); | 702 | mutex_unlock(&inode->i_mutex); |
| 701 | out: | 703 | out: |
| 702 | return error; | 704 | return error; |
| 703 | } | 705 | } |
| @@ -970,7 +972,7 @@ out: | |||
| 970 | 972 | ||
| 971 | EXPORT_SYMBOL(get_unused_fd); | 973 | EXPORT_SYMBOL(get_unused_fd); |
| 972 | 974 | ||
| 973 | static inline void __put_unused_fd(struct files_struct *files, unsigned int fd) | 975 | static void __put_unused_fd(struct files_struct *files, unsigned int fd) |
| 974 | { | 976 | { |
| 975 | struct fdtable *fdt = files_fdtable(files); | 977 | struct fdtable *fdt = files_fdtable(files); |
| 976 | __FD_CLR(fd, fdt->open_fds); | 978 | __FD_CLR(fd, fdt->open_fds); |
