blob: 0d395ec118d0333f043e7f2bcfca2a333a103e4b [file] [log] [blame]
// Copyright 2019 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.
#ifndef ARC_VM_VSOCK_PROXY_PROXY_FILE_SYSTEM_H_
#define ARC_VM_VSOCK_PROXY_PROXY_FILE_SYSTEM_H_
#include <fuse/fuse.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <map>
#include <memory>
#include <base/callback.h>
#include <base/files/file_path.h>
#include <base/files/scoped_file.h>
#include <base/macros.h>
#include <base/memory/ref_counted.h>
#include <base/optional.h>
#include <base/synchronization/lock.h>
#include "arc/vm/vsock_proxy/vsock_proxy.h"
namespace base {
class TaskRunner;
class WaitableEvent;
} // namespace base
namespace arc {
class FuseMount;
// FUSE implementation to support regular file descriptor passing over VSOCK.
// This is designed to be used only in the host side.
class ProxyFileSystem {
public:
class Delegate {
public:
virtual ~Delegate() = default;
using PreadCallback = VSockProxy::PreadCallback;
using FstatCallback = VSockProxy::FstatCallback;
// Implement these methods to handle file operation requests.
virtual void Pread(int64_t handle,
uint64_t count,
uint64_t offset,
PreadCallback callback) = 0;
virtual void Close(int64_t handle) = 0;
virtual void Fstat(int64_t handle, FstatCallback callback) = 0;
};
// |mount_path| is the path to the mount point.
ProxyFileSystem(Delegate* delegate,
scoped_refptr<base::TaskRunner> delegate_task_runner,
const base::FilePath& mount_path);
~ProxyFileSystem();
ProxyFileSystem(const ProxyFileSystem&) = delete;
ProxyFileSystem& operator=(const ProxyFileSystem&) = delete;
// Initializes this object.
bool Init();
// Implementation of the fuse operation callbacks.
int GetAttr(const char* path, struct stat* stat);
int Open(const char* path, struct fuse_file_info* fi);
int Read(const char* path,
char* buf,
size_t size,
off_t off,
struct fuse_file_info* fi);
int Release(const char* path, struct fuse_file_info* fi);
int ReadDir(const char* path,
void* buf,
fuse_fill_dir_t filler,
off_t offset,
struct fuse_file_info* fi);
// Registers the given |handle| to the file system, then returns the file
// descriptor corresponding to the registered file.
// Operations for the returned file descriptor will be directed to the
// fuse operation implementation declared above.
base::ScopedFD RegisterHandle(int64_t handle);
private:
// Helper to operate GetAtt(). Called on the |delegate_task_runner_|.
void GetAttrInternal(base::WaitableEvent* event,
int64_t handle,
int* return_value,
off_t* size);
// Helper to operate Read(). Called on the |delegate_task_runner_|.
void ReadInternal(base::WaitableEvent* event,
int64_t handle,
char* buf,
size_t size,
off_t offset,
int* return_value);
// Returns the opened/not-opened-yet state of the given |handle|.
// If not registered, base::nullopt is returned.
enum class State {
NOT_OPENED,
OPENED,
};
base::Optional<State> GetState(int64_t handle);
Delegate* const delegate_;
scoped_refptr<base::TaskRunner> delegate_task_runner_;
const base::FilePath mount_path_;
std::unique_ptr<FuseMount> fuse_mount_;
// Registered |handle|s to its opened/not-yet-opened state.
// The access to |handle_map_| needs to be guarded by |handle_map_lock_|,
// because fuse starts as many threads as needed so this can be accessed
// from multiple threads.
std::map<int64_t, State> handle_map_;
base::Lock handle_map_lock_;
scoped_refptr<base::TaskRunner> init_task_runner_;
};
} // namespace arc
#endif // ARC_VM_VSOCK_PROXY_PROXY_FILE_SYSTEM_H_