1 /* ftruncate emulations that work on some System V's. 2 This file is in the public domain. */ 3 4 #ifdef HAVE_CONFIG_H 5 # include <config.h> 6 #endif 7 8 #include <sys/types.h> 9 #include <fcntl.h> 10 11 #ifdef F_CHSIZE 12 13 int 14 ftruncate (int fd, off_t length) 15 { 16 return fcntl (fd, F_CHSIZE, length); 17 } 18 19 #else /* not F_CHSIZE */ 20 # ifdef F_FREESP 21 22 /* By William Kucharski <kucharsk@netcom.com>. */ 23 24 # include <sys/stat.h> 25 # include <errno.h> 26 # if HAVE_UNISTD_H 27 # include <unistd.h> 28 # endif 29 30 int 31 ftruncate (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 72 73 int 74 ftruncate (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 83 int 84 ftruncate (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