OSDN Git Service

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