4 * Copyright (C) 1991, 1992 Linus Torvalds
7 #include <linux/config.h>
9 #include <linux/errno.h>
10 #include <linux/file.h>
11 #include <linux/smp_lock.h>
12 #include <linux/highuid.h>
15 #include <asm/uaccess.h>
18 * Revalidate the inode. This is required for proper NFS attribute caching.
21 do_revalidate(struct dentry
*dentry
)
23 struct inode
* inode
= dentry
->d_inode
;
24 if (inode
->i_op
&& inode
->i_op
->revalidate
)
25 return inode
->i_op
->revalidate(dentry
);
29 static int do_getattr(struct vfsmount
*mnt
, struct dentry
*dentry
, struct kstat
*stat
)
32 unsigned int blocks
, indirect
;
33 struct inode
*inode
= dentry
->d_inode
;
35 res
= do_revalidate(dentry
);
39 stat
->dev
= kdev_t_to_nr(inode
->i_dev
);
40 stat
->ino
= inode
->i_ino
;
41 stat
->mode
= inode
->i_mode
;
42 stat
->nlink
= inode
->i_nlink
;
43 stat
->uid
= inode
->i_uid
;
44 stat
->gid
= inode
->i_gid
;
45 stat
->rdev
= kdev_t_to_nr(inode
->i_rdev
);
46 stat
->atime
= inode
->i_atime
;
47 stat
->mtime
= inode
->i_mtime
;
48 stat
->ctime
= inode
->i_ctime
;
49 stat
->ctime
= inode
->i_ctime
;
50 stat
->size
= inode
->i_size
;
52 * st_blocks and st_blksize are approximated with a simple algorithm if
53 * they aren't supported directly by the filesystem. The minix and msdos
54 * filesystems don't keep track of blocks, so they would either have to
55 * be counted explicitly (by delving into the file itself), or by using
56 * this simple algorithm to get a reasonable (although not 100% accurate)
61 * Use minix fs values for the number of direct and indirect blocks. The
62 * count is now exact for the minix fs except that it counts zero blocks.
63 * Everything is in units of BLOCK_SIZE until the assignment to
67 #define I_B (BLOCK_SIZE / sizeof(unsigned short))
69 if (!inode
->i_blksize
) {
70 blocks
= (stat
->size
+ BLOCK_SIZE
- 1) >> BLOCK_SIZE_BITS
;
72 indirect
= (blocks
- D_B
+ I_B
- 1) / I_B
;
75 indirect
= (indirect
- 1 + I_B
- 1) / I_B
;
81 stat
->blocks
= (BLOCK_SIZE
/ 512) * blocks
;
82 stat
->blksize
= BLOCK_SIZE
;
84 stat
->blocks
= inode
->i_blocks
;
85 stat
->blksize
= inode
->i_blksize
;
90 int vfs_stat(char *name
, struct kstat
*stat
)
95 error
= user_path_walk(name
, &nd
);
97 error
= do_getattr(nd
.mnt
, nd
.dentry
, stat
);
103 int vfs_lstat(char *name
, struct kstat
*stat
)
108 error
= user_path_walk_link(name
, &nd
);
110 error
= do_getattr(nd
.mnt
, nd
.dentry
, stat
);
116 int vfs_fstat(unsigned int fd
, struct kstat
*stat
)
118 struct file
*f
= fget(fd
);
122 error
= do_getattr(f
->f_vfsmnt
, f
->f_dentry
, stat
);
128 #if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) \
129 && !defined(CONFIG_ARCH_S390) && !defined(__hppa__) && !defined(__x86_64__) \
133 * For backward compatibility? Maybe this should be moved
134 * into arch/i386 instead?
136 static int cp_old_stat(struct kstat
*stat
, struct __old_kernel_stat
* statbuf
)
138 static int warncount
= 5;
139 struct __old_kernel_stat tmp
;
143 printk(KERN_WARNING
"VFS: Warning: %s using old stat() call. Recompile your binary.\n",
145 } else if (warncount
< 0) {
146 /* it's laughable, but... */
150 tmp
.st_dev
= stat
->dev
;
151 tmp
.st_ino
= stat
->ino
;
152 tmp
.st_mode
= stat
->mode
;
153 tmp
.st_nlink
= stat
->nlink
;
154 SET_OLDSTAT_UID(tmp
, stat
->uid
);
155 SET_OLDSTAT_GID(tmp
, stat
->gid
);
156 tmp
.st_rdev
= stat
->rdev
;
157 #if BITS_PER_LONG == 32
158 if (stat
->size
> MAX_NON_LFS
)
161 tmp
.st_size
= stat
->size
;
162 tmp
.st_atime
= stat
->atime
;
163 tmp
.st_mtime
= stat
->mtime
;
164 tmp
.st_ctime
= stat
->ctime
;
165 return copy_to_user(statbuf
,&tmp
,sizeof(tmp
)) ? -EFAULT
: 0;
168 asmlinkage
long sys_stat(char * filename
, struct __old_kernel_stat
* statbuf
)
171 int error
= vfs_stat(filename
, &stat
);
174 error
= cp_old_stat(&stat
, statbuf
);
178 asmlinkage
long sys_lstat(char * filename
, struct __old_kernel_stat
* statbuf
)
181 int error
= vfs_lstat(filename
, &stat
);
184 error
= cp_old_stat(&stat
, statbuf
);
188 asmlinkage
long sys_fstat(unsigned int fd
, struct __old_kernel_stat
* statbuf
)
191 int error
= vfs_fstat(fd
, &stat
);
194 error
= cp_old_stat(&stat
, statbuf
);
201 static int cp_new_stat(struct kstat
*stat
, struct stat
*statbuf
)
205 memset(&tmp
, 0, sizeof(tmp
));
206 tmp
.st_dev
= stat
->dev
;
207 tmp
.st_ino
= stat
->ino
;
208 tmp
.st_mode
= stat
->mode
;
209 tmp
.st_nlink
= stat
->nlink
;
210 SET_STAT_UID(tmp
, stat
->uid
);
211 SET_STAT_GID(tmp
, stat
->gid
);
212 tmp
.st_rdev
= stat
->rdev
;
213 #if BITS_PER_LONG == 32
214 if (stat
->size
> MAX_NON_LFS
)
217 tmp
.st_size
= stat
->size
;
218 tmp
.st_atime
= stat
->atime
;
219 tmp
.st_mtime
= stat
->mtime
;
220 tmp
.st_ctime
= stat
->ctime
;
221 tmp
.st_blocks
= stat
->blocks
;
222 tmp
.st_blksize
= stat
->blksize
;
223 return copy_to_user(statbuf
,&tmp
,sizeof(tmp
)) ? -EFAULT
: 0;
226 asmlinkage
long sys_newstat(char * filename
, struct stat
* statbuf
)
229 int error
= vfs_stat(filename
, &stat
);
232 error
= cp_new_stat(&stat
, statbuf
);
236 asmlinkage
long sys_newlstat(char * filename
, struct stat
* statbuf
)
239 int error
= vfs_lstat(filename
, &stat
);
242 error
= cp_new_stat(&stat
, statbuf
);
246 asmlinkage
long sys_newfstat(unsigned int fd
, struct stat
* statbuf
)
249 int error
= vfs_fstat(fd
, &stat
);
252 error
= cp_new_stat(&stat
, statbuf
);
257 asmlinkage
long sys_readlink(const char * path
, char * buf
, int bufsiz
)
265 error
= user_path_walk_link(path
, &nd
);
267 struct inode
* inode
= nd
.dentry
->d_inode
;
270 if (inode
->i_op
&& inode
->i_op
->readlink
&&
271 !(error
= do_revalidate(nd
.dentry
))) {
273 error
= inode
->i_op
->readlink(nd
.dentry
, buf
, bufsiz
);
281 /* ---------- LFS-64 ----------- */
282 #if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips64) && !defined(__x86_64__) && !defined(CONFIG_ARCH_S390X)
284 static long cp_new_stat64(struct kstat
*stat
, struct stat64
*statbuf
)
288 memset(&tmp
, 0, sizeof(tmp
));
289 tmp
.st_dev
= stat
->dev
;
290 tmp
.st_ino
= stat
->ino
;
291 #ifdef STAT64_HAS_BROKEN_ST_INO
292 tmp
.__st_ino
= stat
->ino
;
294 tmp
.st_mode
= stat
->mode
;
295 tmp
.st_nlink
= stat
->nlink
;
296 tmp
.st_uid
= stat
->uid
;
297 tmp
.st_gid
= stat
->gid
;
298 tmp
.st_rdev
= stat
->rdev
;
299 tmp
.st_atime
= stat
->atime
;
300 tmp
.st_mtime
= stat
->mtime
;
301 tmp
.st_ctime
= stat
->ctime
;
302 tmp
.st_size
= stat
->size
;
303 tmp
.st_blocks
= stat
->blocks
;
304 tmp
.st_blksize
= stat
->blksize
;
305 return copy_to_user(statbuf
,&tmp
,sizeof(tmp
)) ? -EFAULT
: 0;
308 asmlinkage
long sys_stat64(char * filename
, struct stat64
* statbuf
, long flags
)
311 int error
= vfs_stat(filename
, &stat
);
314 error
= cp_new_stat64(&stat
, statbuf
);
318 asmlinkage
long sys_lstat64(char * filename
, struct stat64
* statbuf
, long flags
)
321 int error
= vfs_lstat(filename
, &stat
);
324 error
= cp_new_stat64(&stat
, statbuf
);
328 asmlinkage
long sys_fstat64(unsigned long fd
, struct stat64
* statbuf
, long flags
)
331 int error
= vfs_fstat(fd
, &stat
);
334 error
= cp_new_stat64(&stat
, statbuf
);