// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "smbfs/smb_filesystem.h"

#include <utility>
#include <vector>

#include <base/bind.h>
#include <base/callback_helpers.h>
#include <base/logging.h>
#include <base/posix/safe_strerror.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_piece.h>
#include <base/strings/string_util.h>

#include "smbfs/samba_interface_impl.h"
#include "smbfs/util.h"

namespace smbfs {

namespace {

constexpr char kSambaThreadName[] = "smbfs-libsmb";
constexpr char kUrlPrefix[] = "smb://";

constexpr double kAttrTimeoutSeconds = 5.0;
constexpr mode_t kAllowedFileTypes = S_IFREG | S_IFDIR;
constexpr mode_t kFileModeMask = kAllowedFileTypes | 0770;

// Cache stat information for the latest 1024 directory entries retrieved.
constexpr int kStatCacheSize = 1024;
constexpr double kStatCacheTimeoutSeconds = kAttrTimeoutSeconds;

bool IsAllowedFileMode(mode_t mode) {
  return mode & kAllowedFileTypes;
}

}  // namespace

SmbFilesystem::Options::Options() = default;

SmbFilesystem::Options::~Options() = default;

SmbFilesystem::Options::Options(Options&&) = default;

SmbFilesystem::Options& SmbFilesystem::Options::operator=(Options&&) = default;

SmbFilesystem::SmbFilesystem(Delegate* delegate, Options options)
    : delegate_(delegate),
      share_path_(options.share_path),
      uid_(options.uid),
      gid_(options.gid),
      use_kerberos_(options.use_kerberos),
      samba_thread_(kSambaThreadName),
      stat_cache_(kStatCacheSize) {
  DCHECK(delegate_);

  // Ensure files are not owned by root.
  CHECK_GT(uid_, 0);
  CHECK_GT(gid_, 0);

  CHECK(!share_path_.empty());
  CHECK_NE(share_path_.back(), '/');

  samba_impl_ = std::make_unique<SambaInterfaceImpl>(
      std::move(options.credentials), options.allow_ntlm);

  CHECK(samba_thread_.Start());
}

SmbFilesystem::SmbFilesystem(Delegate* delegate, const std::string& share_path)
    : delegate_(delegate),
      share_path_(share_path),
      samba_thread_(kSambaThreadName),
      stat_cache_(kStatCacheSize) {
  DCHECK(delegate_);
}

SmbFilesystem::~SmbFilesystem() {
  if (samba_impl_) {
    // Stop the Samba processing thread before destroying the context to avoid a
    // UAF on the context.
    samba_thread_.Stop();
  }
}

base::WeakPtr<SmbFilesystem> SmbFilesystem::GetWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

void SmbFilesystem::SetSambaInterface(
    std::unique_ptr<SambaInterface> samba_interface) {
  samba_impl_ = std::move(samba_interface);
}

SmbFilesystem::ConnectError SmbFilesystem::EnsureConnected() {
  SMBCFILE* dir = nullptr;
  int err = samba_impl_->OpenDirectory(resolved_share_path_, &dir);
  if (err) {
    LOG(INFO) << "EnsureConnected OpenDirectory failed";
    switch (err) {
      case EPERM:
      case EACCES:
        return ConnectError::kAccessDenied;
      case ENODEV:
      case ENOENT:
      case ETIMEDOUT:
      // This means unable to resolve host, in some, but not necessarily all
      // cases.
      case EINVAL:
      // Host unreachable.
      case EHOSTUNREACH:
      // Host not listening on SMB port.
      case ECONNREFUSED:
        return ConnectError::kNotFound;
      case ECONNABORTED:
        return ConnectError::kSmb1Unsupported;
      default:
        LOG(WARNING) << "Unexpected error code " << err << ": "
                     << base::safe_strerror(err);
        return ConnectError::kUnknownError;
    }
  }

  connected_ = true;

  err = samba_impl_->CloseDirectory(dir);
  LOG_IF(WARNING, err) << "CloseDirectory during EnsureConnected failed: "
                       << base::safe_strerror(err);

  return ConnectError::kOk;
}

void SmbFilesystem::SetResolvedAddress(const std::vector<uint8_t>& ip_address) {
  base::AutoLock l(lock_);

  if (ip_address.empty()) {
    resolved_share_path_ = share_path_;
    return;
  } else if (ip_address.size() != 4) {
    // TODO(crbug.com/1051291): Support IPv6.
    LOG(ERROR) << "Invalid IP address";
    return;
  }

  std::string address_str = IpAddressToString(ip_address);
  DCHECK(!address_str.empty());

  const base::StringPiece prefix(kUrlPrefix);
  DCHECK(base::StartsWith(share_path_, prefix, base::CompareCase::SENSITIVE));
  std::string::size_type host_end = share_path_.find('/', prefix.size());
  DCHECK_NE(host_end, std::string::npos);
  resolved_share_path_ =
      std::string(prefix) + address_str + share_path_.substr(host_end);
}

struct stat SmbFilesystem::MakeStat(ino_t inode,
                                    const struct stat& in_stat) const {
  struct stat stat = {0};
  stat.st_ino = inode;
  stat.st_mode = MakeStatModeBits(in_stat.st_mode);
  stat.st_uid = uid_;
  stat.st_gid = gid_;
  stat.st_nlink = 1;
  stat.st_size = in_stat.st_size;
  stat.st_atim = in_stat.st_atim;
  stat.st_ctim = in_stat.st_ctim;
  stat.st_mtim = in_stat.st_mtim;
  return stat;
}

mode_t SmbFilesystem::MakeStatModeBits(mode_t in_mode) const {
  mode_t mode = in_mode;

  // Clear any "other" permission bits.
  mode &= kFileModeMask;

  // If the entry is a directory, it must have the execute bit set.
  if (in_mode & S_IFDIR) {
    mode |= S_IXUSR;
  } else {
    mode &= ~S_IXUSR;
  }

  // Propagate user bits to group bits.
  mode &= ~S_IRWXG;
  if (mode & S_IRUSR) {
    mode |= S_IRGRP;
  }
  if (mode & S_IWUSR) {
    mode |= S_IWGRP;
  }
  if (mode & S_IXUSR) {
    mode |= S_IXGRP;
  }

  return mode;
}

std::string SmbFilesystem::MakeShareFilePath(const base::FilePath& path) const {
  std::string base_share_path;
  {
    base::AutoLock l(lock_);
    DCHECK(!resolved_share_path_.empty());
    base_share_path = resolved_share_path_;
  }

  if (path == base::FilePath("/")) {
    return base_share_path;
  }

  // Paths are constructed and not passed directly over FUSE. Therefore, these
  // two properties should always hold.
  DCHECK(path.IsAbsolute());
  DCHECK(!path.EndsWithSeparator());
  return base_share_path + path.value();
}

std::string SmbFilesystem::ShareFilePathFromInode(ino_t inode) const {
  const base::FilePath file_path = inode_map_.GetPath(inode);
  CHECK(!file_path.empty()) << "Path lookup for invalid inode: " << inode;
  return MakeShareFilePath(file_path);
}

uint64_t SmbFilesystem::AddOpenFile(SMBCFILE* file) {
  uint64_t handle = open_files_seq_++;
  // Disallow wrap around.
  CHECK(handle);
  open_files_[handle] = file;
  return handle;
}

void SmbFilesystem::RemoveOpenFile(uint64_t handle) {
  auto it = open_files_.find(handle);
  if (it == open_files_.end()) {
    NOTREACHED() << "File handle not found";
    return;
  }
  open_files_.erase(it);
}

SMBCFILE* SmbFilesystem::LookupOpenFile(uint64_t handle) const {
  const auto it = open_files_.find(handle);
  if (it == open_files_.end()) {
    return nullptr;
  }
  return it->second;
}

void SmbFilesystem::MaybeUpdateCredentials(int error) {
  if (use_kerberos_) {
    // If Kerberos is being used, it is assumed a valid user/workgroup has
    // already been provided, and password is always ignored.
    return;
  } else if (connected_) {
    // If a connection has already been made successfully, assume the
    // existing credentials are correct.
    return;
  }

  if (error == EPERM || error == EACCES) {
    // Delegate calls must always be made on the constructor thread.
    main_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&SmbFilesystem::RequestCredentialUpdate,
                                  base::Unretained(this)));
  }
}

void SmbFilesystem::RequestCredentialUpdate() {
  DCHECK(main_task_runner_->BelongsToCurrentThread());

  if (requesting_credentials_) {
    // Do nothing if a credential request is already in progress.
    return;
  }

  requesting_credentials_ = true;
  delegate_->RequestCredentials(
      base::Bind(&SmbFilesystem::OnRequestCredentialsDone, GetWeakPtr()));
}

void SmbFilesystem::OnRequestCredentialsDone(
    std::unique_ptr<SmbCredential> credentials) {
  requesting_credentials_ = false;
  if (!credentials) {
    return;
  }

  samba_impl_->UpdateCredentials(std::move(credentials));
}

void SmbFilesystem::StatFs(std::unique_ptr<StatFsRequest> request,
                           fuse_ino_t inode) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&SmbFilesystem::StatFsInternal, base::Unretained(this),
                     std::move(request), inode));
}

void SmbFilesystem::StatFsInternal(std::unique_ptr<StatFsRequest> request,
                                   fuse_ino_t inode) {
  if (request->IsInterrupted()) {
    return;
  }

  std::string share_file_path = ShareFilePathFromInode(inode);
  struct statvfs smb_statvfs = {0};
  int error = samba_impl_->StatVfs(share_file_path, &smb_statvfs);
  if (error) {
    VLOG(1) << "StatVfs path: " << share_file_path
            << " failed: " << base::safe_strerror(error);
    request->ReplyError(error);
    return;
  }

  request->ReplyStatFs(smb_statvfs);
}

void SmbFilesystem::Lookup(std::unique_ptr<EntryRequest> request,
                           fuse_ino_t parent_inode,
                           const std::string& name) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&SmbFilesystem::LookupInternal, base::Unretained(this),
                     std::move(request), parent_inode, name));
}

void SmbFilesystem::LookupInternal(std::unique_ptr<EntryRequest> request,
                                   fuse_ino_t parent_inode,
                                   const std::string& name) {
  if (request->IsInterrupted()) {
    return;
  }

  const base::FilePath parent_path = inode_map_.GetPath(parent_inode);
  CHECK(!parent_path.empty())
      << "Lookup on invalid parent inode: " << parent_inode;
  const base::FilePath file_path = parent_path.Append(name);
  const std::string share_file_path = MakeShareFilePath(file_path);

  ino_t inode = inode_map_.IncInodeRef(file_path);
  struct stat smb_stat = {0};
  if (!GetCachedInodeStat(inode, &smb_stat)) {
    int error = samba_impl_->Stat(share_file_path, &smb_stat);
    if (error) {
      VLOG(1) << "Stat path: " << share_file_path
              << " failed: " << base::safe_strerror(error);
      request->ReplyError(error);
      inode_map_.Forget(inode, 1);
      return;
    } else if (!IsAllowedFileMode(smb_stat.st_mode)) {
      VLOG(1) << "Disallowed file mode " << smb_stat.st_mode << " for path "
              << share_file_path;
      request->ReplyError(EACCES);
      inode_map_.Forget(inode, 1);
      return;
    }
  }

  struct stat entry_stat = MakeStat(inode, smb_stat);
  fuse_entry_param entry = {0};
  entry.ino = inode;
  entry.generation = 1;
  entry.attr = entry_stat;
  entry.attr_timeout = kAttrTimeoutSeconds;
  entry.entry_timeout = kAttrTimeoutSeconds;
  request->ReplyEntry(entry);
}

void SmbFilesystem::Forget(fuse_ino_t inode, uint64_t count) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&SmbFilesystem::ForgetInternal,
                                base::Unretained(this), inode, count));
}

void SmbFilesystem::ForgetInternal(fuse_ino_t inode, uint64_t count) {
  if (inode_map_.Forget(inode, count)) {
    // The inode was removed, invalidate any cached stat information.
    EraseCachedInodeStat(inode);
  }
}

void SmbFilesystem::GetAttr(std::unique_ptr<AttrRequest> request,
                            fuse_ino_t inode) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&SmbFilesystem::GetAttrInternal, base::Unretained(this),
                     std::move(request), inode));
}

void SmbFilesystem::GetAttrInternal(std::unique_ptr<AttrRequest> request,
                                    fuse_ino_t inode) {
  if (request->IsInterrupted()) {
    return;
  }

  struct stat smb_stat = {0};
  const std::string share_file_path = ShareFilePathFromInode(inode);

  if (!GetCachedInodeStat(inode, &smb_stat)) {
    int error = samba_impl_->Stat(share_file_path, &smb_stat);
    if (error) {
      VLOG(1) << "Stat path: " << share_file_path
              << " failed: " << base::safe_strerror(error);

      if (inode == FUSE_ROOT_ID) {
        MaybeUpdateCredentials(error);
      }

      request->ReplyError(error);
      return;
    }
  }

  if (!IsAllowedFileMode(smb_stat.st_mode)) {
    VLOG(1) << "Disallowed file mode " << smb_stat.st_mode << " for path "
            << share_file_path;
    request->ReplyError(EACCES);
    return;
  }

  connected_ = true;
  struct stat reply_stat = MakeStat(inode, smb_stat);
  request->ReplyAttr(reply_stat, kAttrTimeoutSeconds);
}

void SmbFilesystem::SetAttr(std::unique_ptr<AttrRequest> request,
                            fuse_ino_t inode,
                            base::Optional<uint64_t> file_handle,
                            const struct stat& attr,
                            int to_set) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&SmbFilesystem::SetAttrInternal,
                                base::Unretained(this), std::move(request),
                                inode, std::move(file_handle), attr, to_set));
}

void SmbFilesystem::SetAttrInternal(std::unique_ptr<AttrRequest> request,
                                    fuse_ino_t inode,
                                    base::Optional<uint64_t> file_handle,
                                    const struct stat& attr,
                                    int to_set) {
  if (request->IsInterrupted()) {
    return;
  }

  // Currently, only setting size (ie. O_TRUC, ftruncate()) or times (ie.
  // utime(), utimensat()) is supported.
  const int kSupportedAttrs =
      FUSE_SET_ATTR_SIZE | FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME;
  if (to_set & ~kSupportedAttrs) {
    LOG(WARNING) << "Unsupported |to_set| flags on setattr: " << to_set;
    request->ReplyError(ENOTSUP);
    return;
  }
  if (!to_set) {
    VLOG(1) << "No supported |to_set| flags set on setattr: " << to_set;
    request->ReplyError(EINVAL);
    return;
  }

  const std::string share_file_path = ShareFilePathFromInode(inode);

  struct stat smb_stat = {0};
  int error = samba_impl_->Stat(share_file_path, &smb_stat);
  if (error) {
    VLOG(1) << "Stat path: " << share_file_path
            << " failed: " << base::safe_strerror(error);
    request->ReplyError(error);
    return;
  }
  struct stat reply_stat = MakeStat(inode, smb_stat);

  // SetAttrInternal supports changing multiple attributes simultaneously but
  // this is not atomic: all changes must succeed for the request to succeed but
  // a partial failure will not be unapplied.
  if (to_set & FUSE_SET_ATTR_SIZE) {
    error = SetFileSizeInternal(share_file_path, file_handle, attr.st_size,
                                smb_stat, &reply_stat);
    if (error) {
      request->ReplyError(error);
      return;
    }
  }

  if (to_set & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) {
    error = SetUtimesInternal(share_file_path, to_set, attr.st_atim,
                              attr.st_mtim, smb_stat, &reply_stat);
    if (error) {
      request->ReplyError(error);
      return;
    }
  }

  // Modifying the attributes invalidates any cached inode we have.
  EraseCachedInodeStat(inode);

  request->ReplyAttr(reply_stat, kAttrTimeoutSeconds);
}

int SmbFilesystem::SetFileSizeInternal(const std::string& share_file_path,
                                       base::Optional<uint64_t> file_handle,
                                       off_t size,
                                       const struct stat& current_stat,
                                       struct stat* reply_stat) {
  DCHECK(reply_stat);

  if (current_stat.st_mode & S_IFDIR) {
    return EISDIR;
  } else if (!(current_stat.st_mode & S_IFREG)) {
    VLOG(1) << "Disallowed file mode " << current_stat.st_mode << " for path "
            << share_file_path;
    return EACCES;
  }

  SMBCFILE* file = nullptr;
  int error = 0;
  base::ScopedClosureRunner file_closer;
  if (file_handle) {
    file = LookupOpenFile(*file_handle);
    if (!file) {
      return EBADF;
    }
  } else {
    error = samba_impl_->OpenFile(share_file_path, O_WRONLY, 0, &file);
    if (error) {
      VLOG(1) << "OpenFile path: " << share_file_path
              << " failed: " << base::safe_strerror(error);
      return error;
    }

    file_closer.ReplaceClosure(base::BindOnce(
        [](SambaInterface* samba_impl, SMBCFILE* file) {
          int error = samba_impl->CloseFile(file);
          if (error) {
            LOG(ERROR)
                << "CloseFile failed on temporary SetFileSizeInternal file: "
                << base::safe_strerror(error);
          }
        },
        samba_impl_.get(), file));
  }

  error = samba_impl_->TruncateFile(file, size);
  if (error) {
    VLOG(1) << "TruncateFile size: " << size
            << " failed: " << base::safe_strerror(error);
    return error;
  }
  reply_stat->st_size = size;

  return 0;
}

int SmbFilesystem::SetUtimesInternal(const std::string& share_file_path,
                                     int to_set,
                                     const struct timespec& atime,
                                     const struct timespec& mtime,
                                     const struct stat& current_stat,
                                     struct stat* reply_stat) {
  DCHECK(to_set & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME));
  DCHECK(reply_stat);

  struct timespec requested_atime = current_stat.st_atim;
  struct timespec requested_mtime = current_stat.st_mtim;

  if (to_set & FUSE_SET_ATTR_ATIME) {
    requested_atime = atime;
  }
  if (to_set & FUSE_SET_ATTR_MTIME) {
    requested_mtime = mtime;
  }

  int error =
      samba_impl_->SetUtimes(share_file_path, requested_atime, requested_mtime);
  if (error) {
    VLOG(1) << "SetUtimes path: " << share_file_path
            << " failed: " << base::safe_strerror(error);
    return error;
  }

  reply_stat->st_atim = requested_atime;
  reply_stat->st_mtim = requested_mtime;

  return 0;
}

void SmbFilesystem::Open(std::unique_ptr<OpenRequest> request,
                         fuse_ino_t inode,
                         int flags) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&SmbFilesystem::OpenInternal, base::Unretained(this),
                     std::move(request), inode, flags));
}

void SmbFilesystem::OpenInternal(std::unique_ptr<OpenRequest> request,
                                 fuse_ino_t inode,
                                 int flags) {
  if (request->IsInterrupted()) {
    return;
  }

  if (inode == FUSE_ROOT_ID) {
    request->ReplyError(EISDIR);
    return;
  }

  const std::string share_file_path = ShareFilePathFromInode(inode);
  SMBCFILE* file = nullptr;
  int error = samba_impl_->OpenFile(share_file_path, flags, 0, &file);
  if (error) {
    VLOG(1) << "OpenFile path " << share_file_path
            << " failed: " << base::safe_strerror(error);
    request->ReplyError(error);
    return;
  }

  request->ReplyOpen(AddOpenFile(file));
}

void SmbFilesystem::Create(std::unique_ptr<CreateRequest> request,
                           fuse_ino_t parent_inode,
                           const std::string& name,
                           mode_t mode,
                           int flags) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&SmbFilesystem::CreateInternal, base::Unretained(this),
                     std::move(request), parent_inode, name, mode, flags));
}

void SmbFilesystem::CreateInternal(std::unique_ptr<CreateRequest> request,
                                   fuse_ino_t parent_inode,
                                   const std::string& name,
                                   mode_t mode,
                                   int flags) {
  if (request->IsInterrupted()) {
    return;
  }

  flags |= O_CREAT;
  mode &= 0777;

  const base::FilePath parent_path = inode_map_.GetPath(parent_inode);
  CHECK(!parent_path.empty())
      << "Lookup on invalid parent inode: " << parent_inode;
  const base::FilePath file_path = parent_path.Append(name);
  const std::string share_file_path = MakeShareFilePath(file_path);

  // NOTE: |mode| appears to be ignored by libsmbclient.
  SMBCFILE* file = nullptr;
  int error = samba_impl_->OpenFile(share_file_path, flags, mode, &file);
  if (error) {
    VLOG(1) << "OpenFile path: " << share_file_path
            << " failed: " << base::safe_strerror(error);
    request->ReplyError(error);
    return;
  }

  uint64_t handle = AddOpenFile(file);

  ino_t inode = inode_map_.IncInodeRef(file_path);
  struct stat entry_stat = MakeStat(inode, {0});
  entry_stat.st_mode = S_IFREG | mode;
  fuse_entry_param entry = {0};
  entry.ino = inode;
  entry.generation = 1;
  entry.attr = entry_stat;
  // Force readers to see coherent user / group permission bits by not caching
  // stat structure.
  entry.attr_timeout = 0;
  entry.entry_timeout = kAttrTimeoutSeconds;
  request->ReplyCreate(entry, handle);
}

void SmbFilesystem::Read(std::unique_ptr<BufRequest> request,
                         fuse_ino_t inode,
                         uint64_t file_handle,
                         size_t size,
                         off_t offset) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&SmbFilesystem::ReadInternal, base::Unretained(this),
                     std::move(request), inode, file_handle, size, offset));
}

void SmbFilesystem::ReadInternal(std::unique_ptr<BufRequest> request,
                                 fuse_ino_t inode,
                                 uint64_t file_handle,
                                 size_t size,
                                 off_t offset) {
  if (request->IsInterrupted()) {
    return;
  }

  SMBCFILE* file = LookupOpenFile(file_handle);
  if (!file) {
    request->ReplyError(EBADF);
    return;
  }

  int error = samba_impl_->SeekFile(file, offset, SEEK_SET);
  if (error) {
    VLOG(1) << "SeekFile path: " << ShareFilePathFromInode(inode)
            << ", offset: " << offset
            << " failed: " << base::safe_strerror(error);
    request->ReplyError(error);
    return;
  }

  std::vector<char> buf(size);
  size_t bytes_read = 0;
  error = samba_impl_->ReadFile(file, buf.data(), size, &bytes_read);
  if (error) {
    VLOG(1) << "ReadFile path: " << ShareFilePathFromInode(inode)
            << " offset: " << offset << ", size: " << size
            << " failed: " << base::safe_strerror(error);
    request->ReplyError(error);
    return;
  }

  request->ReplyBuf(buf.data(), bytes_read);
}

void SmbFilesystem::Write(std::unique_ptr<WriteRequest> request,
                          fuse_ino_t inode,
                          uint64_t file_handle,
                          const char* buf,
                          size_t size,
                          off_t offset) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&SmbFilesystem::WriteInternal, base::Unretained(this),
                     std::move(request), inode, file_handle,
                     std::vector<char>(buf, buf + size), offset));
}

void SmbFilesystem::WriteInternal(std::unique_ptr<WriteRequest> request,
                                  fuse_ino_t inode,
                                  uint64_t file_handle,
                                  const std::vector<char>& buf,
                                  off_t offset) {
  if (request->IsInterrupted()) {
    return;
  }

  SMBCFILE* file = LookupOpenFile(file_handle);
  if (!file) {
    request->ReplyError(EBADF);
    return;
  }

  int error = samba_impl_->SeekFile(file, offset, SEEK_SET);
  if (error) {
    VLOG(1) << "SeekFile path: " << ShareFilePathFromInode(inode)
            << ", offset: " << offset
            << " failed: " << base::safe_strerror(error);
    request->ReplyError(error);
    return;
  }

  size_t bytes_written = 0;
  error = samba_impl_->WriteFile(file, buf.data(), buf.size(), &bytes_written);
  if (error) {
    VLOG(1) << "WriteFile path: " << ShareFilePathFromInode(inode)
            << " offset: " << offset << ", size: " << buf.size()
            << " failed: " << base::safe_strerror(error);
    request->ReplyError(error);
    return;
  }

  // Modifying the file invalidates any cached inode we have.
  EraseCachedInodeStat(inode);

  request->ReplyWrite(bytes_written);
}

void SmbFilesystem::Release(std::unique_ptr<SimpleRequest> request,
                            fuse_ino_t inode,
                            uint64_t file_handle) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&SmbFilesystem::ReleaseInternal, base::Unretained(this),
                     std::move(request), inode, file_handle));
}

void SmbFilesystem::ReleaseInternal(std::unique_ptr<SimpleRequest> request,
                                    fuse_ino_t inode,
                                    uint64_t file_handle) {
  if (request->IsInterrupted()) {
    return;
  }

  SMBCFILE* file = LookupOpenFile(file_handle);
  if (!file) {
    request->ReplyError(EBADF);
    return;
  }

  int error = samba_impl_->CloseFile(file);
  if (error) {
    request->ReplyError(error);
    return;
  }

  RemoveOpenFile(file_handle);
  request->ReplyOk();
}

void SmbFilesystem::Rename(std::unique_ptr<SimpleRequest> request,
                           fuse_ino_t old_parent_inode,
                           const std::string& old_name,
                           fuse_ino_t new_parent_inode,
                           const std::string& new_name) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&SmbFilesystem::RenameInternal, base::Unretained(this),
                     std::move(request), old_parent_inode, old_name,
                     new_parent_inode, new_name));
}

void SmbFilesystem::RenameInternal(std::unique_ptr<SimpleRequest> request,
                                   fuse_ino_t old_parent_inode,
                                   const std::string& old_name,
                                   fuse_ino_t new_parent_inode,
                                   const std::string& new_name) {
  if (request->IsInterrupted()) {
    return;
  }

  const base::FilePath old_parent_path = inode_map_.GetPath(old_parent_inode);
  CHECK(!old_parent_path.empty())
      << "Lookup on invalid old parent inode: " << old_parent_inode;
  const base::FilePath new_parent_path = inode_map_.GetPath(new_parent_inode);
  CHECK(!new_parent_path.empty())
      << "Lookup on invalid new parent inode: " << new_parent_inode;

  const base::FilePath old_path = old_parent_path.Append(old_name);
  const std::string old_share_path = MakeShareFilePath(old_path);
  const base::FilePath new_path = new_parent_path.Append(new_name);
  const std::string new_share_path = MakeShareFilePath(new_path);

  if (inode_map_.PathExists(new_path)) {
    // This is posix-violating behaviour since rename() is supposed to replace
    // new_path if it exists. However, this is currently complicated by the need
    // to maintain a consistent mapping between inodes and paths.
    VLOG(1) << "Rename failed since new path already exists, new_path: "
            << new_share_path;
    request->ReplyError(EEXIST);
    return;
  }

  int error = samba_impl_->Rename(old_share_path, new_share_path);
  if (error) {
    VLOG(1) << "Rename old_path: " << old_share_path
            << " new_path: " << new_share_path
            << " failed: " << base::safe_strerror(error);
    request->ReplyError(error);
    return;
  }

  // A rename only moves the directory entry and doesn't change the underlying
  // inode. So update our synthesized inode to point to the new location. This
  // is safe since there's no support for hardlinks, and we have a 1:1 mapping
  // between path and inode.
  ino_t inode = inode_map_.IncInodeRef(old_path);
  inode_map_.UpdatePath(inode, new_path);
  // Unref the inode so we don't go out of sync with the kernel's refcount.
  inode_map_.Forget(inode, 1);

  // The SMB server might update attributes for the destination path (eg.
  // modification time). Invalidate our cached stat and force a fetch from the
  // server.
  EraseCachedInodeStat(inode);

  request->ReplyOk();
}

void SmbFilesystem::Unlink(std::unique_ptr<SimpleRequest> request,
                           fuse_ino_t parent_inode,
                           const std::string& name) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&SmbFilesystem::UnlinkInternal, base::Unretained(this),
                     std::move(request), parent_inode, name));
}

void SmbFilesystem::UnlinkInternal(std::unique_ptr<SimpleRequest> request,
                                   fuse_ino_t parent_inode,
                                   const std::string& name) {
  if (request->IsInterrupted()) {
    return;
  }

  const base::FilePath parent_path = inode_map_.GetPath(parent_inode);
  CHECK(!parent_path.empty())
      << "Lookup on invalid parent inode: " << parent_inode;
  const std::string share_file_path =
      MakeShareFilePath(parent_path.Append(name));

  int error = samba_impl_->UnlinkFile(share_file_path);
  if (error) {
    VLOG(1) << "Unlink path: " << share_file_path
            << " failed: " << base::safe_strerror(error);
    request->ReplyError(error);
    return;
  }

  request->ReplyOk();
}

void SmbFilesystem::OpenDir(std::unique_ptr<OpenRequest> request,
                            fuse_ino_t inode,
                            int flags) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&SmbFilesystem::OpenDirInternal, base::Unretained(this),
                     std::move(request), inode, flags));
}

void SmbFilesystem::OpenDirInternal(std::unique_ptr<OpenRequest> request,
                                    fuse_ino_t inode,
                                    int flags) {
  if (request->IsInterrupted()) {
    return;
  }

  if ((flags & O_ACCMODE) != O_RDONLY) {
    request->ReplyError(EACCES);
    return;
  }

  const std::string share_dir_path = ShareFilePathFromInode(inode);
  SMBCFILE* dir = nullptr;
  int error = samba_impl_->OpenDirectory(share_dir_path, &dir);
  if (error) {
    VLOG(1) << "OpenDirectory path: " << share_dir_path
            << " failed: " << base::safe_strerror(error);
    request->ReplyError(error);
    return;
  }

  request->ReplyOpen(AddOpenFile(dir));
}

void SmbFilesystem::ReadDir(std::unique_ptr<DirentryRequest> request,
                            fuse_ino_t inode,
                            uint64_t file_handle,
                            off_t offset) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&SmbFilesystem::ReadDirInternal, base::Unretained(this),
                     std::move(request), inode, file_handle, offset));
}

void SmbFilesystem::ReadDirInternal(std::unique_ptr<DirentryRequest> request,
                                    fuse_ino_t inode,
                                    uint64_t file_handle,
                                    off_t offset) {
  if (request->IsInterrupted()) {
    return;
  }

  SMBCFILE* dir = LookupOpenFile(file_handle);
  if (!dir) {
    request->ReplyError(EBADF);
    return;
  }
  const base::FilePath dir_path = inode_map_.GetPath(inode);
  CHECK(!dir_path.empty()) << "Inode not found: " << inode;

  int error = samba_impl_->SeekDirectory(dir, offset);
  if (error) {
    VLOG(1) << "SeekDirectory path: " << dir_path.value()
            << ", offset: " << offset
            << " failed: " << base::safe_strerror(error);
    request->ReplyError(error);
    return;
  }

  while (true) {
    const struct libsmb_file_info* dirent_info = nullptr;
    struct stat inode_stat = {0};

    error = samba_impl_->ReadDirectory(dir, &dirent_info, &inode_stat);
    if (error) {
      VLOG(1) << "ReadDirectory path: " << dir_path.value()
              << " failed: " << base::safe_strerror(error);
      request->ReplyError(error);
      return;
    }
    if (!dirent_info) {
      // EOF.
      break;
    }
    off_t next_offset = 0;
    error = samba_impl_->TellDirectory(dir, &next_offset);
    if (error) {
      VLOG(1) << "TellDirectory path: " << dir_path.value()
              << " failed: " << base::safe_strerror(error);
      request->ReplyError(error);
      return;
    }

    base::StringPiece filename(dirent_info->name);
    if (filename == "." || filename == "..") {
      // Ignore . and .. since FUSE already takes care of these.
      continue;
    }
    CHECK(!filename.empty());
    CHECK_EQ(filename.find("/"), base::StringPiece::npos);

    // Ensure mode bits are appropriately cleaned and propagated.
    inode_stat.st_mode = MakeStatModeBits(inode_stat.st_mode);

    const base::FilePath entry_path = dir_path.Append(filename);
    ino_t entry_inode = inode_map_.GetWeakInode(entry_path);
    if (!request->AddEntry(filename, entry_inode, inode_stat.st_mode,
                           next_offset)) {
      // Response buffer full.
      break;
    }

    inode_stat = MakeStat(entry_inode, inode_stat);
    AddCachedInodeStat(inode_stat);
  }

  request->ReplyDone();
}

void SmbFilesystem::ReleaseDir(std::unique_ptr<SimpleRequest> request,
                               fuse_ino_t inode,
                               uint64_t file_handle) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&SmbFilesystem::ReleaseDirInternal, base::Unretained(this),
                     std::move(request), inode, file_handle));
}

void SmbFilesystem::ReleaseDirInternal(std::unique_ptr<SimpleRequest> request,
                                       fuse_ino_t inode,
                                       uint64_t file_handle) {
  if (request->IsInterrupted()) {
    return;
  }

  SMBCFILE* dir = LookupOpenFile(file_handle);
  if (!dir) {
    request->ReplyError(EBADF);
    return;
  }

  int error = samba_impl_->CloseDirectory(dir);
  if (error) {
    VLOG(1) << "CloseDirectory failed: " << base::safe_strerror(error);
    request->ReplyError(error);
    return;
  }

  RemoveOpenFile(file_handle);
  request->ReplyOk();
}

void SmbFilesystem::MkDir(std::unique_ptr<EntryRequest> request,
                          fuse_ino_t parent_inode,
                          const std::string& name,
                          mode_t mode) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&SmbFilesystem::MkDirInternal, base::Unretained(this),
                     std::move(request), parent_inode, name, mode));
}

void SmbFilesystem::MkDirInternal(std::unique_ptr<EntryRequest> request,
                                  fuse_ino_t parent_inode,
                                  const std::string& name,
                                  mode_t mode) {
  if (request->IsInterrupted()) {
    return;
  }

  const base::FilePath parent_path = inode_map_.GetPath(parent_inode);
  CHECK(!parent_path.empty())
      << "Lookup on invalid parent inode: " << parent_inode;
  const base::FilePath file_path = parent_path.Append(name);
  const std::string share_file_path = MakeShareFilePath(file_path);

  int error = samba_impl_->CreateDirectory(share_file_path, mode);
  if (error) {
    VLOG(1) << "CreateDirectory path: " << share_file_path
            << " failed: " << base::safe_strerror(error);
    request->ReplyError(error);
    return;
  }

  ino_t inode = inode_map_.IncInodeRef(file_path);
  struct stat entry_stat = MakeStat(inode, {0});
  entry_stat.st_mode = S_IFDIR | mode;
  fuse_entry_param entry = {0};
  entry.ino = inode;
  entry.generation = 1;
  entry.attr = entry_stat;
  // Force readers to see coherent user / group permission bits by not caching
  // stat structure.
  entry.attr_timeout = 0;
  entry.entry_timeout = kAttrTimeoutSeconds;
  request->ReplyEntry(entry);
}

void SmbFilesystem::RmDir(std::unique_ptr<SimpleRequest> request,
                          fuse_ino_t parent_inode,
                          const std::string& name) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&SmbFilesystem::RmDirinternal, base::Unretained(this),
                     std::move(request), parent_inode, name));
}

void SmbFilesystem::RmDirinternal(std::unique_ptr<SimpleRequest> request,
                                  fuse_ino_t parent_inode,
                                  const std::string& name) {
  if (request->IsInterrupted()) {
    return;
  }

  const base::FilePath parent_path = inode_map_.GetPath(parent_inode);
  CHECK(!parent_path.empty())
      << "Lookup on invalid parent inode: " << parent_inode;
  const base::FilePath file_path = parent_path.Append(name);
  const std::string share_file_path = MakeShareFilePath(file_path);

  int error = samba_impl_->RemoveDirectory(share_file_path);
  if (error) {
    VLOG(1) << "RemoveDirectory path: " << share_file_path
            << " failed: " << base::safe_strerror(error);
    request->ReplyError(error);
    return;
  }

  request->ReplyOk();
}

void SmbFilesystem::DeleteRecursively(
    const base::FilePath& path,
    RecursiveDeleteOperation::CompletionCallback callback) {
  samba_thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&SmbFilesystem::DeleteRecursivelyInternal,
                     base::Unretained(this), path, std::move(callback)));
}

void SmbFilesystem::DeleteRecursivelyInternal(
    const base::FilePath& path,
    RecursiveDeleteOperation::CompletionCallback callback) {
  if (recursive_delete_operation_) {
    VLOG(1)
        << "Can't start a recursive delete operation whilst one is in progress";
    main_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(std::move(callback),
                       mojom::DeleteRecursivelyError::kOperationInProgress));
    return;
  }

  recursive_delete_operation_.reset(new RecursiveDeleteOperation(
      samba_impl_.get(), MakeShareFilePath(base::FilePath("/")), path,
      base::BindOnce(&SmbFilesystem::OnDeleteRecursivelyDone,
                     base::Unretained(this), std::move(callback))));
  recursive_delete_operation_->Start();
}

void SmbFilesystem::OnDeleteRecursivelyDone(
    RecursiveDeleteOperation::CompletionCallback callback,
    mojom::DeleteRecursivelyError error) {
  CHECK(recursive_delete_operation_);
  recursive_delete_operation_.reset();
  main_task_runner_->PostTask(FROM_HERE,
                              base::BindOnce(std::move(callback), error));
}

std::ostream& operator<<(std::ostream& out, SmbFilesystem::ConnectError error) {
  switch (error) {
    case SmbFilesystem::ConnectError::kOk:
      return out << "kOk";
    case SmbFilesystem::ConnectError::kNotFound:
      return out << "kNotFound";
    case SmbFilesystem::ConnectError::kAccessDenied:
      return out << "kAccessDenied";
    case SmbFilesystem::ConnectError::kSmb1Unsupported:
      return out << "kSmb1Unsupported";
    case SmbFilesystem::ConnectError::kUnknownError:
      return out << "kUnknownError";
    default:
      NOTREACHED();
      return out << "INVALID_ERROR";
  }
}

void SmbFilesystem::AddCachedInodeStat(const struct stat& inode_stat) {
  DCHECK(inode_stat.st_ino);

  StatCacheItem item;

  item.inode_stat = inode_stat;
  item.expires_at = base::Time::Now() +
                    base::TimeDelta::FromSecondsD(kStatCacheTimeoutSeconds);

  stat_cache_.Put(inode_stat.st_ino, item);
}

void SmbFilesystem::EraseCachedInodeStat(ino_t inode) {
  auto iter = stat_cache_.Peek(inode);
  if (iter != stat_cache_.end()) {
    stat_cache_.Erase(iter);
  }
}

bool SmbFilesystem::GetCachedInodeStat(ino_t inode, struct stat* out_stat) {
  DCHECK(out_stat);
  auto iter = stat_cache_.Get(inode);
  if (iter == stat_cache_.end()) {
    return false;
  }

  StatCacheItem item = iter->second;
  if (item.expires_at < base::Time::Now()) {
    stat_cache_.Erase(iter);
    return false;
  }

  *out_stat = item.inode_stat;
  return true;
}

}  // namespace smbfs
