blob: 17d3d086d362b527c635348d3814a97aa9e1a7e4 [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
37#elif defined(HAVE_LLSEEK)
Theodore Ts'o50e1e101997-04-26 13:58:21 +000038#include <syscall.h>
39
Theodore Ts'ob0b9c4d1997-10-20 23:36:30 +000040#ifndef HAVE_LLSEEK_PROTOTYPE
41extern long long llseek (int fd, long long offset, int origin);
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000042#endif
43
44#define my_llseek llseek
45
Theodore Ts'odc5f68c2000-05-25 23:31:54 +000046#else /* ! HAVE_LLSEEK */
Theodore Ts'o50e1e101997-04-26 13:58:21 +000047
Theodore Ts'o43819662000-10-25 02:06:09 +000048#if defined(__alpha__) || defined (__ia64__)
Theodore Ts'o50e1e101997-04-26 13:58:21 +000049
50#define llseek lseek
51
Theodore Ts'o43819662000-10-25 02:06:09 +000052#else /* !__alpha__ && !__ia64__*/
Theodore Ts'o50e1e101997-04-26 13:58:21 +000053
54#include <linux/unistd.h>
55
Theodore Ts'of3db3561997-04-26 13:34:30 +000056#ifndef __NR__llseek
57#define __NR__llseek 140
58#endif
59
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000060#ifndef __i386__
Theodore Ts'of3db3561997-04-26 13:34:30 +000061static int _llseek (unsigned int, unsigned long,
62 unsigned long, ext2_loff_t *, unsigned int);
63
64static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high,
65 unsigned long, offset_low,ext2_loff_t *,result,
66 unsigned int, origin)
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000067#endif
Theodore Ts'of3db3561997-04-26 13:34:30 +000068
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000069static ext2_loff_t my_llseek (int fd, ext2_loff_t offset, int origin)
Theodore Ts'o50e1e101997-04-26 13:58:21 +000070{
71 ext2_loff_t result;
72 int retval;
73
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000074#ifndef __i386__
75 retval = _llseek(fd, ((unsigned long long) offset) >> 32,
76#else
77 retval = syscall(__NR__llseek, fd, (unsigned long long) (offset >> 32),
78#endif
79 ((unsigned long long) offset) & 0xffffffff,
Theodore Ts'o50e1e101997-04-26 13:58:21 +000080 &result, origin);
81 return (retval == -1 ? (ext2_loff_t) retval : result);
82}
83
Theodore Ts'o43819662000-10-25 02:06:09 +000084#endif /* __alpha__ || __ia64__ */
Theodore Ts'o50e1e101997-04-26 13:58:21 +000085
Theodore Ts'odc5f68c2000-05-25 23:31:54 +000086#endif /* HAVE_LLSEEK */
Theodore Ts'o50e1e101997-04-26 13:58:21 +000087
Theodore Ts'o1c27cac1997-08-14 17:20:42 +000088ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
Theodore Ts'of3db3561997-04-26 13:34:30 +000089{
Theodore Ts'of3db3561997-04-26 13:34:30 +000090 ext2_loff_t result;
Theodore Ts'of3db3561997-04-26 13:34:30 +000091 static int do_compat = 0;
92
Theodore Ts'o50e1e101997-04-26 13:58:21 +000093 if ((sizeof(off_t) >= sizeof(ext2_loff_t)) ||
94 (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1))))
95 return lseek(fd, (off_t) offset, origin);
96
Theodore Ts'of3db3561997-04-26 13:34:30 +000097 if (do_compat) {
Theodore Ts'o50e1e101997-04-26 13:58:21 +000098 errno = EINVAL;
99 return -1;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000100 }
101
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++;
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000109 errno = EINVAL;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000110 }
Theodore Ts'of3db3561997-04-26 13:34:30 +0000111 return result;
112}
113
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000114#else /* !linux */
Theodore Ts'of3db3561997-04-26 13:34:30 +0000115
Theodore Ts'o73f17cf1999-01-04 07:35:45 +0000116#ifndef EINVAL
117#define EINVAL EXT2_ET_INVALID_ARGUMENT
118#endif
119
Theodore Ts'od163b091997-10-03 17:42:28 +0000120ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
Theodore Ts'of3db3561997-04-26 13:34:30 +0000121{
122 if ((sizeof(off_t) < sizeof(ext2_loff_t)) &&
123 (offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) {
Theodore Ts'o73f17cf1999-01-04 07:35:45 +0000124 errno = EINVAL;
Theodore Ts'of3db3561997-04-26 13:34:30 +0000125 return -1;
126 }
127 return lseek (fd, (off_t) offset, origin);
128}
129
Theodore Ts'o50e1e101997-04-26 13:58:21 +0000130#endif /* linux */
Theodore Ts'of3db3561997-04-26 13:34:30 +0000131
132