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
|
/*
* llseek.c -- stub calling the llseek system call
*
* Copyright (C) 1994, 1995, 1996 Theodore Ts'o.
*
* Adapted for defrag
*
* This file may be redistributed under the terms of the GNU Public
* License.
*/
#include <errno.h>
#include <unistd.h>
#include "types.h"
#ifdef HAVE_LLSEEK
#include <syscall.h>
extern __off_t __llseek __P ((int __fd, __off_t __offset, int __whence));
extern __off_t llseek __P ((int __fd, __off_t __offset, int __whence));
#else /* HAVE_LLSEEK */
#ifdef __alpha__
#define llseek lseek
#else /* !__alpha__ */
#include <linux/unistd.h>
extern __off_t __llseek __P ((int __fd, __off_t __offset, int __whence));
extern __off_t llseek __P ((int __fd, __off_t __offset, int __whence));
#ifndef __NR__llseek
#define __NR__llseek 140
#endif
static int _llseek (unsigned int, unsigned long,
unsigned long, loff_t *, unsigned int);
static _syscall5(int,_llseek,unsigned int,fd,unsigned long,offset_high,
unsigned long, offset_low, loff_t *,result,
unsigned int, origin)
static loff_t llseek (unsigned int fd, loff_t offset,
unsigned int origin)
{
loff_t result;
int retval;
retval = _llseek (fd, ((unsigned long long) offset) >> 32,
((unsigned long long) offset) & 0xffffffff,
&result, origin);
return (retval == -1 ? (loff_t) retval : result);
}
#endif /* HAVE_LLSEEK */
#endif /* __alpha__ */
loff_t defrag_llseek (unsigned int fd, loff_t offset,
unsigned int origin)
{
loff_t result;
static int do_compat = 0;
if ((sizeof(off_t) >= sizeof(loff_t)) ||
(offset < ((loff_t) 1 << ((sizeof(off_t)*8) -1))))
return lseek(fd, (off_t) offset, origin);
if (do_compat) {
errno = EINVAL;
return -1;
}
result = 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++;
errno = EINVAL;
}
return result;
}
|