(root)/
binutils-2.41/
gold/
ftruncate.c
       1  /* ftruncate emulations that work on some System V's.
       2     This file is in the public domain.  */
       3  
       4  /* Copyright (C) 2012-2023 Free Software Foundation, Inc.
       5  
       6     This file is part of gold.
       7  
       8     This program is free software; you can redistribute it and/or modify
       9     it under the terms of the GNU General Public License as published by
      10     the Free Software Foundation; either version 3 of the License, or
      11     (at your option) any later version.
      12  
      13     This program is distributed in the hope that it will be useful,
      14     but WITHOUT ANY WARRANTY; without even the implied warranty of
      15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16     GNU General Public License for more details.
      17  
      18     You should have received a copy of the GNU General Public License
      19     along with this program; if not, write to the Free Software
      20     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
      21     MA 02110-1301, USA.  */
      22  
      23  #include <config.h>
      24  
      25  /* Specification.  */
      26  #include <unistd.h>
      27  
      28  #include <sys/types.h>
      29  #include <fcntl.h>
      30  
      31  extern int ftruncate (int, off_t);
      32  
      33  #ifdef F_CHSIZE
      34  
      35  int
      36  ftruncate (int fd, off_t length)
      37  {
      38    return fcntl (fd, F_CHSIZE, length);
      39  }
      40  
      41  #else /* not F_CHSIZE */
      42  # ifdef F_FREESP
      43  
      44  /* By William Kucharski <kucharsk@netcom.com>.  */
      45  
      46  #  include <sys/stat.h>
      47  #  include <errno.h>
      48  
      49  int
      50  ftruncate (int fd, off_t length)
      51  {
      52    struct flock fl;
      53    struct stat filebuf;
      54  
      55    if (fstat (fd, &filebuf) < 0)
      56      return -1;
      57  
      58    if (filebuf.st_size < length)
      59      {
      60        /* Extend file length. */
      61        if (lseek (fd, (length - 1), SEEK_SET) < 0)
      62  	return -1;
      63  
      64        /* Write a "0" byte. */
      65        if (write (fd, "", 1) != 1)
      66  	return -1;
      67      }
      68    else
      69      {
      70  
      71        /* Truncate length. */
      72  
      73        fl.l_whence = 0;
      74        fl.l_len = 0;
      75        fl.l_start = length;
      76        fl.l_type = F_WRLCK;	/* write lock on file space */
      77  
      78        /* This relies on the *undocumented* F_FREESP argument to fcntl,
      79  	 which truncates the file so that it ends at the position
      80  	 indicated by fl.l_start.  Will minor miracles never cease?  */
      81  
      82        if (fcntl (fd, F_FREESP, &fl) < 0)
      83  	return -1;
      84      }
      85  
      86    return 0;
      87  }
      88  
      89  # else /* not F_CHSIZE nor F_FREESP */
      90  #  if HAVE_CHSIZE                      /* native Windows, e.g. mingw */
      91  
      92  int
      93  ftruncate (int fd, off_t length)
      94  {
      95    return chsize (fd, length);
      96  }
      97  
      98  #  else /* not F_CHSIZE nor F_FREESP nor HAVE_CHSIZE */
      99  
     100  #   include <errno.h>
     101  
     102  int
     103  ftruncate (int fd, off_t length)
     104  {
     105    errno = EIO;
     106    return -1;
     107  }
     108  
     109  #  endif /* not HAVE_CHSIZE */
     110  # endif /* not F_FREESP */
     111  #endif /* not F_CHSIZE */