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 | ||
fd03461a ILT |
12 | extern int ftruncate (int, off_t); |
13 | ||
9201d894 ILT |
14 | #ifdef F_CHSIZE |
15 | ||
16 | int | |
17 | ftruncate (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 | ||
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 /* native Windows, e.g. mingw */ | |
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 */ |