Serenity Operating System
1/*
2 * Copyright (c) 2020, Sergey Bugaev <bugaevc@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#pragma once
8
9#include <AK/Types.h>
10#include <Kernel/FileSystem/Plan9FS/Definitions.h>
11#include <Kernel/KBuffer.h>
12#include <Kernel/KBufferBuilder.h>
13
14namespace Kernel {
15
16class Plan9FS;
17class Plan9FSInode;
18
19class Plan9FSMessage {
20 friend class Plan9FS;
21 friend class Plan9FSInode;
22
23public:
24 enum class Type : u8 {
25 // 9P2000.L
26 Tlerror = 6,
27 Rlerror = 7,
28 Tstatfs = 8,
29 Rstatfs = 9,
30
31 Tlopen = 12,
32 Rlopen = 13,
33 Tlcreate = 14,
34 Rlcreate = 15,
35 Tsymlink = 16,
36 Rsymlink = 17,
37 Tmknod = 18,
38 Rmknod = 19,
39 Trename = 20,
40 Rrename = 21,
41 Treadlink = 22,
42 Rreadlink = 23,
43 Tgetattr = 24,
44 Rgetattr = 25,
45 Tsetattr = 26,
46 Rsetattr = 27,
47
48 Txattrwalk = 30,
49 Rxattrwalk = 31,
50 Txattrcreate = 32,
51 Rxattrcreate = 33,
52
53 Treaddir = 40,
54 Rreaddir = 41,
55
56 Tfsync = 50,
57 Rfsync = 51,
58 Tlock = 52,
59 Rlock = 53,
60 Tgetlock = 54,
61 Rgetlock = 55,
62
63 Tlink = 70,
64 Rlink = 71,
65 Tmkdir = 72,
66 Rmkdir = 73,
67 Trenameat = 74,
68 Rrenameat = 75,
69 Tunlinkat = 76,
70 Runlinkat = 77,
71
72 // 9P2000
73 Tversion = 100,
74 Rversion = 101,
75 Tauth = 102,
76 Rauth = 103,
77 Tattach = 104,
78 Rattach = 105,
79 Terror = 106,
80 Rerror = 107,
81 Tflush = 108,
82 Rflush = 109,
83 Twalk = 110,
84 Rwalk = 111,
85 Topen = 112,
86 Ropen = 113,
87 Tcreate = 114,
88 Rcreate = 115,
89 Tread = 116,
90 Rread = 117,
91 Twrite = 118,
92 Rwrite = 119,
93 Tclunk = 120,
94 Rclunk = 121,
95 Tremove = 122,
96 Rremove = 123,
97 Tstat = 124,
98 Rstat = 125,
99 Twstat = 126,
100 Rwstat = 127
101 };
102
103 class Decoder {
104 public:
105 explicit Decoder(StringView data)
106 : m_data(data)
107 {
108 }
109
110 Decoder& operator>>(u8&);
111 Decoder& operator>>(u16&);
112 Decoder& operator>>(u32&);
113 Decoder& operator>>(u64&);
114 Decoder& operator>>(StringView&);
115 Decoder& operator>>(Plan9FSQIdentifier&);
116 StringView read_data();
117
118 bool has_more_data() const { return !m_data.is_empty(); }
119
120 private:
121 StringView m_data;
122
123 template<typename N>
124 Decoder& read_number(N& number)
125 {
126 VERIFY(sizeof(number) <= m_data.length());
127 memcpy(&number, m_data.characters_without_null_termination(), sizeof(number));
128 m_data = m_data.substring_view(sizeof(number), m_data.length() - sizeof(number));
129 return *this;
130 }
131 };
132
133 Plan9FSMessage& operator<<(u8);
134 Plan9FSMessage& operator<<(u16);
135 Plan9FSMessage& operator<<(u32);
136 Plan9FSMessage& operator<<(u64);
137 Plan9FSMessage& operator<<(StringView);
138 ErrorOr<void> append_data(StringView);
139
140 template<typename T>
141 Plan9FSMessage& operator>>(T& t)
142 {
143 VERIFY(m_have_been_built);
144 m_built.decoder >> t;
145 return *this;
146 }
147
148 StringView read_data()
149 {
150 VERIFY(m_have_been_built);
151 return m_built.decoder.read_data();
152 }
153
154 Type type() const { return m_type; }
155 u16 tag() const { return m_tag; }
156
157 Plan9FSMessage(Plan9FS&, Type);
158 Plan9FSMessage(NonnullOwnPtr<KBuffer>&&);
159 ~Plan9FSMessage();
160 Plan9FSMessage& operator=(Plan9FSMessage&&);
161
162 KBuffer const& build();
163
164 static constexpr size_t max_header_size = 24;
165
166private:
167 template<typename N>
168 Plan9FSMessage& append_number(N number)
169 {
170 VERIFY(!m_have_been_built);
171 // FIXME: Handle append failure.
172 (void)m_builder.append(reinterpret_cast<char const*>(&number), sizeof(number));
173 return *this;
174 }
175
176 union {
177 KBufferBuilder m_builder;
178 struct {
179 NonnullOwnPtr<KBuffer> buffer;
180 Decoder decoder;
181 } m_built;
182 };
183
184 u16 m_tag { 0 };
185 Type m_type { 0 };
186 bool m_have_been_built { false };
187};
188
189}