blob: c1591fdfb74f81b949a9b80c91745df49b80662b [file] [log] [blame]
// Copyright 2021 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 <sysexits.h>
#include <unistd.h>
#include <base/check.h>
#include <base/check_op.h>
#include <base/command_line.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <brillo/daemons/dbus_daemon.h>
#include <brillo/syslog_logging.h>
#include <chromeos/dbus/service_constants.h>
#include "fusebox/fuse_frontend.h"
#include "fusebox/util.h"
using base::CommandLine;
namespace {
void SetupLogging() {
brillo::InitLog(brillo::kLogToStderr);
}
} // namespace
namespace fusebox {
class FuseBoxDaemon : public brillo::DBusServiceDaemon {
public:
explicit FuseBoxDaemon(FuseMount* fuse)
: DBusServiceDaemon(kFuseBoxClientName), fuse_(fuse) {}
FuseBoxDaemon(const FuseBoxDaemon&) = delete;
FuseBoxDaemon& operator=(const FuseBoxDaemon&) = delete;
~FuseBoxDaemon() {}
protected:
// brillo::DBusServiceDaemon overrides.
void RegisterDBusObjectsAsync(
brillo::dbus_utils::AsyncEventSequencer* sequencer) override {
bus_->AssertOnDBusThread();
// TODO(noel): register the FuseBoxClient DBUS objects.
}
int OnEventLoopStarted() override {
bus_->AssertOnDBusThread();
int ret = brillo::DBusServiceDaemon::OnEventLoopStarted();
if (ret != EX_OK)
return ret;
// TODO(noel): setup and start the FuseBoxClient here.
CHECK(fuse_);
return EX_OK;
}
void OnShutdown(int* exit_code) override {
bus_->AssertOnDBusThread();
DBusServiceDaemon::OnShutdown(exit_code);
}
private:
// Fuse mount: not owned.
FuseMount* fuse_ = nullptr;
};
int Run(char** mountpoint, fuse_chan* chan, fuse_args* args) {
LOG(INFO) << base::StringPrintf("fusebox %s [%d]", *mountpoint, getpid());
FuseMount fuse = FuseMount(mountpoint, chan, args);
auto daemon = FuseBoxDaemon(&fuse);
return daemon.Run();
}
} // namespace fusebox
int main(int argc, char** argv) {
CommandLine::Init(argc, argv);
SetupLogging();
fuse_args args = FUSE_ARGS_INIT(argc, argv);
char* mountpoint = nullptr;
if (fuse_parse_cmdline(&args, &mountpoint, nullptr, nullptr) == -1) {
LOG(ERROR) << "fuse_parse_cmdline() failed " << ErrorToString(errno);
return EX_USAGE;
}
if (!mountpoint) {
LOG(ERROR) << "fuse_parse_cmdline() mountpoint expected";
return ENODEV;
}
fuse_chan* chan = fuse_mount(mountpoint, &args);
if (!chan) {
LOG(ERROR) << "fuse_mount() failed " << ErrorToString(errno, mountpoint);
return ENODEV;
}
int exit_code = fusebox::Run(&mountpoint, chan, &args);
if (!mountpoint) { // Kernel can remove the FUSE mountpoint: umount(8).
exit_code = ENODEV;
} else {
fuse_unmount(mountpoint, nullptr);
}
LOG_IF(ERROR, exit_code) << ErrorToString(exit_code, "exiting");
fuse_opt_free_args(&args);
return exit_code;
}