blob: c3a98a2c3cf20a94d328c67bf3e9873ae266c90d [file] [log] [blame]
Theodore Ts'of3db3561997-04-26 13:34:30 +00001/*
2 * llseek.c -- stub calling the llseek system call
3 *
Theodore Ts'o1c27cac1997-08-14 17:20:42 +00004 * Copyright (C) 1994, 1995, 1996, 1997 Theodore Ts'o.
Theodore Ts'o19c78dc1997-04-29 16:17:09 +00005 *
6 * %Begin-Header%
Theodore Ts'o543547a2010-05-17 21:31:56 -04007 * This file may be redistributed under the terms of the GNU Library
8 * General Public License, version 2.
Theodore Ts'o19c78dc1997-04-29 16:17:09 +00009 * %End-Header%
Theodore Ts'of3db3561997-04-26 13:34:30 +000010 */
11
Theodore Ts'odc5f68c2000-05-25 23:31:54 +000012#define _LARGEFILE_SOURCE
13#define _LARGEFILE64_SOURCE
14
Theodore Ts'od1154eb2011-09-18 17:34:37 -040015#include "config.h"
Theodore Ts'o1d2ff461997-10-19 23:00:21 +000016#if HAVE_SYS_TYPES_H
Theodore Ts'of3db3561997-04-26 13:34:30 +000017#include <sys/types.h>
Theodore Ts'o1d2ff461997-10-19 23:00:21 +000018#endif
Theodore Ts'of3db3561997-04-26 13:34:30 +000019
Theodore Ts'oc555aeb1997-10-25 04:16:53 +000020#if HAVE_ERRNO_H
Theodore Ts'of3db3561997-04-26 13:34:30 +000021#include <errno.h>
Theodore Ts'oc555aeb1997-10-25 04:16:53 +000022#endif
Theodore Ts'o4cbe8af1997-08-10 23:07:40 +000023#if HAVE_UNISTD_H
Theodore Ts'of3db3561997-04-26 13:34:30 +000024#include <unistd.h>
Theodore Ts'o4cbe8af1997-08-10 23:07:40 +000025#endif
Theodore Ts'o3cb6c501997-08-11 20:29:22 +000026#ifdef __MSDOS__
27#include <io.h>
28#endif
Theodore Ts'of3db3561997-04-26 13:34:30 +000029#include "et/com_err.h"
Theodore Ts'od40259f1997-10-20 00:44:26 +000030#include "ext2fs/ext2_io.h"
Theodore Ts'of3db3561997-04-26 13:34:30 +000031
32#ifdef __linux__
33
Theodore Ts'odc5f68c2000-05-25 23:31:54 +000034#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
35
36#define my_llseek lseek64
37
Theodore Ts'o48e6e812003-07-06 00:36:48 -040038#else
39#if defined(HAVE_LLSEEK)
Theodore Ts'o50e1e101997-04-26 13:58:21 +000040#include <syscall.h>
41
Theodore Ts'ob0b9c4d1997-10-20 23:36:30 +000042#ifndef HAVE_LLSEEK_PROTOTYPE
43extern long long llseek (int fd, long long offset, int origin);
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000044#endif
45
46#define my_llseek llseek
47
Theodore Ts'odc5f68c2000-05-25 23:31:54 +000048#else /* ! HAVE_LLSEEK */
Theodore Ts'o50e1e101997-04-26 13:58:21 +000049
Theodore Ts'oc2dbc182008-01-27 00:35:32 -050050#if SIZEOF_LONG == SIZEOF_LONG_LONG
Theodore Ts'o50e1e101997-04-26 13:58:21 +000051
52#define llseek lseek
53
Theodore Ts'oc2dbc182008-01-27 00:35:32 -050054#else /* SIZEOF_LONG != SIZEOF_LONG_LONG */
Theodore Ts'o50e1e101997-04-26 13:58:21 +000055
56#include <linux/unistd.h>
57
Theodore Ts'of3db3561997-04-26 13:34:30 +000058#ifndef __NR__llseek
59#define __NR__llseek 140
60#endif
61
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000062#ifndef __i386__
Theodore Ts'of3db3561997-04-26 13:34:30 +000063static int _llseek (unsigned int, unsigned long,
64 unsigned long, ext2_loff_t *, unsigned int);
65
66static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high,
67 unsigned long, offset_low,ext2_loff_t *,result,
68 unsigned int, origin)
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000069#endif
Theodore Ts'of3db3561997-04-26 13:34:30 +000070
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000071static ext2_loff_t my_llseek (int fd, ext2_loff_t offset, int origin)
Theodore Ts'o50e1e101997-04-26 13:58:21 +000072{
73 ext2_loff_t result;
74 int retval;
75
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000076#ifndef __i386__
77 retval = _llseek(fd, ((unsigned long long) offset) >> 32,
Theodore Ts'oefc6f622008-08-27 23:07:54 -040078#else
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000079 retval = syscall(__NR__llseek, fd, (unsigned long long) (offset >> 32),
80#endif
81 ((unsigned long long) offset) & 0xffffffff,
Theodore Ts'o50e1e101997-04-26 13:58:21 +000082 &result, origin);
83 return (retval == -1 ? (ext2_loff_t) retval : result);
84}
85
Theodore Ts'o43819662000-10-25 02:06:09 +000086#endif /* __alpha__ || __ia64__ */
Theodore Ts'o50e1e101997-04-26 13:58:21 +000087
Theodore Ts'odc5f68c2000-05-25 23:31:54 +000088#endif /* HAVE_LLSEEK */
Theodore Ts'o48e6e812003-07-06 00:36:48 -040089#endif /* defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) */
Theodore Ts'o50e1e101997-04-26 13:58:21 +000090
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000091ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
Theodore Ts'of3db3561997-04-26 13:34:30 +000092{
Phillip Susi274d46e2013-01-24 11:21:56 -050093#if SIZEOF_OFF_T >= SIZEOF_LONG_LONG
94 return lseek (fd, offset, origin);
95#else
Theodore Ts'of3db3561997-04-26 13:34:30 +000096 ext2_loff_t result;
Theodore Ts'of3db3561997-04-26 13:34:30 +000097 static int do_compat = 0;
98
Phillip Susi274d46e2013-01-24 11:21:56 -050099 if (do_compat)
100 goto fallback;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400101
Theodore Ts'o1c27cac1997-08-14 17:20:42 +0000102 result = my_llseek (fd, offset, origin);
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000103 if (result == -1 && errno == ENOSYS) {
Theodore Ts'of3db3561997-04-26 13:34:30 +0000104 /*
105 * Just in case this code runs on top of an old kernel
106 * which does not support the llseek system call
107 */
108 do_compat++;
Phillip Susi274d46e2013-01-24 11:21:56 -0500109 fallback:
110 if (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))
111 return lseek(fd, (off_t) offset, origin);
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000112 errno = EINVAL;
Phillip Susi274d46e2013-01-24 11:21:56 -0500113 return -1;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000114 }
Theodore Ts'of3db3561997-04-26 13:34:30 +0000115 return result;
Phillip Susi274d46e2013-01-24 11:21:56 -0500116#endif
Theodore Ts'of3db3561997-04-26 13:34:30 +0000117}
118
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000119#else /* !linux */
Theodore Ts'of3db3561997-04-26 13:34:30 +0000120
Theodore Ts'o73f17cf1999-01-04 07:35:45 +0000121#ifndef EINVAL
122#define EINVAL EXT2_ET_INVALID_ARGUMENT
123#endif
124
Theodore Ts'od163b091997-10-03 17:42:28 +0000125ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000126{
Theodore Ts'o488f3c22004-09-17 17:47:12 -0400127#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
128 return lseek64 (fd, offset, origin);
129#else
Theodore Ts'of3db3561997-04-26 13:34:30 +0000130 if ((sizeof(off_t) < sizeof(ext2_loff_t)) &&
131 (offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) {
Theodore Ts'o73f17cf1999-01-04 07:35:45 +0000132 errno = EINVAL;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000133 return -1;
134 }
135 return lseek (fd, (off_t) offset, origin);
Theodore Ts'o488f3c22004-09-17 17:47:12 -0400136#endif
Theodore Ts'of3db3561997-04-26 13:34:30 +0000137}
138
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000139#endif /* linux */
Theodore Ts'of3db3561997-04-26 13:34:30 +0000140
141