blob: 073cf91a061fc8d82d4775bafc0af5bc1ec7af13 [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%
7 * This file may be redistributed under the terms of the GNU Public
8 * License.
9 * %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'o1d2ff461997-10-19 23:00:21 +000015#if HAVE_SYS_TYPES_H
Theodore Ts'of3db3561997-04-26 13:34:30 +000016#include <sys/types.h>
Theodore Ts'o1d2ff461997-10-19 23:00:21 +000017#endif
Theodore Ts'of3db3561997-04-26 13:34:30 +000018
Theodore Ts'oc555aeb1997-10-25 04:16:53 +000019#if HAVE_ERRNO_H
Theodore Ts'of3db3561997-04-26 13:34:30 +000020#include <errno.h>
Theodore Ts'oc555aeb1997-10-25 04:16:53 +000021#endif
Theodore Ts'o4cbe8af1997-08-10 23:07:40 +000022#if HAVE_UNISTD_H
Theodore Ts'of3db3561997-04-26 13:34:30 +000023#include <unistd.h>
Theodore Ts'o4cbe8af1997-08-10 23:07:40 +000024#endif
Theodore Ts'o3cb6c501997-08-11 20:29:22 +000025#ifdef __MSDOS__
26#include <io.h>
27#endif
Theodore Ts'of3db3561997-04-26 13:34:30 +000028#include "et/com_err.h"
Theodore Ts'od40259f1997-10-20 00:44:26 +000029#include "ext2fs/ext2_io.h"
Theodore Ts'of3db3561997-04-26 13:34:30 +000030
31#ifdef __linux__
32
Theodore Ts'odc5f68c2000-05-25 23:31:54 +000033#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
34
35#define my_llseek lseek64
36
Theodore Ts'o48e6e812003-07-06 00:36:48 -040037#else
38#if defined(HAVE_LLSEEK)
Theodore Ts'o50e1e101997-04-26 13:58:21 +000039#include <syscall.h>
40
Theodore Ts'ob0b9c4d1997-10-20 23:36:30 +000041#ifndef HAVE_LLSEEK_PROTOTYPE
42extern long long llseek (int fd, long long offset, int origin);
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000043#endif
44
45#define my_llseek llseek
46
Theodore Ts'odc5f68c2000-05-25 23:31:54 +000047#else /* ! HAVE_LLSEEK */
Theodore Ts'o50e1e101997-04-26 13:58:21 +000048
Theodore Ts'oc2dbc182008-01-27 00:35:32 -050049#if SIZEOF_LONG == SIZEOF_LONG_LONG
Theodore Ts'o50e1e101997-04-26 13:58:21 +000050
51#define llseek lseek
52
Theodore Ts'oc2dbc182008-01-27 00:35:32 -050053#else /* SIZEOF_LONG != SIZEOF_LONG_LONG */
Theodore Ts'o50e1e101997-04-26 13:58:21 +000054
55#include <linux/unistd.h>
56
Theodore Ts'of3db3561997-04-26 13:34:30 +000057#ifndef __NR__llseek
58#define __NR__llseek 140
59#endif
60
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000061#ifndef __i386__
Theodore Ts'of3db3561997-04-26 13:34:30 +000062static int _llseek (unsigned int, unsigned long,
63 unsigned long, ext2_loff_t *, unsigned int);
64
65static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high,
66 unsigned long, offset_low,ext2_loff_t *,result,
67 unsigned int, origin)
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000068#endif
Theodore Ts'of3db3561997-04-26 13:34:30 +000069
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000070static ext2_loff_t my_llseek (int fd, ext2_loff_t offset, int origin)
Theodore Ts'o50e1e101997-04-26 13:58:21 +000071{
72 ext2_loff_t result;
73 int retval;
74
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000075#ifndef __i386__
76 retval = _llseek(fd, ((unsigned long long) offset) >> 32,
Theodore Ts'oefc6f622008-08-27 23:07:54 -040077#else
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000078 retval = syscall(__NR__llseek, fd, (unsigned long long) (offset >> 32),
79#endif
80 ((unsigned long long) offset) & 0xffffffff,
Theodore Ts'o50e1e101997-04-26 13:58:21 +000081 &result, origin);
82 return (retval == -1 ? (ext2_loff_t) retval : result);
83}
84
Theodore Ts'o43819662000-10-25 02:06:09 +000085#endif /* __alpha__ || __ia64__ */
Theodore Ts'o50e1e101997-04-26 13:58:21 +000086
Theodore Ts'odc5f68c2000-05-25 23:31:54 +000087#endif /* HAVE_LLSEEK */
Theodore Ts'o48e6e812003-07-06 00:36:48 -040088#endif /* defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) */
Theodore Ts'o50e1e101997-04-26 13:58:21 +000089
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000090ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
Theodore Ts'of3db3561997-04-26 13:34:30 +000091{
Theodore Ts'of3db3561997-04-26 13:34:30 +000092 ext2_loff_t result;
Theodore Ts'of3db3561997-04-26 13:34:30 +000093 static int do_compat = 0;
94
Theodore Ts'o50e1e101997-04-26 13:58:21 +000095 if ((sizeof(off_t) >= sizeof(ext2_loff_t)) ||
96 (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1))))
97 return lseek(fd, (off_t) offset, origin);
98
Theodore Ts'of3db3561997-04-26 13:34:30 +000099 if (do_compat) {
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000100 errno = EINVAL;
101 return -1;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000102 }
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400103
Theodore Ts'o1c27cac1997-08-14 17:20:42 +0000104 result = my_llseek (fd, offset, origin);
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000105 if (result == -1 && errno == ENOSYS) {
Theodore Ts'of3db3561997-04-26 13:34:30 +0000106 /*
107 * Just in case this code runs on top of an old kernel
108 * which does not support the llseek system call
109 */
110 do_compat++;
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000111 errno = EINVAL;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000112 }
Theodore Ts'of3db3561997-04-26 13:34:30 +0000113 return result;
114}
115
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000116#else /* !linux */
Theodore Ts'of3db3561997-04-26 13:34:30 +0000117
Theodore Ts'o73f17cf1999-01-04 07:35:45 +0000118#ifndef EINVAL
119#define EINVAL EXT2_ET_INVALID_ARGUMENT
120#endif
121
Theodore Ts'od163b091997-10-03 17:42:28 +0000122ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000123{
Theodore Ts'o488f3c22004-09-17 17:47:12 -0400124#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
125 return lseek64 (fd, offset, origin);
126#else
Theodore Ts'of3db3561997-04-26 13:34:30 +0000127 if ((sizeof(off_t) < sizeof(ext2_loff_t)) &&
128 (offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) {
Theodore Ts'o73f17cf1999-01-04 07:35:45 +0000129 errno = EINVAL;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000130 return -1;
131 }
132 return lseek (fd, (off_t) offset, origin);
Theodore Ts'o488f3c22004-09-17 17:47:12 -0400133#endif
Theodore Ts'of3db3561997-04-26 13:34:30 +0000134}
135
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000136#endif /* linux */
Theodore Ts'of3db3561997-04-26 13:34:30 +0000137
138