]>
Commit | Line | Data |
---|---|---|
6dbe3af9 KZ |
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> | |
fd6b7a7f | 12 | |
df1dddf9 | 13 | extern long long ext2_llseek (unsigned int, long long, unsigned int); |
6dbe3af9 KZ |
14 | |
15 | #ifdef __linux__ | |
16 | ||
fd6b7a7f KZ |
17 | #ifdef HAVE_LLSEEK |
18 | #include <syscall.h> | |
19 | ||
20 | #else /* HAVE_LLSEEK */ | |
21 | ||
95f1bdee | 22 | #if defined(__alpha__) || defined(__ia64__) || defined(__s390x__) |
fd6b7a7f KZ |
23 | |
24 | #define my_llseek lseek | |
25 | ||
2b6fc908 KZ |
26 | #else |
27 | #include <linux/unistd.h> /* for __NR__llseek */ | |
6dbe3af9 KZ |
28 | |
29 | static int _llseek (unsigned int, unsigned long, | |
df1dddf9 | 30 | unsigned long, long long *, unsigned int); |
6dbe3af9 | 31 | |
66ee8158 KZ |
32 | #ifdef __NR__llseek |
33 | ||
6dbe3af9 | 34 | static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high, |
df1dddf9 | 35 | unsigned long, offset_low,long long *,result, |
6dbe3af9 KZ |
36 | unsigned int, origin) |
37 | ||
66ee8158 KZ |
38 | #else |
39 | ||
40 | /* no __NR__llseek on compilation machine - might give it explicitly */ | |
41 | static int _llseek (unsigned int fd, unsigned long oh, | |
df1dddf9 | 42 | unsigned long ol, long long *result, |
66ee8158 KZ |
43 | unsigned int origin) { |
44 | errno = ENOSYS; | |
45 | return -1; | |
46 | } | |
47 | ||
48 | #endif | |
49 | ||
df1dddf9 | 50 | static long long my_llseek (unsigned int fd, long long offset, |
fd6b7a7f KZ |
51 | unsigned int origin) |
52 | { | |
df1dddf9 | 53 | long long result; |
fd6b7a7f KZ |
54 | int retval; |
55 | ||
56 | retval = _llseek (fd, ((unsigned long long) offset) >> 32, | |
57 | ((unsigned long long) offset) & 0xffffffff, | |
58 | &result, origin); | |
df1dddf9 | 59 | return (retval == -1 ? (long long) retval : result); |
fd6b7a7f KZ |
60 | } |
61 | ||
fd6b7a7f KZ |
62 | #endif /* __alpha__ */ |
63 | ||
64 | #endif /* HAVE_LLSEEK */ | |
65 | ||
df1dddf9 | 66 | long long ext2_llseek (unsigned int fd, long long offset, |
6dbe3af9 KZ |
67 | unsigned int origin) |
68 | { | |
df1dddf9 | 69 | long long result; |
6dbe3af9 KZ |
70 | static int do_compat = 0; |
71 | ||
2b6fc908 KZ |
72 | if (!do_compat) { |
73 | result = my_llseek (fd, offset, origin); | |
74 | if (!(result == -1 && errno == ENOSYS)) | |
75 | return result; | |
fd6b7a7f | 76 | |
6dbe3af9 KZ |
77 | /* |
78 | * Just in case this code runs on top of an old kernel | |
79 | * which does not support the llseek system call | |
80 | */ | |
2b6fc908 KZ |
81 | do_compat = 1; |
82 | /* | |
83 | * Now try ordinary lseek. | |
84 | */ | |
6dbe3af9 | 85 | } |
2b6fc908 | 86 | |
df1dddf9 KZ |
87 | if ((sizeof(off_t) >= sizeof(long long)) || |
88 | (offset < ((long long) 1 << ((sizeof(off_t)*8) -1)))) | |
2b6fc908 KZ |
89 | return lseek(fd, (off_t) offset, origin); |
90 | ||
91 | errno = EINVAL; | |
92 | return -1; | |
6dbe3af9 KZ |
93 | } |
94 | ||
fd6b7a7f | 95 | #else /* !linux */ |
6dbe3af9 | 96 | |
df1dddf9 | 97 | long long ext2_llseek (unsigned int fd, long long offset, |
6dbe3af9 KZ |
98 | unsigned int origin) |
99 | { | |
df1dddf9 KZ |
100 | if ((sizeof(off_t) < sizeof(long long)) && |
101 | (offset >= ((long long) 1 << ((sizeof(off_t)*8) -1)))) { | |
fd6b7a7f | 102 | errno = EINVAL; |
6dbe3af9 KZ |
103 | return -1; |
104 | } | |
105 | return lseek (fd, (off_t) offset, origin); | |
106 | } | |
107 | ||
fd6b7a7f | 108 | #endif /* linux */ |
6dbe3af9 KZ |
109 | |
110 |