master
h 134 lines 5.11 KB
Raw
1 // Copyright (C) Microsoft Corporation. All rights reserved.
2 #pragma once
3
4 #include "p9io.h"
5 #include "p9fid.h"
6 #include "p9readdir.h"
7 #include <pwd.h>
8 #include <grp.h>
9
10 namespace p9fs {
11
12 struct Share
13 {
14 wil::unique_fd RootFd;
15 };
16
17 struct Root final : public IRoot
18 {
19 Root(std::shared_ptr<const Share> share, int rootFd, uid_t uid, gid_t gid) : Share{share}, RootFd{rootFd}, Uid{uid}, Gid{gid}
20 {
21 Plan9TraceLoggingProvider::LogMessage(std::format("Instantiate root, uid={}", uid));
22 if (uid == -1)
23 {
24 return; // No uid passed, don't try to get the additional groups.
25 }
26
27 auto bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
28 if (bufsize == -1)
29 {
30 bufsize = 16384; // Recommended by the man page if _SC_GETPW_R_SIZE_MAX is not set.
31 }
32
33 std::vector<char> buffer(bufsize);
34 passwd pwd{};
35 passwd* result = nullptr;
36 if (getpwuid_r(uid, &pwd, buffer.data(), buffer.size(), &result) != 0 || result == nullptr)
37 {
38 Plan9TraceLoggingProvider::LogMessage(std::format("getpwuid_r failed for uid: {}, errno={}", uid, errno));
39 return;
40 }
41
42 // Find the number of groups
43 int groupCount = 0;
44 getgrouplist(pwd.pw_name, gid, nullptr, &groupCount);
45 Groups.resize(groupCount);
46
47 // Query the groups
48 if (getgrouplist(pwd.pw_name, gid, Groups.data(), &groupCount) < 0)
49 {
50 Plan9TraceLoggingProvider::LogMessage(std::format("getgrouplist failed for user: {}, errno={}", pwd.pw_name, errno));
51 Groups.clear();
52 }
53 }
54
55 std::shared_ptr<const Share> Share;
56
57 int RootFd;
58
59 // The uid that the client attached with, and the associated primary gid.
60 // If these are -1, then no change is necessary.
61 uid_t Uid;
62 gid_t Gid;
63 std::vector<gid_t> Groups;
64
65 bool ReadOnly() const
66 {
67 return false;
68 }
69 };
70
71 class File final : public Fid
72 {
73 public:
74 File(std::shared_ptr<const Root> root);
75 File(const File&);
76
77 Expected<Qid> Initialize();
78 Expected<Qid> Walk(std::string_view Name) override;
79 Expected<std::tuple<UINT64, Qid, StatResult>> GetAttr(UINT64 Mask) override;
80 LX_INT SetAttr(UINT32 Valid, const StatResult& Stat) override;
81 Expected<Qid> Open(OpenFlags Flags) override;
82 Expected<Qid> Create(std::string_view Name, OpenFlags /* Flags */, UINT32 /* Mode */, UINT32 /* Gid */) override;
83 Expected<Qid> MkDir(std::string_view Name, UINT32 /* Mode */, UINT32 /* Gid */) override;
84 LX_INT ReadDir(UINT64 Offset, SpanWriter& writer, bool includeAttributes) override;
85 Task<Expected<UINT32>> Read(UINT64 Offset, gsl::span<gsl::byte> Buffer) override;
86 Task<Expected<UINT32>> Write(UINT64 Offset, gsl::span<const gsl::byte> Buffer) override;
87 LX_INT UnlinkAt(std::string_view Name, UINT32 /* Flags */) override;
88 LX_INT Remove() override;
89 LX_INT RenameAt(std::string_view OldName, Fid& NewParent, std::string_view NewName) override;
90 LX_INT Rename(Fid& NewParent, std::string_view NewName) override;
91 Expected<Qid> SymLink(std::string_view /* name */, std::string_view /* target */, UINT32 /* gid */) override;
92 Expected<Qid> MkNod(std::string_view /* name */, UINT32 /* mode */, UINT32 /* major */, UINT32 /* minor */, UINT32 /* gid */) override;
93 LX_INT Link(std::string_view /* name */, Fid& /* target */) override;
94 Expected<UINT32> ReadLink(gsl::span<char> /* name */) override;
95 LX_INT Fsync() override;
96 Expected<StatFsResult> StatFs() override;
97 Expected<LockStatus> Lock(LockType Type, UINT32 Flags, UINT64 Start, UINT64 Length, UINT32 ProcId, std::string_view ClientId) override;
98 Expected<std::tuple<LockType, UINT64, UINT64, UINT32, std::string_view>> GetLock(
99 LockType Type, UINT64 Start, UINT64 Length, UINT32 ProcId, std::string_view ClientId) override;
100 Expected<std::shared_ptr<XAttrBase>> XattrWalk(const std::string& Name) override;
101 Expected<std::shared_ptr<XAttrBase>> XattrCreate(const std::string& Name, UINT64 Size, UINT32 Flags) override;
102
103 // 9P2000.W operations
104 LX_INT Access(AccessFlags Flags) override;
105
106 std::shared_ptr<Fid> Clone() const override;
107 bool IsOnRoot(const std::shared_ptr<const IRoot>& root) override;
108 bool IsFile() const override;
109 Qid GetQid() const override;
110 bool IsOpen() const;
111
112 private:
113 Expected<wil::unique_fd> OpenFile(int openFlags);
114 LX_INT ValidateExists();
115 std::string GetFileName() const;
116 std::string ChildPath(std::string_view name);
117 std::string ChildPathWithLockHeld(std::string_view name);
118 Expected<struct stat> Stat();
119 LX_INT ReadDirHelper(UINT64 offset, SpanWriter& writer, bool extendedAttributes);
120
121 // This lock protects all state except:
122 // - Read access to m_File: once non-NULL, this member never becomes NULL
123 // again.
124 // - m_Root, m_Uid: these members don't change after initialization.
125 mutable std::shared_mutex m_Lock;
126 std::string m_FileName;
127 std::unique_ptr<DirectoryEnumerator> m_Enumerator;
128 wil::unique_fd m_File;
129 CoroutineIoIssuer m_Io;
130 const std::shared_ptr<const Root> m_Root;
131 Qid m_Qid{};
132 dev_t m_Device{};
133 };
134 } // namespace p9fs