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 12extern int ftruncate (int, off_t); 13 14#ifdef F_CHSIZE 15 16int 17ftruncate (int fd, off_t length) 18{ 19 return fcntl (fd, F_CHSIZE, length); 20} 21 22#else /* not F_CHSIZE */ 23# ifdef F_FREESP 24 25/* By William Kucharski <kucharsk@netcom.com>. */ 26 27# include <sys/stat.h> 28# include <errno.h> 29 30int 31ftruncate (int fd, off_t length) 32{ 33 struct flock fl; 34 struct stat filebuf; 35 36 if (fstat (fd, &filebuf) < 0) 37 return -1; 38 39 if (filebuf.st_size < length) 40 { 41 /* Extend file length. */ 42 if (lseek (fd, (length - 1), SEEK_SET) < 0) 43 return -1; 44 45 /* Write a "0" byte. */ 46 if (write (fd, "", 1) != 1) 47 return -1; 48 } 49 else 50 { 51 52 /* Truncate length. */ 53 54 fl.l_whence = 0; 55 fl.l_len = 0; 56 fl.l_start = length; 57 fl.l_type = F_WRLCK; /* write lock on file space */ 58 59 /* This relies on the *undocumented* F_FREESP argument to fcntl, 60 which truncates the file so that it ends at the position 61 indicated by fl.l_start. Will minor miracles never cease? */ 62 63 if (fcntl (fd, F_FREESP, &fl) < 0) 64 return -1; 65 } 66 67 return 0; 68} 69 70# else /* not F_CHSIZE nor F_FREESP */ 71# if HAVE_CHSIZE /* native Windows, e.g. mingw */ 72 73int 74ftruncate (int fd, off_t length) 75{ 76 return chsize (fd, length); 77} 78 79# else /* not F_CHSIZE nor F_FREESP nor HAVE_CHSIZE */ 80 81# include <errno.h> 82 83int 84ftruncate (int fd, off_t length) 85{ 86 errno = EIO; 87 return -1; 88} 89 90# endif /* not HAVE_CHSIZE */ 91# endif /* not F_FREESP */ 92#endif /* not F_CHSIZE */ 93