1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
/*
TODO:
- add arguments to methods
- switch from returned strings to exceptions
*/
/**
* The [ProtocolTranslator] interface provides methods that coincide 1:1 with each request type in the 9P protocol.
* Every method that can fail, that is, every request that can receive a response with `Rerror` type instead of the same
* type as itself, returns a non-null `String` that contains the error message received in the response.
*
* Tags and the `msize` value are supposed to be managed internally by the implementing class.
*
* When compared to 9P's formal message descriptions, like those which can be read in Plan 9's manual pages, some of the
* methods might lack parameters. Those which can be inferred from the existing parameters are purposefully omitted. An
* example is [walk], which omits `nwname` because it can be obtained by calculating the size of `wname`.
*
* Trivia: comments for each method are taken from each message type's manual page in section 5.
*/
interface ProtocolTranslator {
/**
* Negotiate protocol version.
*
* This must be the first message sent on the 9P connection and no other requests can be issued until a response has
* been received.
*
* @param msize The maximum length, in bytes, that the client will ever generate or expect to receive in a single
* 9P message.
* @param version Should be "9P2000", which is the only defined value.
* @throws except.InvalidMessageException if the received message is invalid.
* @throws except.RErrorException if the received message is an R-error message.
* @throws except.MsizeValueTooBigException if the received `msize` value is bigger than what the client requested.
* @throws except.UnknownVersionException if the version negotiation failed.
*/
fun version(msize: UInt, version: String)
/**
* Perform authentication.
*/
fun auth(afid: UInt, uname: String, aname: String)
/**
* Abort a message.
*
* @param oldtag The tag of the message that needs to be purged.
* @throws except.InvalidMessageException if the received message is invalid.
* @throws except.RErrorException if the received message is an R-error message.
*/
fun flush(oldtag: UShort)
/**
* Establish a connection.
*
* @param fid FID that represents the root directory of the desired file tree.
* @param afid A FID previously established by an auth message.
* @param uname A user identifier.
* @param aname The desired file tree to access.
* @return The QID of the file tree's root.
* @throws except.InvalidMessageException if the received message is invalid.
* @throws except.RErrorException if the received message is an R-error message.
*/
fun attach(fid: UInt, afid: UInt, uname: String, aname: String): QID
/**
* Descend a directory hierarchy.
*
* @param fid The existing FID. It must represent a directory.
* @param newfid The proposed FID, which is going to be associated with the result of walking the hierarchy. It must
* be not in use, unless it is the same as [fid].
* @param wname The successive path name elements which describe the file to walk to.
* @return The QID of each path element that has been walked through.
* @throws except.InvalidMessageException if the received message is invalid.
* @throws except.RErrorException if the received message is an R-error message.
* @throws except.UnaccessibleFileException if [wname] contains one or more path elements that do not exist.
*/
fun walk(fid: UInt, newfid: UInt, wname: List<String>): List<QID>
/**
* Prepare an FID for I/O on an existing file.
*
* @param fid The FID of the file to open.
* @param mode The mode in which the file is opened.
* @return A pair of: (1) the returned QID, and (2) a value called `iounit` that indicates, if non-zero, the maximum
* number of bytes that are guaranteed to be read from or written to the file without breaking the I/O transfer into
* multiple 9P messages.
* @throws except.InvalidMessageException if the received message is invalid.
* @throws except.RErrorException if the received message is an R-error message.
*/
fun open(fid: UInt, mode: FileMode): Pair<QID, UInt>
/**
* Prepare an FID for I/O on a new file.
*
* @param fid The FID of the directory that is going to contain the file. The specified directory requires write
* permission.
* @param name The file name.
* @param perm The permissions of the new file.
* @param mode The open mode after successful creation.
* @return A pair of: (1) the QID of the newly created file, and (2) a value called `iounit` that indicates, if
* non-zero, the maximum number of bytes that are guaranteed to be read from or written to the file without breaking
* the I/O transfer into multiple 9P messages.
* @throws except.InvalidMessageException if the received message is invalid.
* @throws except.RErrorException if the received message is an R-error message.
*/
fun create(fid: UInt, name: String, perm: FilePermissions, mode: FileMode): Pair<QID, UInt>
/**
* Transfer data from file. Due to the negotiated maximum size of 9P messages, called `msize`, one is supposed to
* call this method multiple times, unless the content is smaller than `msize`.
*
* @return The content read with the call just made.
* @throws except.InvalidMessageException if the received message is invalid.
* @throws except.RErrorException if the received message is an R-error message.
*/
fun read(fid: UInt, offset: ULong, count: UInt): Array<UByte>
/**
* Transfer data to file. Due to the negotiated maximum size of 9P messages, called `msize`, this method is supposed
* to be called multiple times, unless the content is smaller than `msize`.
*
* @param fid The FID to write to.
* @param offset The distance between the beginning of the file and the first written byte.
* @param data The raw bytes that are going to be written.
* @return The amount of bytes written with the call just made.
* @throws except.InvalidMessageException if the received message is invalid.
* @throws except.RErrorException if the received message is an R-error message.
*/
fun write(fid: UInt, offset: ULong, count: UInt, data: Iterable<UByte>): UInt
/**
* Forget about a FID.
*
* @param fid The FID to forget.
* @throws except.InvalidMessageException if the received message is invalid.
* @throws except.RErrorException if the received message is an R-error message.
*/
fun clunk(fid: UInt)
/**
* Remove a file from a server.
*
* @param fid The FID of the file to remove.
* @throws except.InvalidMessageException if the received message is invalid.
* @throws except.RErrorException if the received message is an R-error message.
*/
fun remove(fid: UInt)
/**
* Inquire file attributes.
*
* @param fid The FID of the file to inquire.
* @return All the file attributes of the file associated with [fid].
* @throws except.InvalidMessageException if the received message is invalid.
* @throws except.RErrorException if the received message is an R-error message.
*/
fun stat(fid: UInt): Stat
/**
* Change file attributes.
*
* @param fid The FID of the file to set attributes of.
* @param stat The attributes to set.
* @throws except.InvalidMessageException if the received message is invalid.
* @throws except.RErrorException if the received message is an R-error message.
*/
fun wstat(fid: UInt, stat: Stat)
}
|