diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index d5e8f8c05..9b76ce67a 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -506,6 +506,7 @@ fabsf NOSIGFE fabsl NOSIGFE faccessat SIGFE facl SIGFE +fallocate SIGFE fchdir SIGFE fchmod SIGFE fchmodat SIGFE diff --git a/winsup/cygwin/fhandler/disk_file.cc b/winsup/cygwin/fhandler/disk_file.cc index 51602f30f..b49b25c71 100644 --- a/winsup/cygwin/fhandler/disk_file.cc +++ b/winsup/cygwin/fhandler/disk_file.cc @@ -1153,15 +1153,46 @@ fhandler_disk_file::fallocate (int mode, off_t offset, off_t length) if (!NT_SUCCESS (status)) return geterrno_from_nt_status (status); - /* If called through posix_fallocate, silently succeed if - offset + length is less than the file's actual length. */ - if (mode == 0 && offset + length < fsi.EndOfFile.QuadPart) - return 0; + /* Never change file size if FALLOC_FL_KEEP_SIZE is specified. */ + if ((mode & FALLOC_FL_KEEP_SIZE) + && offset + length > fsi.EndOfFile.QuadPart) + { + if (offset > fsi.EndOfFile.QuadPart) /* no-op */ + return 0; + length = fsi.EndOfFile.QuadPart - offset; + } + mode &= ~FALLOC_FL_KEEP_SIZE; + + switch (mode) + { + case 0: + case __FALLOC_FL_TRUNCATE: + break; + case FALLOC_FL_PUNCH_HOLE: /* TODO */ + return EOPNOTSUPP; + break; + case FALLOC_FL_ZERO_RANGE: /* TODO */ + return EOPNOTSUPP; + break; + default: + return EINVAL; + } + + if (mode == 0) + { + /* If called through posix_fallocate, silently succeed if + offset + length is less than the file's actual length. */ + + /* TODO: If the file is sparse, POSIX requires to allocate + the holes within offset and offset + length. */ + if (offset + length < fsi.EndOfFile.QuadPart) + return 0; + } feofi.EndOfFile.QuadPart = offset + length; /* Create sparse files only when called through ftruncate, not when called through posix_fallocate. */ - if ((mode & __FALLOC_FL_TRUNCATE) + if (mode == __FALLOC_FL_TRUNCATE && !has_attribute (FILE_ATTRIBUTE_SPARSE_FILE) && pc.support_sparse () && offset + length >= fsi.EndOfFile.QuadPart + (128 * 1024)) diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index 833de646c..c8177c2b1 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -483,12 +483,13 @@ details. */ posix_spawn_file_actions_addfchdir_np. 347: Add c16rtomb, c32rtomb, mbrtoc16, mbrtoc32. 348: Add c8rtomb, mbrtoc. + 349: Add fallocate. Note that we forgot to bump the api for ualarm, strtoll, strtoull, sigaltstack, sethostname. */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 348 +#define CYGWIN_VERSION_API_MINOR 349 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible changes are made to the shared diff --git a/winsup/cygwin/include/fcntl.h b/winsup/cygwin/include/fcntl.h index 1ef51e50c..b38dfa50b 100644 --- a/winsup/cygwin/include/fcntl.h +++ b/winsup/cygwin/include/fcntl.h @@ -42,12 +42,24 @@ details. */ #define POSIX_FADV_DONTNEED 4 #define POSIX_FADV_NOREUSE 5 -#define __FALLOC_FL_TRUNCATE 0x0001 /* internal */ +#if __GNU_VISIBLE +#define FALLOC_FL_PUNCH_HOLE 0x0001 +#define FALLOC_FL_ZERO_RANGE 0x0002 +#define FALLOC_FL_UNSHARE_RANGE 0x0004 +#define FALLOC_FL_COLLAPSE_RANGE 0x0008 +#define FALLOC_FL_INSERT_RANGE 0x0010 +#define FALLOC_FL_KEEP_SIZE 0x1000 +/* Internal flags */ +#define __FALLOC_FL_TRUNCATE 0x2000 +#endif __BEGIN_DECLS extern int posix_fadvise (int, off_t, off_t, int); extern int posix_fallocate (int, off_t, off_t); +#if __GNU_VISIBLE +extern int fallocate (int, int, off_t, off_t); +#endif __END_DECLS diff --git a/winsup/cygwin/release/3.5.0 b/winsup/cygwin/release/3.5.0 index aee21c972..3b6df951d 100644 --- a/winsup/cygwin/release/3.5.0 +++ b/winsup/cygwin/release/3.5.0 @@ -43,6 +43,8 @@ What's new: - New API calls: c8rtomb, c16rtomb, c32rtomb, mbrtoc8, mbrtoc16, mbrtoc32. +- New API call: fallocate (Linux-specific). + - Implement OSS-based sound mixer device (/dev/mixer). What changed: diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index b2e6ba16c..0e4c54bcf 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -2987,6 +2987,40 @@ posix_fadvise (int fd, off_t offset, off_t len, int advice) return res; } +extern "C" int +fallocate (int fd, int mode, off_t offset, off_t len) +{ + int res = 0; + + /* First check mask of allowed flags */ + if (mode & ~(FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE + | FALLOC_FL_UNSHARE_RANGE | FALLOC_FL_COLLAPSE_RANGE + | FALLOC_FL_INSERT_RANGE | FALLOC_FL_KEEP_SIZE)) + res = EOPNOTSUPP; + /* Either FALLOC_FL_PUNCH_HOLE or FALLOC_FL_ZERO_RANGE, never both */ + else if ((mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE)) + == (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE)) + res = EOPNOTSUPP; + /* FALLOC_FL_PUNCH_HOLE must be ORed with FALLOC_FL_KEEP_SIZE */ + else if ((mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE)) + == FALLOC_FL_PUNCH_HOLE) + res = EOPNOTSUPP; + else if (offset < 0 || len == 0) + res = EINVAL; + else + { + cygheap_fdget cfd (fd); + if (cfd >= 0) + res = cfd->fallocate (mode, offset, len); + else + res = EBADF; + if (res == EISDIR) + res = ENODEV; + } + syscall_printf ("%R = posix_fallocate(%d, %D, %D)", res, fd, offset, len); + return 0; +} + extern "C" int posix_fallocate (int fd, off_t offset, off_t len) { diff --git a/winsup/doc/new-features.xml b/winsup/doc/new-features.xml index 2c31a4acc..c5e6cdd7f 100644 --- a/winsup/doc/new-features.xml +++ b/winsup/doc/new-features.xml @@ -74,6 +74,10 @@ posix_spawn_file_actions_addfchdir_np. New API calls: c8rtomb, c16rtomb, c32rtomb, mbrtoc8, mbrtoc16, mbrtoc32. + +New API call: fallocate (Linux-specific). + + FIFOs now also work over NFS.