blob: ea717a35f84cea236a642d26bdab8bf45b39c2c0 [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 SMBFS_SMB_FILESYSTEM_H_
#define SMBFS_SMB_FILESYSTEM_H_
#include <libsmbclient.h>
#include <sys/types.h>
#include <memory>
#include <ostream>
#include <string>
#include <vector>
#include <base/id_map.h>
#include <base/macros.h>
#include <base/threading/thread.h>
#include "smbfs/filesystem.h"
#include "smbfs/inode_map.h"
namespace smbfs {
class SmbFilesystem : public Filesystem {
public:
enum class ConnectError {
kOk = 0,
kNotFound,
kAccessDenied,
kSmb1Unsupported,
kUnknownError,
};
SmbFilesystem(const std::string& share_path, uid_t uid, gid_t gid);
~SmbFilesystem() override;
// Ensures that the SMB share can be connected to. Must NOT be called after
// the filesystem is attached to a FUSE session.
ConnectError EnsureConnected();
// Filesystem overrides.
void Lookup(std::unique_ptr<EntryRequest> request,
fuse_ino_t parent_inode,
const std::string& name) override;
void Forget(fuse_ino_t inode, uint64_t count) override;
void GetAttr(std::unique_ptr<AttrRequest> request, fuse_ino_t inode) override;
void SetAttr(std::unique_ptr<AttrRequest> request,
fuse_ino_t inode,
base::Optional<uint64_t> file_handle,
const struct stat& attr,
int to_set) override;
void Open(std::unique_ptr<OpenRequest> request,
fuse_ino_t inode,
int flags) override;
void Create(std::unique_ptr<CreateRequest> request,
fuse_ino_t parent_inode,
const std::string& name,
mode_t mode,
int flags) override;
void Read(std::unique_ptr<BufRequest> request,
fuse_ino_t inode,
uint64_t file_handle,
size_t size,
off_t offset) override;
void Write(std::unique_ptr<WriteRequest> request,
fuse_ino_t inode,
uint64_t file_handle,
const char* buf,
size_t size,
off_t offset) override;
void Release(std::unique_ptr<SimpleRequest> request,
fuse_ino_t inode,
uint64_t file_handle) override;
void OpenDir(std::unique_ptr<OpenRequest> request,
fuse_ino_t inode,
int flags) override;
void ReadDir(std::unique_ptr<DirentryRequest> request,
fuse_ino_t inode,
uint64_t file_handle,
off_t offset) override;
void ReleaseDir(std::unique_ptr<SimpleRequest> request,
fuse_ino_t inode,
uint64_t file_handle) override;
private:
// Filesystem implementations that execute on |samba_thread_|.
void LookupInternal(std::unique_ptr<EntryRequest> request,
fuse_ino_t parent_inode,
const std::string& name);
void ForgetInternal(fuse_ino_t inode, uint64_t count);
void GetAttrInternal(std::unique_ptr<AttrRequest> request, fuse_ino_t inode);
void SetAttrInternal(std::unique_ptr<AttrRequest> request,
fuse_ino_t inode,
base::Optional<uint64_t> file_handle,
const struct stat& attr,
int to_set);
void OpenInternal(std::unique_ptr<OpenRequest> request,
fuse_ino_t inode,
int flags);
void CreateInternal(std::unique_ptr<CreateRequest> request,
fuse_ino_t parent_inode,
const std::string& name,
mode_t mode,
int flags);
void ReadInternal(std::unique_ptr<BufRequest> request,
fuse_ino_t inode,
uint64_t file_handle,
size_t size,
off_t offset);
void WriteInternal(std::unique_ptr<WriteRequest> request,
fuse_ino_t inode,
uint64_t file_handle,
const std::vector<char>& buf,
off_t offset);
void ReleaseInternal(std::unique_ptr<SimpleRequest> request,
fuse_ino_t inode,
uint64_t file_handle);
void OpenDirInternal(std::unique_ptr<OpenRequest> request,
fuse_ino_t inode,
int flags);
void ReadDirInternal(std::unique_ptr<DirentryRequest> request,
fuse_ino_t inode,
uint64_t file_handle,
off_t offset);
void ReleaseDirInternal(std::unique_ptr<SimpleRequest> request,
fuse_ino_t inode,
uint64_t file_handle);
// Constructs a sanitised stat struct for sending as a response.
struct stat MakeStat(ino_t inode, const struct stat& in_stat) const;
// Constructs a share file path suitable for passing to libsmbclient from the
// given absolute file path.
std::string MakeShareFilePath(const base::FilePath& path) const;
// Construct a share file path from the |inode|. |inode| must be a valid inode
// number.
std::string ShareFilePathFromInode(ino_t inode) const;
const std::string share_path_;
const uid_t uid_;
const gid_t gid_;
base::Thread samba_thread_;
InodeMap inode_map_{FUSE_ROOT_ID};
IDMap<SMBCFILE*, uint64_t> open_files_;
SMBCCTX* context_ = nullptr;
smbc_close_fn smbc_close_ctx_ = nullptr;
smbc_closedir_fn smbc_closedir_ctx_ = nullptr;
smbc_ftruncate_fn smbc_ftruncate_ctx_ = nullptr;
smbc_lseek_fn smbc_lseek_ctx_ = nullptr;
smbc_lseekdir_fn smbc_lseekdir_ctx_ = nullptr;
smbc_open_fn smbc_open_ctx_ = nullptr;
smbc_opendir_fn smbc_opendir_ctx_ = nullptr;
smbc_read_fn smbc_read_ctx_ = nullptr;
smbc_readdir_fn smbc_readdir_ctx_ = nullptr;
smbc_stat_fn smbc_stat_ctx_ = nullptr;
smbc_telldir_fn smbc_telldir_ctx_ = nullptr;
smbc_write_fn smbc_write_ctx_ = nullptr;
DISALLOW_IMPLICIT_CONSTRUCTORS(SmbFilesystem);
};
std::ostream& operator<<(std::ostream& out, SmbFilesystem::ConnectError error);
} // namespace smbfs
#endif // SMBFS_SMB_FILESYSTEM_H_