diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/open.c | 50 |
1 files changed, 27 insertions, 23 deletions
@@ -61,33 +61,22 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, | |||
61 | return ret; | 61 | return ret; |
62 | } | 62 | } |
63 | 63 | ||
64 | static long do_sys_truncate(const char __user *pathname, loff_t length) | 64 | long vfs_truncate(struct path *path, loff_t length) |
65 | { | 65 | { |
66 | struct path path; | ||
67 | struct inode *inode; | 66 | struct inode *inode; |
68 | int error; | 67 | long error; |
69 | |||
70 | error = -EINVAL; | ||
71 | if (length < 0) /* sorry, but loff_t says... */ | ||
72 | goto out; | ||
73 | 68 | ||
74 | error = user_path(pathname, &path); | 69 | inode = path->dentry->d_inode; |
75 | if (error) | ||
76 | goto out; | ||
77 | inode = path.dentry->d_inode; | ||
78 | 70 | ||
79 | /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ | 71 | /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ |
80 | error = -EISDIR; | ||
81 | if (S_ISDIR(inode->i_mode)) | 72 | if (S_ISDIR(inode->i_mode)) |
82 | goto dput_and_out; | 73 | return -EISDIR; |
83 | |||
84 | error = -EINVAL; | ||
85 | if (!S_ISREG(inode->i_mode)) | 74 | if (!S_ISREG(inode->i_mode)) |
86 | goto dput_and_out; | 75 | return -EINVAL; |
87 | 76 | ||
88 | error = mnt_want_write(path.mnt); | 77 | error = mnt_want_write(path->mnt); |
89 | if (error) | 78 | if (error) |
90 | goto dput_and_out; | 79 | goto out; |
91 | 80 | ||
92 | error = inode_permission(inode, MAY_WRITE); | 81 | error = inode_permission(inode, MAY_WRITE); |
93 | if (error) | 82 | if (error) |
@@ -111,19 +100,34 @@ static long do_sys_truncate(const char __user *pathname, loff_t length) | |||
111 | 100 | ||
112 | error = locks_verify_truncate(inode, NULL, length); | 101 | error = locks_verify_truncate(inode, NULL, length); |
113 | if (!error) | 102 | if (!error) |
114 | error = security_path_truncate(&path); | 103 | error = security_path_truncate(path); |
115 | if (!error) | 104 | if (!error) |
116 | error = do_truncate(path.dentry, length, 0, NULL); | 105 | error = do_truncate(path->dentry, length, 0, NULL); |
117 | 106 | ||
118 | put_write_and_out: | 107 | put_write_and_out: |
119 | put_write_access(inode); | 108 | put_write_access(inode); |
120 | mnt_drop_write_and_out: | 109 | mnt_drop_write_and_out: |
121 | mnt_drop_write(path.mnt); | 110 | mnt_drop_write(path->mnt); |
122 | dput_and_out: | ||
123 | path_put(&path); | ||
124 | out: | 111 | out: |
125 | return error; | 112 | return error; |
126 | } | 113 | } |
114 | EXPORT_SYMBOL_GPL(vfs_truncate); | ||
115 | |||
116 | static long do_sys_truncate(const char __user *pathname, loff_t length) | ||
117 | { | ||
118 | struct path path; | ||
119 | int error; | ||
120 | |||
121 | if (length < 0) /* sorry, but loff_t says... */ | ||
122 | return -EINVAL; | ||
123 | |||
124 | error = user_path(pathname, &path); | ||
125 | if (!error) { | ||
126 | error = vfs_truncate(&path, length); | ||
127 | path_put(&path); | ||
128 | } | ||
129 | return error; | ||
130 | } | ||
127 | 131 | ||
128 | SYSCALL_DEFINE2(truncate, const char __user *, path, long, length) | 132 | SYSCALL_DEFINE2(truncate, const char __user *, path, long, length) |
129 | { | 133 | { |