WSL/src/linux/plan9/p9file.h

135 lines
5.1 KiB
C++

// Copyright (C) Microsoft Corporation. All rights reserved.
#pragma once
#include "p9io.h"
#include "p9fid.h"
#include "p9readdir.h"
#include <pwd.h>
#include <grp.h>
namespace p9fs {
struct Share
{
wil::unique_fd RootFd;
};
struct Root final : public IRoot
{
Root(std::shared_ptr<const Share> share, int rootFd, uid_t uid, gid_t gid) : Share{share}, RootFd{rootFd}, Uid{uid}, Gid{gid}
{
Plan9TraceLoggingProvider::LogMessage(std::format("Instantiate root, uid={}", uid));
if (uid == -1)
{
return; // No uid passed, don't try to get the additional groups.
}
auto bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
if (bufsize == -1)
{
bufsize = 16384; // Recommended by the man page if _SC_GETPW_R_SIZE_MAX is not set.
}
std::vector<char> buffer(bufsize);
passwd pwd{};
passwd* result = nullptr;
if (getpwuid_r(uid, &pwd, buffer.data(), buffer.size(), &result) < 0 || result == nullptr)
{
Plan9TraceLoggingProvider::LogMessage(std::format("getpwuid_r failed for uid: {}, errno={}", uid, errno));
return;
}
// Find the number of groups
int groupCount = 0;
getgrouplist(pwd.pw_name, gid, nullptr, &groupCount);
Groups.resize(groupCount);
// Query the groups
if (getgrouplist(pwd.pw_name, gid, Groups.data(), &groupCount) < 0)
{
Plan9TraceLoggingProvider::LogMessage(std::format("getgrouplist failed for user: {}, errno={}", pwd.pw_name, errno));
Groups.clear();
}
}
std::shared_ptr<const Share> Share;
int RootFd;
// The uid that the client attached with, and the associated primary gid.
// If these are -1, then no change is necessary.
uid_t Uid;
gid_t Gid;
std::vector<gid_t> Groups;
bool ReadOnly() const
{
return false;
}
};
class File final : public Fid
{
public:
File(std::shared_ptr<const Root> root);
File(const File&);
Expected<Qid> Initialize();
Expected<Qid> Walk(std::string_view Name) override;
Expected<std::tuple<UINT64, Qid, StatResult>> GetAttr(UINT64 Mask) override;
LX_INT SetAttr(UINT32 Valid, const StatResult& Stat) override;
Expected<Qid> Open(OpenFlags Flags) override;
Expected<Qid> Create(std::string_view Name, OpenFlags /* Flags */, UINT32 /* Mode */, UINT32 /* Gid */) override;
Expected<Qid> MkDir(std::string_view Name, UINT32 /* Mode */, UINT32 /* Gid */) override;
LX_INT ReadDir(UINT64 Offset, SpanWriter& writer, bool includeAttributes) override;
Task<Expected<UINT32>> Read(UINT64 Offset, gsl::span<gsl::byte> Buffer) override;
Task<Expected<UINT32>> Write(UINT64 Offset, gsl::span<const gsl::byte> Buffer) override;
LX_INT UnlinkAt(std::string_view Name, UINT32 /* Flags */) override;
LX_INT Remove() override;
LX_INT RenameAt(std::string_view OldName, Fid& NewParent, std::string_view NewName) override;
LX_INT Rename(Fid& NewParent, std::string_view NewName) override;
Expected<Qid> SymLink(std::string_view /* name */, std::string_view /* target */, UINT32 /* gid */) override;
Expected<Qid> MkNod(std::string_view /* name */, UINT32 /* mode */, UINT32 /* major */, UINT32 /* minor */, UINT32 /* gid */) override;
LX_INT Link(std::string_view /* name */, Fid& /* target */) override;
Expected<UINT32> ReadLink(gsl::span<char> /* name */) override;
LX_INT Fsync() override;
Expected<StatFsResult> StatFs() override;
Expected<LockStatus> Lock(LockType Type, UINT32 Flags, UINT64 Start, UINT64 Length, UINT32 ProcId, std::string_view ClientId) override;
Expected<std::tuple<LockType, UINT64, UINT64, UINT32, std::string_view>> GetLock(
LockType Type, UINT64 Start, UINT64 Length, UINT32 ProcId, std::string_view ClientId) override;
Expected<std::shared_ptr<XAttrBase>> XattrWalk(const std::string& Name) override;
Expected<std::shared_ptr<XAttrBase>> XattrCreate(const std::string& Name, UINT64 Size, UINT32 Flags) override;
// 9P2000.W operations
LX_INT Access(AccessFlags Flags) override;
std::shared_ptr<Fid> Clone() const override;
bool IsOnRoot(const std::shared_ptr<const IRoot>& root) override;
bool IsFile() const override;
Qid GetQid() const override;
bool IsOpen() const;
private:
Expected<wil::unique_fd> OpenFile(int openFlags);
LX_INT ValidateExists();
std::string GetFileName() const;
std::string ChildPath(std::string_view name);
std::string ChildPathWithLockHeld(std::string_view name);
Expected<struct stat> Stat();
LX_INT ReadDirHelper(UINT64 offset, SpanWriter& writer, bool extendedAttributes);
// This lock protects all state except:
// - Read access to m_File: once non-NULL, this member never becomes NULL
// again.
// - m_Root, m_Uid: these members don't change after initialization.
mutable std::shared_mutex m_Lock;
std::string m_FileName;
std::unique_ptr<DirectoryEnumerator> m_Enumerator;
wil::unique_fd m_File;
CoroutineIoIssuer m_Io;
const std::shared_ptr<const Root> m_Root;
Qid m_Qid{};
dev_t m_Device{};
};
} // namespace p9fs