root/maint/gnulib/lib/lseek.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rpl_lseek

   1 /* An lseek() function that detects pipes.
   2    Copyright (C) 2007, 2009-2021 Free Software Foundation, Inc.
   3 
   4    This file is free software: you can redistribute it and/or modify
   5    it under the terms of the GNU Lesser General Public License as
   6    published by the Free Software Foundation; either version 2.1 of the
   7    License, or (at your option) any later version.
   8 
   9    This file is distributed in the hope that it will be useful,
  10    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12    GNU Lesser General Public License for more details.
  13 
  14    You should have received a copy of the GNU Lesser General Public License
  15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  16 
  17 #include <config.h>
  18 
  19 /* Specification.  */
  20 #include <unistd.h>
  21 
  22 #if defined _WIN32 && ! defined __CYGWIN__
  23 /* Windows platforms.  */
  24 /* Get GetFileType.  */
  25 # include <windows.h>
  26 /* Get _get_osfhandle.  */
  27 # if GNULIB_MSVC_NOTHROW
  28 #  include "msvc-nothrow.h"
  29 # else
  30 #  include <io.h>
  31 # endif
  32 #else
  33 # include <sys/stat.h>
  34 #endif
  35 #include <errno.h>
  36 
  37 #undef lseek
  38 
  39 off_t
  40 rpl_lseek (int fd, off_t offset, int whence)
     /* [previous][next][first][last][top][bottom][index][help] */
  41 {
  42 #if defined _WIN32 && ! defined __CYGWIN__
  43   /* mingw lseek mistakenly succeeds on pipes, sockets, and terminals.  */
  44   HANDLE h = (HANDLE) _get_osfhandle (fd);
  45   if (h == INVALID_HANDLE_VALUE)
  46     {
  47       errno = EBADF;
  48       return -1;
  49     }
  50   if (GetFileType (h) != FILE_TYPE_DISK)
  51     {
  52       errno = ESPIPE;
  53       return -1;
  54     }
  55 #elif defined __APPLE__ && defined __MACH__ && defined SEEK_DATA
  56   if (whence == SEEK_DATA)
  57     {
  58       /* If OFFSET points to data, macOS lseek+SEEK_DATA returns the
  59          start S of the first data region that begins *after* OFFSET,
  60          where the region from OFFSET to S consists of possibly-empty
  61          data followed by a possibly-empty hole.  To work around this
  62          portability glitch, check whether OFFSET is within data by
  63          using lseek+SEEK_HOLE, and if so return to OFFSET by using
  64          lseek+SEEK_SET.  Also, contrary to the macOS documentation,
  65          lseek+SEEK_HOLE can fail with ENXIO if there are no holes on
  66          or after OFFSET.  What a mess!  */
  67       off_t next_hole = lseek (fd, offset, SEEK_HOLE);
  68       if (next_hole < 0)
  69         return errno == ENXIO ? offset : next_hole;
  70       if (next_hole != offset)
  71         whence = SEEK_SET;
  72     }
  73 #else
  74   /* BeOS lseek mistakenly succeeds on pipes...  */
  75   struct stat statbuf;
  76   if (fstat (fd, &statbuf) < 0)
  77     return -1;
  78   if (!S_ISREG (statbuf.st_mode))
  79     {
  80       errno = ESPIPE;
  81       return -1;
  82     }
  83 #endif
  84 #if _GL_WINDOWS_64_BIT_OFF_T || (defined __MINGW32__ && defined _FILE_OFFSET_BITS && (_FILE_OFFSET_BITS == 64))
  85   return _lseeki64 (fd, offset, whence);
  86 #else
  87   return lseek (fd, offset, whence);
  88 #endif
  89 }

/* [previous][next][first][last][top][bottom][index][help] */