aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/i386/fcntl.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-08-12 08:39:46 +0000
committerUlrich Drepper <drepper@redhat.com>2000-08-12 08:39:46 +0000
commit590a63937a90e36bf0cfaffc523545601955d8f5 (patch)
treebd42631a35836032e427c70282adb2aab7f0c6f8 /sysdeps/unix/sysv/linux/i386/fcntl.c
parent21f6a10036e2458ec9ee11afe307de6d0989ddec (diff)
downloadglibc-590a63937a90e36bf0cfaffc523545601955d8f5.zip
glibc-590a63937a90e36bf0cfaffc523545601955d8f5.tar.gz
glibc-590a63937a90e36bf0cfaffc523545601955d8f5.tar.bz2
Update.
2000-08-12 Andreas Jaeger <aj@suse.de> * sysdeps/unix/sysv/linux/i386/fcntl.c (__libc_fcntl): Try fcntl if fnctl64 is not available for F_*LK*64. * sysdeps/unix/sysv/linux/i386/lockf64.c: New file.
Diffstat (limited to 'sysdeps/unix/sysv/linux/i386/fcntl.c')
-rw-r--r--sysdeps/unix/sysv/linux/i386/fcntl.c101
1 files changed, 84 insertions, 17 deletions
diff --git a/sysdeps/unix/sysv/linux/i386/fcntl.c b/sysdeps/unix/sysv/linux/i386/fcntl.c
index 457ec2e..05708bf 100644
--- a/sysdeps/unix/sysv/linux/i386/fcntl.c
+++ b/sysdeps/unix/sysv/linux/i386/fcntl.c
@@ -25,37 +25,104 @@
#include "../kernel-features.h"
+# if __ASSUME_FCNTL64 == 0
+/* This variable is shared with all files that check for fcntl64. */
+int __have_no_fcntl64;
+# endif
+#endif
+
int
__libc_fcntl (int fd, int cmd, ...)
{
va_list ap;
-#if __NR_fcntl64
- int result;
-#endif
void *arg;
va_start (ap, cmd);
arg = va_arg (ap, void *);
va_end (ap);
-#if __NR_fcntl64
- result = INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg);
+#if __ASSUME_FCNTL64 > 0
+ return INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg);
+#else
+# ifdef __NR_fcntl64
+ if (! __have_no_fcntl64)
+ {
+ int result = INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg);
+ if (result >= 0 || errno != ENOSYS)
+ return result;
-# if __ASSUME_FCNTL64 == 0
- if (result != -1 || errno != ENOSYS)
+ __have_no_fcntl64 = 1;
+ }
# endif
- return result;
-#endif
-
-#if __ASSUME_FCNTL64 == 0
- if (cmd == F_GETLK64 || cmd == F_SETLK64 || cmd == F_SETLKW64)
+ switch (cmd)
{
- __set_errno (EINVAL);
- return -1;
- }
+ case F_GETLK64:
+ /* Convert arg from flock64 to flock and back. */
+ {
+ struct flock fl;
+ struct flock64 *fl64 = arg;
+ int res;
- return INLINE_SYSCALL (fcntl, 3, fd, cmd, arg);
-#endif
+ fl.l_start = (off_t)fl64->l_start;
+ /* Check if we can represent the values with the smaller type. */
+ if ((off64_t)fl.l_start != fl64->l_start)
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+ fl.l_len = (off_t)fl64->l_len;
+ /* Check if we can represent the values with the smaller type. */
+ if ((off64_t)fl.l_len != fl64->l_len)
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+ fl.l_type = fl64->l_type;
+ fl.l_whence = fl64->l_whence;
+ fl.l_pid = fl64->l_pid;
+
+ res = INLINE_SYSCALL (fcntl, 3, fd, cmd, &fl);
+ if (res != 0)
+ return res;
+ /* Everything ok, convert back. */
+ fl64->l_type = fl.l_type;
+ fl64->l_whence = fl.l_whence;
+ fl64->l_start = fl.l_start;
+ fl64->l_len = fl.l_len;
+ fl64->l_pid = fl.l_pid;
+
+ return 0;
+ }
+ case F_SETLK64:
+ case F_SETLKW64:
+ /* Try to convert arg from flock64 to flock. */
+ {
+ struct flock fl;
+ struct flock64 *fl64 = arg;
+ fl.l_start = (off_t)fl64->l_start;
+ /* Check if we can represent the values with the smaller type. */
+ if ((off64_t)fl.l_start != fl64->l_start)
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+ fl.l_len = (off_t)fl64->l_len;
+ /* Check if we can represent the values with the smaller type. */
+ if ((off64_t)fl.l_len != fl64->l_len)
+ {
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+ fl.l_type = fl64->l_type;
+ fl.l_whence = fl64->l_whence;
+ fl.l_pid = fl64->l_pid;
+ return INLINE_SYSCALL (fcntl, 3, fd, cmd, &fl);
+ }
+ default:
+ return INLINE_SYSCALL (fcntl, 3, fd, cmd, arg);
+ }
+ return -1;
+#endif /* __ASSUME_FCNTL64 */
}
weak_alias (__libc_fcntl, __fcntl)