aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2006-02-11 20:55:47 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-02-12 00:41:10 -0500
commitcff2b760096d1e6feaa31948e7af4abbefe47822 (patch)
tree9bd6d2796ffb8c6611ca06b74c6349f8f1289ce2
parent25bf368b3d98668c5d5f38e2201d8bca16e52680 (diff)
[PATCH] fstatat64 support
The *at patches introduced fstatat and, due to inusfficient research, I used the newfstat functions generally as the guideline. The result is that on 32-bit platforms we don't have all the information needed to implement fstatat64. This patch modifies the code to pass up 64-bit information if __ARCH_WANT_STAT64 is defined. I renamed the syscall entry point to make this clear. Other archs will continue to use the existing code. On x86-64 the compat code is implemented using a new sys32_ function. this is what is done for the other stat syscalls as well. This patch might break some other archs (those which define __ARCH_WANT_STAT64 and which already wired up the syscall). Yet others might need changes to accomodate the compatibility mode. I really don't want to do that work because all this stat handling is a mess (more so in glibc, but the kernel is also affected). It should be done by the arch maintainers. I'll provide some stand-alone test shortly. Those who are eager could compile glibc and run 'make check' (no installation needed). The patch below has been tested on x86 and x86-64. Signed-off-by: Ulrich Drepper <drepper@redhat.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Andi Kleen <ak@muc.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/i386/kernel/syscall_table.S2
-rw-r--r--arch/x86_64/ia32/ia32entry.S2
-rw-r--r--arch/x86_64/ia32/sys_ia32.c22
-rw-r--r--fs/stat.c22
-rw-r--r--include/asm-i386/unistd.h2
-rw-r--r--include/asm-x86_64/ia32_unistd.h2
-rw-r--r--include/linux/syscalls.h2
7 files changed, 50 insertions, 4 deletions
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index 5a8b3fb6d27b..ac687d00a1ce 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -299,7 +299,7 @@ ENTRY(sys_call_table)
299 .long sys_mknodat 299 .long sys_mknodat
300 .long sys_fchownat 300 .long sys_fchownat
301 .long sys_futimesat 301 .long sys_futimesat
302 .long sys_newfstatat /* 300 */ 302 .long sys_fstatat64 /* 300 */
303 .long sys_unlinkat 303 .long sys_unlinkat
304 .long sys_renameat 304 .long sys_renameat
305 .long sys_linkat 305 .long sys_linkat
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index ada4535d0161..00dee176c08e 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -677,7 +677,7 @@ ia32_sys_call_table:
677 .quad sys_mknodat 677 .quad sys_mknodat
678 .quad sys_fchownat 678 .quad sys_fchownat
679 .quad compat_sys_futimesat 679 .quad compat_sys_futimesat
680 .quad compat_sys_newfstatat /* 300 */ 680 .quad sys32_fstatat /* 300 */
681 .quad sys_unlinkat 681 .quad sys_unlinkat
682 .quad sys_renameat 682 .quad sys_renameat
683 .quad sys_linkat 683 .quad sys_linkat
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index 54481af5344a..2bc55af95419 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -180,6 +180,28 @@ sys32_fstat64(unsigned int fd, struct stat64 __user *statbuf)
180 return ret; 180 return ret;
181} 181}
182 182
183asmlinkage long
184sys32_fstatat(unsigned int dfd, char __user *filename,
185 struct stat64 __user* statbuf, int flag)
186{
187 struct kstat stat;
188 int error = -EINVAL;
189
190 if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
191 goto out;
192
193 if (flag & AT_SYMLINK_NOFOLLOW)
194 error = vfs_lstat_fd(dfd, filename, &stat);
195 else
196 error = vfs_stat_fd(dfd, filename, &stat);
197
198 if (!error)
199 error = cp_stat64(statbuf, &stat);
200
201out:
202 return error;
203}
204
183/* 205/*
184 * Linux/i386 didn't use to be able to handle more than 206 * Linux/i386 didn't use to be able to handle more than
185 * 4 system call parameters, so these system calls used a memory 207 * 4 system call parameters, so these system calls used a memory
diff --git a/fs/stat.c b/fs/stat.c
index 24211b030f39..9948cc1685a4 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -261,6 +261,7 @@ asmlinkage long sys_newlstat(char __user *filename, struct stat __user *statbuf)
261 return error; 261 return error;
262} 262}
263 263
264#ifndef __ARCH_WANT_STAT64
264asmlinkage long sys_newfstatat(int dfd, char __user *filename, 265asmlinkage long sys_newfstatat(int dfd, char __user *filename,
265 struct stat __user *statbuf, int flag) 266 struct stat __user *statbuf, int flag)
266{ 267{
@@ -281,6 +282,7 @@ asmlinkage long sys_newfstatat(int dfd, char __user *filename,
281out: 282out:
282 return error; 283 return error;
283} 284}
285#endif
284 286
285asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf) 287asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf)
286{ 288{
@@ -395,6 +397,26 @@ asmlinkage long sys_fstat64(unsigned long fd, struct stat64 __user * statbuf)
395 return error; 397 return error;
396} 398}
397 399
400asmlinkage long sys_fstatat64(int dfd, char __user *filename,
401 struct stat64 __user *statbuf, int flag)
402{
403 struct kstat stat;
404 int error = -EINVAL;
405
406 if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
407 goto out;
408
409 if (flag & AT_SYMLINK_NOFOLLOW)
410 error = vfs_lstat_fd(dfd, filename, &stat);
411 else
412 error = vfs_stat_fd(dfd, filename, &stat);
413
414 if (!error)
415 error = cp_new_stat64(&stat, statbuf);
416
417out:
418 return error;
419}
398#endif /* __ARCH_WANT_STAT64 */ 420#endif /* __ARCH_WANT_STAT64 */
399 421
400void inode_add_bytes(struct inode *inode, loff_t bytes) 422void inode_add_bytes(struct inode *inode, loff_t bytes)
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index cf6f2cd9c514..dc81a55dd94d 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -305,7 +305,7 @@
305#define __NR_mknodat 297 305#define __NR_mknodat 297
306#define __NR_fchownat 298 306#define __NR_fchownat 298
307#define __NR_futimesat 299 307#define __NR_futimesat 299
308#define __NR_newfstatat 300 308#define __NR_fstatat64 300
309#define __NR_unlinkat 301 309#define __NR_unlinkat 301
310#define __NR_renameat 302 310#define __NR_renameat 302
311#define __NR_linkat 303 311#define __NR_linkat 303
diff --git a/include/asm-x86_64/ia32_unistd.h b/include/asm-x86_64/ia32_unistd.h
index 20468983d453..eeb2bcd635de 100644
--- a/include/asm-x86_64/ia32_unistd.h
+++ b/include/asm-x86_64/ia32_unistd.h
@@ -305,7 +305,7 @@
305#define __NR_ia32_mknodat 297 305#define __NR_ia32_mknodat 297
306#define __NR_ia32_fchownat 298 306#define __NR_ia32_fchownat 298
307#define __NR_ia32_futimesat 299 307#define __NR_ia32_futimesat 299
308#define __NR_ia32_newfstatat 300 308#define __NR_ia32_fstatat64 300
309#define __NR_ia32_unlinkat 301 309#define __NR_ia32_unlinkat 301
310#define __NR_ia32_renameat 302 310#define __NR_ia32_renameat 302
311#define __NR_ia32_linkat 303 311#define __NR_ia32_linkat 303
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 3877209d23c3..d73501ba7e44 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -557,6 +557,8 @@ asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
557 int mode); 557 int mode);
558asmlinkage long sys_newfstatat(int dfd, char __user *filename, 558asmlinkage long sys_newfstatat(int dfd, char __user *filename,
559 struct stat __user *statbuf, int flag); 559 struct stat __user *statbuf, int flag);
560asmlinkage long sys_fstatat64(int dfd, char __user *filename,
561 struct stat64 __user *statbuf, int flag);
560asmlinkage long sys_readlinkat(int dfd, const char __user *path, char __user *buf, 562asmlinkage long sys_readlinkat(int dfd, const char __user *path, char __user *buf,
561 int bufsiz); 563 int bufsiz);
562asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename, 564asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename,