compat: move cp_compat_stat to common code
Christoph Hellwig [Thu, 16 Oct 2008 05:02:05 +0000 (22:02 -0700)]
struct stat / compat_stat is the same on all architectures, so
cp_compat_stat should be, too.

Turns out it is, except that various architectures have slightly and some
high2lowuid/high2lowgid or the direct assignment instead of the
SET_UID/SET_GID that expands to the correct one anyway.

This patch replaces the arch-specific cp_compat_stat implementations with
a common one based on the x86-64 one.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Acked-by: David S. Miller <davem@davemloft.net> [ sparc bits ]
Acked-by: Kyle McMartin <kyle@mcmartin.ca> [ parisc bits ]
Cc: <linux-arch@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

arch/ia64/ia32/sys_ia32.c
arch/mips/kernel/linux32.c
arch/parisc/kernel/sys_parisc32.c
arch/powerpc/kernel/sys_ppc32.c
arch/s390/kernel/compat_linux.c
arch/sparc64/kernel/sys_sparc32.c
arch/x86/ia32/sys_ia32.c
fs/compat.c
include/linux/compat.h

index bf196cb..2362a8e 100644 (file)
@@ -118,41 +118,6 @@ sys32_execve (char __user *name, compat_uptr_t __user *argv, compat_uptr_t __use
        return error;
 }
 
-int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
-{
-       compat_ino_t ino;
-       int err;
-
-       if ((u64) stat->size > MAX_NON_LFS ||
-           !old_valid_dev(stat->dev) ||
-           !old_valid_dev(stat->rdev))
-               return -EOVERFLOW;
-
-       ino = stat->ino;
-       if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
-               return -EOVERFLOW;
-
-       if (clear_user(ubuf, sizeof(*ubuf)))
-               return -EFAULT;
-
-       err  = __put_user(old_encode_dev(stat->dev), &ubuf->st_dev);
-       err |= __put_user(ino, &ubuf->st_ino);
-       err |= __put_user(stat->mode, &ubuf->st_mode);
-       err |= __put_user(stat->nlink, &ubuf->st_nlink);
-       err |= __put_user(high2lowuid(stat->uid), &ubuf->st_uid);
-       err |= __put_user(high2lowgid(stat->gid), &ubuf->st_gid);
-       err |= __put_user(old_encode_dev(stat->rdev), &ubuf->st_rdev);
-       err |= __put_user(stat->size, &ubuf->st_size);
-       err |= __put_user(stat->atime.tv_sec, &ubuf->st_atime);
-       err |= __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec);
-       err |= __put_user(stat->mtime.tv_sec, &ubuf->st_mtime);
-       err |= __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec);
-       err |= __put_user(stat->ctime.tv_sec, &ubuf->st_ctime);
-       err |= __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec);
-       err |= __put_user(stat->blksize, &ubuf->st_blksize);
-       err |= __put_user(stat->blocks, &ubuf->st_blocks);
-       return err;
-}
 
 #if PAGE_SHIFT > IA32_PAGE_SHIFT
 
index 2fefb14..89223a9 100644 (file)
 #define merge_64(r1, r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL))
 #endif
 
-/*
- * Revalidate the inode. This is required for proper NFS attribute caching.
- */
-
-int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
-{
-       struct compat_stat tmp;
-
-       if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
-               return -EOVERFLOW;
-
-       memset(&tmp, 0, sizeof(tmp));
-       tmp.st_dev = new_encode_dev(stat->dev);
-       tmp.st_ino = stat->ino;
-       if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
-               return -EOVERFLOW;
-       tmp.st_mode = stat->mode;
-       tmp.st_nlink = stat->nlink;
-       SET_UID(tmp.st_uid, stat->uid);
-       SET_GID(tmp.st_gid, stat->gid);
-       tmp.st_rdev = new_encode_dev(stat->rdev);
-       tmp.st_size = stat->size;
-       tmp.st_atime = stat->atime.tv_sec;
-       tmp.st_mtime = stat->mtime.tv_sec;
-       tmp.st_ctime = stat->ctime.tv_sec;
-#ifdef STAT_HAVE_NSEC
-       tmp.st_atime_nsec = stat->atime.tv_nsec;
-       tmp.st_mtime_nsec = stat->mtime.tv_nsec;
-       tmp.st_ctime_nsec = stat->ctime.tv_nsec;
-#endif
-       tmp.st_blocks = stat->blocks;
-       tmp.st_blksize = stat->blksize;
-       return copy_to_user(statbuf, &tmp, sizeof(tmp)) ? -EFAULT : 0;
-}
-
 asmlinkage unsigned long
 sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
          unsigned long flags, unsigned long fd, unsigned long pgoff)
index 71efd6a..2c3af17 100644 (file)
@@ -237,53 +237,6 @@ int sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user
        return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
 }
 
-int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
-{
-       compat_ino_t ino;
-       int err;
-
-       if (stat->size > MAX_NON_LFS || !new_valid_dev(stat->dev) ||
-           !new_valid_dev(stat->rdev))
-               return -EOVERFLOW;
-
-       ino = stat->ino;
-       if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
-               return -EOVERFLOW;
-
-       err  = put_user(new_encode_dev(stat->dev), &statbuf->st_dev);
-       err |= put_user(ino, &statbuf->st_ino);
-       err |= put_user(stat->mode, &statbuf->st_mode);
-       err |= put_user(stat->nlink, &statbuf->st_nlink);
-       err |= put_user(0, &statbuf->st_reserved1);
-       err |= put_user(0, &statbuf->st_reserved2);
-       err |= put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev);
-       err |= put_user(stat->size, &statbuf->st_size);
-       err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
-       err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
-       err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
-       err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
-       err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
-       err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
-       err |= put_user(stat->blksize, &statbuf->st_blksize);
-       err |= put_user(stat->blocks, &statbuf->st_blocks);
-       err |= put_user(0, &statbuf->__unused1);
-       err |= put_user(0, &statbuf->__unused2);
-       err |= put_user(0, &statbuf->__unused3);
-       err |= put_user(0, &statbuf->__unused4);
-       err |= put_user(0, &statbuf->__unused5);
-       err |= put_user(0, &statbuf->st_fstype); /* not avail */
-       err |= put_user(0, &statbuf->st_realdev); /* not avail */
-       err |= put_user(0, &statbuf->st_basemode); /* not avail */
-       err |= put_user(0, &statbuf->st_spareshort);
-       err |= put_user(stat->uid, &statbuf->st_uid);
-       err |= put_user(stat->gid, &statbuf->st_gid);
-       err |= put_user(0, &statbuf->st_spare4[0]);
-       err |= put_user(0, &statbuf->st_spare4[1]);
-       err |= put_user(0, &statbuf->st_spare4[2]);
-
-       return err;
-}
-
 /*** copied from mips64 ***/
 /*
  * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
index ff7de7b..d00599b 100644 (file)
@@ -61,42 +61,6 @@ asmlinkage long ppc32_select(u32 n, compat_ulong_t __user *inp,
        return compat_sys_select((int)n, inp, outp, exp, compat_ptr(tvp_x));
 }
 
-int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
-{
-       compat_ino_t ino;
-       long err;
-
-       if (stat->size > MAX_NON_LFS || !new_valid_dev(stat->dev) ||
-           !new_valid_dev(stat->rdev))
-               return -EOVERFLOW;
-
-       ino = stat->ino;
-       if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
-               return -EOVERFLOW;
-
-       err  = access_ok(VERIFY_WRITE, statbuf, sizeof(*statbuf)) ? 0 : -EFAULT;
-       err |= __put_user(new_encode_dev(stat->dev), &statbuf->st_dev);
-       err |= __put_user(ino, &statbuf->st_ino);
-       err |= __put_user(stat->mode, &statbuf->st_mode);
-       err |= __put_user(stat->nlink, &statbuf->st_nlink);
-       err |= __put_user(stat->uid, &statbuf->st_uid);
-       err |= __put_user(stat->gid, &statbuf->st_gid);
-       err |= __put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev);
-       err |= __put_user(stat->size, &statbuf->st_size);
-       err |= __put_user(stat->atime.tv_sec, &statbuf->st_atime);
-       err |= __put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
-       err |= __put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
-       err |= __put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
-       err |= __put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
-       err |= __put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
-       err |= __put_user(stat->blksize, &statbuf->st_blksize);
-       err |= __put_user(stat->blocks, &statbuf->st_blocks);
-       err |= __put_user(0, &statbuf->__unused4[0]);
-       err |= __put_user(0, &statbuf->__unused4[1]);
-
-       return err;
-}
-
 /* Note: it is necessary to treat option as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
index 98e246d..9b471d7 100644 (file)
@@ -362,41 +362,6 @@ asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned
                return sys_ftruncate(fd, (high << 32) | low);
 }
 
-int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
-{
-       compat_ino_t ino;
-       int err;
-
-       if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
-               return -EOVERFLOW;
-
-       ino = stat->ino;
-       if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
-               return -EOVERFLOW;
-
-       err = put_user(old_encode_dev(stat->dev), &statbuf->st_dev);
-       err |= put_user(stat->ino, &statbuf->st_ino);
-       err |= put_user(stat->mode, &statbuf->st_mode);
-       err |= put_user(stat->nlink, &statbuf->st_nlink);
-       err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
-       err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
-       err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev);
-       err |= put_user(stat->size, &statbuf->st_size);
-       err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
-       err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
-       err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
-       err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
-       err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
-       err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
-       err |= put_user(stat->blksize, &statbuf->st_blksize);
-       err |= put_user(stat->blocks, &statbuf->st_blocks);
-/* fixme
-       err |= put_user(0, &statbuf->__unused4[0]);
-       err |= put_user(0, &statbuf->__unused4[1]);
-*/
-       return err;
-}
-
 asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid,
                                struct compat_timespec __user *interval)
 {
index 3320c9d..73a33dc 100644 (file)
@@ -148,41 +148,6 @@ asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned
                return sys_ftruncate(fd, (high << 32) | low);
 }
 
-int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
-{
-       compat_ino_t ino;
-       int err;
-
-       if (stat->size > MAX_NON_LFS || !old_valid_dev(stat->dev) ||
-           !old_valid_dev(stat->rdev))
-               return -EOVERFLOW;
-
-       ino = stat->ino;
-       if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
-               return -EOVERFLOW;
-
-       err  = put_user(old_encode_dev(stat->dev), &statbuf->st_dev);
-       err |= put_user(stat->ino, &statbuf->st_ino);
-       err |= put_user(stat->mode, &statbuf->st_mode);
-       err |= put_user(stat->nlink, &statbuf->st_nlink);
-       err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
-       err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
-       err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev);
-       err |= put_user(stat->size, &statbuf->st_size);
-       err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
-       err |= put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec);
-       err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
-       err |= put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec);
-       err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
-       err |= put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec);
-       err |= put_user(stat->blksize, &statbuf->st_blksize);
-       err |= put_user(stat->blocks, &statbuf->st_blocks);
-       err |= put_user(0, &statbuf->__unused4[0]);
-       err |= put_user(0, &statbuf->__unused4[1]);
-
-       return err;
-}
-
 static int cp_compat_stat64(struct kstat *stat,
                            struct compat_stat64 __user *statbuf)
 {
index beda423..4d3ad8d 100644 (file)
 
 #define AA(__x)                ((unsigned long)(__x))
 
-int cp_compat_stat(struct kstat *kbuf, struct compat_stat __user *ubuf)
-{
-       compat_ino_t ino;
-
-       typeof(ubuf->st_uid) uid = 0;
-       typeof(ubuf->st_gid) gid = 0;
-       SET_UID(uid, kbuf->uid);
-       SET_GID(gid, kbuf->gid);
-       if (!old_valid_dev(kbuf->dev) || !old_valid_dev(kbuf->rdev))
-               return -EOVERFLOW;
-       if (kbuf->size >= 0x7fffffff)
-               return -EOVERFLOW;
-       ino = kbuf->ino;
-       if (sizeof(ino) < sizeof(kbuf->ino) && ino != kbuf->ino)
-               return -EOVERFLOW;
-       if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct compat_stat)) ||
-           __put_user(old_encode_dev(kbuf->dev), &ubuf->st_dev) ||
-           __put_user(ino, &ubuf->st_ino) ||
-           __put_user(kbuf->mode, &ubuf->st_mode) ||
-           __put_user(kbuf->nlink, &ubuf->st_nlink) ||
-           __put_user(uid, &ubuf->st_uid) ||
-           __put_user(gid, &ubuf->st_gid) ||
-           __put_user(old_encode_dev(kbuf->rdev), &ubuf->st_rdev) ||
-           __put_user(kbuf->size, &ubuf->st_size) ||
-           __put_user(kbuf->atime.tv_sec, &ubuf->st_atime) ||
-           __put_user(kbuf->atime.tv_nsec, &ubuf->st_atime_nsec) ||
-           __put_user(kbuf->mtime.tv_sec, &ubuf->st_mtime) ||
-           __put_user(kbuf->mtime.tv_nsec, &ubuf->st_mtime_nsec) ||
-           __put_user(kbuf->ctime.tv_sec, &ubuf->st_ctime) ||
-           __put_user(kbuf->ctime.tv_nsec, &ubuf->st_ctime_nsec) ||
-           __put_user(kbuf->blksize, &ubuf->st_blksize) ||
-           __put_user(kbuf->blocks, &ubuf->st_blocks))
-               return -EFAULT;
-       return 0;
-}
 
 asmlinkage long sys32_truncate64(char __user *filename,
                                 unsigned long offset_low,
index aae13d3..5f9ec44 100644 (file)
@@ -137,6 +137,45 @@ asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval _
        return compat_sys_futimesat(AT_FDCWD, filename, t);
 }
 
+static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
+{
+       compat_ino_t ino = stat->ino;
+       typeof(ubuf->st_uid) uid = 0;
+       typeof(ubuf->st_gid) gid = 0;
+       int err;
+
+       SET_UID(uid, stat->uid);
+       SET_GID(gid, stat->gid);
+
+       if ((u64) stat->size > MAX_NON_LFS ||
+           !old_valid_dev(stat->dev) ||
+           !old_valid_dev(stat->rdev))
+               return -EOVERFLOW;
+       if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
+               return -EOVERFLOW;
+
+       if (clear_user(ubuf, sizeof(*ubuf)))
+               return -EFAULT;
+
+       err  = __put_user(old_encode_dev(stat->dev), &ubuf->st_dev);
+       err |= __put_user(ino, &ubuf->st_ino);
+       err |= __put_user(stat->mode, &ubuf->st_mode);
+       err |= __put_user(stat->nlink, &ubuf->st_nlink);
+       err |= __put_user(uid, &ubuf->st_uid);
+       err |= __put_user(gid, &ubuf->st_gid);
+       err |= __put_user(old_encode_dev(stat->rdev), &ubuf->st_rdev);
+       err |= __put_user(stat->size, &ubuf->st_size);
+       err |= __put_user(stat->atime.tv_sec, &ubuf->st_atime);
+       err |= __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec);
+       err |= __put_user(stat->mtime.tv_sec, &ubuf->st_mtime);
+       err |= __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec);
+       err |= __put_user(stat->ctime.tv_sec, &ubuf->st_ctime);
+       err |= __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec);
+       err |= __put_user(stat->blksize, &ubuf->st_blksize);
+       err |= __put_user(stat->blocks, &ubuf->st_blocks);
+       return err;
+}
+
 asmlinkage long compat_sys_newstat(char __user * filename,
                struct compat_stat __user *statbuf)
 {
index cf8d11c..999dddd 100644 (file)
@@ -78,7 +78,6 @@ typedef struct {
        compat_sigset_word      sig[_COMPAT_NSIG_WORDS];
 } compat_sigset_t;
 
-extern int cp_compat_stat(struct kstat *, struct compat_stat __user *);
 extern int get_compat_timespec(struct timespec *, const struct compat_timespec __user *);
 extern int put_compat_timespec(const struct timespec *, struct compat_timespec __user *);