diff options
Diffstat (limited to 'src/nvim/os/fileio.c')
| -rw-r--r-- | src/nvim/os/fileio.c | 45 | 
1 files changed, 31 insertions, 14 deletions
diff --git a/src/nvim/os/fileio.c b/src/nvim/os/fileio.c index a95adc86b6..ccf35fd57c 100644 --- a/src/nvim/os/fileio.c +++ b/src/nvim/os/fileio.c @@ -83,7 +83,7 @@ int file_open(FileDescriptor *const ret_fp, const char *const fname,    if (fd < 0) {      return fd;    } -  return file_open_fd(ret_fp, fd, (wr == kTrue)); +  return file_open_fd(ret_fp, fd, flags);  }  /// Wrap file descriptor with FileDescriptor structure @@ -94,14 +94,23 @@ int file_open(FileDescriptor *const ret_fp, const char *const fname,  /// @param[out]  ret_fp  Address where information needed for reading from or  ///                      writing to a file is saved  /// @param[in]  fd  File descriptor to wrap. -/// @param[in]  wr  True if fd is opened for writing only, false if it is read -///                 only. +/// @param[in]  flags  Flags, @see FileOpenFlags. Currently reading from and +///                    writing to the file at once is not supported, so either +///                    FILE_WRITE_ONLY or FILE_READ_ONLY is required.  ///  /// @return Error code (@see os_strerror()) or 0. Currently always returns 0. -int file_open_fd(FileDescriptor *const ret_fp, const int fd, const bool wr) +int file_open_fd(FileDescriptor *const ret_fp, const int fd, +                 const int flags)    FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT  { -  ret_fp->wr = wr; +  ret_fp->wr = !!(flags & (kFileCreate +                           |kFileCreateOnly +                           |kFileTruncate +                           |kFileAppend +                           |kFileWriteOnly)); +  ret_fp->non_blocking = !!(flags & kFileNonBlocking); +  // Non-blocking writes not supported currently. +  assert(!ret_fp->wr || !ret_fp->non_blocking);    ret_fp->fd = fd;    ret_fp->eof = false;    ret_fp->rv = rbuffer_new(kRWBufferSize); @@ -138,15 +147,17 @@ FileDescriptor *file_open_new(int *const error, const char *const fname,  ///  /// @param[out]  error  Error code, or 0 on success. @see os_strerror()  /// @param[in]  fd  File descriptor to wrap. -/// @param[in]  wr  True if fd is opened for writing only, false if it is read -///                 only. +/// @param[in]  flags  Flags, @see FileOpenFlags. +/// @param[in]  mode  Permissions for the newly created file (ignored if flags +///                   does not have FILE_CREATE\*).  ///  /// @return [allocated] Opened file or NULL in case of error. -FileDescriptor *file_open_fd_new(int *const error, const int fd, const bool wr) +FileDescriptor *file_open_fd_new(int *const error, const int fd, +                                 const int flags)    FUNC_ATTR_NONNULL_ALL FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT  {    FileDescriptor *const fp = xmalloc(sizeof(*fp)); -  if ((*error = file_open_fd(fp, fd, wr)) != 0) { +  if ((*error = file_open_fd(fp, fd, flags)) != 0) {      xfree(fp);      return NULL;    } @@ -244,7 +255,8 @@ static void file_rb_write_full_cb(RBuffer *const rv, FileDescriptor *const fp)      return;    }    const size_t read_bytes = rbuffer_read(rv, writebuf, kRWBufferSize); -  const ptrdiff_t wres = os_write(fp->fd, writebuf, read_bytes); +  const ptrdiff_t wres = os_write(fp->fd, writebuf, read_bytes, +                                  fp->non_blocking);    if (wres != (ptrdiff_t)read_bytes) {      if (wres >= 0) {        fp->_error = UV_EIO; @@ -270,6 +282,7 @@ ptrdiff_t file_read(FileDescriptor *const fp, char *const ret_buf,    char *buf = ret_buf;    size_t read_remaining = size;    RBuffer *const rv = fp->rv; +  bool called_read = false;    while (read_remaining) {      const size_t rv_size = rbuffer_size(rv);      if (rv_size > 0) { @@ -277,7 +290,9 @@ ptrdiff_t file_read(FileDescriptor *const fp, char *const ret_buf,        buf += rsize;        read_remaining -= rsize;      } -    if (fp->eof) { +    if (fp->eof +        // Allow only at most one os_read[v] call. +        || (called_read && fp->non_blocking)) {        break;      }      if (read_remaining) { @@ -294,7 +309,7 @@ ptrdiff_t file_read(FileDescriptor *const fp, char *const ret_buf,        };        assert(write_count == kRWBufferSize);        const ptrdiff_t r_ret = os_readv(fp->fd, &fp->eof, iov, -                                       ARRAY_SIZE(iov)); +                                       ARRAY_SIZE(iov), fp->non_blocking);        if (r_ret > 0) {          if (r_ret > (ptrdiff_t)read_remaining) {            rbuffer_produced(rv, (size_t)(r_ret - (ptrdiff_t)read_remaining)); @@ -310,7 +325,8 @@ ptrdiff_t file_read(FileDescriptor *const fp, char *const ret_buf,        if (read_remaining >= kRWBufferSize) {          // …otherwise leave RBuffer empty and populate only target buffer,          // because filtering information through rbuffer will be more syscalls. -        const ptrdiff_t r_ret = os_read(fp->fd, &fp->eof, buf, read_remaining); +        const ptrdiff_t r_ret = os_read(fp->fd, &fp->eof, buf, read_remaining, +                                        fp->non_blocking);          if (r_ret >= 0) {            read_remaining -= (size_t)r_ret;            return (ptrdiff_t)(size - read_remaining); @@ -321,7 +337,7 @@ ptrdiff_t file_read(FileDescriptor *const fp, char *const ret_buf,          size_t write_count;          const ptrdiff_t r_ret = os_read(fp->fd, &fp->eof,                                          rbuffer_write_ptr(rv, &write_count), -                                        kRWBufferSize); +                                        kRWBufferSize, fp->non_blocking);          assert(write_count == kRWBufferSize);          if (r_ret > 0) {            rbuffer_produced(rv, (size_t)r_ret); @@ -330,6 +346,7 @@ ptrdiff_t file_read(FileDescriptor *const fp, char *const ret_buf,          }        }  #endif +      called_read = true;      }    }    return (ptrdiff_t)(size - read_remaining);  | 
