1f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o/*
2f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o * llseek.c -- stub calling the llseek system call
3f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o *
41c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o * Copyright (C) 1994, 1995, 1996, 1997 Theodore Ts'o.
519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o *
619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %Begin-Header%
7543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library
8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2.
919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %End-Header%
10f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o */
11f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
12dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#define _LARGEFILE_SOURCE
13dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#define _LARGEFILE64_SOURCE
14dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o
151d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#if HAVE_SYS_TYPES_H
16f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <sys/types.h>
171d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#endif
18f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
19c555aebde40afdc0d15d674f2c81c0e05cfded3fTheodore Ts'o#if HAVE_ERRNO_H
20f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <errno.h>
21c555aebde40afdc0d15d674f2c81c0e05cfded3fTheodore Ts'o#endif
224cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#if HAVE_UNISTD_H
23f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <unistd.h>
244cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#endif
253cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o#ifdef __MSDOS__
263cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o#include <io.h>
273cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o#endif
28f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include "et/com_err.h"
29d40259fd552d942903f2fd0b426c75a5c2516017Theodore Ts'o#include "ext2fs/ext2_io.h"
30f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
31f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#ifdef __linux__
32f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
33dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
34dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o
35dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#define my_llseek lseek64
36dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o
3748e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o#else
3848e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o#if defined(HAVE_LLSEEK)
3950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <syscall.h>
4050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
41b0b9c4dece61ec03c655d50c2eade45ca427e069Theodore Ts'o#ifndef HAVE_LLSEEK_PROTOTYPE
42b0b9c4dece61ec03c655d50c2eade45ca427e069Theodore Ts'oextern long long llseek (int fd, long long offset, int origin);
431c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o#endif
441c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o
451c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o#define my_llseek llseek
461c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o
47dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#else	/* ! HAVE_LLSEEK */
4850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
49c2dbc18a9425815b6e93eb8b95d05a1168fb6e23Theodore Ts'o#if SIZEOF_LONG == SIZEOF_LONG_LONG
5050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
516c6a75dc1ed760f80417dd52a2a7b570fb738a0aJP Abgrall#define my_llseek lseek
5250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
53c2dbc18a9425815b6e93eb8b95d05a1168fb6e23Theodore Ts'o#else /* SIZEOF_LONG != SIZEOF_LONG_LONG */
5450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
5550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <linux/unistd.h>
5650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
57f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#ifndef __NR__llseek
58f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#define __NR__llseek            140
59f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#endif
60f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
611c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o#ifndef __i386__
62f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ostatic int _llseek (unsigned int, unsigned long,
63f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		   unsigned long, ext2_loff_t *, unsigned int);
64f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
65f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ostatic _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high,
66f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		 unsigned long, offset_low,ext2_loff_t *,result,
67f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		 unsigned int, origin)
681c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o#endif
69f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
701c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'ostatic ext2_loff_t my_llseek (int fd, ext2_loff_t offset, int origin)
7150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{
7250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	ext2_loff_t result;
7350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	int retval;
7450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
751c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o#ifndef __i386__
761c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o	retval = _llseek(fd, ((unsigned long long) offset) >> 32,
77efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o#else
781c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o	retval = syscall(__NR__llseek, fd, (unsigned long long) (offset >> 32),
791c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o#endif
801c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o			  ((unsigned long long) offset) & 0xffffffff,
8150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			&result, origin);
8250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	return (retval == -1 ? (ext2_loff_t) retval : result);
8350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o}
8450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
856c6a75dc1ed760f80417dd52a2a7b570fb738a0aJP Abgrall#endif	/* SIZE_LONG == SIZEOF_LONG_LONG */
8650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
87dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#endif /* HAVE_LLSEEK */
8848e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o#endif /* defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) */
8950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
901c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'oext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
91f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{
92e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#if SIZEOF_OFF_T >= SIZEOF_LONG_LONG
936c6a75dc1ed760f80417dd52a2a7b570fb738a0aJP Abgrall	return my_llseek (fd, offset, origin);
94e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#else
95f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	ext2_loff_t result;
96f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	static int do_compat = 0;
97f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
98e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (do_compat)
99e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		goto fallback;
100efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1011c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o	result = my_llseek (fd, offset, origin);
10250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (result == -1 && errno == ENOSYS) {
103f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		/*
104f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		 * Just in case this code runs on top of an old kernel
105f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		 * which does not support the llseek system call
106f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		 */
107f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		do_compat++;
108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	fallback:
109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))
110e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			return lseek(fd, (off_t) offset, origin);
11150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		errno = EINVAL;
112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		return -1;
113f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	}
114f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	return result;
115e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif
116f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o}
117f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
11850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#else /* !linux */
119f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
12073f17cfc391221a5466e95c9dc1802564ce38973Theodore Ts'o#ifndef EINVAL
12173f17cfc391221a5466e95c9dc1802564ce38973Theodore Ts'o#define EINVAL EXT2_ET_INVALID_ARGUMENT
12273f17cfc391221a5466e95c9dc1802564ce38973Theodore Ts'o#endif
12373f17cfc391221a5466e95c9dc1802564ce38973Theodore Ts'o
124d163b0948731e6d84bd3efe75075a2d0a8009272Theodore Ts'oext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
125f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{
126488f3c2dad93af023e8db2394d9b2af6439048f0Theodore Ts'o#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
127488f3c2dad93af023e8db2394d9b2af6439048f0Theodore Ts'o	return lseek64 (fd, offset, origin);
128488f3c2dad93af023e8db2394d9b2af6439048f0Theodore Ts'o#else
129f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	if ((sizeof(off_t) < sizeof(ext2_loff_t)) &&
130f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	    (offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) {
13173f17cfc391221a5466e95c9dc1802564ce38973Theodore Ts'o		errno = EINVAL;
132f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		return -1;
133f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	}
134f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	return lseek (fd, (off_t) offset, origin);
135488f3c2dad93af023e8db2394d9b2af6439048f0Theodore Ts'o#endif
136f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o}
137f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
13850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif 	/* linux */
139f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
140f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
141