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 #ifndef _LARGEFILE_SOURCE
     13 #define _LARGEFILE_SOURCE
     14 #endif
     15 #ifndef _LARGEFILE64_SOURCE
     16 #define _LARGEFILE64_SOURCE
     17 #endif
     18 
     19 #include "config.h"
     20 #if HAVE_SYS_TYPES_H
     21 #include <sys/types.h>
     22 #endif
     23 
     24 #if HAVE_ERRNO_H
     25 #include <errno.h>
     26 #endif
     27 #if HAVE_UNISTD_H
     28 #include <unistd.h>
     29 #endif
     30 #ifdef __MSDOS__
     31 #include <io.h>
     32 #endif
     33 
     34 #include "blkidP.h"
     35 
     36 #ifdef __linux__
     37 
     38 #if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
     39 
     40 #define my_llseek lseek64
     41 
     42 #elif defined(HAVE_LLSEEK)
     43 #include <sys/syscall.h>
     44 
     45 #ifndef HAVE_LLSEEK_PROTOTYPE
     46 extern long long llseek(int fd, long long offset, int origin);
     47 #endif
     48 
     49 #define my_llseek llseek
     50 
     51 #else	/* ! HAVE_LLSEEK */
     52 
     53 #if SIZEOF_LONG == SIZEOF_LONG_LONG
     54 
     55 #define llseek lseek
     56 
     57 #else /* SIZEOF_LONG != SIZEOF_LONG_LONG */
     58 
     59 #include <linux/unistd.h>
     60 
     61 #ifndef __NR__llseek
     62 #define __NR__llseek            140
     63 #endif
     64 
     65 #ifndef __i386__
     66 static int _llseek(unsigned int, unsigned long, unsigned long,
     67 		   blkid_loff_t *, unsigned int);
     68 
     69 static _syscall5(int, _llseek, unsigned int, fd, unsigned long, offset_high,
     70 		 unsigned long, offset_low, blkid_loff_t *, result,
     71 		 unsigned int, origin)
     72 #endif
     73 
     74 static blkid_loff_t my_llseek(int fd, blkid_loff_t offset, int origin)
     75 {
     76 	blkid_loff_t result;
     77 	int retval;
     78 
     79 #ifndef __i386__
     80 	retval = _llseek(fd, ((unsigned long long) offset) >> 32,
     81 			 ((unsigned long long)offset) & 0xffffffff,
     82 			 &result, origin);
     83 #else
     84 	retval = syscall(__NR__llseek, fd, ((unsigned long long) offset) >> 32,
     85 			 ((unsigned long long)offset) & 0xffffffff,
     86 			 &result, origin);
     87 #endif
     88 	return (retval == -1 ? (blkid_loff_t) retval : result);
     89 }
     90 
     91 #endif	/* __alpha__ || __ia64__ */
     92 
     93 #endif /* HAVE_LLSEEK */
     94 
     95 blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int whence)
     96 {
     97 	blkid_loff_t result;
     98 	static int do_compat = 0;
     99 
    100 	if ((sizeof(off_t) >= sizeof(blkid_loff_t)) ||
    101 	    (offset < ((blkid_loff_t) 1 << ((sizeof(off_t)*8) -1))))
    102 		return lseek(fd, (off_t) offset, whence);
    103 
    104 	if (do_compat) {
    105 		errno = EOVERFLOW;
    106 		return -1;
    107 	}
    108 
    109 	result = my_llseek(fd, offset, whence);
    110 	if (result == -1 && errno == ENOSYS) {
    111 		/*
    112 		 * Just in case this code runs on top of an old kernel
    113 		 * which does not support the llseek system call
    114 		 */
    115 		do_compat++;
    116 		errno = EOVERFLOW;
    117 	}
    118 	return result;
    119 }
    120 
    121 #else /* !linux */
    122 
    123 #ifndef EOVERFLOW
    124 #ifdef EXT2_ET_INVALID_ARGUMENT
    125 #define EOVERFLOW EXT2_ET_INVALID_ARGUMENT
    126 #else
    127 #define EOVERFLOW 112
    128 #endif
    129 #endif
    130 
    131 blkid_loff_t blkid_llseek(int fd, blkid_loff_t offset, int origin)
    132 {
    133 #if defined(HAVE_LSEEK64) && defined(HAVE_LSEEK64_PROTOTYPE)
    134 	return lseek64 (fd, offset, origin);
    135 #else
    136 	if ((sizeof(off_t) < sizeof(blkid_loff_t)) &&
    137 	    (offset >= ((blkid_loff_t) 1 << ((sizeof(off_t)*8) - 1)))) {
    138 		errno = EOVERFLOW;
    139 		return -1;
    140 	}
    141 	return lseek(fd, (off_t) offset, origin);
    142 #endif
    143 }
    144 
    145 #endif	/* linux */
    146 
    147 
    148