diff options
author | Ulrich Drepper <drepper@redhat.com> | 2006-02-11 20:55:47 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-12 00:41:10 -0500 |
commit | cff2b760096d1e6feaa31948e7af4abbefe47822 (patch) | |
tree | 9bd6d2796ffb8c6611ca06b74c6349f8f1289ce2 | |
parent | 25bf368b3d98668c5d5f38e2201d8bca16e52680 (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.S | 2 | ||||
-rw-r--r-- | arch/x86_64/ia32/ia32entry.S | 2 | ||||
-rw-r--r-- | arch/x86_64/ia32/sys_ia32.c | 22 | ||||
-rw-r--r-- | fs/stat.c | 22 | ||||
-rw-r--r-- | include/asm-i386/unistd.h | 2 | ||||
-rw-r--r-- | include/asm-x86_64/ia32_unistd.h | 2 | ||||
-rw-r--r-- | include/linux/syscalls.h | 2 |
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 | ||
183 | asmlinkage long | ||
184 | sys32_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 | |||
201 | out: | ||
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 |
@@ -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 | ||
264 | asmlinkage long sys_newfstatat(int dfd, char __user *filename, | 265 | asmlinkage 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, | |||
281 | out: | 282 | out: |
282 | return error; | 283 | return error; |
283 | } | 284 | } |
285 | #endif | ||
284 | 286 | ||
285 | asmlinkage long sys_newfstat(unsigned int fd, struct stat __user *statbuf) | 287 | asmlinkage 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 | ||
400 | asmlinkage 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 | |||
417 | out: | ||
418 | return error; | ||
419 | } | ||
398 | #endif /* __ARCH_WANT_STAT64 */ | 420 | #endif /* __ARCH_WANT_STAT64 */ |
399 | 421 | ||
400 | void inode_add_bytes(struct inode *inode, loff_t bytes) | 422 | void 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); |
558 | asmlinkage long sys_newfstatat(int dfd, char __user *filename, | 558 | asmlinkage long sys_newfstatat(int dfd, char __user *filename, |
559 | struct stat __user *statbuf, int flag); | 559 | struct stat __user *statbuf, int flag); |
560 | asmlinkage long sys_fstatat64(int dfd, char __user *filename, | ||
561 | struct stat64 __user *statbuf, int flag); | ||
560 | asmlinkage long sys_readlinkat(int dfd, const char __user *path, char __user *buf, | 562 | asmlinkage long sys_readlinkat(int dfd, const char __user *path, char __user *buf, |
561 | int bufsiz); | 563 | int bufsiz); |
562 | asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename, | 564 | asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename, |