diff options
Diffstat (limited to 'erts/emulator/nifs/unix/unix_prim_file.c')
-rw-r--r-- | erts/emulator/nifs/unix/unix_prim_file.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/erts/emulator/nifs/unix/unix_prim_file.c b/erts/emulator/nifs/unix/unix_prim_file.c index 6d51ccd83b..2bb51651ef 100644 --- a/erts/emulator/nifs/unix/unix_prim_file.c +++ b/erts/emulator/nifs/unix/unix_prim_file.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson 2017-2021. All Rights Reserved. + * Copyright Ericsson 2017-2022. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +42,8 @@ #include <utime.h> +#define FALLBACK_RW_LENGTH ((1ull << 31) - 1) + /* Macros for testing file types. */ #ifdef NO_UMASK #define FILE_MODE 0644 @@ -139,11 +141,7 @@ static int get_flags(enum efile_modes_t modes) { if(modes & EFILE_MODE_READ && !(modes & EFILE_MODE_WRITE)) { flags |= O_RDONLY; } else if(modes & EFILE_MODE_WRITE && !(modes & EFILE_MODE_READ)) { - if(!(modes & EFILE_MODE_NO_TRUNCATE)) { - flags |= O_TRUNC; - } - - flags |= O_WRONLY | O_CREAT; + flags |= O_TRUNC | O_WRONLY | O_CREAT; } else if(modes & EFILE_MODE_READ_WRITE) { flags |= O_RDWR | O_CREAT; } else { @@ -317,6 +315,11 @@ Sint64 efile_readv(efile_data_t *d, SysIOVec *iov, int iovlen) { if(use_fallback) { result = read(u->fd, iov->iov_base, iov->iov_len); + + /* Some OSs (e.g. macOS) does not allow reads greater than 2 GB, + so if we get EINVAL in the fallback, we try with a smaller length */ + if (result < 0 && errno == EINVAL && iov->iov_len > FALLBACK_RW_LENGTH) + result = read(u->fd, iov->iov_base, FALLBACK_RW_LENGTH); } if(result > 0) { @@ -362,6 +365,11 @@ Sint64 efile_writev(efile_data_t *d, SysIOVec *iov, int iovlen) { if(use_fallback) { result = write(u->fd, iov->iov_base, iov->iov_len); + + /* Some OSs (e.g. macOS) does not allow writes greater than 2 GB, + so if we get EINVAL in the fallback, we try with a smaller length */ + if (result < 0 && errno == EINVAL && iov->iov_len > FALLBACK_RW_LENGTH) + result = write(u->fd, iov->iov_base, FALLBACK_RW_LENGTH); } if(result > 0) { @@ -542,7 +550,9 @@ int efile_sync(efile_data_t *d, int data_only) { } #endif -#if defined(__DARWIN__) && defined(F_FULLFSYNC) +#if defined(__DARWIN__) && defined(F_BARRIERFSYNC) + if(fcntl(u->fd, F_BARRIERFSYNC) < 0) { +#elif defined(__DARWIN__) && defined(F_FULLFSYNC) if(fcntl(u->fd, F_FULLFSYNC) < 0) { #else if(fsync(u->fd) < 0) { |