1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
/*
* llseek.c -- stub calling the llseek system call
*
* Copyright (C) 1994, 1995, 1996, 1997 Theodore Ts'o.
*
* %Begin-Header%
* This file may be redistributed under the terms of the GNU Library
* General Public License, version 2.
* %End-Header%
*/
#ifndef _LARGEFILE_SOURCE
#define _LARGEFILE_SOURCE
#endif
#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
#endif
#include "config.h"
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef __MSDOS__
#include <io.h>
#endif
#include "et/com_err.h"
#include "ext2fs/ext2_io.h"
#ifdef __linux__
#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
#define my_llseek lseek64
#else
#if defined(HAVE_LLSEEK)
#include <sys/syscall.h>
#ifndef HAVE_LLSEEK_PROTOTYPE
extern long long llseek (int fd, long long offset, int origin);
#endif
#define my_llseek llseek
#else /* ! HAVE_LLSEEK */
#if SIZEOF_LONG == SIZEOF_LONG_LONG
#define my_llseek lseek
#else /* SIZEOF_LONG != SIZEOF_LONG_LONG */
#include <linux/unistd.h>
#ifndef __NR__llseek
#define __NR__llseek 140
#endif
#ifndef __i386__
static int _llseek (unsigned int, unsigned long,
unsigned long, ext2_loff_t *, unsigned int);
static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high,
unsigned long, offset_low,ext2_loff_t *,result,
unsigned int, origin)
#endif
static ext2_loff_t my_llseek (int fd, ext2_loff_t offset, int origin)
{
ext2_loff_t result;
int retval;
#ifndef __i386__
retval = _llseek(fd, ((unsigned long long) offset) >> 32,
#else
retval = syscall(__NR__llseek, fd, (unsigned long long) (offset >> 32),
#endif
((unsigned long long) offset) & 0xffffffff,
&result, origin);
return (retval == -1 ? (ext2_loff_t) retval : result);
}
#endif /* SIZE_LONG == SIZEOF_LONG_LONG */
#endif /* HAVE_LLSEEK */
#endif /* defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE) */
ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
{
#if SIZEOF_OFF_T >= SIZEOF_LONG_LONG
return my_llseek (fd, offset, origin);
#else
ext2_loff_t result;
static int do_compat = 0;
if (do_compat)
goto fallback;
result = my_llseek (fd, offset, origin);
if (result == -1 && errno == ENOSYS) {
/*
* Just in case this code runs on top of an old kernel
* which does not support the llseek system call
*/
do_compat++;
fallback:
if (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))
return lseek(fd, (off_t) offset, origin);
errno = EINVAL;
return -1;
}
return result;
#endif
}
#else /* !linux */
#ifndef EINVAL
#define EINVAL EXT2_ET_INVALID_ARGUMENT
#endif
ext2_loff_t ext2fs_llseek (int fd, ext2_loff_t offset, int origin)
{
#if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
return lseek64 (fd, offset, origin);
#else
if ((sizeof(off_t) < sizeof(ext2_loff_t)) &&
(offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) {
errno = EINVAL;
return -1;
}
return lseek (fd, (off_t) offset, origin);
#endif
}
#endif /* linux */
|