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