--- ./arch/x86/ia32/ia32entry.S.orig 2009-04-07 01:49:27.000000000 -0400 +++ ./arch/x86/ia32/ia32entry.S 2009-04-07 01:52:44.000000000 -0400 @@ -828,4 +828,7 @@ .quad sys_dup3 /* 330 */ .quad sys_pipe2 .quad sys_inotify_init1 + .quad sys_fstatlight + .quad sys_lstatlight + .quad sys_statlight ia32_syscall_end: --- ./arch/x86/include/asm/unistd_32.h.orig 2009-04-07 01:26:02.000000000 -0400 +++ ./arch/x86/include/asm/unistd_32.h 2009-04-07 01:38:39.000000000 -0400 @@ -338,6 +338,9 @@ #define __NR_dup3 330 #define __NR_pipe2 331 #define __NR_inotify_init1 332 +#define __NR_fstat_light 333 +#define __NR_lstat_light 334 +#define __NR_stat_light 335 #ifdef __KERNEL__ --- ./arch/x86/include/asm/unistd_64.h.orig 2009-04-07 01:26:12.000000000 -0400 +++ ./arch/x86/include/asm/unistd_64.h 2009-04-07 01:53:40.000000000 -0400 @@ -653,7 +653,12 @@ __SYSCALL(__NR_pipe2, sys_pipe2) #define __NR_inotify_init1 294 __SYSCALL(__NR_inotify_init1, sys_inotify_init1) - +#define __NR_fstat_light 295 +__SYSCALL(__NR_fstat_light, sys_fstatlight) +#define __NR_lstat_light 296 +__SYSCALL(__NR_lstat_light, sys_lstatlight) +#define __NR_stat_light 297 +__SYSCALL(__NR_inotify_init1, sys_statlight) #ifndef __NO_STUBS #define __ARCH_WANT_OLD_READDIR --- ./fs/stat.c.orig 2009-04-07 00:23:22.000000000 -0400 +++ ./fs/stat.c 2009-04-07 01:51:49.000000000 -0400 @@ -37,7 +37,8 @@ EXPORT_SYMBOL(generic_fillattr); -int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) +int vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat, + unsigned int flags) { struct inode *inode = dentry->d_inode; int retval; @@ -46,6 +47,9 @@ if (retval) return retval; + if (inode->i_op->getattr_light) + return inode->i_op->getattr_light(mnt, dentry, stat, flags); + if (inode->i_op->getattr) return inode->i_op->getattr(mnt, dentry, stat); @@ -55,53 +59,56 @@ EXPORT_SYMBOL(vfs_getattr); -int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat) +int vfs_stat_fd(int dfd, char __user *name, struct kstat *stat, + unsigned int flags) { struct path path; int error; error = user_path_at(dfd, name, LOOKUP_FOLLOW, &path); if (!error) { - error = vfs_getattr(path.mnt, path.dentry, stat); + error = vfs_getattr(path.mnt, path.dentry, stat, flags); path_put(&path); } return error; } -int vfs_stat(char __user *name, struct kstat *stat) +int vfs_stat(char __user *name, struct kstat *stat, unsigned int flags) { - return vfs_stat_fd(AT_FDCWD, name, stat); + return vfs_stat_fd(AT_FDCWD, name, stat, flags); } EXPORT_SYMBOL(vfs_stat); -int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat) +int vfs_lstat_fd(int dfd, char __user *name, struct kstat *stat, + unsigned int flags) { struct path path; int error; error = user_path_at(dfd, name, 0, &path); if (!error) { - error = vfs_getattr(path.mnt, path.dentry, stat); + error = vfs_getattr(path.mnt, path.dentry, stat, flags); path_put(&path); } return error; } -int vfs_lstat(char __user *name, struct kstat *stat) +int vfs_lstat(char __user *name, struct kstat *stat, unsigned int flags) { - return vfs_lstat_fd(AT_FDCWD, name, stat); + return vfs_lstat_fd(AT_FDCWD, name, stat, flags); } EXPORT_SYMBOL(vfs_lstat); -int vfs_fstat(unsigned int fd, struct kstat *stat) +int vfs_fstat(unsigned int fd, struct kstat *stat, unsigned int flags) { struct file *f = fget(fd); int error = -EBADF; if (f) { - error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat); + error = vfs_getattr(f->f_path.mnt, f->f_path.dentry, stat, + flags); fput(f); } return error; @@ -155,7 +162,7 @@ SYSCALL_DEFINE2(stat, char __user *, filename, struct __old_kernel_stat __user *, statbuf) { struct kstat stat; - int error = vfs_stat_fd(AT_FDCWD, filename, &stat); + int error = vfs_stat_fd(AT_FDCWD, filename, &stat, STAT_EVERYTHING); if (!error) error = cp_old_stat(&stat, statbuf); @@ -166,7 +173,7 @@ SYSCALL_DEFINE2(lstat, char __user *, filename, struct __old_kernel_stat __user *, statbuf) { struct kstat stat; - int error = vfs_lstat_fd(AT_FDCWD, filename, &stat); + int error = vfs_lstat_fd(AT_FDCWD, filename, &stat, STAT_EVERYTHING); if (!error) error = cp_old_stat(&stat, statbuf); @@ -177,7 +184,7 @@ SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, statbuf) { struct kstat stat; - int error = vfs_fstat(fd, &stat); + int error = vfs_fstat(fd, &stat, STAT_EVERYTHING); if (!error) error = cp_old_stat(&stat, statbuf); @@ -240,7 +247,7 @@ SYSCALL_DEFINE2(newstat, char __user *, filename, struct stat __user *, statbuf) { struct kstat stat; - int error = vfs_stat_fd(AT_FDCWD, filename, &stat); + int error = vfs_stat_fd(AT_FDCWD, filename, &stat, STAT_EVERYTHING); if (!error) error = cp_new_stat(&stat, statbuf); @@ -251,7 +258,7 @@ SYSCALL_DEFINE2(newlstat, char __user *, filename, struct stat __user *, statbuf) { struct kstat stat; - int error = vfs_lstat_fd(AT_FDCWD, filename, &stat); + int error = vfs_lstat_fd(AT_FDCWD, filename, &stat, STAT_EVERYTHING); if (!error) error = cp_new_stat(&stat, statbuf); @@ -270,9 +277,9 @@ goto out; if (flag & AT_SYMLINK_NOFOLLOW) - error = vfs_lstat_fd(dfd, filename, &stat); + error = vfs_lstat_fd(dfd, filename, &stat, STAT_EVERYTHING); else - error = vfs_stat_fd(dfd, filename, &stat); + error = vfs_stat_fd(dfd, filename, &stat, STAT_EVERYTHING); if (!error) error = cp_new_stat(&stat, statbuf); @@ -285,7 +292,43 @@ SYSCALL_DEFINE2(newfstat, unsigned int, fd, struct stat __user *, statbuf) { struct kstat stat; - int error = vfs_fstat(fd, &stat); + int error = vfs_fstat(fd, &stat, STAT_EVERYTHING); + + if (!error) + error = cp_new_stat(&stat, statbuf); + + return error; +} + +SYSCALL_DEFINE3(statlight, char __user *, filename, + struct stat __user *, statbuf, unsigned int, flags) +{ + struct kstat stat; + int error = vfs_stat_fd(AT_FDCWD, filename, &stat, flags); + + if (!error) + error = cp_new_stat(&stat, statbuf); + + return error; +} + +SYSCALL_DEFINE3(lstatlight, char __user *, filename, + struct stat __user *, statbuf, unsigned int, flags) +{ + struct kstat stat; + int error = vfs_lstat_fd(AT_FDCWD, filename, &stat, flags); + + if (!error) + error = cp_new_stat(&stat, statbuf); + + return error; +} + +SYSCALL_DEFINE3(fstatlight, unsigned int, fd, struct stat __user *, statbuf, + unsigned int, flags) +{ + struct kstat stat; + int error = vfs_fstat(fd, &stat, flags); if (!error) error = cp_new_stat(&stat, statbuf); @@ -370,7 +413,7 @@ SYSCALL_DEFINE2(stat64, char __user *, filename, struct stat64 __user *, statbuf) { struct kstat stat; - int error = vfs_stat(filename, &stat); + int error = vfs_stat(filename, &stat, STAT_EVERYTHING); if (!error) error = cp_new_stat64(&stat, statbuf); @@ -381,7 +424,7 @@ SYSCALL_DEFINE2(lstat64, char __user *, filename, struct stat64 __user *, statbuf) { struct kstat stat; - int error = vfs_lstat(filename, &stat); + int error = vfs_lstat(filename, &stat, STAT_EVERYTHING); if (!error) error = cp_new_stat64(&stat, statbuf); @@ -392,7 +435,7 @@ SYSCALL_DEFINE2(fstat64, unsigned long, fd, struct stat64 __user *, statbuf) { struct kstat stat; - int error = vfs_fstat(fd, &stat); + int error = vfs_fstat(fd, &stat, STAT_EVERYTHING); if (!error) error = cp_new_stat64(&stat, statbuf); @@ -410,9 +453,9 @@ goto out; if (flag & AT_SYMLINK_NOFOLLOW) - error = vfs_lstat_fd(dfd, filename, &stat); + error = vfs_lstat_fd(dfd, filename, &stat, STAT_EVERYTHING); else - error = vfs_stat_fd(dfd, filename, &stat); + error = vfs_stat_fd(dfd, filename, &stat, STAT_EVERYTHING); if (!error) error = cp_new_stat64(&stat, statbuf); --- ./include/linux/fcntl.h.orig 2009-04-07 00:31:36.000000000 -0400 +++ ./include/linux/fcntl.h 2009-04-07 00:44:41.000000000 -0400 @@ -40,6 +40,14 @@ unlinking file. */ #define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */ +/* Bits to define what fields the "stat light" syscall must fill in struct stat, + * should not intersect with abovr AT_* bits */ +#define STAT_NLINK 0x01000 /* nlink */ +#define STAT_TIMES 0x02000 /* atime, mtime, ctime */ +#define STAT_SIZE 0x04000 /* File size and blocks */ +#define STAT_ACCESS 0x08000 /* mode, user, group */ +#define STAT_EVERYTHING 0x0f000 /* Just a normal stat */ + #ifdef __KERNEL__ #ifndef force_o_largefile --- ./include/linux/fs.h.orig 2009-04-07 00:30:52.000000000 -0400 +++ ./include/linux/fs.h 2009-04-07 01:03:58.000000000 -0400 @@ -1354,6 +1354,8 @@ int (*permission) (struct inode *, int); int (*setattr) (struct dentry *, struct iattr *); int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); + int (*getattr_light) (struct vfsmount *mnt, struct dentry *, + struct kstat *, unsigned int); int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); ssize_t (*listxattr) (struct dentry *, char *, size_t); @@ -2062,7 +2064,8 @@ extern const struct inode_operations page_symlink_inode_operations; extern int generic_readlink(struct dentry *, char __user *, int); extern void generic_fillattr(struct inode *, struct kstat *); -extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); +extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *, + unsigned int); void inode_add_bytes(struct inode *inode, loff_t bytes); void inode_sub_bytes(struct inode *inode, loff_t bytes); loff_t inode_get_bytes(struct inode *inode); @@ -2070,11 +2073,11 @@ extern int vfs_readdir(struct file *, filldir_t, void *); -extern int vfs_stat(char __user *, struct kstat *); -extern int vfs_lstat(char __user *, struct kstat *); -extern int vfs_stat_fd(int dfd, char __user *, struct kstat *); -extern int vfs_lstat_fd(int dfd, char __user *, struct kstat *); -extern int vfs_fstat(unsigned int, struct kstat *); +extern int vfs_stat(char __user *, struct kstat *, unsigned int); +extern int vfs_lstat(char __user *, struct kstat *, unsigned int); +extern int vfs_stat_fd(int dfd, char __user *, struct kstat *, unsigned int); +extern int vfs_lstat_fd(int dfd, char __user *, struct kstat *, unsigned int); +extern int vfs_fstat(unsigned int, struct kstat *, unsigned int); extern int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg); --- ./include/linux/syscalls.h.orig 2009-04-07 01:18:06.000000000 -0400 +++ ./include/linux/syscalls.h 2009-04-07 01:57:34.000000000 -0400 @@ -304,6 +304,13 @@ struct stat __user *statbuf); asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf); asmlinkage long sys_ustat(unsigned dev, struct ustat __user *ubuf); +asmlinkage long sys_fstatlight(unsigned int fd, + struct stat __user *statbuf, + unsigned int); +asmlinkage long sys_statlight(char __user *filename, + struct stat __user *statbuf, unsigned int); +asmlinkage long sys_lstatlight(char __user *filename, + struct stat __user *statbuf, unsigned int); #if BITS_PER_LONG == 32 asmlinkage long sys_stat64(char __user *filename, struct stat64 __user *statbuf);