Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 244 lines (213 sloc) 5.279 kb
6cfcb53 Giulio Cervera Initial ASUS 8.4.4.5 import
authored
1 #include <linux/syscalls.h>
2 #include <linux/module.h>
3 #include <linux/fs.h>
4 #include <linux/file.h>
5 #include <linux/mount.h>
6 #include <linux/namei.h>
7 #include <linux/statfs.h>
8 #include <linux/security.h>
9 #include <linux/uaccess.h>
10
11 static int flags_by_mnt(int mnt_flags)
12 {
13 int flags = 0;
14
15 if (mnt_flags & MNT_READONLY)
16 flags |= ST_RDONLY;
17 if (mnt_flags & MNT_NOSUID)
18 flags |= ST_NOSUID;
19 if (mnt_flags & MNT_NODEV)
20 flags |= ST_NODEV;
21 if (mnt_flags & MNT_NOEXEC)
22 flags |= ST_NOEXEC;
23 if (mnt_flags & MNT_NOATIME)
24 flags |= ST_NOATIME;
25 if (mnt_flags & MNT_NODIRATIME)
26 flags |= ST_NODIRATIME;
27 if (mnt_flags & MNT_RELATIME)
28 flags |= ST_RELATIME;
29 return flags;
30 }
31
32 static int flags_by_sb(int s_flags)
33 {
34 int flags = 0;
35 if (s_flags & MS_SYNCHRONOUS)
36 flags |= ST_SYNCHRONOUS;
37 if (s_flags & MS_MANDLOCK)
38 flags |= ST_MANDLOCK;
39 return flags;
40 }
41
42 static int calculate_f_flags(struct vfsmount *mnt)
43 {
44 return ST_VALID | flags_by_mnt(mnt->mnt_flags) |
45 flags_by_sb(mnt->mnt_sb->s_flags);
46 }
47
48 int statfs_by_dentry(struct dentry *dentry, struct kstatfs *buf)
49 {
50 int retval;
51
52 if (!dentry->d_sb->s_op->statfs)
53 return -ENOSYS;
54
55 memset(buf, 0, sizeof(*buf));
56 retval = security_sb_statfs(dentry);
57 if (retval)
58 return retval;
59 retval = dentry->d_sb->s_op->statfs(dentry, buf);
60 if (retval == 0 && buf->f_frsize == 0)
61 buf->f_frsize = buf->f_bsize;
62 return retval;
63 }
64
65 int vfs_statfs(struct path *path, struct kstatfs *buf)
66 {
67 int error;
68
69 error = statfs_by_dentry(path->dentry, buf);
70 if (!error)
71 buf->f_flags = calculate_f_flags(path->mnt);
72 return error;
73 }
74 EXPORT_SYMBOL(vfs_statfs);
75
76 static int do_statfs_native(struct path *path, struct statfs *buf)
77 {
78 struct kstatfs st;
79 int retval;
80
81 retval = vfs_statfs(path, &st);
82 if (retval)
83 return retval;
84
85 if (sizeof(*buf) == sizeof(st))
86 memcpy(buf, &st, sizeof(st));
87 else {
88 if (sizeof buf->f_blocks == 4) {
89 if ((st.f_blocks | st.f_bfree | st.f_bavail |
90 st.f_bsize | st.f_frsize) &
91 0xffffffff00000000ULL)
92 return -EOVERFLOW;
93 /*
94 * f_files and f_ffree may be -1; it's okay to stuff
95 * that into 32 bits
96 */
97 if (st.f_files != -1 &&
98 (st.f_files & 0xffffffff00000000ULL))
99 return -EOVERFLOW;
100 if (st.f_ffree != -1 &&
101 (st.f_ffree & 0xffffffff00000000ULL))
102 return -EOVERFLOW;
103 }
104
105 buf->f_type = st.f_type;
106 buf->f_bsize = st.f_bsize;
107 buf->f_blocks = st.f_blocks;
108 buf->f_bfree = st.f_bfree;
109 buf->f_bavail = st.f_bavail;
110 buf->f_files = st.f_files;
111 buf->f_ffree = st.f_ffree;
112 buf->f_fsid = st.f_fsid;
113 buf->f_namelen = st.f_namelen;
114 buf->f_frsize = st.f_frsize;
115 buf->f_flags = st.f_flags;
116 memset(buf->f_spare, 0, sizeof(buf->f_spare));
117 }
118 return 0;
119 }
120
121 static int do_statfs64(struct path *path, struct statfs64 *buf)
122 {
123 struct kstatfs st;
124 int retval;
125
126 retval = vfs_statfs(path, &st);
127 if (retval)
128 return retval;
129
130 if (sizeof(*buf) == sizeof(st))
131 memcpy(buf, &st, sizeof(st));
132 else {
133 buf->f_type = st.f_type;
134 buf->f_bsize = st.f_bsize;
135 buf->f_blocks = st.f_blocks;
136 buf->f_bfree = st.f_bfree;
137 buf->f_bavail = st.f_bavail;
138 buf->f_files = st.f_files;
139 buf->f_ffree = st.f_ffree;
140 buf->f_fsid = st.f_fsid;
141 buf->f_namelen = st.f_namelen;
142 buf->f_frsize = st.f_frsize;
143 buf->f_flags = st.f_flags;
144 memset(buf->f_spare, 0, sizeof(buf->f_spare));
145 }
146 return 0;
147 }
148
149 SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct statfs __user *, buf)
150 {
151 struct path path;
152 int error;
153
154 error = user_path(pathname, &path);
155 if (!error) {
156 struct statfs tmp;
157 error = do_statfs_native(&path, &tmp);
158 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
159 error = -EFAULT;
160 path_put(&path);
161 }
162 return error;
163 }
164
165 SYSCALL_DEFINE3(statfs64, const char __user *, pathname, size_t, sz, struct statfs64 __user *, buf)
166 {
167 struct path path;
168 long error;
169
170 if (sz != sizeof(*buf))
171 return -EINVAL;
172 error = user_path(pathname, &path);
173 if (!error) {
174 struct statfs64 tmp;
175 error = do_statfs64(&path, &tmp);
176 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
177 error = -EFAULT;
178 path_put(&path);
179 }
180 return error;
181 }
182
183 SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct statfs __user *, buf)
184 {
185 struct file *file;
186 struct statfs tmp;
187 int error;
188
189 error = -EBADF;
190 file = fget(fd);
191 if (!file)
192 goto out;
193 error = do_statfs_native(&file->f_path, &tmp);
194 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
195 error = -EFAULT;
196 fput(file);
197 out:
198 return error;
199 }
200
201 SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, size_t, sz, struct statfs64 __user *, buf)
202 {
203 struct file *file;
204 struct statfs64 tmp;
205 int error;
206
207 if (sz != sizeof(*buf))
208 return -EINVAL;
209
210 error = -EBADF;
211 file = fget(fd);
212 if (!file)
213 goto out;
214 error = do_statfs64(&file->f_path, &tmp);
215 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
216 error = -EFAULT;
217 fput(file);
218 out:
219 return error;
220 }
221
222 SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf)
223 {
224 struct super_block *s;
225 struct ustat tmp;
226 struct kstatfs sbuf;
227 int err;
228
229 s = user_get_super(new_decode_dev(dev));
230 if (!s)
231 return -EINVAL;
232
233 err = statfs_by_dentry(s->s_root, &sbuf);
234 drop_super(s);
235 if (err)
236 return err;
237
238 memset(&tmp,0,sizeof(struct ustat));
239 tmp.f_tfree = sbuf.f_bfree;
240 tmp.f_tinode = sbuf.f_ffree;
241
242 return copy_to_user(ubuf, &tmp, sizeof(struct ustat)) ? -EFAULT : 0;
243 }
Something went wrong with that request. Please try again.