// 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.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/memory/ptr_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/stringprintf.h>
#include <crypto/sha2.h>
#include <dbus/smbprovider/dbus-constants.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/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.h"
#include "smbprovider/smbprovider_helper.h"

namespace smbprovider {
namespace {

constexpr mode_t kDirMode = 16877;  // Dir entry

void PopulateMountRootStat(struct stat* mount_root_stat) {
  mount_root_stat->st_size = 0;
  mount_root_stat->st_mode = kDirMode;
  mount_root_stat->st_mtime = 0;
}

base::FilePath MakePasswordFileName(const std::string& share_path,
                                    const std::string& username,
                                    const std::string& workgroup) {
  const std::string raw_name = base::StringPrintf(
      "%s@@%s@%s", share_path.c_str(), username.c_str(), workgroup.c_str());
  const std::string raw_hash = crypto::SHA256HashString(raw_name);
  CHECK_EQ(raw_hash.size(), crypto::kSHA256Length);
  return base::FilePath(base::HexEncode(raw_hash.c_str(), raw_hash.size()));
}

}  // namespace

bool GetEntries(const ReadDirectoryOptionsProto& options,
                CachingIterator 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;
}

bool GetShareEntries(const GetSharesOptionsProto& options,
                     ShareIterator 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<MountManager> mount_manager,
    std::unique_ptr<KerberosArtifactSynchronizer> kerberos_synchronizer,
    const base::FilePath& daemon_store_directory)
    : org::chromium::SmbProviderAdaptor(this),
      dbus_object_(std::move(dbus_object)),
      mount_manager_(std::move(mount_manager)),
      kerberos_synchronizer_(std::move(kerberos_synchronizer)),
      copy_tracker_(kInitialCopyProgressTrackerId),
      read_dir_tracker_(kInitialReadDirProgressTrackerId),
      daemon_store_directory_(daemon_store_directory) {}

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

base::FilePath SmbProvider::GetDaemonStoreDirectory(
    const std::string& username_hash) const {
  CHECK(!username_hash.empty());
  return daemon_store_directory_.Append(username_hash);
}

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);

  MountOptionsProto options;
  if (!ParseOptionsProto(options_blob, &options, error_code)) {
    return;  // Error with parsing proto.
  }
  if ((options.restore_password() || options.save_password()) &&
      options.account_hash().empty()) {
    // |account_hash| should always be set if the password is being saved or
    // restored.
    LOG(ERROR) << "Unknown profile for password save/restore";
    *error_code = static_cast<int32_t>(ERROR_DBUS_PARSE_FAILED);
    return;
  }

  std::string original_share_path = options.original_path();
  if (original_share_path.empty()) {
    original_share_path = options.path();
  }

  MountConfig mount_config = ConvertToMountConfig(options);

  const base::ScopedFD* passed_password_fd = &password_fd;

  base::ScopedFD saved_password_fd;
  base::FilePath password_filepath;
  if (options.restore_password() || options.save_password()) {
    password_filepath =
        GetDaemonStoreDirectory(options.account_hash())
            .Append(MakePasswordFileName(
                original_share_path, options.username(), options.workgroup()));
  }

  if (options.restore_password()) {
    LOG(INFO) << "Restoring saved password";
    base::File password_file(password_filepath,
                             base::File::FLAG_OPEN | base::File::FLAG_READ);
    if (!password_file.IsValid()) {
      LOG(ERROR) << "Unable to open password file for read with error: "
                 << password_file.error_details();
    } else {
      saved_password_fd.reset(password_file.TakePlatformFile());
      passed_password_fd = &saved_password_fd;
    }
  }

  // AddMount() has to be called first since the credential has to be stored
  // before calling CanReadMountRoot().
  AddMount(options.path(), mount_config, options.workgroup(),
           options.username(), *passed_password_fd, password_filepath,
           mount_id);
  if (options.skip_connect()) {
    return;
  }

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

  if (options.save_password()) {
    LOG(INFO) << "Saving password for mount [" << *mount_id << "]";
    bool success = mount_manager_->SavePasswordToFile(*mount_id);
    DCHECK(success);
  }
}

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)) {
    return error_code;
  }

  if (options.remove_password()) {
    bool success = mount_manager_->ErasePasswordFile(GetMountId(options));
    DCHECK(success);
  }

  if (!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(options_blob, error_code, out_entries);
}

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

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

    SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));
      // Purge the cache of expired entries before reading next directory.
    cache->PurgeExpiredEntries();
    GetEntries(options, CachingIterator(full_path, samba_interface, cache),
               error_code, out_entries);
  }
}

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

  std::string full_path;
  GetSharesOptionsProto options;
  if (ParseOptionsAndPath(options_blob, &options, &full_path, error_code)) {
    SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));

    GetShareEntries(options, ShareIterator(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 we have the result cached, then return it.
  if (GetCachedEntry(GetMountId(options), full_path, out_entry)) {
    *error_code = static_cast<int32_t>(ERROR_OK);
    return;
  }

  SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));

  int32_t get_status_error = 0;
  struct stat stat_info;
  // Always return a successful response on the root. If the files app detects
  // a failure here it will block any further requests to the mount.
  if (options.entry_path() == "/") {
    PopulateMountRootStat(&stat_info);
  } else {
    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);

  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) &&
                 WriteTempFile(options, content_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;

  const bool result =
      ParseOptionsProto(options_blob, &options, &error_code) &&
      ReadFromFD(options, temp_fd, &error_code, &content_buffer_) &&
      Seek(options, &error_code) &&
      WriteFileFromBuffer(options, options.file_id(), &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);

  ReadShareEntries(options_blob, 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_.Contains(copy_token)) {
    LogAndSetError(kContinueCopyMethod, mount_id, ERROR_COPY_FAILED,
                   &error_code);
    return error_code;
  }

  if (!mount_manager_->IsAlreadyMounted(mount_id)) {
    copy_tracker_.Remove(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);
}

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

  std::string directory_path;
  ReadDirectoryOptionsProto options;

  if (!ParseOptionsAndPath(options_blob, &options, &directory_path,
                           error_code)) {
    return;
  }

  DirectoryEntryListProto entries;
  ErrorType error =
      StartReadDirectory(options, directory_path, &entries, read_dir_token);

  if (error != ERROR_OK && error != ERROR_OPERATION_PENDING) {
    LogAndSetError(options, error, error_code);
    return;
  }

  ErrorType serialize_error = SerializeProtoToBlob(entries, out_entries);
  if (serialize_error != ERROR_OK) {
    LogAndSetError(options, serialize_error, error_code);
    return;
  }

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

void SmbProvider::ContinueReadDirectory(int32_t mount_id,
                                        int32_t read_dir_token,
                                        int32_t* error_code,
                                        ProtoBlob* out_entries) {
  DCHECK_GE(mount_id, 0);
  DCHECK_GE(read_dir_token, 0);
  DCHECK(error_code);
  DCHECK(out_entries);

  if (!read_dir_tracker_.Contains(read_dir_token)) {
    LogAndSetError(kContinueReadDirectoryMethod, mount_id,
                   ERROR_OPERATION_FAILED, error_code);
    return;
  }

  if (!mount_manager_->IsAlreadyMounted(mount_id)) {
    read_dir_tracker_.Remove(read_dir_token);
    LogAndSetError(kContinueReadDirectoryMethod, mount_id,
                   ERROR_OPERATION_FAILED, error_code);
    return;
  }

  DirectoryEntryListProto entries;
  ErrorType error = ContinueReadDirectory(read_dir_token, &entries);

  if (error != ERROR_OK && error != ERROR_OPERATION_PENDING) {
    LogAndSetError(kContinueReadDirectoryMethod, mount_id, error, error_code);
    return;
  }

  ErrorType serialize_error = SerializeProtoToBlob(entries, out_entries);
  if (serialize_error != ERROR_OK) {
    LogAndSetError(kContinueReadDirectoryMethod, mount_id, serialize_error,
                   error_code);
    return;
  }

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

int32_t SmbProvider::UpdateMountCredentials(const ProtoBlob& options_blob,
                                            const base::ScopedFD& password_fd) {
  int32_t error_code;
  UpdateMountCredentialsOptionsProto options;

  const bool success =
      ParseOptionsProto(options_blob, &options, &error_code) &&
      mount_manager_->UpdateMountCredential(
          options.mount_id(),
          SmbCredential(options.workgroup(), options.username(),
                        GetPassword(password_fd), {}));
  if (!success) {
    LOG(ERROR) << "Failed to update credentials of mount id: "
               << options.mount_id();
    return static_cast<int32_t>(ERROR_NOT_FOUND);
  }
  return static_cast<int32_t>(ERROR_OK);
}

int32_t SmbProvider::UpdateSharePath(const ProtoBlob& options_blob) {
  int32_t error_code;
  UpdateSharePathOptionsProto options;

  const bool success =
      ParseOptionsProto(options_blob, &options, &error_code) &&
      mount_manager_->UpdateSharePath(options.mount_id(), options.path());

  if (!success) {
    LOG(ERROR) << "Failed to update share path of mount id: "
               << options.mount_id();
    return static_cast<int32_t>(ERROR_NOT_FOUND);
  }
  return static_cast<int32_t>(ERROR_OK);
}

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;
}

SambaInterface* SmbProvider::GetSambaInterface(int32_t mount_id) const {
  SambaInterface* samba_interface;
  if (mount_id == kInternalMountId) {
    samba_interface = mount_manager_->GetSystemSambaInterface();
  } else {
    bool success =
        mount_manager_->GetSambaInterface(mount_id, &samba_interface);
    DCHECK(success);
  }

  DCHECK(samba_interface);
  return samba_interface;
}

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::CanReadMountRoot(int32_t mount_id,
                                   const std::string& mount_root,
                                   int32_t* error_code) {
  DCHECK(error_code);

  SambaInterface* samba_interface = GetSambaInterface(mount_id);
  DCHECK(samba_interface);

  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;
}

void SmbProvider::AddMount(const std::string& mount_root,
                           const MountConfig& mount_config,
                           const std::string& workgroup,
                           const std::string& username,
                           const base::ScopedFD& password_fd,
                           const base::FilePath& password_file,
                           int32_t* mount_id) {
  SmbCredential credential(workgroup, username, GetPassword(password_fd),
                           password_file);
  mount_manager_->AddMount(mount_root, std::move(credential), mount_config,
                           mount_id);
  DCHECK_GE(*mount_id, 0);
}

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) {
  DCHECK(error_code);

  // Read the data in the member |content_buffer_|.
  if (!ReadToContentBuffer(options, options.file_id(), 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;
}

bool SmbProvider::WriteFileFromBuffer(const WriteFileOptionsProto& options,
                                      int32_t file_id,
                                      int32_t* error_code) {
  DCHECK(error_code);

  SambaInterface* samba_interface = GetSambaInterface(GetMountId(options));
  int32_t result = samba_interface->WriteFile(file_id, content_buffer_.data(),
                                              content_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) {
  // It's always safe to invalidate the cache regardless of whether the delete
  // is successful or not.
  InvalidateCacheEntry(mount_id, 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) {
  // It's always safe to invalidate the cache regardless of whether the delete
  // is successful or not.
  InvalidateCacheEntry(mount_id, dir_path);
  SambaInterface* samba_interface = GetSambaInterface(mount_id);
  return samba_interface->RemoveDirectory(dir_path.c_str());
}

void SmbProvider::InvalidateCacheEntry(int32_t mount_id,
                                       const std::string& full_path) {
  MetadataCache* cache = nullptr;
  bool got_cache = mount_manager_->GetMetadataCache(mount_id, &cache);
  DCHECK(got_cache);
  DCHECK(cache);

  // The result can be ignored since it may or may not be in the cache.
  cache->RemoveEntry(full_path);
}

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);

  // Invalidate the cache for the source path. This is always safe even if the
  // move fails because it will just cause a cache miss.
  int32_t mount_id = GetMountId(options);
  InvalidateCacheEntry(mount_id, source_path);

  SambaInterface* samba_interface = GetSambaInterface(mount_id);
  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_tracker_.Insert(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);
  DCHECK(copy_tracker_.Contains(copy_token));

  int32_t copy_result;
  const bool should_continue_copy =
      copy_tracker_.Find(copy_token)->second->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_.Remove(copy_token);

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

  return GetErrorFromErrno(copy_result);
}

bool SmbProvider::ReadToContentBuffer(const ReadFileOptionsProto& options,
                                      int32_t file_id,
                                      int32_t* error_code) {
  DCHECK(error_code);

  // Make sure the buffer is at least large enough for the content.
  content_buffer_.resize(options.length());

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

  DCHECK_GE(bytes_read, 0);
  DCHECK_LE(bytes_read, content_buffer_.size());

  // Make sure buffer is only as big as bytes_read.
  content_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;
}

ErrorType SmbProvider::StartReadDirectory(
    const ReadDirectoryOptionsProto& options,
    const std::string& directory_path,
    DirectoryEntryListProto* entries,
    int32_t* read_dir_token) {
  DCHECK(entries);
  DCHECK(read_dir_token);

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

  MetadataCache* cache = nullptr;
  bool got_cache =
      mount_manager_->GetMetadataCache(GetMountId(options), &cache);
  DCHECK(got_cache);
  DCHECK(cache);

  int32_t read_dir_result;
  const bool should_continue_read_dir = read_dir_progress->StartReadDir(
      directory_path, cache, &read_dir_result, entries);

  if (should_continue_read_dir) {
    DCHECK_EQ(0, read_dir_result);
    // The read directory needs to be continued.
    *read_dir_token = read_dir_tracker_.Insert(std::move(read_dir_progress));
    return ERROR_OPERATION_PENDING;
  }

  if (read_dir_result == 0) {
    // The readdir is complete.
    return ERROR_OK;
  }

  return GetErrorFromErrnoForReadDir(read_dir_result);
}

ErrorType SmbProvider::ContinueReadDirectory(int32_t read_dir_token,
                                             DirectoryEntryListProto* entries) {
  DCHECK(entries);

  DCHECK_GE(read_dir_token, 0);
  DCHECK(read_dir_tracker_.Contains(read_dir_token));

  int32_t read_dir_result;
  const bool should_continue_read_dir =
      read_dir_tracker_.Find(read_dir_token)
          ->second->ContinueReadDir(&read_dir_result, entries);

  if (should_continue_read_dir) {
    DCHECK_EQ(0, read_dir_result);
    // The read directory needs to be continued.
    return ERROR_OPERATION_PENDING;
  }

  // The read directory no longer needs to be continued as it has either
  // completed successfully or it failed so remove it for |read_dir_tracker_|.
  read_dir_tracker_.Remove(read_dir_token);

  if (read_dir_result == 0) {
    // The readdir is complete.
    return ERROR_OK;
  }

  return GetErrorFromErrno(read_dir_result);
}

// 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
