[PATCH] Fix bugs in analog tv i2c-helper chipset drivers
[linux-2.6/history.git] / fs / stat.c
blob26cdf651fab125cd2fbd49a43c5b094402275ce1
1 /*
2 * linux/fs/stat.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
7 #include <linux/config.h>
8 #include <linux/module.h>
9 #include <linux/mm.h>
10 #include <linux/errno.h>
11 #include <linux/file.h>
12 #include <linux/smp_lock.h>
13 #include <linux/highuid.h>
14 #include <linux/fs.h>
15 #include <linux/namei.h>
16 #include <linux/security.h>
18 #include <asm/uaccess.h>
20 void generic_fillattr(struct inode *inode, struct kstat *stat)
22 stat->dev = inode->i_sb->s_dev;
23 stat->ino = inode->i_ino;
24 stat->mode = inode->i_mode;
25 stat->nlink = inode->i_nlink;
26 stat->uid = inode->i_uid;
27 stat->gid = inode->i_gid;
28 stat->rdev = inode->i_rdev;
29 stat->atime = inode->i_atime;
30 stat->mtime = inode->i_mtime;
31 stat->ctime = inode->i_ctime;
32 stat->size = i_size_read(inode);
33 stat->blocks = inode->i_blocks;
34 stat->blksize = inode->i_blksize;
37 EXPORT_SYMBOL(generic_fillattr);
39 int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
41 struct inode *inode = dentry->d_inode;
42 int retval;
44 retval = security_inode_getattr(mnt, dentry);
45 if (retval)
46 return retval;
48 if (inode->i_op->getattr)
49 return inode->i_op->getattr(mnt, dentry, stat);
51 generic_fillattr(inode, stat);
52 if (!stat->blksize) {
53 struct super_block *s = inode->i_sb;
54 unsigned blocks;
55 blocks = (stat->size+s->s_blocksize-1) >> s->s_blocksize_bits;
56 stat->blocks = (s->s_blocksize / 512) * blocks;
57 stat->blksize = s->s_blocksize;
59 return 0;
62 EXPORT_SYMBOL(vfs_getattr);
64 int vfs_stat(char __user *name, struct kstat *stat)
66 struct nameidata nd;
67 int error;
69 error = user_path_walk(name, &nd);
70 if (!error) {
71 error = vfs_getattr(nd.mnt, nd.dentry, stat);
72 path_release(&nd);
74 return error;
77 EXPORT_SYMBOL(vfs_stat);
79 int vfs_lstat(char __user *name, struct kstat *stat)
81 struct nameidata nd;
82 int error;
84 error = user_path_walk_link(name, &nd);
85 if (!error) {
86 error = vfs_getattr(nd.mnt, nd.dentry, stat);
87 path_release(&nd);
89 return error;
92 EXPORT_SYMBOL(vfs_lstat);
94 int vfs_fstat(unsigned int fd, struct kstat *stat)
96 struct file *f = fget(fd);
97 int error = -EBADF;
99 if (f) {
100 error = vfs_getattr(f->f_vfsmnt, f->f_dentry, stat);
101 fput(f);
103 return error;
106 EXPORT_SYMBOL(vfs_fstat);
108 #if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) \
109 && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) \
110 && !defined(__arm__) && !defined(CONFIG_V850) && !defined(__powerpc64__)
113 * For backward compatibility? Maybe this should be moved
114 * into arch/i386 instead?
116 static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * statbuf)
118 static int warncount = 5;
119 struct __old_kernel_stat tmp;
121 if (warncount > 0) {
122 warncount--;
123 printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
124 current->comm);
125 } else if (warncount < 0) {
126 /* it's laughable, but... */
127 warncount = 0;
130 memset(&tmp, 0, sizeof(struct __old_kernel_stat));
131 tmp.st_dev = old_encode_dev(stat->dev);
132 tmp.st_ino = stat->ino;
133 tmp.st_mode = stat->mode;
134 tmp.st_nlink = stat->nlink;
135 SET_UID(tmp.st_uid, stat->uid);
136 SET_GID(tmp.st_gid, stat->gid);
137 tmp.st_rdev = old_encode_dev(stat->rdev);
138 #if BITS_PER_LONG == 32
139 if (stat->size > MAX_NON_LFS)
140 return -EOVERFLOW;
141 #endif
142 tmp.st_size = stat->size;
143 tmp.st_atime = stat->atime.tv_sec;
144 tmp.st_mtime = stat->mtime.tv_sec;
145 tmp.st_ctime = stat->ctime.tv_sec;
146 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
149 asmlinkage long sys_stat(char __user * filename, struct __old_kernel_stat __user * statbuf)
151 struct kstat stat;
152 int error = vfs_stat(filename, &stat);
154 if (!error)
155 error = cp_old_stat(&stat, statbuf);
157 return error;
159 asmlinkage long sys_lstat(char __user * filename, struct __old_kernel_stat __user * statbuf)
161 struct kstat stat;
162 int error = vfs_lstat(filename, &stat);
164 if (!error)
165 error = cp_old_stat(&stat, statbuf);
167 return error;
169 asmlinkage long sys_fstat(unsigned int fd, struct __old_kernel_stat __user * statbuf)
171 struct kstat stat;
172 int error = vfs_fstat(fd, &stat);
174 if (!error)
175 error = cp_old_stat(&stat, statbuf);
177 return error;
180 #endif
182 static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
184 struct stat tmp;
186 #if BITS_PER_LONG == 32
187 if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
188 return -EOVERFLOW;
189 #else
190 if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
191 return -EOVERFLOW;
192 #endif
194 memset(&tmp, 0, sizeof(tmp));
195 #if BITS_PER_LONG == 32
196 tmp.st_dev = old_encode_dev(stat->dev);
197 #else
198 tmp.st_dev = new_encode_dev(stat->dev);
199 #endif
200 tmp.st_ino = stat->ino;
201 tmp.st_mode = stat->mode;
202 tmp.st_nlink = stat->nlink;
203 SET_UID(tmp.st_uid, stat->uid);
204 SET_GID(tmp.st_gid, stat->gid);
205 #if BITS_PER_LONG == 32
206 tmp.st_rdev = old_encode_dev(stat->rdev);
207 #else
208 tmp.st_rdev = new_encode_dev(stat->rdev);
209 #endif
210 #if BITS_PER_LONG == 32
211 if (stat->size > MAX_NON_LFS)
212 return -EOVERFLOW;
213 #endif
214 tmp.st_size = stat->size;
215 tmp.st_atime = stat->atime.tv_sec;
216 tmp.st_mtime = stat->mtime.tv_sec;
217 tmp.st_ctime = stat->ctime.tv_sec;
218 #ifdef STAT_HAVE_NSEC
219 tmp.st_atime_nsec = stat->atime.tv_nsec;
220 tmp.st_mtime_nsec = stat->mtime.tv_nsec;
221 tmp.st_ctime_nsec = stat->ctime.tv_nsec;
222 #endif
223 tmp.st_blocks = stat->blocks;
224 tmp.st_blksize = stat->blksize;
225 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
228 asmlinkage long sys_newstat(char __user * filename, struct stat __user * statbuf)
230 struct kstat stat;
231 int error = vfs_stat(filename, &stat);
233 if (!error)
234 error = cp_new_stat(&stat, statbuf);
236 return error;
238 asmlinkage long sys_newlstat(char __user * filename, struct stat __user * statbuf)
240 struct kstat stat;
241 int error = vfs_lstat(filename, &stat);
243 if (!error)
244 error = cp_new_stat(&stat, statbuf);
246 return error;
248 asmlinkage long sys_newfstat(unsigned int fd, struct stat __user * statbuf)
250 struct kstat stat;
251 int error = vfs_fstat(fd, &stat);
253 if (!error)
254 error = cp_new_stat(&stat, statbuf);
256 return error;
259 asmlinkage long sys_readlink(const char __user * path, char __user * buf, int bufsiz)
261 struct nameidata nd;
262 int error;
264 if (bufsiz <= 0)
265 return -EINVAL;
267 error = user_path_walk_link(path, &nd);
268 if (!error) {
269 struct inode * inode = nd.dentry->d_inode;
271 error = -EINVAL;
272 if (inode->i_op && inode->i_op->readlink) {
273 error = security_inode_readlink(nd.dentry);
274 if (!error) {
275 update_atime(inode);
276 error = inode->i_op->readlink(nd.dentry, buf, bufsiz);
279 path_release(&nd);
281 return error;
285 /* ---------- LFS-64 ----------- */
286 #if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips64) && !defined(__x86_64__) && !defined(CONFIG_ARCH_S390X)
288 static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf)
290 struct stat64 tmp;
292 memset(&tmp, 0, sizeof(struct stat64));
293 #ifdef CONFIG_MIPS
294 /* mips has weird padding, so we don't get 64 bits there */
295 if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
296 return -EOVERFLOW;
297 tmp.st_dev = new_encode_dev(stat->dev);
298 tmp.st_rdev = new_encode_dev(stat->rdev);
299 #else
300 tmp.st_dev = huge_encode_dev(stat->dev);
301 tmp.st_rdev = huge_encode_dev(stat->rdev);
302 #endif
303 tmp.st_ino = stat->ino;
304 #ifdef STAT64_HAS_BROKEN_ST_INO
305 tmp.__st_ino = stat->ino;
306 #endif
307 tmp.st_mode = stat->mode;
308 tmp.st_nlink = stat->nlink;
309 tmp.st_uid = stat->uid;
310 tmp.st_gid = stat->gid;
311 tmp.st_atime = stat->atime.tv_sec;
312 tmp.st_atime_nsec = stat->atime.tv_nsec;
313 tmp.st_mtime = stat->mtime.tv_sec;
314 tmp.st_mtime_nsec = stat->mtime.tv_nsec;
315 tmp.st_ctime = stat->ctime.tv_sec;
316 tmp.st_ctime_nsec = stat->ctime.tv_nsec;
317 tmp.st_size = stat->size;
318 tmp.st_blocks = stat->blocks;
319 tmp.st_blksize = stat->blksize;
320 return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
323 asmlinkage long sys_stat64(char __user * filename, struct stat64 __user * statbuf, long flags)
325 struct kstat stat;
326 int error = vfs_stat(filename, &stat);
328 if (!error)
329 error = cp_new_stat64(&stat, statbuf);
331 return error;
333 asmlinkage long sys_lstat64(char __user * filename, struct stat64 __user * statbuf, long flags)
335 struct kstat stat;
336 int error = vfs_lstat(filename, &stat);
338 if (!error)
339 error = cp_new_stat64(&stat, statbuf);
341 return error;
343 asmlinkage long sys_fstat64(unsigned long fd, struct stat64 __user * statbuf, long flags)
345 struct kstat stat;
346 int error = vfs_fstat(fd, &stat);
348 if (!error)
349 error = cp_new_stat64(&stat, statbuf);
351 return error;
354 #endif /* LFS-64 */
356 void inode_add_bytes(struct inode *inode, loff_t bytes)
358 spin_lock(&inode->i_lock);
359 inode->i_blocks += bytes >> 9;
360 bytes &= 511;
361 inode->i_bytes += bytes;
362 if (inode->i_bytes >= 512) {
363 inode->i_blocks++;
364 inode->i_bytes -= 512;
366 spin_unlock(&inode->i_lock);
369 EXPORT_SYMBOL(inode_add_bytes);
371 void inode_sub_bytes(struct inode *inode, loff_t bytes)
373 spin_lock(&inode->i_lock);
374 inode->i_blocks -= bytes >> 9;
375 bytes &= 511;
376 if (inode->i_bytes < bytes) {
377 inode->i_blocks--;
378 inode->i_bytes += 512;
380 inode->i_bytes -= bytes;
381 spin_unlock(&inode->i_lock);
384 EXPORT_SYMBOL(inode_sub_bytes);
386 loff_t inode_get_bytes(struct inode *inode)
388 loff_t ret;
390 spin_lock(&inode->i_lock);
391 ret = (((loff_t)inode->i_blocks) << 9) + inode->i_bytes;
392 spin_unlock(&inode->i_lock);
393 return ret;
396 EXPORT_SYMBOL(inode_get_bytes);
398 void inode_set_bytes(struct inode *inode, loff_t bytes)
400 inode->i_blocks = bytes >> 9;
401 inode->i_bytes = bytes & 511;
404 EXPORT_SYMBOL(inode_set_bytes);