// 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/check.h>
#include <base/check_op.h>
#include <base/logging.h>
#include <base/notreached.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
