labath created this revision.
labath added reviewers: zturner, clayborg.
labath added a subscriber: lldb-commits.
Herald added a subscriber: mgorny.

This is a rework of https://reviews.llvm.org/D25783, which was blocked by my 
objections to using pwrite
wholesale. This version keeps the benefits of the code simplification in the
previous version, but keeps the distinction between write/pwrite system calls
and their windows equivalents. Besides allowing appends to be atomic, I believe
this actually makes the code simpler(*), as there is no need to do manual
lseeks() to get the file positions.

I had made the retry logic less aggressive than previously, as it was hanging
the test suite - the problem was parts of the codebase were depending on read
returning with a non-full buffer, for example when reading from the inferior
process pseudo-terminal (/dev/pts/ptmx). So, now, I only retry the read if the
user requested a read larger than READ_MAX, and the syscall returned READ_MAX
bytes, which I believe is the original problem we were trying to solve.

This does not make the API particularly nice, but I am not actually
changing that - it was always that. I believe a good cleanup here would be to
let the user specify whether he wants to read the full buffer, or whether he
will be satisfied with a partial read -- a behaviour we already needed in
AdbClient, which is currently rolling out its own implementation of that.

I also fixed some typos in the previous version, and added unit tests for the
modified functions.

(*) It turns out there are windows equivalents for the posix semantics of file

  append - just pass FFFF... as file position. This is even automatic if the
  file was opened with the appropriate CreateFile flags - a thing I could not do
  immediately, as we are using a different function (_wsopen_s) to open files.


https://reviews.llvm.org/D28305

Files:
  include/lldb/Host/File.h
  source/Host/common/File.cpp
  unittests/Host/CMakeLists.txt
  unittests/Host/FileTest.cpp
  unittests/Host/Inputs/Read.test

Index: unittests/Host/Inputs/Read.test
===================================================================
--- /dev/null
+++ unittests/Host/Inputs/Read.test
@@ -0,0 +1,2 @@
+Read
+Read
Index: unittests/Host/FileTest.cpp
===================================================================
--- /dev/null
+++ unittests/Host/FileTest.cpp
@@ -0,0 +1,167 @@
+//===-- FileTest.cpp --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+#include "lldb/Core/Error.h"
+#include "lldb/Host/File.h"
+#include "lldb/Host/Pipe.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+
+extern const char *TestMainArgv0;
+
+using namespace lldb_private;
+
+class FileTest : public testing::Test {
+public:
+  void SetUp() override {
+    llvm::StringRef exe_folder = llvm::sys::path::parent_path(TestMainArgv0);
+    llvm::SmallString<128> output_folder = exe_folder;
+    llvm::sys::path::append(output_folder, "Output");
+    ASSERT_FALSE(llvm::sys::fs::create_directory(output_folder, true));
+
+    output_file = output_folder;
+    llvm::StringRef test_name =
+        testing::UnitTest::GetInstance()->current_test_info()->name();
+    llvm::sys::path::append(output_file, test_name + ".test");
+
+    input_file = exe_folder;
+    llvm::sys::path::append(input_file, "Inputs", "Read.test");
+  }
+
+protected:
+  llvm::SmallString<128> input_file;
+  llvm::SmallString<128> output_file;
+};
+
+TEST_F(FileTest, Write) {
+  File f(output_file.c_str(),
+         File::eOpenOptionWrite | File::eOpenOptionRead |
+             File::eOpenOptionTruncate | File::eOpenOptionCanCreate);
+  ASSERT_TRUE(f.IsValid());
+
+  char buf[100] = "Write";
+  size_t len = strlen(buf);
+  ASSERT_TRUE(f.Write(buf, len).Success());
+  EXPECT_EQ(strlen(buf), len);
+  ASSERT_TRUE(f.Write(buf, len).Success());
+  EXPECT_EQ(strlen(buf), len);
+
+  len = sizeof buf;
+  off_t offset = 0;
+  ASSERT_TRUE(f.Read(buf, len, offset).Success());
+  EXPECT_EQ(10, offset);
+  EXPECT_EQ(10u, len);
+  EXPECT_STREQ("WriteWrite", buf);
+}
+
+TEST_F(FileTest, WriteOffset) {
+  File f(output_file.c_str(),
+         File::eOpenOptionWrite | File::eOpenOptionRead |
+             File::eOpenOptionTruncate | File::eOpenOptionCanCreate);
+  ASSERT_TRUE(f.IsValid());
+
+  char buf[100] = "Write";
+  size_t len = strlen(buf);
+  off_t offset = 0;
+  ASSERT_TRUE(f.Write(buf, len, offset).Success());
+  EXPECT_EQ(off_t(strlen(buf)), offset);
+  EXPECT_EQ(strlen(buf), len);
+  offset = 1;
+  ASSERT_TRUE(f.Write(buf, len, offset).Success());
+  EXPECT_EQ(off_t(strlen(buf)+1), offset);
+  EXPECT_EQ(strlen(buf), len);
+
+  len = sizeof buf;
+  offset = 0;
+  ASSERT_TRUE(f.Read(buf, len, offset).Success());
+  EXPECT_EQ(6, offset);
+  EXPECT_EQ(6u, len);
+  EXPECT_STREQ("WWrite", buf);
+}
+
+TEST_F(FileTest, WriteAppend) {
+  File f(output_file.c_str(),
+         File::eOpenOptionWrite | File::eOpenOptionRead |
+             File::eOpenOptionTruncate | File::eOpenOptionAppend |
+             File::eOpenOptionCanCreate);
+  ASSERT_TRUE(f.IsValid());
+
+  char buf[100] = "Write";
+  size_t len = strlen(buf);
+  off_t offset = 0;
+  ASSERT_TRUE(f.Write(buf, len, offset).Success());
+  EXPECT_EQ(off_t(strlen(buf)), offset);
+  EXPECT_EQ(strlen(buf), len);
+  offset = 1;
+  ASSERT_TRUE(f.Write(buf, len, offset).Success());
+  EXPECT_EQ(off_t(strlen(buf)+1), offset);
+  EXPECT_EQ(strlen(buf), len);
+
+  len = sizeof buf;
+  offset = 0;
+  ASSERT_TRUE(f.Read(buf, len, offset).Success());
+  EXPECT_EQ(10, offset);
+  EXPECT_EQ(10u, len);
+  EXPECT_STREQ("WriteWrite", buf);
+}
+
+TEST_F(FileTest, Read) {
+  File f(input_file.c_str(), File::eOpenOptionRead);
+  ASSERT_TRUE(f.IsValid());
+
+  char buf[100] = "";
+  size_t len = 2;
+  ASSERT_TRUE(f.Read(buf, len).Success());
+  EXPECT_EQ(2u, len);
+  EXPECT_STREQ("Re", buf);
+  len = sizeof buf;
+  ASSERT_TRUE(f.Read(buf, len).Success());
+  EXPECT_EQ(8u, len);
+  EXPECT_STREQ("ad\nRead\n", buf);
+}
+
+TEST_F(FileTest, ReadOffset) {
+  File f(input_file.c_str(), File::eOpenOptionRead);
+  ASSERT_TRUE(f.IsValid());
+
+  char buf[100] = "";
+  size_t len = 2;
+  off_t offset = 0;
+  ASSERT_TRUE(f.Read(buf, len, offset).Success());
+  EXPECT_EQ(2u, len);
+  EXPECT_EQ(2, offset);
+  EXPECT_STREQ("Re", buf);
+  len = sizeof buf;
+  offset = 5;
+  ASSERT_TRUE(f.Read(buf, len, offset).Success());
+  EXPECT_EQ(5u, len);
+  EXPECT_EQ(10, offset);
+  EXPECT_STREQ("Read\n", buf);
+}
+
+#if LLVM_ON_UNIX
+#define REQUIRES_UNIX(Test) Test
+#else
+#define REQUIRES_UNIX(Test) DISABLED_##Test
+#endif
+
+TEST_F(FileTest, ReadPipe) {
+  Pipe pipe;
+  ASSERT_TRUE(pipe.CreateNew(false).Success());
+  File f(pipe.GetReadFileDescriptor(), false);
+  size_t bytes_written;
+  ASSERT_TRUE(pipe.Write("X", 1, bytes_written).Success());
+  char buf[10] = "";
+  size_t len = sizeof buf;
+  ASSERT_TRUE(f.Read(buf, len).Success());
+  EXPECT_EQ(1u, len);
+}
Index: unittests/Host/CMakeLists.txt
===================================================================
--- unittests/Host/CMakeLists.txt
+++ unittests/Host/CMakeLists.txt
@@ -1,7 +1,13 @@
 add_lldb_unittest(HostTests
   FileSpecTest.cpp
   FileSystemTest.cpp
+  FileTest.cpp
   SocketAddressTest.cpp
   SocketTest.cpp
   SymbolsTest.cpp
   )
+
+set(test_inputs
+  Read.test)
+
+add_unittest_inputs(HostTests "${test_inputs}")
Index: source/Host/common/File.cpp
===================================================================
--- source/Host/common/File.cpp
+++ source/Host/common/File.cpp
@@ -367,58 +367,6 @@
   return result;
 }
 
-off_t File::SeekFromCurrent(off_t offset, Error *error_ptr) {
-  off_t result = -1;
-  if (DescriptorIsValid()) {
-    result = ::lseek(m_descriptor, offset, SEEK_CUR);
-
-    if (error_ptr) {
-      if (result == -1)
-        error_ptr->SetErrorToErrno();
-      else
-        error_ptr->Clear();
-    }
-  } else if (StreamIsValid()) {
-    result = ::fseek(m_stream, offset, SEEK_CUR);
-
-    if (error_ptr) {
-      if (result == -1)
-        error_ptr->SetErrorToErrno();
-      else
-        error_ptr->Clear();
-    }
-  } else if (error_ptr) {
-    error_ptr->SetErrorString("invalid file handle");
-  }
-  return result;
-}
-
-off_t File::SeekFromEnd(off_t offset, Error *error_ptr) {
-  off_t result = -1;
-  if (DescriptorIsValid()) {
-    result = ::lseek(m_descriptor, offset, SEEK_END);
-
-    if (error_ptr) {
-      if (result == -1)
-        error_ptr->SetErrorToErrno();
-      else
-        error_ptr->Clear();
-    }
-  } else if (StreamIsValid()) {
-    result = ::fseek(m_stream, offset, SEEK_END);
-
-    if (error_ptr) {
-      if (result == -1)
-        error_ptr->SetErrorToErrno();
-      else
-        error_ptr->Clear();
-    }
-  } else if (error_ptr) {
-    error_ptr->SetErrorString("invalid file handle");
-  }
-  return result;
-}
-
 Error File::Flush() {
   Error error;
   if (StreamIsValid()) {
@@ -435,218 +383,104 @@
   return error;
 }
 
-Error File::Sync() {
-  Error error;
-  if (DescriptorIsValid()) {
-#ifdef _WIN32
-    int err = FlushFileBuffers((HANDLE)_get_osfhandle(m_descriptor));
-    if (err == 0)
-      error.SetErrorToGenericError();
-#else
-    int err = 0;
-    do {
-      err = ::fsync(m_descriptor);
-    } while (err == -1 && errno == EINTR);
-
-    if (err == -1)
-      error.SetErrorToErrno();
-#endif
-  } else {
-    error.SetErrorString("invalid file handle");
-  }
-  return error;
-}
-
 #if defined(__APPLE__)
 // Darwin kernels only can read/write <= INT_MAX bytes
-#define MAX_READ_SIZE INT_MAX
-#define MAX_WRITE_SIZE INT_MAX
+constexpr size_t MAX_READ_SIZE = INT_MAX;
+constexpr size_t MAX_WRITE_SIZE = INT_MAX;
+#elif defined(LLVM_ON_WIN32)
+constexpr size_t MAX_READ_SIZE = ULONG_MAX;
+constexpr size_t MAX_WRITE_SIZE = ULONG_MAX;
+#else
+constexpr size_t MAX_READ_SIZE = SIZE_MAX;
+constexpr size_t MAX_WRITE_SIZE = SIZE_MAX;
 #endif
 
 Error File::Read(void *buf, size_t &num_bytes) {
-  Error error;
-
-#if defined(MAX_READ_SIZE)
-  if (num_bytes > MAX_READ_SIZE) {
-    uint8_t *p = (uint8_t *)buf;
-    size_t bytes_left = num_bytes;
-    // Init the num_bytes read to zero
-    num_bytes = 0;
-
-    while (bytes_left > 0) {
-      size_t curr_num_bytes;
-      if (bytes_left > MAX_READ_SIZE)
-        curr_num_bytes = MAX_READ_SIZE;
-      else
-        curr_num_bytes = bytes_left;
-
-      error = Read(p + num_bytes, curr_num_bytes);
-
-      // Update how many bytes were read
-      num_bytes += curr_num_bytes;
-      if (bytes_left < curr_num_bytes)
-        bytes_left = 0;
-      else
-        bytes_left -= curr_num_bytes;
-
-      if (error.Fail())
-        break;
-    }
-    return error;
-  }
-#endif
-
-  ssize_t bytes_read = -1;
-  if (DescriptorIsValid()) {
-    do {
-      bytes_read = ::read(m_descriptor, buf, num_bytes);
-    } while (bytes_read < 0 && errno == EINTR);
-
-    if (bytes_read == -1) {
-      error.SetErrorToErrno();
-      num_bytes = 0;
-    } else
-      num_bytes = bytes_read;
-  } else if (StreamIsValid()) {
-    bytes_read = ::fread(buf, 1, num_bytes, m_stream);
-
-    if (bytes_read == 0) {
-      if (::feof(m_stream))
-        error.SetErrorString("feof");
-      else if (::ferror(m_stream))
-        error.SetErrorString("ferror");
-      num_bytes = 0;
-    } else
-      num_bytes = bytes_read;
-  } else {
-    num_bytes = 0;
-    error.SetErrorString("invalid file handle");
-  }
-  return error;
+  return DoRead(buf, num_bytes, nullptr);
 }
 
 Error File::Write(const void *buf, size_t &num_bytes) {
-  Error error;
-
-#if defined(MAX_WRITE_SIZE)
-  if (num_bytes > MAX_WRITE_SIZE) {
-    const uint8_t *p = (const uint8_t *)buf;
-    size_t bytes_left = num_bytes;
-    // Init the num_bytes written to zero
-    num_bytes = 0;
-
-    while (bytes_left > 0) {
-      size_t curr_num_bytes;
-      if (bytes_left > MAX_WRITE_SIZE)
-        curr_num_bytes = MAX_WRITE_SIZE;
-      else
-        curr_num_bytes = bytes_left;
-
-      error = Write(p + num_bytes, curr_num_bytes);
-
-      // Update how many bytes were read
-      num_bytes += curr_num_bytes;
-      if (bytes_left < curr_num_bytes)
-        bytes_left = 0;
-      else
-        bytes_left -= curr_num_bytes;
-
-      if (error.Fail())
-        break;
-    }
-    return error;
-  }
-#endif
-
-  ssize_t bytes_written = -1;
-  if (DescriptorIsValid()) {
-    do {
-      bytes_written = ::write(m_descriptor, buf, num_bytes);
-    } while (bytes_written < 0 && errno == EINTR);
-
-    if (bytes_written == -1) {
-      error.SetErrorToErrno();
-      num_bytes = 0;
-    } else
-      num_bytes = bytes_written;
-  } else if (StreamIsValid()) {
-    bytes_written = ::fwrite(buf, 1, num_bytes, m_stream);
-
-    if (bytes_written == 0) {
-      if (::feof(m_stream))
-        error.SetErrorString("feof");
-      else if (::ferror(m_stream))
-        error.SetErrorString("ferror");
-      num_bytes = 0;
-    } else
-      num_bytes = bytes_written;
+  return DoWrite(buf, num_bytes, nullptr);
+}
 
-  } else {
-    num_bytes = 0;
-    error.SetErrorString("invalid file handle");
-  }
+Error File::Read(void *buf, size_t &num_bytes, off_t &offset) {
+  return DoRead(buf, num_bytes, &offset);
+}
 
-  return error;
+Error File::Write(const void *buf, size_t &num_bytes, off_t &offset) {
+  return DoWrite(buf, num_bytes, &offset);
 }
 
-Error File::Read(void *buf, size_t &num_bytes, off_t &offset) {
+Error File::DoRead(void *buf, size_t &num_bytes, off_t *offset) {
   Error error;
-
-#if defined(MAX_READ_SIZE)
-  if (num_bytes > MAX_READ_SIZE) {
-    uint8_t *p = (uint8_t *)buf;
-    size_t bytes_left = num_bytes;
-    // Init the num_bytes read to zero
+  size_t bytes_left = num_bytes;
+  int fd = GetDescriptor();
+  if (fd == kInvalidDescriptor) {
     num_bytes = 0;
-
-    while (bytes_left > 0) {
-      size_t curr_num_bytes;
-      if (bytes_left > MAX_READ_SIZE)
-        curr_num_bytes = MAX_READ_SIZE;
-      else
-        curr_num_bytes = bytes_left;
-
-      error = Read(p + num_bytes, curr_num_bytes, offset);
-
-      // Update how many bytes were read
-      num_bytes += curr_num_bytes;
-      if (bytes_left < curr_num_bytes)
-        bytes_left = 0;
-      else
-        bytes_left -= curr_num_bytes;
-
-      if (error.Fail())
-        break;
-    }
-    return error;
+    return Error("invalid file handle");
   }
-#endif
 
+  uint8_t *dest = static_cast<uint8_t *>(buf);
 #ifndef _WIN32
-  int fd = GetDescriptor();
-  if (fd != kInvalidDescriptor) {
-    ssize_t bytes_read = -1;
+  ssize_t bytes_read = -1;
+  size_t bytes_to_read = std::min(MAX_READ_SIZE, bytes_left);
+  while (bytes_left != 0 && bytes_read != 0) {
     do {
-      bytes_read = ::pread(fd, buf, num_bytes, offset);
+      if (offset)
+        bytes_read = ::pread(fd, dest, bytes_to_read, *offset);
+      else
+        bytes_read = ::read(fd, dest, bytes_to_read);
     } while (bytes_read < 0 && errno == EINTR);
 
     if (bytes_read < 0) {
       num_bytes = 0;
       error.SetErrorToErrno();
-    } else {
-      offset += bytes_read;
-      num_bytes = bytes_read;
+      return error;
     }
-  } else {
-    num_bytes = 0;
-    error.SetErrorString("invalid file handle");
+
+    dest += bytes_read;
+    if (offset)
+      *offset += bytes_read;
+    bytes_left -= bytes_read;
+    if (size_t(bytes_read) != MAX_READ_SIZE)
+      break;
   }
+  num_bytes -= bytes_left;
 #else
-  long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
-  SeekFromStart(offset);
-  error = Read(buf, num_bytes);
-  if (!error.Fail())
-    SeekFromStart(cur);
+  HANDLE H = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
+  if (!H || H == INVALID_HANDLE_VALUE)
+    return Error("invalid file handle");
+
+  while (bytes_left != 0) {
+    OVERLAPPED OV = {};
+    if (offset) {
+      LARGE_INTEGER large_off;
+      large_off.QuadPart = *offset;
+
+      OV.Offset = large_off.LowPart;
+      OV.OffsetHigh = large_off.HighPart;
+    }
+
+    DWORD req_size = static_cast<DWORD>(std::min(MAX_READ_SIZE, bytes_left));
+    DWORD actual_size = 0;
+    BOOL result =
+        ::ReadFile(H, dest, req_size, &actual_size, offset ? &OV : nullptr);
+    if (actual_size == 0) {
+      // EOF was reached.
+      break;
+    }
+    if (!result) {
+      error.SetError(GetLastError(), eErrorTypeWin32);
+      return error;
+    }
+    dest += actual_size;
+    bytes_left -= actual_size;
+    if(offset)
+      *offset += actual_size;
+    if (actual_size != MAX_READ_SIZE)
+      break;
+  }
+  num_bytes -= bytes_left;
 #endif
   return error;
 }
@@ -695,68 +529,76 @@
   return error;
 }
 
-Error File::Write(const void *buf, size_t &num_bytes, off_t &offset) {
+Error File::DoWrite(const void *buf, size_t &num_bytes, off_t *offset) {
   Error error;
-
-#if defined(MAX_WRITE_SIZE)
-  if (num_bytes > MAX_WRITE_SIZE) {
-    const uint8_t *p = (const uint8_t *)buf;
-    size_t bytes_left = num_bytes;
-    // Init the num_bytes written to zero
+  size_t bytes_left = num_bytes;
+  int fd = GetDescriptor();
+  if (fd == kInvalidDescriptor) {
     num_bytes = 0;
-
-    while (bytes_left > 0) {
-      size_t curr_num_bytes;
-      if (bytes_left > MAX_WRITE_SIZE)
-        curr_num_bytes = MAX_WRITE_SIZE;
-      else
-        curr_num_bytes = bytes_left;
-
-      error = Write(p + num_bytes, curr_num_bytes, offset);
-
-      // Update how many bytes were read
-      num_bytes += curr_num_bytes;
-      if (bytes_left < curr_num_bytes)
-        bytes_left = 0;
-      else
-        bytes_left -= curr_num_bytes;
-
-      if (error.Fail())
-        break;
-    }
-    return error;
+    return Error("invalid file handle");
   }
-#endif
 
-  int fd = GetDescriptor();
-  if (fd != kInvalidDescriptor) {
+  const uint8_t *src = static_cast<const uint8_t *>(buf);
 #ifndef _WIN32
-    ssize_t bytes_written = -1;
+  ssize_t bytes_written = -1;
+  size_t bytes_to_write = std::min(MAX_WRITE_SIZE, bytes_left);
+  while (bytes_left != 0) {
     do {
-      bytes_written = ::pwrite(m_descriptor, buf, num_bytes, offset);
+      if (offset)
+        bytes_written = ::pwrite(fd, src, bytes_to_write, *offset);
+      else
+        bytes_written = ::write(fd, src, bytes_to_write);
     } while (bytes_written < 0 && errno == EINTR);
 
     if (bytes_written < 0) {
       num_bytes = 0;
       error.SetErrorToErrno();
-    } else {
-      offset += bytes_written;
-      num_bytes = bytes_written;
+      return error;
     }
-#else
-    long cur = ::lseek(m_descriptor, 0, SEEK_CUR);
-    error = Write(buf, num_bytes);
-    long after = ::lseek(m_descriptor, 0, SEEK_CUR);
 
-    if (!error.Fail())
-      SeekFromStart(cur);
-
-    offset = after;
-#endif
-  } else {
-    num_bytes = 0;
-    error.SetErrorString("invalid file handle");
+    src += bytes_written;
+    if (offset)
+      *offset += bytes_written;
+    bytes_left -= bytes_written;
+    if (size_t(bytes_written) != MAX_WRITE_SIZE)
+      break;
   }
+#else
+  HANDLE H = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
+  if (!H || H == INVALID_HANDLE_VALUE)
+    return Error("invalid file handle");
+
+  while (bytes_left != 0) {
+    DWORD req_size = static_cast<DWORD>(std::min(MAX_WRITE_SIZE, bytes_left));
+    DWORD actual_size = 0;
+    BOOL result;
+    if (!offset)
+      result = ::WriteFile(H, src, req_size, &actual_size, nullptr);
+    else {
+      OVERLAPPED OV = {};
+      if (m_options & File::eOpenOptionAppend)
+        OV.Offset = OV.OffsetHigh = 0xFFFFFFFF;
+      else {
+        LARGE_INTEGER large_off;
+        large_off.QuadPart = *offset;
+
+        OV.Offset = large_off.LowPart;
+        OV.OffsetHigh = large_off.HighPart;
+      }
+      result = ::WriteFile(H, src, req_size, &actual_size, &OV);
+    }
+    if (!result) {
+      error.SetError(GetLastError(), eErrorTypeWin32);
+      return error;
+    }
+    src += actual_size;
+    bytes_left -= actual_size;
+    if (offset)
+      *offset += actual_size;
+    if (actual_size != MAX_WRITE_SIZE)
+      break;
+  }
+#endif
   return error;
 }
 
Index: include/lldb/Host/File.h
===================================================================
--- include/lldb/Host/File.h
+++ include/lldb/Host/File.h
@@ -265,51 +265,6 @@
   off_t SeekFromStart(off_t offset, Error *error_ptr = nullptr);
 
   //------------------------------------------------------------------
-  /// Seek to an offset relative to the current file position.
-  ///
-  /// NOTE: This function is NOT thread safe, other threads that
-  /// access this object might also change the current file position.
-  /// For thread safe reads and writes see the following functions:
-  /// @see File::Read (void *, size_t, off_t &)
-  /// @see File::Write (const void *, size_t, off_t &)
-  ///
-  /// @param[in] offset
-  ///     The offset to seek to within the file relative to the
-  ///     current file position.
-  ///
-  /// @param[in] error_ptr
-  ///     A pointer to a lldb_private::Error object that will be
-  ///     filled in if non-nullptr.
-  ///
-  /// @return
-  ///     The resulting seek offset, or -1 on error.
-  //------------------------------------------------------------------
-  off_t SeekFromCurrent(off_t offset, Error *error_ptr = nullptr);
-
-  //------------------------------------------------------------------
-  /// Seek to an offset relative to the end of the file.
-  ///
-  /// NOTE: This function is NOT thread safe, other threads that
-  /// access this object might also change the current file position.
-  /// For thread safe reads and writes see the following functions:
-  /// @see File::Read (void *, size_t, off_t &)
-  /// @see File::Write (const void *, size_t, off_t &)
-  ///
-  /// @param[in,out] offset
-  ///     The offset to seek to within the file relative to the
-  ///     end of the file which gets filled in with the resulting
-  ///     absolute file offset.
-  ///
-  /// @param[in] error_ptr
-  ///     A pointer to a lldb_private::Error object that will be
-  ///     filled in if non-nullptr.
-  ///
-  /// @return
-  ///     The resulting seek offset, or -1 on error.
-  //------------------------------------------------------------------
-  off_t SeekFromEnd(off_t offset, Error *error_ptr = nullptr);
-
-  //------------------------------------------------------------------
   /// Read bytes from a file from the specified file offset.
   ///
   /// NOTE: This function is thread safe in that clients manager their
@@ -403,15 +358,6 @@
   Error Flush();
 
   //------------------------------------------------------------------
-  /// Sync to disk.
-  ///
-  /// @return
-  ///     An error object that indicates success or the reason for
-  ///     failure.
-  //------------------------------------------------------------------
-  Error Sync();
-
-  //------------------------------------------------------------------
   /// Get the permissions for a this file.
   ///
   /// @return
@@ -472,6 +418,9 @@
 
   void CalculateInteractiveAndTerminal();
 
+  Error DoRead(void *dst, size_t &num_bytes, off_t *offset);
+
+  Error DoWrite(const void *src, size_t &num_bytes, off_t *offset);
   //------------------------------------------------------------------
   // Member variables
   //------------------------------------------------------------------
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to