Commit | Line | Data |
---|---|---|
9201d894 ILT |
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 | ||
14 | int | |
15 | ftruncate (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 | ||
28 | int | |
29 | ftruncate (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 | ||
71 | int | |
72 | ftruncate (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 | ||
81 | int | |
82 | ftruncate (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 */ |