blob: cd47b2df20069b15d3a154f0820b4d48e968c3a0 [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
12#include <sys/types.h>
13
14#include <errno.h>
Theodore Ts'o3cb6c501997-08-11 20:29:22 +000015#include <stdlib.h>
Theodore Ts'o4cbe8af1997-08-10 23:07:40 +000016#if HAVE_UNISTD_H
Theodore Ts'of3db3561997-04-26 13:34:30 +000017#include <unistd.h>
Theodore Ts'o4cbe8af1997-08-10 23:07:40 +000018#endif
Theodore Ts'o3cb6c501997-08-11 20:29:22 +000019#ifdef __MSDOS__
20#include <io.h>
21#endif
Theodore Ts'of3db3561997-04-26 13:34:30 +000022#include "et/com_err.h"
23#include "ext2fs/io.h"
24
25#ifdef __linux__
26
Theodore Ts'o50e1e101997-04-26 13:58:21 +000027#ifdef HAVE_LLSEEK
Theodore Ts'o4cbe8af1997-08-10 23:07:40 +000028#if HAVE_UNISTD_H
Theodore Ts'o50e1e101997-04-26 13:58:21 +000029#include <unistd.h>
Theodore Ts'o4cbe8af1997-08-10 23:07:40 +000030#endif
Theodore Ts'o50e1e101997-04-26 13:58:21 +000031#include <syscall.h>
32
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000033#if (__GLIBC__ == 2)
34ext2_loff_t llseek (int fd, ext2_loff_t offset, int origin)
35#endif
36
37#define my_llseek llseek
38
Theodore Ts'o50e1e101997-04-26 13:58:21 +000039#else /* HAVE_LLSEEK */
40
41#ifdef __alpha__
42
43#define llseek lseek
44
45#else /* !__alpha__ */
46
47#include <linux/unistd.h>
48
Theodore Ts'of3db3561997-04-26 13:34:30 +000049#ifndef __NR__llseek
50#define __NR__llseek 140
51#endif
52
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000053#ifndef __i386__
Theodore Ts'of3db3561997-04-26 13:34:30 +000054static int _llseek (unsigned int, unsigned long,
55 unsigned long, ext2_loff_t *, unsigned int);
56
57static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high,
58 unsigned long, offset_low,ext2_loff_t *,result,
59 unsigned int, origin)
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000060#endif
Theodore Ts'of3db3561997-04-26 13:34:30 +000061
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000062static ext2_loff_t my_llseek (int fd, ext2_loff_t offset, int origin)
Theodore Ts'o50e1e101997-04-26 13:58:21 +000063{
64 ext2_loff_t result;
65 int retval;
66
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000067#ifndef __i386__
68 retval = _llseek(fd, ((unsigned long long) offset) >> 32,
69#else
70 retval = syscall(__NR__llseek, fd, (unsigned long long) (offset >> 32),
71#endif
72 ((unsigned long long) offset) & 0xffffffff,
Theodore Ts'o50e1e101997-04-26 13:58:21 +000073 &result, origin);
74 return (retval == -1 ? (ext2_loff_t) retval : result);
75}
76
77#endif /* HAVE_LLSEEK */
78
79#endif /* __alpha__ */
80
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000081ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
Theodore Ts'of3db3561997-04-26 13:34:30 +000082{
Theodore Ts'of3db3561997-04-26 13:34:30 +000083 ext2_loff_t result;
Theodore Ts'of3db3561997-04-26 13:34:30 +000084 static int do_compat = 0;
85
Theodore Ts'o50e1e101997-04-26 13:58:21 +000086 if ((sizeof(off_t) >= sizeof(ext2_loff_t)) ||
87 (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1))))
88 return lseek(fd, (off_t) offset, origin);
89
Theodore Ts'of3db3561997-04-26 13:34:30 +000090 if (do_compat) {
Theodore Ts'o50e1e101997-04-26 13:58:21 +000091 errno = EINVAL;
92 return -1;
Theodore Ts'of3db3561997-04-26 13:34:30 +000093 }
94
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000095 result = my_llseek (fd, offset, origin);
Theodore Ts'o50e1e101997-04-26 13:58:21 +000096 if (result == -1 && errno == ENOSYS) {
Theodore Ts'of3db3561997-04-26 13:34:30 +000097 /*
98 * Just in case this code runs on top of an old kernel
99 * which does not support the llseek system call
100 */
101 do_compat++;
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000102 errno = EINVAL;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000103 }
Theodore Ts'of3db3561997-04-26 13:34:30 +0000104 return result;
105}
106
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000107#else /* !linux */
Theodore Ts'of3db3561997-04-26 13:34:30 +0000108
Theodore Ts'o19c78dc1997-04-29 16:17:09 +0000109ext2_loff_t ext2fs_llseek (unsigned int fd, ext2_loff_t offset,
Theodore Ts'of3db3561997-04-26 13:34:30 +0000110 unsigned int origin)
111{
112 if ((sizeof(off_t) < sizeof(ext2_loff_t)) &&
113 (offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) {
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000114 errno = EINVAL;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000115 return -1;
116 }
117 return lseek (fd, (off_t) offset, origin);
118}
119
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000120#endif /* linux */
Theodore Ts'of3db3561997-04-26 13:34:30 +0000121
122