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 15int 16ftruncate (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 32int 33ftruncate (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 75int 76ftruncate (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 85int 86ftruncate (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