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