1e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o/*
2e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * llseek.c -- stub calling the llseek system call
3e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o *
4e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * Copyright (C) 1994, 1995, 1996, 1997 Theodore Ts'o.
5e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o *
6e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * %Begin-Header%
7e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * This file may be redistributed under the terms of the
8e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * GNU Lesser General Public License.
9e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o * %End-Header%
10e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o */
11e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
12e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#define _LARGEFILE_SOURCE
13e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#define _LARGEFILE64_SOURCE
14e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
15e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#if HAVE_SYS_TYPES_H
16e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <sys/types.h>
17e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
18e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
19e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#if HAVE_ERRNO_H
20e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <errno.h>
21e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
22e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#if HAVE_UNISTD_H
23e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <unistd.h>
24e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
25e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#ifdef __MSDOS__
26e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <io.h>
27e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
28e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
297a603aa89fcffb8798eca34ca3858db6f0393046Theodore Ts'o#include "blkidP.h"
30e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
31e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#ifdef __linux__
32e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
33e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
34e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
35e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#define my_llseek lseek64
36e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
37e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#elif defined(HAVE_LLSEEK)
38e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <syscall.h>
39e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
40e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#ifndef HAVE_LLSEEK_PROTOTYPE
41e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'oextern long long llseek(int fd, long long offset, int origin);
42e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
43e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
44e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#define my_llseek llseek
45e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
46e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#else	/* ! HAVE_LLSEEK */
47e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
48c2dbc18a9425815b6e93eb8b95d05a1168fb6e23Theodore Ts'o#if SIZEOF_LONG == SIZEOF_LONG_LONG
49e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
50e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#define llseek lseek
51e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
52c2dbc18a9425815b6e93eb8b95d05a1168fb6e23Theodore Ts'o#else /* SIZEOF_LONG != SIZEOF_LONG_LONG */
53e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
54e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#include <linux/unistd.h>
55e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
56e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#ifndef __NR__llseek
57e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#define __NR__llseek            140
58e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
59e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
60e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#ifndef __i386__
61e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'ostatic int _llseek(unsigned int, unsigned long, unsigned long,
62e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		   blkid_loff_t *, unsigned int);
63e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
64e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'ostatic _syscall5(int, _llseek, unsigned int, fd, unsigned long, offset_high,
65e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		 unsigned long, offset_low, blkid_loff_t *, result,
66e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		 unsigned int, origin)
67e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
68e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
69e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'ostatic blkid_loff_t my_llseek(int fd, blkid_loff_t offset, int origin)
70e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o{
71e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	blkid_loff_t result;
72e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	int retval;
73e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
74e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#ifndef __i386__
75e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	retval = _llseek(fd, ((unsigned long long) offset) >> 32,
76e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o			 ((unsigned long long)offset) & 0xffffffff,
77e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o			 &result, origin);
78e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#else
79e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	retval = syscall(__NR__llseek, fd, ((unsigned long long) offset) >> 32,
80e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o			 ((unsigned long long)offset) & 0xffffffff,
81e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o			 &result, origin);
82e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
83e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	return (retval == -1 ? (blkid_loff_t) retval : result);
84e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o}
85e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
86e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif	/* __alpha__ || __ia64__ */
87e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
88e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif /* HAVE_LLSEEK */
89e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
90e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'oblkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence)
91e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o{
92e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	blkid_loff_t result;
93e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	static int do_compat = 0;
94e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
95e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	if ((sizeof(off_t) >= sizeof(blkid_loff_t)) ||
96e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	    (offset < ((blkid_loff_t) 1 << ((sizeof(off_t)*8) -1))))
97e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		return lseek(fd, (off_t) offset, whence);
98e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
99e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	if (do_compat) {
100e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		errno = EOVERFLOW;
101e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		return -1;
102e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	}
103e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
104e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	result = my_llseek(fd, offset, whence);
105e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	if (result == -1 && errno == ENOSYS) {
106e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		/*
107e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		 * Just in case this code runs on top of an old kernel
108e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		 * which does not support the llseek system call
109e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		 */
110e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		do_compat++;
111e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		errno = EOVERFLOW;
112e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	}
113e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	return result;
114e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o}
115e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
116e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#else /* !linux */
117e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
118e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#ifndef EOVERFLOW
119e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#ifdef EXT2_ET_INVALID_ARGUMENT
120e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#define EOVERFLOW EXT2_ET_INVALID_ARGUMENT
121e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#else
122e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#define EOVERFLOW 112
123e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
124e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif
125e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
126e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'oblkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int origin)
127e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o{
128488f3c2dad93af023e8db2394d9b2af6439048f0Theodore Ts'o#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
129488f3c2dad93af023e8db2394d9b2af6439048f0Theodore Ts'o	return lseek64 (fd, offset, origin);
130488f3c2dad93af023e8db2394d9b2af6439048f0Theodore Ts'o#else
131e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	if ((sizeof(off_t) < sizeof(blkid_loff_t)) &&
132e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	    (offset >= ((blkid_loff_t) 1 << ((sizeof(off_t)*8) - 1)))) {
133e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		errno = EOVERFLOW;
134e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o		return -1;
135e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	}
136e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o	return lseek(fd, (off_t) offset, origin);
137488f3c2dad93af023e8db2394d9b2af6439048f0Theodore Ts'o#endif
138e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o}
139e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
140e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o#endif	/* linux */
141e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
142e12f2ae74c2eb8997bf13adf8fdd7e7313971eaeTheodore Ts'o
143