1/* ftruncate emulations that work on some System V's. 2 This file is in the public domain. */ 3 4#include <config.h> 5 6/* Specification. */ 7#include <unistd.h> 8 9#include <sys/types.h> 10#include <fcntl.h> 11 12#ifdef F_CHSIZE 13 14int 15ftruncate (int fd, off_t length) 16{ 17 return fcntl (fd, F_CHSIZE, length); 18} 19 20#else /* not F_CHSIZE */ 21# ifdef F_FREESP 22 23/* By William Kucharski <kucharsk@netcom.com>. */ 24 25# include <sys/stat.h> 26# include <errno.h> 27 28int 29ftruncate (int fd, off_t length) 30{ 31 struct flock fl; 32 struct stat filebuf; 33 34 if (fstat (fd, &filebuf) < 0) 35 return -1; 36 37 if (filebuf.st_size < length) 38 { 39 /* Extend file length. */ 40 if (lseek (fd, (length - 1), SEEK_SET) < 0) 41 return -1; 42 43 /* Write a "0" byte. */ 44 if (write (fd, "", 1) != 1) 45 return -1; 46 } 47 else 48 { 49 50 /* Truncate length. */ 51 52 fl.l_whence = 0; 53 fl.l_len = 0; 54 fl.l_start = length; 55 fl.l_type = F_WRLCK; /* write lock on file space */ 56 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 61 if (fcntl (fd, F_FREESP, &fl) < 0) 62 return -1; 63 } 64 65 return 0; 66} 67 68# else /* not F_CHSIZE nor F_FREESP */ 69# if HAVE_CHSIZE /* native Windows, e.g. mingw */ 70 71int 72ftruncate (int fd, off_t length) 73{ 74 return chsize (fd, length); 75} 76 77# else /* not F_CHSIZE nor F_FREESP nor HAVE_CHSIZE */ 78 79# include <errno.h> 80 81int 82ftruncate (int fd, off_t length) 83{ 84 errno = EIO; 85 return -1; 86} 87 88# endif /* not HAVE_CHSIZE */ 89# endif /* not F_FREESP */ 90#endif /* not F_CHSIZE */ 91