// Copyright 2017 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 "smbprovider/smbprovider.h"

#include <algorithm>
#include <map>
#include <utility>

#include <base/files/file_path.h>
#include <base/memory/ptr_util.h>

#include "smbprovider/constants.h"
#include "smbprovider/file_copy_progress.h"
#include "smbprovider/iterator/caching_iterator.h"
#include "smbprovider/iterator/directory_iterator.h"
#include "smbprovider/iterator/post_depth_first_iterator.h"
#include "smbprovider/iterator/share_iterator.h"
#include "smbprovider/mount_manager.h"
#include "smbprovider/netbios_packet_parser.h"
#include "smbprovider/proto.h"
#include "smbprovider/proto_bindings/directory_entry.pb.h"
#include "smbprovider/recursive_copy_progress.h"
#include "smbprovider/samba_interface_impl.h"
#include "smbprovider/smbprovider_helper.h"

namespace smbprovider {

template <typename Proto, typename Iterator>
bool GetEntries(const Proto& options,
                Iterator iterator,
                int32_t* error_code,
                ProtoBlob* out_entries) {
  DCHECK(error_code);
  DCHECK(out_entries);

  DirectoryEntryListProto directory_entries;

  int32_t result = iterator.Init();
  while (result == 0) {
    if (iterator.IsDone()) {
      *error_code = static_cast<int32_t>(
          SerializeProtoToBlob(directory_entries, out_entries));
      return true;
    }
    AddDirectoryEntry(iterator.Get(), &directory_entries);
    result = iterator.Next();
  }

  // The while-loop is only exited if there is an error. A full successful
  // execution will return from inside the above while-loop.
  *error_code = GetErrorFromErrno(result);
  LogOperationError(GetMethodName(options), GetMountId(options),
                    static_cast<ErrorType>(*error_code));
  return false;
}

SmbProvider::SmbProvider(
    std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object,
    std::unique_ptr<SambaInterface> samba_interface,
    std::unique_ptr<MountManager> mount_manager,
    std::unique_ptr<KerberosArtifactSynchronizer> kerberos_synchronizer,
    bool enable_metadata_cache)
    : org::chromium::SmbProviderAdaptor(this),
      samba_interface_(std::move(samba_interface)),
      dbus_object_(std::move(dbus_object)),
      mount_manager_(std::move(mount_manager)),
      kerberos_synchronizer_(std::move(kerberos_synchronizer)),
      metadata_cache_enabled_(enable_metadata_cache) {}

void SmbProvider::RegisterAsync(
    const AsyncEventSequencer::CompletionAction& completion_callback) {
  RegisterWithDBusObject(dbus_object_.get());
  dbus_object_->RegisterAsync(completion_callback);
}

void SmbProvider::Mount(const ProtoBlob& options_blob,
                        const base::ScopedFD& password_fd,
                        int32_t* error_code,
                        int32_t* mount_id) {
  DCHECK(error_code);
  DCHECK(mount_id);
  *mount_id = -1;

  // The functions below will set the error if they fail.
  *error_code = static_cast<int32_t>(ERROR_OK);

  // AddMount() has to be called first since the credentials have to be stored
  // before calling CanAccessMount().
  MountOptionsProto options;
  const bool success =
      ParseOptionsProto(options_blob, &options, error_code) &&
      AddMount(options.path(), options.workgroup(), options.username(),
               password_fd, error_code, mount_id) &&
      CanAccessMount(*mount_id, options.path(), error_code);

  if (!success) {
    // If AddMount() was successful but the mount could not be accessed, remove
    // the mount from mount_manager_.
    RemoveMountIfMounted(*mount_id);
  }
}

int32_t SmbProvider::Remount(const ProtoBlob& options_blob,
                             const base::ScopedFD& password_fd) {
  // The functions below will set the error if they fail.
  int32_t error_code = static_cast<int32_t>(ERROR_OK);

  RemountOptionsProto options;
  const bool remounted =
      ParseOptionsProto(options_blob, &options, &error_code) &&
      Remount(options.path(), GetMountId(options), options.workgroup(),
              options.username(), password_fd, &error_code);

  if (!remounted) {
    return error_code;
  }

  if (!CanAccessMount(GetMountId(options), options.path(), &error_code)) {
    RemoveMountIfMounted(GetMountId(options));
  }

  return error_code;
}

int32_t SmbProvider::Unmount(const ProtoBlob& options_blob) {
  int32_t error_code;
  UnmountOptionsProto options;
  if (!ParseOptionsProto(options_blob, &options, &error_code) ||
      !IsMounted(options, &error_code) ||
      !RemoveMount(GetMountId(options), &error_code)) {
    return error_code;
  }

  return ERROR_OK;
}

void SmbProvider::ReadDirectory(const ProtoBlob& options_blob,
                                int32_t* error_code,
                                ProtoBlob* out_entries) {
  DCHECK(error_code);
  DCHECK(out_entries);

  ReadDirectoryEntries<ReadDirectoryOptionsProto, DirectoryIterator>(
      options_blob, metadata_cache_enabled_, error_code, out_entries);
}

template <typename Proto, typename Iterator>
void SmbProvider::ReadDirectoryEntries(const ProtoBlob& options_blob,
                                       bool include_metadata,
                                       int32_t* error_code,
                                       ProtoBlob* out_entries) {
  DCHECK(error_code);
  DCHECK(out_entries);
  out_entries->clear();

  std::string full_path;
  Proto options;
  if (ParseOptionsAndPath(options_blob, &options, &full_path, error_code)) {
    MetadataCache* cache = nullptr;
    if (include_metadata) {
      bool got_cache =
          mount_manager_->GetMetadataCache(GetMountId(options), &cache);
      DCHECK(got_cache);
      DCHECK(cache);
    }

    SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));
    if (include_metadata && cache) {
      // Purge the cache of expired entries before reading next directory.
      cache->PurgeExpiredEntries();
      GetEntries(
          options,
          GetCachingIterator<Iterator>(full_path, samba_interface, cache),
          error_code, out_entries);
    } else {
      GetEntries(options, GetIterator<Iterator>(full_path, samba_interface),
                 error_code, out_entries);
    }
  }
}

void SmbProvider::GetMetadataEntry(const ProtoBlob& options_blob,
                                   int32_t* error_code,
                                   ProtoBlob* out_entry) {
  DCHECK(error_code);
  DCHECK(out_entry);
  out_entry->clear();

  std::string full_path;
  GetMetadataEntryOptionsProto options;
  if (!ParseOptionsAndPath(options_blob, &options, &full_path, error_code)) {
    return;
  }

  // If the cache is enabled and we have the result, then return it.
  if (metadata_cache_enabled_ &&
      GetCachedEntry(GetMountId(options), full_path, out_entry)) {
    *error_code = static_cast<int32_t>(ERROR_OK);
    return;
  }

  SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));
  struct stat stat_info;
  int32_t get_status_error =
      samba_interface->GetEntryStatus(full_path.c_str(), &stat_info);
  if (get_status_error != 0) {
    LogAndSetError(options, GetErrorFromErrno(get_status_error), error_code);
    return;
  }
  *error_code = GetDirectoryEntryProtoFromStat(full_path, stat_info, out_entry);
}

void SmbProvider::OpenFile(const ProtoBlob& options_blob,
                           int32_t* error_code,
                           int32_t* file_id) {
  DCHECK(error_code);
  DCHECK(file_id);

  std::string full_path;
  OpenFileOptionsProto options;
  if (!ParseOptionsAndPath(options_blob, &options, &full_path, error_code)) {
    return;
  }

  if (!OpenFile(options, full_path, error_code, file_id)) {
    *file_id = -1;
    return;
  }

  *error_code = static_cast<int32_t>(ERROR_OK);
}

int32_t SmbProvider::CloseFile(const ProtoBlob& options_blob) {
  int32_t error_code;
  CloseFileOptionsProto options;
  if (!ParseOptionsProto(options_blob, &options, &error_code)) {
    return error_code;
  }

  if (!IsMounted(options, &error_code)) {
    return error_code;
  }

  if (!CloseFile(options, options.file_id(), &error_code)) {
    return error_code;
  }

  return static_cast<int32_t>(ERROR_OK);
}

int32_t SmbProvider::DeleteEntry(const ProtoBlob& options_blob) {
  int32_t error_code;
  DeleteEntryOptionsProto options;
  std::string full_path;
  if (!ParseOptionsAndPath(options_blob, &options, &full_path, &error_code)) {
    return error_code;
  }

  bool is_directory;
  int32_t get_type_result;
  if (!GetEntryType(GetMountId(options), full_path, &get_type_result,
                    &is_directory)) {
    LogAndSetError(options, GetErrorFromErrno(get_type_result), &error_code);
    return error_code;
  }

  int32_t result;
  if (is_directory) {
    if (options.recursive()) {
      result = RecursiveDelete(GetMountId(options), full_path);
    } else {
      result = DeleteDirectory(GetMountId(options), full_path);
    }
  } else {
    result = DeleteFile(GetMountId(options), full_path);
  }

  if (result != 0) {
    LogAndSetError(options, GetErrorFromErrno(result), &error_code);
    return error_code;
  }

  return static_cast<int32_t>(ERROR_OK);
}

void SmbProvider::ReadFile(const ProtoBlob& options_blob,
                           int32_t* error_code,
                           brillo::dbus_utils::FileDescriptor* temp_fd) {
  DCHECK(error_code);
  DCHECK(temp_fd);

  // TODO(allenvic): Investigate having a single shared buffer in the class.
  std::vector<uint8_t> buffer;
  ReadFileOptionsProto options;

  // The functions below will set the error if they fail.
  *error_code = static_cast<int32_t>(ERROR_OK);
  bool success = ParseOptionsProto(options_blob, &options, error_code) &&
                 IsMounted(options, error_code) && Seek(options, error_code) &&
                 ReadFileIntoBuffer(options, error_code, &buffer) &&
                 WriteTempFile(options, buffer, error_code, temp_fd);

  if (!success) {
    *temp_fd = GenerateEmptyFile();
  }
}

int32_t SmbProvider::CreateFile(const ProtoBlob& options_blob) {
  int32_t error_code;
  std::string full_path;
  CreateFileOptionsProto options;
  if (!ParseOptionsAndPath(options_blob, &options, &full_path, &error_code)) {
    return error_code;
  }

  int32_t file_id;
  // CreateFile() gives us back an open file descriptor to the newly created
  // file.
  if (!CreateFile(options, full_path, &file_id, &error_code)) {
    return error_code;
  }

  // Close the file handle from CreateFile().
  if (!CloseFile(options, file_id, &error_code)) {
    // Attempt to delete the file since file will not be usable.
    SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));
    int32_t unlink_result = samba_interface->Unlink(full_path);
    if (unlink_result != 0) {
      // Log the unlink error but return the original error.
      LOG(ERROR) << "Error unlinking after error closing file: "
                 << GetErrorFromErrno(unlink_result);
    }
    return error_code;
  }

  return static_cast<int32_t>(ERROR_OK);
}

int32_t SmbProvider::Truncate(const ProtoBlob& options_blob) {
  int32_t error_code;
  std::string full_path;
  TruncateOptionsProto options;
  int32_t file_id;

  const bool result =
      ParseOptionsAndPath(options_blob, &options, &full_path, &error_code) &&
      OpenFile(options, full_path, &error_code, &file_id) &&
      TruncateAndCloseFile(options, file_id, options.length(), &error_code);

  return result ? static_cast<int32_t>(ERROR_OK) : error_code;
}

int32_t SmbProvider::WriteFile(const ProtoBlob& options_blob,
                               const base::ScopedFD& temp_fd) {
  int32_t error_code;
  WriteFileOptionsProto options;
  std::vector<uint8_t> buffer;

  const bool result =
      ParseOptionsProto(options_blob, &options, &error_code) &&
      ReadFromFD(options, temp_fd, &error_code, &buffer) &&
      Seek(options, &error_code) &&
      WriteFileFromBuffer(options, options.file_id(), buffer, &error_code);

  return result ? static_cast<int32_t>(ERROR_OK) : error_code;
}

int32_t SmbProvider::CreateDirectory(const ProtoBlob& options_blob) {
  int32_t error_code;
  CreateDirectoryOptionsProto options;
  std::string full_path;

  const bool result =
      ParseOptionsAndPath(options_blob, &options, &full_path, &error_code) &&
      CreateParentsIfNecessary(options, &error_code) &&
      CreateSingleDirectory(options, full_path, false /* ignore_existing */,
                            &error_code);

  return result ? static_cast<int32_t>(ERROR_OK) : error_code;
}

int32_t SmbProvider::MoveEntry(const ProtoBlob& options_blob) {
  int32_t error_code;
  std::string source_path;
  std::string target_path;
  MoveEntryOptionsProto options;

  const bool success =
      ParseOptionsAndPaths(options_blob, &options, &source_path, &target_path,
                           &error_code) &&
      MoveEntry(options, source_path, target_path, &error_code);

  return success ? static_cast<int32_t>(ERROR_OK) : error_code;
}

int32_t SmbProvider::CopyEntry(const ProtoBlob& options_blob) {
  int32_t error_code;
  std::string source_path;
  std::string target_path;
  CopyEntryOptionsProto options;

  const bool success =
      ParseOptionsAndPaths(options_blob, &options, &source_path, &target_path,
                           &error_code) &&
      CopyEntry(options, source_path, target_path, &error_code);

  return success ? static_cast<int32_t>(ERROR_OK) : error_code;
}

void SmbProvider::GetShares(const ProtoBlob& options_blob,
                            int32_t* error_code,
                            ProtoBlob* shares) {
  DCHECK(error_code);
  DCHECK(shares);

  ReadDirectoryEntries<GetSharesOptionsProto, ShareIterator>(
      options_blob, false /* include_metadata */, error_code, shares);
}

void SmbProvider::SetupKerberos(SetupKerberosCallback callback,
                                const std::string& account_id) {
  kerberos_synchronizer_->SetupKerberos(
      account_id,
      base::Bind(&SmbProvider::HandleSetupKerberosResponse,
                 base::Unretained(this), base::Passed(std::move(callback))));
}

void SmbProvider::HandleSetupKerberosResponse(SetupKerberosCallback callback,
                                              bool result) {
  callback->Return(result);
}

ProtoBlob SmbProvider::ParseNetBiosPacket(const std::vector<uint8_t>& packet,
                                          uint16_t transaction_id) {
  const std::vector<std::string> servers =
      netbios::ParsePacket(packet, transaction_id);

  const HostnamesProto hostnames_proto = BuildHostnamesProto(servers);
  std::vector<uint8_t> out_blob;
  if (SerializeProtoToBlob(hostnames_proto, &out_blob) != ERROR_OK) {
    return ProtoBlob();
  }
  return out_blob;
}

void SmbProvider::StartCopy(const ProtoBlob& options_blob,
                            int32_t* error_code,
                            int32_t* copy_token) {
  DCHECK(error_code);
  DCHECK(copy_token);

  std::string source_path;
  std::string target_path;
  CopyEntryOptionsProto options;

  if (!ParseOptionsAndPaths(options_blob, &options, &source_path, &target_path,
                            error_code)) {
    return;
  }

  ErrorType error = StartCopy(options, source_path, target_path, copy_token);
  if (error != ERROR_OK || error != ERROR_COPY_PENDING) {
    LogAndSetError(options, error, error_code);
    return;
  }

  *error_code = static_cast<int32_t>(error);
}

int32_t SmbProvider::ContinueCopy(int32_t mount_id, int32_t copy_token) {
  DCHECK_GE(mount_id, 0);
  DCHECK_GE(copy_token, 0);

  int32_t error_code;
  if (!copy_tracker_.count(copy_token)) {
    LogAndSetError(kContinueCopyMethod, mount_id, ERROR_COPY_FAILED,
                   &error_code);
    return error_code;
  }

  if (!mount_manager_->IsAlreadyMounted(mount_id)) {
    copy_tracker_.erase(copy_token);
    LogAndSetError(kContinueCopyMethod, mount_id, ERROR_COPY_FAILED,
                   &error_code);
    return error_code;
  }

  ErrorType error = ContinueCopy(copy_token);
  if (error != ERROR_OK || error != ERROR_COPY_PENDING) {
    LogAndSetError(kContinueCopyMethod, mount_id, error, &error_code);
    return error_code;
  }

  return static_cast<int32_t>(error);
}

HostnamesProto SmbProvider::BuildHostnamesProto(
    const std::vector<std::string>& hostnames) const {
  HostnamesProto hostnames_proto;
  for (const auto& hostname : hostnames) {
    AddToHostnamesProto(hostname, &hostnames_proto);
  }
  return hostnames_proto;
}

// TODO(baileyberro): Return a different SambaInterface for each mount.
SambaInterface* SmbProvider::GetSambaInterface(int32_t mount_id) const {
  return samba_interface_.get();
}

template <typename Proto>
bool SmbProvider::GetFullPath(const Proto* options,
                              std::string* full_path) const {
  DCHECK(options);
  DCHECK(full_path);

  const int32_t mount_id = GetMountId(*options);
  const std::string entry_path = GetEntryPath(*options);

  bool success = mount_manager_->GetFullPath(mount_id, entry_path, full_path);
  if (!success) {
    LOG(ERROR) << GetMethodName(*options) << " requested unknown mount_id "
               << mount_id;
  }

  return success;
}

template <>
bool SmbProvider::GetFullPath(const GetSharesOptionsProto* options,
                              std::string* full_path) const {
  DCHECK(options);
  DCHECK(full_path);

  *full_path = GetEntryPath(*options);
  return true;
}

template <typename Proto>
bool SmbProvider::GetFullPaths(const Proto* options,
                               std::string* source_full_path,
                               std::string* target_full_path) const {
  DCHECK(options);
  DCHECK(source_full_path);
  DCHECK(target_full_path);

  const int32_t mount_id = GetMountId(*options);
  const std::string source_path = GetSourcePath(*options);
  const std::string target_path = GetDestinationPath(*options);

  const bool success =
      mount_manager_->GetFullPath(mount_id, source_path, source_full_path) &&
      mount_manager_->GetFullPath(mount_id, target_path, target_full_path);
  if (!success) {
    LOG(ERROR) << GetMethodName(*options) << " requested unknown mount_id "
               << mount_id;
  }

  return success;
}

template <typename Proto>
bool SmbProvider::ParseOptionsAndPath(const ProtoBlob& blob,
                                      Proto* options,
                                      std::string* full_path,
                                      int32_t* error_code) {
  if (!ParseOptionsProto(blob, options, error_code)) {
    return false;
  }

  if (!GetFullPath(options, full_path)) {
    *error_code = static_cast<int32_t>(ERROR_NOT_FOUND);
    return false;
  }

  return true;
}

template <typename Proto>
bool SmbProvider::ParseOptionsAndPaths(const ProtoBlob& blob,
                                       Proto* options,
                                       std::string* source_path,
                                       std::string* target_path,
                                       int32_t* error_code) {
  DCHECK(options);
  DCHECK(source_path);
  DCHECK(target_path);
  DCHECK(error_code);

  if (!ParseOptionsProto(blob, options, error_code)) {
    return false;
  }

  if (!GetFullPaths(options, source_path, target_path)) {
    *error_code = static_cast<int32_t>(ERROR_NOT_FOUND);
    return false;
  }

  return true;
}

bool SmbProvider::GetEntryType(int32_t mount_id,
                               const std::string& full_path,
                               int32_t* error_code,
                               bool* is_directory) {
  DCHECK(error_code);
  DCHECK(is_directory);

  SambaInterface* samba_interface = GetSambaInterface(mount_id);
  struct stat stat_info;
  *error_code = samba_interface->GetEntryStatus(full_path.c_str(), &stat_info);
  if (*error_code != 0) {
    return false;
  }

  if (IsDirectory(stat_info)) {
    *is_directory = true;
    return true;
  }
  if (IsFile(stat_info)) {
    *is_directory = false;
    return true;
  }
  *error_code = ENOENT;
  return false;
}

template <typename Proto>
bool SmbProvider::Seek(const Proto& options, int32_t* error_code) {
  DCHECK(error_code);

  SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));
  int32_t result = samba_interface->Seek(options.file_id(), options.offset());
  if (result != 0) {
    LogAndSetError(options, GetErrorFromErrno(result), error_code);
    return false;
  }
  return true;
}

bool SmbProvider::CanAccessMount(int32_t mount_id,
                                 const std::string& mount_root,
                                 int32_t* error_code) {
  DCHECK(error_code);

  SambaInterface* samba_interface = GetSambaInterface(mount_id);
  int32_t dir_id = -1;
  int32_t result = samba_interface->OpenDirectory(mount_root, &dir_id);
  if (result != 0) {
    LogAndSetError(kMountMethod, -1, GetErrorFromErrno(result), error_code);
    return false;
  }

  CloseDirectory(mount_id, dir_id);
  return true;
}

void SmbProvider::CloseDirectory(int32_t mount_id, int32_t dir_id) {
  SambaInterface* samba_interface = GetSambaInterface(mount_id);
  int32_t result = samba_interface->CloseDirectory(dir_id);
  if (result != 0) {
    LOG(ERROR) << "Error closing directory " << dir_id;
  }
}

bool SmbProvider::RemoveMount(int32_t mount_id, int32_t* error_code) {
  bool removed = mount_manager_->RemoveMount(mount_id);
  if (!removed) {
    *error_code = static_cast<int32_t>(ERROR_NOT_FOUND);
  }

  return removed;
}

bool SmbProvider::AddMount(const std::string& mount_root,
                           const std::string& workgroup,
                           const std::string& username,
                           const base::ScopedFD& password_fd,
                           int32_t* error_code,
                           int32_t* mount_id) {
  bool added = mount_manager_->AddMount(mount_root, workgroup, username,
                                        password_fd, mount_id);
  if (!added) {
    *error_code = static_cast<int32_t>(ERROR_IN_USE);
  }

  return added;
}

bool SmbProvider::Remount(const std::string& mount_root,
                          int32_t mount_id,
                          const std::string& workgroup,
                          const std::string& username,
                          const base::ScopedFD& password_fd,
                          int32_t* error_code) {
  bool remounted = mount_manager_->Remount(mount_root, mount_id, workgroup,
                                           username, password_fd);
  if (!remounted) {
    *error_code = static_cast<int32_t>(ERROR_IN_USE);
  }

  return remounted;
}

void SmbProvider::RemoveMountIfMounted(int32_t mount_id) {
  if (mount_id != -1) {
    mount_manager_->RemoveMount(mount_id);
  }
}

bool SmbProvider::ReadFileIntoBuffer(const ReadFileOptionsProto& options,
                                     int32_t* error_code,
                                     std::vector<uint8_t>* buffer) {
  DCHECK(buffer);
  DCHECK(error_code);

  buffer->resize(options.length());
  size_t bytes_read;

  if (!ReadToBuffer(options, options.file_id(), buffer, &bytes_read,
                    error_code)) {
    return false;
  }
  return true;
}

template <typename Proto>
bool SmbProvider::WriteTempFile(const Proto& options,
                                const std::vector<uint8_t>& buffer,
                                int32_t* error_code,
                                brillo::dbus_utils::FileDescriptor* temp_fd) {
  base::ScopedFD scoped_fd = temp_file_manager_.CreateTempFile(buffer);
  if (!scoped_fd.is_valid()) {
    LogAndSetError(options, ERROR_IO, error_code);
    return false;
  }

  // get() is called here instead of release() since FileDescriptor duplicates
  // the FD when getting assigned, meaning the local FD still needs to be
  // closed by ScopedFD when it goes out of scope.
  *temp_fd = scoped_fd.get();
  return true;
}

template <typename Proto>
bool SmbProvider::WriteFileFromBuffer(const Proto& options,
                                      int32_t file_id,
                                      const std::vector<uint8_t>& buffer,
                                      int32_t* error_code) {
  DCHECK(error_code);

  SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));
  int32_t result =
      samba_interface->WriteFile(file_id, buffer.data(), buffer.size());
  if (result != 0) {
    LogAndSetError(options, GetErrorFromErrno(result), error_code);
    return false;
  }
  return true;
}

int32_t SmbProvider::RecursiveDelete(int32_t mount_id,
                                     const std::string& dir_path) {
  PostDepthFirstIterator it = GetPostOrderIterator(mount_id, dir_path);
  int32_t it_result = it.Init();
  while (it_result == 0) {
    if (it.IsDone()) {
      return 0;
    }

    int32_t del_result = DeleteDirectoryEntry(mount_id, it.Get());
    if (del_result != 0) {
      return del_result;
    }

    it_result = it.Next();
  }

  // while-loop is only exited from if there's an iterator error.
  DCHECK_NE(0, it_result);
  return it_result;
}

int32_t SmbProvider::DeleteDirectoryEntry(int32_t mount_id,
                                          const DirectoryEntry& entry) {
  if (entry.is_directory) {
    return DeleteDirectory(mount_id, entry.full_path);
  }
  return DeleteFile(mount_id, entry.full_path);
}

int32_t SmbProvider::DeleteFile(int32_t mount_id,
                                const std::string& file_path) {
  SambaInterface* samba_interface = GetSambaInterface(mount_id);
  return samba_interface->Unlink(file_path.c_str());
}

int32_t SmbProvider::DeleteDirectory(int32_t mount_id,
                                     const std::string& dir_path) {
  SambaInterface* samba_interface = GetSambaInterface(mount_id);
  return samba_interface->RemoveDirectory(dir_path.c_str());
}

PostDepthFirstIterator SmbProvider::GetPostOrderIterator(
    int32_t mount_id, const std::string& full_path) {
  SambaInterface* samba_interface = GetSambaInterface(mount_id);
  return PostDepthFirstIterator(full_path, samba_interface);
}

template <typename Proto>
bool SmbProvider::OpenFile(const Proto& options,
                           const std::string& full_path,
                           int32_t* error,
                           int32_t* file_id) {
  DCHECK(error);
  DCHECK(file_id);

  SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));
  int32_t result = samba_interface->OpenFile(
      full_path, GetOpenFilePermissions(options), file_id);
  if (result != 0) {
    LogAndSetError(options, GetErrorFromErrno(result), error);
    return false;
  }
  return true;
}

template <typename Proto>
bool SmbProvider::CloseFile(const Proto& options,
                            int32_t file_id,
                            int32_t* error) {
  DCHECK(error);

  SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));
  int32_t result = samba_interface->CloseFile(file_id);
  if (result != 0) {
    LogAndSetError(options, GetErrorFromErrno(result), error);
    return false;
  }
  return true;
}

template <typename Proto>
bool SmbProvider::TruncateAndCloseFile(const Proto& options,
                                       const int32_t file_id,
                                       int64_t length,
                                       int32_t* error) {
  DCHECK(error);

  SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));
  int32_t truncate_result = samba_interface->Truncate(file_id, length);
  if (truncate_result != 0) {
    LogAndSetError(options, GetErrorFromErrno(truncate_result), error);
    // Continue to close on error.
  }

  int32_t close_error;
  if (!CloseFile(options, file_id, &close_error)) {
    if (truncate_result == 0) {
      // If Truncate was successful, set error to the close error, otherwise
      // keep the truncate error.
      *error = close_error;
    }
    return false;
  }

  // Return if the truncate was successful.
  return truncate_result == 0;
}

bool SmbProvider::MoveEntry(const MoveEntryOptionsProto& options,
                            const std::string& source_path,
                            const std::string& target_path,
                            int32_t* error) {
  DCHECK(error);

  SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));
  int32_t result = samba_interface->MoveEntry(source_path, target_path);
  if (result != 0) {
    LogAndSetError(options, GetErrorFromErrno(result), error);
    return false;
  }
  return true;
}

bool SmbProvider::GenerateParentPaths(
    const CreateDirectoryOptionsProto& options,
    int32_t* error_code,
    std::vector<std::string>* parent_paths) {
  DCHECK(error_code);
  DCHECK(parent_paths);
  base::FilePath current_path(options.directory_path());
  DCHECK(current_path.IsAbsolute());

  // Skip the leaf path and start with the lowest parent.
  current_path = current_path.DirName();

  while (current_path.value() != "/") {
    std::string full_path;
    if (!mount_manager_->GetFullPath(
            GetMountId(options), current_path.StripTrailingSeparators().value(),
            &full_path)) {
      *error_code = static_cast<int32_t>(ERROR_NOT_FOUND);
      return false;
    }

    current_path = current_path.DirName();
    parent_paths->push_back(std::move(full_path));
  }

  // Reverse the vector so the top parent will be first.
  std::reverse(parent_paths->begin(), parent_paths->end());
  return true;
}

bool SmbProvider::CreateNestedDirectories(
    const CreateDirectoryOptionsProto& options,
    const std::vector<std::string>& paths,
    int32_t* error_code) {
  DCHECK(error_code);

  for (auto const& path : paths) {
    if (!CreateSingleDirectory(options, path, true /* ignore_existing */,
                               error_code)) {
      return false;
    }
  }
  return true;
}

bool SmbProvider::CreateParentsIfNecessary(
    const CreateDirectoryOptionsProto& options, int32_t* error_code) {
  DCHECK(error_code);

  if (!options.recursive()) {
    // Return true in this case since no parents need to be created.
    return true;
  }

  std::vector<std::string> paths;
  return GenerateParentPaths(options, error_code, &paths) &&
         CreateNestedDirectories(options, paths, error_code);
}

template <typename Proto>
bool SmbProvider::CreateSingleDirectory(const Proto& options,
                                        const std::string& full_path,
                                        bool ignore_existing,
                                        int32_t* error_code) {
  DCHECK(error_code);

  SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));
  const int32_t result = samba_interface->CreateDirectory(full_path);
  if (ShouldReportCreateDirError(result, ignore_existing)) {
    LogAndSetError(options, GetErrorFromErrno(result), error_code);
    return false;
  }

  return true;
}

template <typename Proto>
bool SmbProvider::CreateFile(const Proto& options,
                             const std::string& full_path,
                             int32_t* file_id,
                             int32_t* error) {
  DCHECK(file_id);
  DCHECK(error);

  SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));
  int32_t result = samba_interface->CreateFile(full_path, file_id);
  if (result != 0) {
    LogAndSetError(options, GetErrorFromErrno(result), error);
    return false;
  }
  return true;
}

bool SmbProvider::CopyEntry(const CopyEntryOptionsProto& options,
                            const std::string& source_path,
                            const std::string& target_path,
                            int32_t* error_code) {
  DCHECK(error_code);
  bool is_directory;
  int32_t get_type_result;
  if (!GetEntryType(GetMountId(options), source_path, &get_type_result,
                    &is_directory)) {
    LogAndSetError(options, GetErrorFromErrno(get_type_result), error_code);
    return false;
  }

  if (is_directory) {
    return CreateSingleDirectory(options, target_path,
                                 false /* ignore_existing */, error_code);
  }

  return CopyFile(options, source_path, target_path, error_code);
}

bool SmbProvider::CopyFile(const CopyEntryOptionsProto& options,
                           const std::string& source_path,
                           const std::string& target_path,
                           int32_t* error_code) {
  DCHECK(error_code);

  SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));
  int32_t result = samba_interface->CopyFile(source_path, target_path);
  if (result != 0) {
    LogAndSetError(options, GetErrorFromErrno(result), error_code);
    return false;
  }

  return true;
}

ErrorType SmbProvider::StartCopy(const CopyEntryOptionsProto& options,
                                 const std::string& source_path,
                                 const std::string& target_path,
                                 int32_t* copy_token) {
  DCHECK(copy_token);

  bool is_directory;
  int32_t get_type_result;
  if (!GetEntryType(GetMountId(options), source_path, &get_type_result,
                    &is_directory)) {
    return GetErrorFromErrno(get_type_result);
  }

  if (is_directory) {
    return StartDirectoryCopy(options, source_path, target_path, copy_token);
  }

  return StartFileCopy(options, source_path, target_path, copy_token);
}

template <typename CopyProgressType>
ErrorType SmbProvider::StartCopyProgress(const CopyEntryOptionsProto& options,
                                         const std::string& source_path,
                                         const std::string& target_path,
                                         int32_t* copy_token) {
  DCHECK(copy_token);

  SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));
  auto copy_progress = std::make_unique<CopyProgressType>(samba_interface);

  int32_t copy_result;
  bool should_continue_copy =
      copy_progress->StartCopy(source_path, target_path, &copy_result);
  if (should_continue_copy) {
    // The copy needs to be continued.
    *copy_token = copy_counter_++;
    copy_tracker_[*copy_token] = std::move(copy_progress);
    return ERROR_COPY_PENDING;
  }
  if (copy_result == 0) {
    // The copy is complete.
    return ERROR_OK;
  }

  return GetErrorFromErrno(copy_result);
}

ErrorType SmbProvider::StartDirectoryCopy(const CopyEntryOptionsProto& options,
                                          const std::string& source_path,
                                          const std::string& target_path,
                                          int32_t* copy_token) {
  DCHECK(copy_token);

  return StartCopyProgress<RecursiveCopyProgress>(options, source_path,
                                                  target_path, copy_token);
}

ErrorType SmbProvider::StartFileCopy(const CopyEntryOptionsProto& options,
                                     const std::string& source_path,
                                     const std::string& target_path,
                                     int32_t* copy_token) {
  DCHECK(copy_token);

  return StartCopyProgress<FileCopyProgress>(options, source_path, target_path,
                                             copy_token);
}

ErrorType SmbProvider::ContinueCopy(int32_t copy_token) {
  DCHECK_GE(copy_token, 0);

  int32_t copy_result;
  const bool should_continue_copy =
      copy_tracker_[copy_token]->ContinueCopy(&copy_result);
  if (should_continue_copy) {
    // The copy needs to be continued.
    return ERROR_COPY_PENDING;
  }

  // The copy no longer needs to be continued as it has either completed
  // successfully or it failed so remove it from |copy_tracker_|.
  copy_tracker_.erase(copy_token);

  if (copy_result == 0) {
    // The copy is complete.
    return ERROR_OK;
  }

  return GetErrorFromErrno(copy_result);
}

template <typename Proto>
bool SmbProvider::ReadToBuffer(const Proto& options,
                               int32_t file_id,
                               std::vector<uint8_t>* buffer,
                               size_t* bytes_read,
                               int32_t* error_code) {
  DCHECK(buffer);
  DCHECK(bytes_read);
  DCHECK(error_code);

  SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));
  int32_t result = samba_interface->ReadFile(file_id, buffer->data(),
                                             buffer->size(), bytes_read);
  if (result != 0) {
    LogAndSetError(options, GetErrorFromErrno(result), error_code);
    return false;
  }

  DCHECK_GE(*bytes_read, 0);
  DCHECK_LE(*bytes_read, buffer->size());
  // Make sure buffer is only as big as bytes_read.
  buffer->resize(*bytes_read);
  return true;
}

void SmbProvider::GetDeleteList(const ProtoBlob& options_blob,
                                int32_t* error_code,
                                brillo::dbus_utils::FileDescriptor* temp_fd,
                                int32_t* bytes_written) {
  DCHECK(error_code);
  DCHECK(temp_fd);
  DCHECK(bytes_written);

  std::string full_path;
  GetDeleteListOptionsProto options;
  if (!ParseOptionsAndPath(options_blob, &options, &full_path, error_code)) {
    *temp_fd = GenerateEmptyFile();
    return;
  }

  bool is_directory;
  int32_t get_type_result;
  if (!GetEntryType(GetMountId(options), full_path, &get_type_result,
                    &is_directory)) {
    LogAndSetError(options, GetErrorFromErrno(get_type_result), error_code);
    *temp_fd = GenerateEmptyFile();
    return;
  }

  DeleteListProto delete_list;
  int32_t result =
      GenerateDeleteList(options, full_path, is_directory, &delete_list);
  if (result != 0) {
    LogAndSetError(options, GetErrorFromErrno(result), error_code);
    *temp_fd = GenerateEmptyFile();
    return;
  }

  WriteDeleteListToTempFile(options, delete_list, error_code, temp_fd,
                            bytes_written);
}

bool SmbProvider::WriteDeleteListToTempFile(
    const GetDeleteListOptionsProto& options,
    const DeleteListProto& delete_list,
    int32_t* error_code,
    brillo::dbus_utils::FileDescriptor* temp_fd,
    int32_t* bytes_written) {
  DCHECK(error_code);
  DCHECK(temp_fd);
  DCHECK(bytes_written);

  std::vector<uint8_t> buffer;
  *error_code =
      static_cast<int32_t>(SerializeProtoToBlob(delete_list, &buffer));
  if (*error_code != ERROR_OK) {
    *temp_fd = GenerateEmptyFile();
    return false;
  }

  bool success = WriteTempFile(options, buffer, error_code, temp_fd);
  *bytes_written = success ? buffer.size() : -1;

  return success;
}

int32_t SmbProvider::GenerateDeleteList(
    const GetDeleteListOptionsProto& options,
    const std::string& full_path,
    bool is_directory,
    DeleteListProto* delete_list) {
  DCHECK(delete_list);

  if (!is_directory) {
    // |delete_list| will only contain the relative path to the file.
    AddToDeleteList(GetRelativePath(GetMountId(options), full_path),
                    delete_list);
    return 0;
  }

  PostDepthFirstIterator it =
      GetPostOrderIterator(GetMountId(options), full_path);
  int32_t it_result = it.Init();
  while (it_result == 0) {
    if (it.IsDone()) {
      return 0;
    }

    AddToDeleteList(GetRelativePath(GetMountId(options), it.Get().full_path),
                    delete_list);
    it_result = it.Next();
  }

  // while-loop is only exited from if there's an iterator error.
  DCHECK_NE(0, it_result);
  return it_result;
}

bool SmbProvider::GetCachedEntry(int32_t mount_id,
                                 const std::string full_path,
                                 ProtoBlob* out_entry) {
  MetadataCache* cache = nullptr;
  if (!mount_manager_->GetMetadataCache(mount_id, &cache)) {
    return false;
  }

  DCHECK(cache);
  DirectoryEntry entry;
  if (!cache->FindEntry(full_path, &entry)) {
    return false;
  }

  DirectoryEntryProto proto;
  ConvertToProto(entry, &proto);
  if (SerializeProtoToBlob(proto, out_entry) != ERROR_OK) {
    return false;
  }

  return true;
}

brillo::dbus_utils::FileDescriptor SmbProvider::GenerateEmptyFile() {
  base::ScopedFD temp_fd = temp_file_manager_.CreateTempFile();
  DCHECK(temp_fd.is_valid());

  // get() is called here instead of release() since FileDescriptor duplicates
  // the FD when getting assigned, meaning the local FD still needs to be
  // closed by ScopedFD when it goes out of scope.
  return brillo::dbus_utils::FileDescriptor(temp_fd.get());
}

std::string SmbProvider::GetRelativePath(int32_t mount_id,
                                         const std::string& entry_path) {
  return mount_manager_->GetRelativePath(mount_id, entry_path);
}

template <typename Proto>
bool SmbProvider::IsMounted(const Proto& options, int32_t* error_code) const {
  const bool is_valid = mount_manager_->IsAlreadyMounted(GetMountId(options));
  if (!is_valid) {
    LogAndSetError(options, ERROR_NOT_FOUND, error_code);
  }
  return is_valid;
}

// These are required to explicitly instantiate the template functions.
template ErrorType SmbProvider::StartCopyProgress<FileCopyProgress>(
    const CopyEntryOptionsProto&,
    const std::string&,
    const std::string&,
    int32_t*);
template ErrorType SmbProvider::StartCopyProgress<RecursiveCopyProgress>(
    const CopyEntryOptionsProto&,
    const std::string&,
    const std::string&,
    int32_t*);

}  // namespace smbprovider
