mirror of https://github.com/microsoft/WSL
135 lines
5.1 KiB
C++
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
|