ftruncate.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /* ftruncate emulations that work on some System V's.
  2. This file is in the public domain. */
  3. /* Copyright (C) 2012-2015 Free Software Foundation, Inc.
  4. This file is part of gold.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3 of the License, or
  8. (at your option) any later version.
  9. This program 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 General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  16. MA 02110-1301, USA. */
  17. #include <config.h>
  18. /* Specification. */
  19. #include <unistd.h>
  20. #include <sys/types.h>
  21. #include <fcntl.h>
  22. extern int ftruncate (int, off_t);
  23. #ifdef F_CHSIZE
  24. int
  25. ftruncate (int fd, off_t length)
  26. {
  27. return fcntl (fd, F_CHSIZE, length);
  28. }
  29. #else /* not F_CHSIZE */
  30. # ifdef F_FREESP
  31. /* By William Kucharski <kucharsk@netcom.com>. */
  32. # include <sys/stat.h>
  33. # include <errno.h>
  34. int
  35. ftruncate (int fd, off_t length)
  36. {
  37. struct flock fl;
  38. struct stat filebuf;
  39. if (fstat (fd, &filebuf) < 0)
  40. return -1;
  41. if (filebuf.st_size < length)
  42. {
  43. /* Extend file length. */
  44. if (lseek (fd, (length - 1), SEEK_SET) < 0)
  45. return -1;
  46. /* Write a "0" byte. */
  47. if (write (fd, "", 1) != 1)
  48. return -1;
  49. }
  50. else
  51. {
  52. /* Truncate length. */
  53. fl.l_whence = 0;
  54. fl.l_len = 0;
  55. fl.l_start = length;
  56. fl.l_type = F_WRLCK; /* write lock on file space */
  57. /* This relies on the *undocumented* F_FREESP argument to fcntl,
  58. which truncates the file so that it ends at the position
  59. indicated by fl.l_start. Will minor miracles never cease? */
  60. if (fcntl (fd, F_FREESP, &fl) < 0)
  61. return -1;
  62. }
  63. return 0;
  64. }
  65. # else /* not F_CHSIZE nor F_FREESP */
  66. # if HAVE_CHSIZE /* native Windows, e.g. mingw */
  67. int
  68. ftruncate (int fd, off_t length)
  69. {
  70. return chsize (fd, length);
  71. }
  72. # else /* not F_CHSIZE nor F_FREESP nor HAVE_CHSIZE */
  73. # include <errno.h>
  74. int
  75. ftruncate (int fd, off_t length)
  76. {
  77. errno = EIO;
  78. return -1;
  79. }
  80. # endif /* not HAVE_CHSIZE */
  81. # endif /* not F_FREESP */
  82. #endif /* not F_CHSIZE */