// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "client/settings.h"

#include <stdint.h>

#include <limits>

#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
#include "util/file/filesystem.h"
#include "util/numeric/in_range_cast.h"

namespace crashpad {

#if defined(OS_FUCHSIA)

Settings::ScopedLockedFileHandle::ScopedLockedFileHandle()
    : handle_(kInvalidFileHandle), lockfile_path_() {
    }

Settings::ScopedLockedFileHandle::ScopedLockedFileHandle(
    FileHandle handle,
    const base::FilePath& lockfile_path)
    : handle_(handle), lockfile_path_(lockfile_path) {
}

Settings::ScopedLockedFileHandle::ScopedLockedFileHandle(
    ScopedLockedFileHandle&& other)
    : handle_(other.handle_), lockfile_path_(other.lockfile_path_) {
  other.handle_ = kInvalidFileHandle;
  other.lockfile_path_ = base::FilePath();
}

Settings::ScopedLockedFileHandle& Settings::ScopedLockedFileHandle::operator=(
    ScopedLockedFileHandle&& other) {
  handle_ = other.handle_;
  lockfile_path_ = other.lockfile_path_;

  other.handle_ = kInvalidFileHandle;
  other.lockfile_path_ = base::FilePath();
  return *this;
}

Settings::ScopedLockedFileHandle::~ScopedLockedFileHandle() {
  Destroy();
}

void Settings::ScopedLockedFileHandle::Destroy() {
  if (handle_ != kInvalidFileHandle) {
    CheckedCloseFile(handle_);
  }
  if (!lockfile_path_.empty()) {
    const bool success = LoggingRemoveFile(lockfile_path_);
    DCHECK(success);
  }
}

#else // OS_FUCHSIA

namespace internal {

// static
void ScopedLockedFileHandleTraits::Free(FileHandle handle) {
  if (handle != kInvalidFileHandle) {
    LoggingUnlockFile(handle);
    CheckedCloseFile(handle);
  }
}

}  // namespace internal

#endif  // OS_FUCHSIA

struct Settings::Data {
  static constexpr uint32_t kSettingsMagic = 'CPds';
  static constexpr uint32_t kSettingsVersion = 1;

  enum Options : uint32_t {
    kUploadsEnabled = 1 << 0,
  };

  Data() : magic(kSettingsMagic),
           version(kSettingsVersion),
           options(0),
           padding_0(0),
           last_upload_attempt_time(0),
           client_id() {}

  uint32_t magic;
  uint32_t version;
  uint32_t options;
  uint32_t padding_0;
  int64_t last_upload_attempt_time;  // time_t
  UUID client_id;
};

Settings::Settings() = default;

Settings::~Settings() = default;

bool Settings::Initialize(const base::FilePath& file_path) {
  DCHECK(initialized_.is_uninitialized());
  initialized_.set_invalid();
  file_path_ = file_path;

  Data settings;
  if (!OpenForWritingAndReadSettings(&settings).is_valid())
    return false;

  initialized_.set_valid();
  return true;
}

bool Settings::GetClientID(UUID* client_id) {
  DCHECK(initialized_.is_valid());

  Data settings;
  if (!OpenAndReadSettings(&settings))
    return false;

  *client_id = settings.client_id;
  return true;
}

bool Settings::GetUploadsEnabled(bool* enabled) {
  DCHECK(initialized_.is_valid());

  Data settings;
  if (!OpenAndReadSettings(&settings))
    return false;

  *enabled = (settings.options & Data::Options::kUploadsEnabled) != 0;
  return true;
}

bool Settings::SetUploadsEnabled(bool enabled) {
  DCHECK(initialized_.is_valid());

  Data settings;
  ScopedLockedFileHandle handle = OpenForWritingAndReadSettings(&settings);
  if (!handle.is_valid())
    return false;

  if (enabled)
    settings.options |= Data::Options::kUploadsEnabled;
  else
    settings.options &= ~Data::Options::kUploadsEnabled;

  return WriteSettings(handle.get(), settings);
}

bool Settings::GetLastUploadAttemptTime(time_t* time) {
  DCHECK(initialized_.is_valid());

  Data settings;
  if (!OpenAndReadSettings(&settings))
    return false;

  *time = InRangeCast<time_t>(settings.last_upload_attempt_time,
                              std::numeric_limits<time_t>::max());
  return true;
}

bool Settings::SetLastUploadAttemptTime(time_t time) {
  DCHECK(initialized_.is_valid());

  Data settings;
  ScopedLockedFileHandle handle = OpenForWritingAndReadSettings(&settings);
  if (!handle.is_valid())
    return false;

  settings.last_upload_attempt_time = InRangeCast<int64_t>(time, 0);

  return WriteSettings(handle.get(), settings);
}

// static
Settings::ScopedLockedFileHandle Settings::MakeScopedLockedFileHandle(
    FileHandle file,
    FileLocking locking,
    const base::FilePath& file_path) {
  ScopedFileHandle scoped(file);
#if defined(OS_FUCHSIA)
  base::FilePath lockfile_path(file_path.value() + ".__lock__");
  if (scoped.is_valid()) {
    ScopedFileHandle lockfile_scoped(
        LoggingOpenFileForWrite(lockfile_path,
                                FileWriteMode::kCreateOrFail,
                                FilePermissions::kWorldReadable));
    // This is a lightweight attempt to try to catch racy behavior.
    DCHECK(lockfile_scoped.is_valid());
    return ScopedLockedFileHandle(scoped.release(), lockfile_path);
  }
  return ScopedLockedFileHandle(scoped.release(), base::FilePath());
#else
  if (scoped.is_valid()) {
    if (LoggingLockFile(
            scoped.get(), locking, FileLockingBlocking::kBlocking) !=
        FileLockingResult::kSuccess) {
      scoped.reset();
    }
  }
  return ScopedLockedFileHandle(scoped.release());
#endif
}

Settings::ScopedLockedFileHandle Settings::OpenForReading() {
  return MakeScopedLockedFileHandle(
      LoggingOpenFileForRead(file_path()), FileLocking::kShared, file_path());
}

Settings::ScopedLockedFileHandle Settings::OpenForReadingAndWriting(
    FileWriteMode mode, bool log_open_error) {
  DCHECK(mode != FileWriteMode::kTruncateOrCreate);

  FileHandle handle;
  if (log_open_error) {
    handle = LoggingOpenFileForReadAndWrite(
        file_path(), mode, FilePermissions::kOwnerOnly);
  } else {
    handle = OpenFileForReadAndWrite(
        file_path(), mode, FilePermissions::kOwnerOnly);
  }

  return MakeScopedLockedFileHandle(
      handle, FileLocking::kExclusive, file_path());
}

bool Settings::OpenAndReadSettings(Data* out_data) {
  ScopedLockedFileHandle handle = OpenForReading();
  if (!handle.is_valid())
    return false;

  if (ReadSettings(handle.get(), out_data, true))
    return true;

  // The settings file is corrupt, so reinitialize it.
  handle.reset();

  // The settings failed to be read, so re-initialize them.
  return RecoverSettings(kInvalidFileHandle, out_data);
}

Settings::ScopedLockedFileHandle Settings::OpenForWritingAndReadSettings(
    Data* out_data) {
  ScopedLockedFileHandle handle;
  bool created = false;
  if (!initialized_.is_valid()) {
    // If this object is initializing, it hasn’t seen a settings file already,
    // so go easy on errors. Creating a new settings file for the first time
    // shouldn’t spew log messages.
    //
    // First, try to use an existing settings file.
    handle = OpenForReadingAndWriting(FileWriteMode::kReuseOrFail, false);

    if (!handle.is_valid()) {
      // Create a new settings file if it didn’t already exist.
      handle = OpenForReadingAndWriting(FileWriteMode::kCreateOrFail, false);

      if (handle.is_valid()) {
        created = true;
      }

      // There may have been a race to create the file, and something else may
      // have won. There will be one more attempt to try to open or create the
      // file below.
    }
  }

  if (!handle.is_valid()) {
    // Either the object is initialized, meaning it’s already seen a valid
    // settings file, or the object is initializing and none of the above
    // attempts to create the settings file succeeded. Either way, this is the
    // last chance for success, so if this fails, log a message.
    handle = OpenForReadingAndWriting(FileWriteMode::kReuseOrCreate, true);
  }

  if (!handle.is_valid())
    return ScopedLockedFileHandle();

  // Attempt reading the settings even if the file is known to have just been
  // created. The file-create and file-lock operations don’t occur atomically,
  // and something else may have written the settings before this invocation
  // took the lock. If the settings file was definitely just created, though,
  // don’t log any read errors. The expected non-race behavior in this case is a
  // zero-length read, with ReadSettings() failing.
  if (!ReadSettings(handle.get(), out_data, !created)) {
    if (!RecoverSettings(handle.get(), out_data))
      return ScopedLockedFileHandle();
  }

  return handle;
}

bool Settings::ReadSettings(FileHandle handle,
                            Data* out_data,
                            bool log_read_error) {
  if (LoggingSeekFile(handle, 0, SEEK_SET) != 0)
    return false;

  bool read_result =
      log_read_error
          ? LoggingReadFileExactly(handle, out_data, sizeof(*out_data))
          : ReadFileExactly(handle, out_data, sizeof(*out_data));

  if (!read_result)
    return false;

  if (out_data->magic != Data::kSettingsMagic) {
    LOG(ERROR) << "Settings magic is not " << Data::kSettingsMagic;
    return false;
  }

  if (out_data->version != Data::kSettingsVersion) {
    LOG(ERROR) << "Settings version is not " << Data::kSettingsVersion;
    return false;
  }

  return true;
}

bool Settings::WriteSettings(FileHandle handle, const Data& data) {
  if (LoggingSeekFile(handle, 0, SEEK_SET) != 0)
    return false;

  if (!LoggingTruncateFile(handle))
    return false;

  return LoggingWriteFile(handle, &data, sizeof(Data));
}

bool Settings::RecoverSettings(FileHandle handle, Data* out_data) {
  ScopedLockedFileHandle scoped_handle;
  if (handle == kInvalidFileHandle) {
    scoped_handle =
        OpenForReadingAndWriting(FileWriteMode::kReuseOrCreate, true);
    handle = scoped_handle.get();

    // Test if the file has already been recovered now that the exclusive lock
    // is held.
    if (ReadSettings(handle, out_data, true))
      return true;
  }

  if (handle == kInvalidFileHandle) {
    LOG(ERROR) << "Invalid file handle";
    return false;
  }

  if (!InitializeSettings(handle))
    return false;

  return ReadSettings(handle, out_data, true);
}

bool Settings::InitializeSettings(FileHandle handle) {
  Data settings;
  if (!settings.client_id.InitializeWithNew())
    return false;

  return WriteSettings(handle, settings);
}

}  // namespace crashpad
