Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / fs / stat.c
1 /*
2  *  linux/fs/stat.c
3  *
4  *  Copyright (C) 1991, 1992  Linus Torvalds
5  */
6
7 #include <linux/module.h>
8 #include <linux/mm.h>
9 #include <linux/errno.h>
10 #include <linux/file.h>
11 #include <linux/smp_lock.h>
12 #include <linux/highuid.h>
13 #include <linux/fs.h>
14 #include <linux/namei.h>
15 #include <linux/security.h>
16 #include <linux/syscalls.h>
17 #include <linux/pagemap.h>
18
19 #include <asm/uaccess.h>
20 #include <asm/unistd.h>
21
22 void generic_fillattr(struct inode *inode, struct kstat *stat)
23 {
24         stat->dev = inode->i_sb->s_dev;
25         stat->ino = inode->i_ino;
26         stat->mode = inode->i_mode;
27         stat->nlink = inode->i_nlink;
28         stat->uid = inode->i_uid;
29         stat->gid = inode->i_gid;
30         stat->xid = inode->i_xid;
31         stat->rdev = inode->i_rdev;
32         stat->atime = inode->i_atime;
33         stat->mtime = inode->i_mtime;
34         stat->ctime = inode->i_ctime;
35         stat->size = i_size_read(inode);
36         stat->blocks = inode->i_blocks;
37         stat->blksize = PAGE_CACHE_SIZE;
38 }
39
40 EXPORT_SYMBOL(generic_fillattr);
41
42 int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
43 {
44         struct inode *inode = dentry->d_inode;
45         int retval;
46
47         retval = security_inode_getattr(mnt, dentry);
48         if (retval)
49                 return retval;
50
51         if (inode->i_op->getattr)
52                 return inode->i_op->getattr(mnt, dentry, stat);
53
54         generic_fillattr(inode, stat);
55         if (!stat->blksize) {
56                 struct super_block *s = inode->i_sb;
57                 unsigned blocks;
58                 blocks = (stat->size+s->s_blocksize-1) >> s->s_blocksize_bits;
59                 stat->blocks = (s->s_blocksize / 512) * blocks;
60                 stat->blksize = s->s_blocksize;
61         }
62         return 0;
63 }
64
65 EXPORT_SYMBOL(vfs_getattr);
66
67 int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat)
68 {
69         struct nameidata nd;
70         int error;
71
72         error = __user_walk_fd(dfd, name, LOOKUP_FOLLOW, &nd);
73         if (!error) {
74                 error = vfs_getattr(nd.mnt, nd.dentry, stat);
75                 path_release(&nd);
76         }
77         return error;
78 }
79
80 int vfs_stat(char __user *name, struct kstat *stat)
81 {
82         return vfs_stat_fd(AT_FDCWD, name, stat);
83 }
84
85 EXPORT_SYMBOL(vfs_stat);
86
87 int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat)
88 {
89         struct nameidata nd;
90         int error;
91
92         error = __user_walk_fd(dfd, name, 0, &nd);
93         if (!error) {
94                 error = vfs_getattr(nd.mnt, nd.dentry, stat);
95                 path_release(&nd);
96         }
97         return error;
98 }
99
100 int vfs_lstat(char __user *name, struct kstat *stat)
101 {
102         return vfs_lstat_fd(AT_FDCWD, name, stat);
103 }
104
105 EXPORT_SYMBOL(vfs_lstat);
106
107 int vfs_fstat(unsigned int fd, struct kstat *stat)
108 {
109         struct file *f = fget(fd);
110         int error = -EBADF;
111
112         if (f) {
113                 error = vfs_getattr(f->f_vfsmnt, f->f_dentry, stat);
114                 fput(f);
115         }
116         return error;
117 }
118
119 EXPORT_SYMBOL(vfs_fstat);
120
121 #ifdef __ARCH_WANT_OLD_STAT
122
123 /*
124  * For backward compatibility?  Maybe this should be moved
125  * into arch/i386 instead?
126  */
127 static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * statbuf)
128 {
129         static int warncount = 5;
130         struct __old_kernel_stat tmp;
131         
132         if (warncount > 0) {
133                 warncount--;
134                 printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
135                         current->comm);
136         } else if (warncount < 0) {
137                 /* it's laughable, but... */
138                 warncount = 0;
139         }
140
141         memset(&tmp, 0, sizeof(struct __old_kernel_stat));
142         tmp.st_dev = old_encode_dev(stat->dev);
143         tmp.st_ino = stat->ino;
144         if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
145                 return -EOVERFLOW;
146         tmp.st_mode = stat->mode;
147         tmp.st_nlink = stat->nlink;
148         if (tmp.st_nlink != stat->nlink)
149                 return -EOVERFLOW;
150         SET_UID(tmp.st_uid, stat->uid);
151         SET_GID(tmp.st_gid, stat->gid);
152         tmp.st_rdev = old_encode_dev(stat->rdev);
153 #if BITS_PER_LONG == 32
154         if (stat->size > MAX_NON_LFS)
155                 return -EOVERFLOW;
156 #endif  
157         tmp.st_size = stat->size;
158         tmp.st_atime = stat->atime.tv_sec;
159         tmp.st_mtime = stat->mtime.tv_sec;
160         tmp.st_ctime = stat->ctime.tv_sec;
161         return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
162 }
163
164 asmlinkage long sys_stat(char __user * filename, struct __old_kernel_stat __user * statbuf)
165 {
166         struct kstat stat;
167         int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
168
169         if (!error)
170                 error = cp_old_stat(&stat, statbuf);
171
172         return error;
173 }
174 asmlinkage long sys_lstat(char __user * filename, struct __old_kernel_stat __user * statbuf)
175 {
176         struct kstat stat;
177         int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
178
179         if (!error)
180                 error = cp_old_stat(&stat, statbuf);
181
182         return error;
183 }
184 asmlinkage long sys_fstat(unsigned int fd, struct __old_kernel_stat __user * statbuf)
185 {
186         struct kstat stat;
187         int error = vfs_fstat(fd, &stat);
188
189         if (!error)
190                 error = cp_old_stat(&stat, statbuf);
191
192         return error;
193 }
194
195 #endif /* __ARCH_WANT_OLD_STAT */
196
197 static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
198 {
199         struct stat tmp;
200
201 #if BITS_PER_LONG == 32
202         if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
203                 return -EOVERFLOW;
204 #else
205         if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
206                 return -EOVERFLOW;
207 #endif
208
209         memset(&tmp, 0, sizeof(tmp));
210 #if BITS_PER_LONG == 32
211         tmp.st_dev = old_encode_dev(stat->dev);
212 #else
213         tmp.st_dev = new_encode_dev(stat->dev);
214 #endif
215         tmp.st_ino = stat->ino;
216         if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
217                 return -EOVERFLOW;
218         tmp.st_mode = stat->mode;
219         tmp.st_nlink = stat->nlink;
220         if (tmp.st_nlink != stat->nlink)
221                 return -EOVERFLOW;
222         SET_UID(tmp.st_uid, stat->uid);
223         SET_GID(tmp.st_gid, stat->gid);
224 #if BITS_PER_LONG == 32
225         tmp.st_rdev = old_encode_dev(stat->rdev);
226 #else
227         tmp.st_rdev = new_encode_dev(stat->rdev);
228 #endif
229 #if BITS_PER_LONG == 32
230         if (stat->size > MAX_NON_LFS)
231                 return -EOVERFLOW;
232 #endif  
233         tmp.st_size = stat->size;
234         tmp.st_atime = stat->atime.tv_sec;
235         tmp.st_mtime = stat->mtime.tv_sec;
236         tmp.st_ctime = stat->ctime.tv_sec;
237 #ifdef STAT_HAVE_NSEC
238         tmp.st_atime_nsec = stat->atime.tv_nsec;
239         tmp.st_mtime_nsec = stat->mtime.tv_nsec;
240         tmp.st_ctime_nsec = stat->ctime.tv_nsec;
241 #endif
242         tmp.st_blocks = stat->blocks;
243         tmp.st_blksize = stat->blksize;
244         return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
245 }
246
247 asmlinkage long sys_newstat(char __user *filename, struct stat __user *statbuf)
248 {
249         struct kstat stat;
250         int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
251
252         if (!error)
253                 error = cp_new_stat(&stat, statbuf);
254
255         return error;
256 }
257
258 asmlinkage long sys_newlstat(char __user *filename, struct stat __user *statbuf)
259 {
260         struct kstat stat;
261         int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
262
263         if (!error)
264                 error = cp_new_stat(&stat, statbuf);
265
266         return error;
267 }
268
269 #if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT)
270 asmlinkage long sys_newfstatat(int dfd, char __user *filename,
271                                 struct stat __user *statbuf, int flag)
272 {
273         struct kstat stat;
274         int error = -EINVAL;
275
276         if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
277                 goto out;
278
279         if (flag & AT_SYMLINK_NOFOLLOW)
280                 error = vfs_lstat_fd(dfd, filename, &stat);
281         else
282                 error = vfs_stat_fd(dfd, filename, &stat);
283
284         if (!error)
285                 error = cp_new_stat(&stat, statbuf);
286
287 out:
288         return error;
289 }
290 #endif
291
292 asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf)
293 {
294         struct kstat stat;
295         int error = vfs_fstat(fd, &stat);
296
297         if (!error)
298                 error = cp_new_stat(&stat, statbuf);
299
300         return error;
301 }
302
303 asmlinkage long sys_readlinkat(int dfd, const char __user *path,
304                                 char __user *buf, int bufsiz)
305 {
306         struct nameidata nd;
307         int error;
308
309         if (bufsiz <= 0)
310                 return -EINVAL;
311
312         error = __user_walk_fd(dfd, path, 0, &nd);
313         if (!error) {
314                 struct inode * inode = nd.dentry->d_inode;
315
316                 error = -EINVAL;
317                 if (inode->i_op && inode->i_op->readlink) {
318                         error = security_inode_readlink(nd.dentry);
319                         if (!error) {
320                                 touch_atime(nd.mnt, nd.dentry);
321                                 error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
322                         }
323                 }
324                 path_release(&nd);
325         }
326         return error;
327 }
328
329 asmlinkage long sys_readlink(const char __user *path, char __user *buf,
330                                 int bufsiz)
331 {
332         return sys_readlinkat(AT_FDCWD, path, buf, bufsiz);
333 }
334
335
336 /* ---------- LFS-64 ----------- */
337 #ifdef __ARCH_WANT_STAT64
338
339 static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf)
340 {
341         struct stat64 tmp;
342
343         memset(&tmp, 0, sizeof(struct stat64));
344 #ifdef CONFIG_MIPS
345         /* mips has weird padding, so we don't get 64 bits there */
346         if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
347                 return -EOVERFLOW;
348         tmp.st_dev = new_encode_dev(stat->dev);
349         tmp.st_rdev = new_encode_dev(stat->rdev);
350 #else
351         tmp.st_dev = huge_encode_dev(stat->dev);
352         tmp.st_rdev = huge_encode_dev(stat->rdev);
353 #endif
354         tmp.st_ino = stat->ino;
355         if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
356                 return -EOVERFLOW;
357 #ifdef STAT64_HAS_BROKEN_ST_INO
358         tmp.__st_ino = stat->ino;
359 #endif
360         tmp.st_mode = stat->mode;
361         tmp.st_nlink = stat->nlink;
362         tmp.st_uid = stat->uid;
363         tmp.st_gid = stat->gid;
364         tmp.st_atime = stat->atime.tv_sec;
365         tmp.st_atime_nsec = stat->atime.tv_nsec;
366         tmp.st_mtime = stat->mtime.tv_sec;
367         tmp.st_mtime_nsec = stat->mtime.tv_nsec;
368         tmp.st_ctime = stat->ctime.tv_sec;
369         tmp.st_ctime_nsec = stat->ctime.tv_nsec;
370         tmp.st_size = stat->size;
371         tmp.st_blocks = stat->blocks;
372         tmp.st_blksize = stat->blksize;
373         return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
374 }
375
376 asmlinkage long sys_stat64(char __user * filename, struct stat64 __user * statbuf)
377 {
378         struct kstat stat;
379         int error = vfs_stat(filename, &stat);
380
381         if (!error)
382                 error = cp_new_stat64(&stat, statbuf);
383
384         return error;
385 }
386 asmlinkage long sys_lstat64(char __user * filename, struct stat64 __user * statbuf)
387 {
388         struct kstat stat;
389         int error = vfs_lstat(filename, &stat);
390
391         if (!error)
392                 error = cp_new_stat64(&stat, statbuf);
393
394         return error;
395 }
396 asmlinkage long sys_fstat64(unsigned long fd, struct stat64 __user * statbuf)
397 {
398         struct kstat stat;
399         int error = vfs_fstat(fd, &stat);
400
401         if (!error)
402                 error = cp_new_stat64(&stat, statbuf);
403
404         return error;
405 }
406
407 asmlinkage long sys_fstatat64(int dfd, char __user *filename,
408                                struct stat64 __user *statbuf, int flag)
409 {
410         struct kstat stat;
411         int error = -EINVAL;
412
413         if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
414                 goto out;
415
416         if (flag & AT_SYMLINK_NOFOLLOW)
417                 error = vfs_lstat_fd(dfd, filename, &stat);
418         else
419                 error = vfs_stat_fd(dfd, filename, &stat);
420
421         if (!error)
422                 error = cp_new_stat64(&stat, statbuf);
423
424 out:
425         return error;
426 }
427 #endif /* __ARCH_WANT_STAT64 */
428
429 void inode_add_bytes(struct inode *inode, loff_t bytes)
430 {
431         spin_lock(&inode->i_lock);
432         inode->i_blocks += bytes >> 9;
433         bytes &= 511;
434         inode->i_bytes += bytes;
435         if (inode->i_bytes >= 512) {
436                 inode->i_blocks++;
437                 inode->i_bytes -= 512;
438         }
439         spin_unlock(&inode->i_lock);
440 }
441
442 EXPORT_SYMBOL(inode_add_bytes);
443
444 void inode_sub_bytes(struct inode *inode, loff_t bytes)
445 {
446         spin_lock(&inode->i_lock);
447         inode->i_blocks -= bytes >> 9;
448         bytes &= 511;
449         if (inode->i_bytes < bytes) {
450                 inode->i_blocks--;
451                 inode->i_bytes += 512;
452         }
453         inode->i_bytes -= bytes;
454         spin_unlock(&inode->i_lock);
455 }
456
457 EXPORT_SYMBOL(inode_sub_bytes);
458
459 loff_t inode_get_bytes(struct inode *inode)
460 {
461         loff_t ret;
462
463         spin_lock(&inode->i_lock);
464         ret = (((loff_t)inode->i_blocks) << 9) + inode->i_bytes;
465         spin_unlock(&inode->i_lock);
466         return ret;
467 }
468
469 EXPORT_SYMBOL(inode_get_bytes);
470
471 void inode_set_bytes(struct inode *inode, loff_t bytes)
472 {
473         /* Caller is here responsible for sufficient locking
474          * (ie. inode->i_lock) */
475         inode->i_blocks = bytes >> 9;
476         inode->i_bytes = bytes & 511;
477 }
478
479 EXPORT_SYMBOL(inode_set_bytes);