// 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 <sys/vfs.h>

#include <memory>

#include <base/at_exit.h>
#include <base/bind.h>
#include <base/location.h>
#include <base/logging.h>
#include <base/message_loop/message_loop.h>
#include <base/posix/eintr_wrapper.h>
#include <base/threading/platform_thread.h>
#include <base/threading/thread.h>
#include <brillo/syslog_logging.h>

#include "virtual_file_provider/fuse_main.h"
#include "virtual_file_provider/service.h"
#include "virtual_file_provider/util.h"

namespace virtual_file_provider {

namespace {

// Service thread handles D-Bus method calls.
class ServiceThread : public base::Thread {
 public:
  ServiceThread(const base::FilePath& fuse_mount_path, SizeMap* size_map)
      : Thread("Service thread"),
        fuse_mount_path_(fuse_mount_path),
        service_(std::make_unique<Service>(fuse_mount_path, size_map)) {}

  ~ServiceThread() override { Stop(); }

  Service* service() { return service_.get(); }

 protected:
  // base::Thread overrides:
  void Init() override {
    CHECK(WaitForFuseMount());
    CHECK(ClearCapabilities());
    CHECK(service_->Initialize());
  }

  void CleanUp() override {
    service_.reset();  // Must be destructed on the same thread as Initialize().
  }

 private:
  // Waits for the FUSE mount to get ready.
  bool WaitForFuseMount() {
    constexpr int kMaxRetryCount = 3000;
    constexpr base::TimeDelta kRetryInterval =
        base::TimeDelta::FromMilliseconds(1);

    for (int retry_count = 0; retry_count < kMaxRetryCount; ++retry_count) {
      struct statfs buf = {};
      if (HANDLE_EINTR(statfs(fuse_mount_path_.value().c_str(), &buf)) < 0) {
        PLOG(ERROR) << "statfs() failed.";
        return false;
      }
      // Compare with FUSE_SUPER_MAGIC (defined in <kernel>/fs/fuse/inode.c).
      if (buf.f_type == 0x65735546)
        return true;

      base::PlatformThread::Sleep(kRetryInterval);
    }
    LOG(ERROR) << "Timed out while waiting for FUSE mount.";
    return false;
  }

  const base::FilePath fuse_mount_path_;
  std::unique_ptr<Service> service_;

  DISALLOW_COPY_AND_ASSIGN(ServiceThread);
};

class FuseMainDelegateImpl : public FuseMainDelegate {
 public:
  FuseMainDelegateImpl(ServiceThread* service_thread, SizeMap* size_map)
      : service_thread_(service_thread), size_map_(size_map) {}
  ~FuseMainDelegateImpl() override = default;

  // FuseMainDelegate overrides:
  int64_t GetSize(const std::string& id) override;
  void HandleReadRequest(const std::string& id,
                         int64_t offset,
                         int64_t size,
                         base::ScopedFD fd) override;
  void NotifyIdReleased(const std::string& id) override;

 private:
  ServiceThread* const service_thread_;
  SizeMap* const size_map_;

  DISALLOW_COPY_AND_ASSIGN(FuseMainDelegateImpl);
};

int64_t FuseMainDelegateImpl::GetSize(const std::string& id) {
  return size_map_->GetSize(id);
}

void FuseMainDelegateImpl::HandleReadRequest(const std::string& id,
                                             int64_t offset,
                                             int64_t size,
                                             base::ScopedFD fd) {
  service_thread_->task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&Service::SendReadRequest,
                 // This is safe as service_thread outlives the FUSE main loop.
                 base::Unretained(service_thread_->service()),
                 id, offset, size, base::Passed(&fd)));
}

void FuseMainDelegateImpl::NotifyIdReleased(const std::string& id) {
  if (!size_map_->Erase(id)) {
    LOG(ERROR) << "Invalid ID " << id;
    return;
  }
  service_thread_->task_runner()->PostTask(
      FROM_HERE,
      base::Bind(&Service::SendIdReleased,
                 // This is safe as service_thread outlives the FUSE main loop.
                 base::Unretained(service_thread_->service()), id));
}

}  // namespace

}  // namespace virtual_file_provider

int main(int argc, char** argv) {
  if (argc != 2) {
    fprintf(stderr, "usage: %s <FUSE mount path>\n", argv[0]);
    return 1;
  }
  base::FilePath fuse_mount_path(argv[1]);

  brillo::InitLog(brillo::kLogToSyslog | brillo::kLogToStderr);
  base::AtExitManager at_exit_manager;

  virtual_file_provider::SizeMap size_map;

  // Run D-Bus service on the service thread.
  virtual_file_provider::ServiceThread service_thread(
      fuse_mount_path, &size_map);
  base::Thread::Options options;
  options.message_loop_type = base::MessageLoop::TYPE_IO;
  service_thread.StartWithOptions(options);

  // Enter the FUSE main loop.
  virtual_file_provider::FuseMainDelegateImpl delegate(&service_thread,
                                                       &size_map);
  return virtual_file_provider::FuseMain(fuse_mount_path, &delegate);
}
