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
12f1644c324bd6bc0ed8f48275d64ccde4ce13a044Theodore Ts'o#ifndef _LARGEFILE_SOURCE
13dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#define _LARGEFILE_SOURCE
14f1644c324bd6bc0ed8f48275d64ccde4ce13a044Theodore Ts'o#endif
15f1644c324bd6bc0ed8f48275d64ccde4ce13a044Theodore Ts'o#ifndef _LARGEFILE64_SOURCE
16dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#define _LARGEFILE64_SOURCE
17f1644c324bd6bc0ed8f48275d64ccde4ce13a044Theodore Ts'o#endif
18dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o
19d1154eb460efe588eaed3d439c1caaca149fa362Theodore Ts'o#include "config.h"
201d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#if HAVE_SYS_TYPES_H
21f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <sys/types.h>
221d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#endif
23f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
24c555aebde40afdc0d15d674f2c81c0e05cfded3fTheodore Ts'o#if HAVE_ERRNO_H
25f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <errno.h>
26c555aebde40afdc0d15d674f2c81c0e05cfded3fTheodore Ts'o#endif
274cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#if HAVE_UNISTD_H
28f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <unistd.h>
294cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#endif
303cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o#ifdef __MSDOS__
313cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o#include <io.h>
323cb6c5021d722e17b7105d1bc090880671f6fc6dTheodore Ts'o#endif
33f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include "et/com_err.h"
34d40259fd552d942903f2fd0b426c75a5c2516017Theodore Ts'o#include "ext2fs/ext2_io.h"
35f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
36f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#ifdef __linux__
37f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
38dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
39dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o
40dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#define my_llseek lseek64
41dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o
4248e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o#else
4348e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o#if defined(HAVE_LLSEEK)
44599915f080dc0f62a3e800c5bc8fe31ae8b45707Theodore Ts'o#include <sys/syscall.h>
4550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
46b0b9c4dece61ec03c655d50c2eade45ca427e069Theodore Ts'o#ifndef HAVE_LLSEEK_PROTOTYPE
47b0b9c4dece61ec03c655d50c2eade45ca427e069Theodore Ts'oextern long long llseek (int fd, long long offset, int origin);
481c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o#endif
491c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o
501c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o#define my_llseek llseek
511c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o
52dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#else	/* ! HAVE_LLSEEK */
5350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
54c2dbc18a9425815b6e93eb8b95d05a1168fb6e23Theodore Ts'o#if SIZEOF_LONG == SIZEOF_LONG_LONG
5550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
565efe492d19ae6fc876b504a53621169f63f1ce96JP Abgrall#define my_llseek lseek
5750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
58c2dbc18a9425815b6e93eb8b95d05a1168fb6e23Theodore Ts'o#else /* SIZEOF_LONG != SIZEOF_LONG_LONG */
5950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
6050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <linux/unistd.h>
6150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
62f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#ifndef __NR__llseek
63f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#define __NR__llseek            140
64f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#endif
65f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
661c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o#ifndef __i386__
67f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ostatic int _llseek (unsigned int, unsigned long,
68f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		   unsigned long, ext2_loff_t *, unsigned int);
69f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
70f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ostatic _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high,
71f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		 unsigned long, offset_low,ext2_loff_t *,result,
72f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		 unsigned int, origin)
731c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o#endif
74f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
751c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'ostatic ext2_loff_t my_llseek (int fd, ext2_loff_t offset, int origin)
7650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{
7750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	ext2_loff_t result;
7850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	int retval;
7950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
801c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o#ifndef __i386__
811c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o	retval = _llseek(fd, ((unsigned long long) offset) >> 32,
82efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o#else
831c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o	retval = syscall(__NR__llseek, fd, (unsigned long long) (offset >> 32),
841c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o#endif
851c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o			  ((unsigned long long) offset) & 0xffffffff,
8650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o			&result, origin);
8750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	return (retval == -1 ? (ext2_loff_t) retval : result);
8850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o}
8950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
905efe492d19ae6fc876b504a53621169f63f1ce96JP Abgrall#endif	/* SIZE_LONG == SIZEOF_LONG_LONG */
9150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
92dc5f68cad3c8ee4c583acf9afbfdb7354cd3d6afTheodore Ts'o#endif /* HAVE_LLSEEK */
9348e6e81362f264aee4f3945c14928efaf71a06c9Theodore Ts'o#endif /* defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) */
9450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
951c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'oext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
96f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{
97274d46e1d35af423d0292d63c4d0ad7a03be82baPhillip Susi#if SIZEOF_OFF_T >= SIZEOF_LONG_LONG
985efe492d19ae6fc876b504a53621169f63f1ce96JP Abgrall	return my_llseek (fd, offset, origin);
99274d46e1d35af423d0292d63c4d0ad7a03be82baPhillip Susi#else
100f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	ext2_loff_t result;
101f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	static int do_compat = 0;
102f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
103274d46e1d35af423d0292d63c4d0ad7a03be82baPhillip Susi	if (do_compat)
104274d46e1d35af423d0292d63c4d0ad7a03be82baPhillip Susi		goto fallback;
105efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1061c27cac2e848300a515cc994bc71ee48e2f3fa19Theodore Ts'o	result = my_llseek (fd, offset, origin);
10750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (result == -1 && errno == ENOSYS) {
108f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		/*
109f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		 * Just in case this code runs on top of an old kernel
110f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		 * which does not support the llseek system call
111f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		 */
112f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		do_compat++;
113274d46e1d35af423d0292d63c4d0ad7a03be82baPhillip Susi	fallback:
114274d46e1d35af423d0292d63c4d0ad7a03be82baPhillip Susi		if (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))
115274d46e1d35af423d0292d63c4d0ad7a03be82baPhillip Susi			return lseek(fd, (off_t) offset, origin);
11650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		errno = EINVAL;
117274d46e1d35af423d0292d63c4d0ad7a03be82baPhillip Susi		return -1;
118f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	}
119f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	return result;
120274d46e1d35af423d0292d63c4d0ad7a03be82baPhillip Susi#endif
121f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o}
122f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
12350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#else /* !linux */
124f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
12573f17cfc391221a5466e95c9dc1802564ce38973Theodore Ts'o#ifndef EINVAL
12673f17cfc391221a5466e95c9dc1802564ce38973Theodore Ts'o#define EINVAL EXT2_ET_INVALID_ARGUMENT
12773f17cfc391221a5466e95c9dc1802564ce38973Theodore Ts'o#endif
12873f17cfc391221a5466e95c9dc1802564ce38973Theodore Ts'o
129d163b0948731e6d84bd3efe75075a2d0a8009272Theodore Ts'oext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
130f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{
131488f3c2dad93af023e8db2394d9b2af6439048f0Theodore Ts'o#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
132488f3c2dad93af023e8db2394d9b2af6439048f0Theodore Ts'o	return lseek64 (fd, offset, origin);
133488f3c2dad93af023e8db2394d9b2af6439048f0Theodore Ts'o#else
134f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	if ((sizeof(off_t) < sizeof(ext2_loff_t)) &&
135f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	    (offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) {
13673f17cfc391221a5466e95c9dc1802564ce38973Theodore Ts'o		errno = EINVAL;
137f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		return -1;
138f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	}
139f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	return lseek (fd, (off_t) offset, origin);
140488f3c2dad93af023e8db2394d9b2af6439048f0Theodore Ts'o#endif
141f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o}
142f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
14350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif 	/* linux */
144f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
145f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
146