]> git.ipfire.org Git - thirdparty/util-linux.git/blob - fdisk/llseek.c
Imported from util-linux-2.12 tarball.
[thirdparty/util-linux.git] / fdisk / llseek.c
1 /*
2 * llseek.c -- stub calling the llseek system call
3 *
4 * Copyright (C) 1994 Remy Card. This file may be redistributed
5 * under the terms of the GNU Public License.
6 */
7
8 #include <sys/types.h>
9
10 #include <errno.h>
11 #include <unistd.h>
12
13 extern long long ext2_llseek (unsigned int, long long, unsigned int);
14
15 #ifdef __linux__
16
17 #ifdef HAVE_LLSEEK
18 #include <syscall.h>
19
20 #else /* HAVE_LLSEEK */
21
22 #if defined(__alpha__) || defined(__ia64__) || defined(__s390x__)
23
24 #define my_llseek lseek
25
26 #else
27 #include <linux/unistd.h> /* for __NR__llseek */
28
29 static int _llseek (unsigned int, unsigned long,
30 unsigned long, long long *, unsigned int);
31
32 #ifdef __NR__llseek
33
34 static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high,
35 unsigned long, offset_low,long long *,result,
36 unsigned int, origin)
37
38 #else
39
40 /* no __NR__llseek on compilation machine - might give it explicitly */
41 static int _llseek (unsigned int fd, unsigned long oh,
42 unsigned long ol, long long *result,
43 unsigned int origin) {
44 errno = ENOSYS;
45 return -1;
46 }
47
48 #endif
49
50 static long long my_llseek (unsigned int fd, long long offset,
51 unsigned int origin)
52 {
53 long long result;
54 int retval;
55
56 retval = _llseek (fd, ((unsigned long long) offset) >> 32,
57 ((unsigned long long) offset) & 0xffffffff,
58 &result, origin);
59 return (retval == -1 ? (long long) retval : result);
60 }
61
62 #endif /* __alpha__ */
63
64 #endif /* HAVE_LLSEEK */
65
66 long long ext2_llseek (unsigned int fd, long long offset,
67 unsigned int origin)
68 {
69 long long result;
70 static int do_compat = 0;
71
72 if (!do_compat) {
73 result = my_llseek (fd, offset, origin);
74 if (!(result == -1 && errno == ENOSYS))
75 return result;
76
77 /*
78 * Just in case this code runs on top of an old kernel
79 * which does not support the llseek system call
80 */
81 do_compat = 1;
82 /*
83 * Now try ordinary lseek.
84 */
85 }
86
87 if ((sizeof(off_t) >= sizeof(long long)) ||
88 (offset < ((long long) 1 << ((sizeof(off_t)*8) -1))))
89 return lseek(fd, (off_t) offset, origin);
90
91 errno = EINVAL;
92 return -1;
93 }
94
95 #else /* !linux */
96
97 long long ext2_llseek (unsigned int fd, long long offset,
98 unsigned int origin)
99 {
100 if ((sizeof(off_t) < sizeof(long long)) &&
101 (offset >= ((long long) 1 << ((sizeof(off_t)*8) -1)))) {
102 errno = EINVAL;
103 return -1;
104 }
105 return lseek (fd, (off_t) offset, origin);
106 }
107
108 #endif /* linux */
109
110