1 /* ftruncate emulations that work on some System V's. 2 This file is in the public domain. */ 3 #include <sys/cdefs.h> 4 __RCSID("$NetBSD: ftruncate.c,v 1.2 2016/05/17 14:00:09 christos Exp $"); 5 6 #ifdef HAVE_CONFIG_H 7 # include <config.h> 8 #endif 9 10 #include <sys/types.h> 11 #include <fcntl.h> 12 13 #ifdef F_CHSIZE 14 15 int 16 ftruncate (int fd, off_t length) 17 { 18 return fcntl (fd, F_CHSIZE, length); 19 } 20 21 #else /* not F_CHSIZE */ 22 # ifdef F_FREESP 23 24 /* By William Kucharski <kucharsk@netcom.com>. */ 25 26 # include <sys/stat.h> 27 # include <errno.h> 28 # if HAVE_UNISTD_H 29 # include <unistd.h> 30 # endif 31 32 int 33 ftruncate (int fd, off_t length) 34 { 35 struct flock fl; 36 struct stat filebuf; 37 38 if (fstat (fd, &filebuf) < 0) 39 return -1; 40 41 if (filebuf.st_size < length) 42 { 43 /* Extend file length. */ 44 if (lseek (fd, (length - 1), SEEK_SET) < 0) 45 return -1; 46 47 /* Write a "0" byte. */ 48 if (write (fd, "", 1) != 1) 49 return -1; 50 } 51 else 52 { 53 54 /* Truncate length. */ 55 56 fl.l_whence = 0; 57 fl.l_len = 0; 58 fl.l_start = length; 59 fl.l_type = F_WRLCK; /* write lock on file space */ 60 61 /* This relies on the *undocumented* F_FREESP argument to fcntl, 62 which truncates the file so that it ends at the position 63 indicated by fl.l_start. Will minor miracles never cease? */ 64 65 if (fcntl (fd, F_FREESP, &fl) < 0) 66 return -1; 67 } 68 69 return 0; 70 } 71 72 # else /* not F_CHSIZE nor F_FREESP */ 73 # if HAVE_CHSIZE 74 75 int 76 ftruncate (int fd, off_t length) 77 { 78 return chsize (fd, length); 79 } 80 81 # else /* not F_CHSIZE nor F_FREESP nor HAVE_CHSIZE */ 82 83 # include <errno.h> 84 85 int 86 ftruncate (int fd, off_t length) 87 { 88 errno = EIO; 89 return -1; 90 } 91 92 # endif /* not HAVE_CHSIZE */ 93 # endif /* not F_FREESP */ 94 #endif /* not F_CHSIZE */ 95