@k13engineering/linux-fuse 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/abi.d.ts +331 -0
- package/dist/lib/abi.js +1019 -0
- package/dist/lib/constants.d.ts +225 -0
- package/dist/lib/constants.js +272 -0
- package/dist/lib/convenience.d.ts +63 -0
- package/dist/lib/convenience.js +463 -0
- package/dist/lib/fuse-lowlevel.d.ts +42 -0
- package/dist/lib/fuse-lowlevel.js +133 -0
- package/dist/lib/index.d.ts +40 -0
- package/dist/lib/index.js +313 -0
- package/dist/lib/linux.d.ts +12 -0
- package/dist/lib/linux.js +32 -0
- package/dist/lib/message.d.ts +50 -0
- package/dist/lib/message.js +177 -0
- package/dist/lib/mount.d.ts +33 -0
- package/dist/lib/mount.js +149 -0
- package/dist/lib/protocol.d.ts +756 -0
- package/dist/lib/protocol.js +3783 -0
- package/dist/lib/server.d.ts +18 -0
- package/dist/lib/server.js +73 -0
- package/dist/lib/syscalls.d.ts +73 -0
- package/dist/lib/syscalls.js +275 -0
- package/package.json +1 -1
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
/*import type { TFuseRequest, TFuseResponse } from "./protocol.ts";*/
|
|
2
|
+
/*import type { TRequestHandler } from "./server.ts";*/
|
|
3
|
+
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5
|
+
/*type DistributiveOmit<T, K extends PropertyKey> = T extends any ? Omit<T, K> : never;*/
|
|
6
|
+
|
|
7
|
+
/*type TConvenienceRequest<T extends string> = Extract<TFuseRequest, { opcode: T }>;*/
|
|
8
|
+
/*type TConvenienceResponse<T extends string> = DistributiveOmit<Extract<TFuseResponse, { forOpcode: T }>, "unique">;*/
|
|
9
|
+
|
|
10
|
+
/*type TFuseServerInterface = {
|
|
11
|
+
init: (req: TConvenienceRequest<"INIT">) => Promise<TConvenienceResponse<"INIT">>;
|
|
12
|
+
forget: (req: TConvenienceRequest<"FORGET">) => Promise<void>;
|
|
13
|
+
batchForget: (req: TConvenienceRequest<"BATCH_FORGET">) => Promise<void>;
|
|
14
|
+
getattr: (req: Extract<TConvenienceRequest<"GETATTR">, { getattrMode: "node" }>) => Promise<TConvenienceResponse<"GETATTR">>;
|
|
15
|
+
fgetattr: (req: Extract<TConvenienceRequest<"GETATTR">, { getattrMode: "fileHandle" }>) => Promise<TConvenienceResponse<"GETATTR">>;
|
|
16
|
+
setattr: (req: TConvenienceRequest<"SETATTR">) => Promise<TConvenienceResponse<"SETATTR">>;
|
|
17
|
+
listxattr: (req: TConvenienceRequest<"LISTXATTR">) => Promise<TConvenienceResponse<"LISTXATTR">>;
|
|
18
|
+
getxattr: (req: TConvenienceRequest<"GETXATTR">) => Promise<TConvenienceResponse<"GETXATTR">>;
|
|
19
|
+
readlink: (req: TConvenienceRequest<"READLINK">) => Promise<TConvenienceResponse<"READLINK">>;
|
|
20
|
+
symlink: (req: TConvenienceRequest<"SYMLINK">) => Promise<TConvenienceResponse<"SYMLINK">>;
|
|
21
|
+
mknod: (req: TConvenienceRequest<"MKNOD">) => Promise<TConvenienceResponse<"MKNOD">>;
|
|
22
|
+
mkdir: (req: TConvenienceRequest<"MKDIR">) => Promise<TConvenienceResponse<"MKDIR">>;
|
|
23
|
+
unlink: (req: TConvenienceRequest<"UNLINK">) => Promise<TConvenienceResponse<"UNLINK">>;
|
|
24
|
+
rmdir: (req: TConvenienceRequest<"RMDIR">) => Promise<TConvenienceResponse<"RMDIR">>;
|
|
25
|
+
rename: (req: TConvenienceRequest<"RENAME">) => Promise<TConvenienceResponse<"RENAME">>;
|
|
26
|
+
link: (req: TConvenienceRequest<"LINK">) => Promise<TConvenienceResponse<"LINK">>;
|
|
27
|
+
opendir: (req: TConvenienceRequest<"OPENDIR">) => Promise<TConvenienceResponse<"OPENDIR">>;
|
|
28
|
+
readdir: (req: TConvenienceRequest<"READDIR">) => Promise<TConvenienceResponse<"READDIR">>;
|
|
29
|
+
release: (req: TConvenienceRequest<"RELEASE">) => Promise<TConvenienceResponse<"RELEASE">>;
|
|
30
|
+
releasedir: (req: TConvenienceRequest<"RELEASEDIR">) => Promise<TConvenienceResponse<"RELEASEDIR">>;
|
|
31
|
+
fsyncdir: (req: TConvenienceRequest<"FSYNCDIR">) => Promise<TConvenienceResponse<"FSYNCDIR">>;
|
|
32
|
+
statfs: (req: TConvenienceRequest<"STATFS">) => Promise<TConvenienceResponse<"STATFS">>;
|
|
33
|
+
lookup: (req: TConvenienceRequest<"LOOKUP">) => Promise<TConvenienceResponse<"LOOKUP">>;
|
|
34
|
+
open: (req: TConvenienceRequest<"OPEN">) => Promise<TConvenienceResponse<"OPEN">>;
|
|
35
|
+
read: (req: TConvenienceRequest<"READ">) => Promise<TConvenienceResponse<"READ">>;
|
|
36
|
+
write: (req: TConvenienceRequest<"WRITE">) => Promise<TConvenienceResponse<"WRITE">>;
|
|
37
|
+
flush: (req: TConvenienceRequest<"FLUSH">) => Promise<TConvenienceResponse<"FLUSH">>;
|
|
38
|
+
fsync: (req: TConvenienceRequest<"FSYNC">) => Promise<TConvenienceResponse<"FSYNC">>;
|
|
39
|
+
access: (req: TConvenienceRequest<"ACCESS">) => Promise<TConvenienceResponse<"ACCESS">>;
|
|
40
|
+
setxattr: (req: TConvenienceRequest<"SETXATTR">) => Promise<TConvenienceResponse<"SETXATTR">>;
|
|
41
|
+
removexattr: (req: TConvenienceRequest<"REMOVEXATTR">) => Promise<TConvenienceResponse<"REMOVEXATTR">>;
|
|
42
|
+
create: (req: TConvenienceRequest<"CREATE">) => Promise<TConvenienceResponse<"CREATE">>;
|
|
43
|
+
destroy: (req: TConvenienceRequest<"DESTROY">) => Promise<TConvenienceResponse<"DESTROY">>;
|
|
44
|
+
getlk: (req: TConvenienceRequest<"GETLK">) => Promise<TConvenienceResponse<"GETLK">>;
|
|
45
|
+
setlk: (req: TConvenienceRequest<"SETLK">) => Promise<TConvenienceResponse<"SETLK">>;
|
|
46
|
+
setlkw: (req: TConvenienceRequest<"SETLKW">) => Promise<TConvenienceResponse<"SETLKW">>;
|
|
47
|
+
interrupt: (req: TConvenienceRequest<"INTERRUPT">) => Promise<void>;
|
|
48
|
+
bmap: (req: TConvenienceRequest<"BMAP">) => Promise<TConvenienceResponse<"BMAP">>;
|
|
49
|
+
ioctl: (req: TConvenienceRequest<"IOCTL">) => Promise<TConvenienceResponse<"IOCTL">>;
|
|
50
|
+
poll: (req: TConvenienceRequest<"POLL">) => Promise<TConvenienceResponse<"POLL">>;
|
|
51
|
+
notifyReply: (req: TConvenienceRequest<"NOTIFY_REPLY">) => Promise<void>;
|
|
52
|
+
fallocate: (req: TConvenienceRequest<"FALLOCATE">) => Promise<TConvenienceResponse<"FALLOCATE">>;
|
|
53
|
+
readdirplus: (req: TConvenienceRequest<"READDIRPLUS">) => Promise<TConvenienceResponse<"READDIRPLUS">>;
|
|
54
|
+
};*/
|
|
55
|
+
|
|
56
|
+
const createConvenienceRequestHandler = ({
|
|
57
|
+
serverInterface
|
|
58
|
+
}/*: {
|
|
59
|
+
serverInterface: TFuseServerInterface
|
|
60
|
+
}*/)/*: TRequestHandler*/ => {
|
|
61
|
+
// eslint-disable-next-line max-statements, complexity
|
|
62
|
+
const handleRequest/*: TRequestHandler["handleRequest"]*/ = async ({ request }) => {
|
|
63
|
+
switch (request.opcode) {
|
|
64
|
+
case "INIT": {
|
|
65
|
+
const response = await serverInterface.init(request);
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
...response,
|
|
69
|
+
unique: request.unique,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
case "FORGET": {
|
|
74
|
+
await serverInterface.forget(request);
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
case "BATCH_FORGET": {
|
|
79
|
+
await serverInterface.batchForget(request);
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
case "GETATTR": {
|
|
84
|
+
|
|
85
|
+
switch (request.getattrMode) {
|
|
86
|
+
case "node": {
|
|
87
|
+
const response = await serverInterface.getattr(request);
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
...response,
|
|
91
|
+
unique: request.unique,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
case "fileHandle": {
|
|
96
|
+
const response = await serverInterface.fgetattr(request);
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
...response,
|
|
100
|
+
unique: request.unique,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
default: {
|
|
105
|
+
// @ts-expect-error exhaustive check
|
|
106
|
+
throw Error(`unsupported getattr mode: ${request.getattrMode}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
case "SETATTR": {
|
|
112
|
+
const response = await serverInterface.setattr(request);
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
...response,
|
|
116
|
+
unique: request.unique,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
case "LISTXATTR": {
|
|
121
|
+
const response = await serverInterface.listxattr(request);
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
...response,
|
|
125
|
+
unique: request.unique,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
case "GETXATTR": {
|
|
130
|
+
const response = await serverInterface.getxattr(request);
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
...response,
|
|
134
|
+
unique: request.unique,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
case "READLINK": {
|
|
139
|
+
const response = await serverInterface.readlink(request);
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
...response,
|
|
143
|
+
unique: request.unique,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
case "SYMLINK": {
|
|
148
|
+
const response = await serverInterface.symlink(request);
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
...response,
|
|
152
|
+
unique: request.unique,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
case "MKNOD": {
|
|
157
|
+
const response = await serverInterface.mknod(request);
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
...response,
|
|
161
|
+
unique: request.unique,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
case "MKDIR": {
|
|
166
|
+
const response = await serverInterface.mkdir(request);
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
...response,
|
|
170
|
+
unique: request.unique,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
case "UNLINK": {
|
|
175
|
+
const response = await serverInterface.unlink(request);
|
|
176
|
+
|
|
177
|
+
return {
|
|
178
|
+
...response,
|
|
179
|
+
unique: request.unique,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
case "RMDIR": {
|
|
184
|
+
const response = await serverInterface.rmdir(request);
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
...response,
|
|
188
|
+
unique: request.unique,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
case "RENAME": {
|
|
193
|
+
const response = await serverInterface.rename(request);
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
...response,
|
|
197
|
+
unique: request.unique,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
case "LINK": {
|
|
202
|
+
const response = await serverInterface.link(request);
|
|
203
|
+
|
|
204
|
+
return {
|
|
205
|
+
...response,
|
|
206
|
+
unique: request.unique,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
case "OPENDIR": {
|
|
211
|
+
const response = await serverInterface.opendir(request);
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
...response,
|
|
215
|
+
unique: request.unique,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
case "READDIR": {
|
|
220
|
+
const response = await serverInterface.readdir(request);
|
|
221
|
+
|
|
222
|
+
return {
|
|
223
|
+
...response,
|
|
224
|
+
unique: request.unique,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
case "RELEASE": {
|
|
229
|
+
const response = await serverInterface.release(request);
|
|
230
|
+
|
|
231
|
+
return {
|
|
232
|
+
...response,
|
|
233
|
+
unique: request.unique,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
case "RELEASEDIR": {
|
|
238
|
+
const response = await serverInterface.releasedir(request);
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
...response,
|
|
242
|
+
unique: request.unique,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
case "FSYNCDIR": {
|
|
247
|
+
const response = await serverInterface.fsyncdir(request);
|
|
248
|
+
|
|
249
|
+
return {
|
|
250
|
+
...response,
|
|
251
|
+
unique: request.unique,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
case "STATFS": {
|
|
256
|
+
const response = await serverInterface.statfs(request);
|
|
257
|
+
|
|
258
|
+
return {
|
|
259
|
+
...response,
|
|
260
|
+
unique: request.unique,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
case "LOOKUP": {
|
|
265
|
+
const response = await serverInterface.lookup(request);
|
|
266
|
+
|
|
267
|
+
return {
|
|
268
|
+
...response,
|
|
269
|
+
unique: request.unique,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
case "OPEN": {
|
|
274
|
+
const response = await serverInterface.open(request);
|
|
275
|
+
|
|
276
|
+
return {
|
|
277
|
+
...response,
|
|
278
|
+
unique: request.unique,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
case "READ": {
|
|
283
|
+
const response = await serverInterface.read(request);
|
|
284
|
+
|
|
285
|
+
return {
|
|
286
|
+
...response,
|
|
287
|
+
unique: request.unique,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
case "WRITE": {
|
|
292
|
+
const response = await serverInterface.write(request);
|
|
293
|
+
|
|
294
|
+
return {
|
|
295
|
+
...response,
|
|
296
|
+
unique: request.unique,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
case "FLUSH": {
|
|
301
|
+
const response = await serverInterface.flush(request);
|
|
302
|
+
|
|
303
|
+
return {
|
|
304
|
+
...response,
|
|
305
|
+
unique: request.unique,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
case "FSYNC": {
|
|
310
|
+
const response = await serverInterface.fsync(request);
|
|
311
|
+
|
|
312
|
+
return {
|
|
313
|
+
...response,
|
|
314
|
+
unique: request.unique,
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
case "ACCESS": {
|
|
319
|
+
const response = await serverInterface.access(request);
|
|
320
|
+
|
|
321
|
+
return {
|
|
322
|
+
...response,
|
|
323
|
+
unique: request.unique,
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
case "SETXATTR": {
|
|
328
|
+
const response = await serverInterface.setxattr(request);
|
|
329
|
+
|
|
330
|
+
return {
|
|
331
|
+
...response,
|
|
332
|
+
unique: request.unique,
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
case "REMOVEXATTR": {
|
|
337
|
+
const response = await serverInterface.removexattr(request);
|
|
338
|
+
|
|
339
|
+
return {
|
|
340
|
+
...response,
|
|
341
|
+
unique: request.unique,
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
case "CREATE": {
|
|
346
|
+
const response = await serverInterface.create(request);
|
|
347
|
+
|
|
348
|
+
return {
|
|
349
|
+
...response,
|
|
350
|
+
unique: request.unique,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
case "DESTROY": {
|
|
355
|
+
const response = await serverInterface.destroy(request);
|
|
356
|
+
|
|
357
|
+
return {
|
|
358
|
+
...response,
|
|
359
|
+
unique: request.unique,
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
case "GETLK": {
|
|
364
|
+
const response = await serverInterface.getlk(request);
|
|
365
|
+
|
|
366
|
+
return {
|
|
367
|
+
...response,
|
|
368
|
+
unique: request.unique,
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
case "SETLK": {
|
|
373
|
+
const response = await serverInterface.setlk(request);
|
|
374
|
+
|
|
375
|
+
return {
|
|
376
|
+
...response,
|
|
377
|
+
unique: request.unique,
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
case "SETLKW": {
|
|
382
|
+
const response = await serverInterface.setlkw(request);
|
|
383
|
+
|
|
384
|
+
return {
|
|
385
|
+
...response,
|
|
386
|
+
unique: request.unique,
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
case "INTERRUPT": {
|
|
391
|
+
await serverInterface.interrupt(request);
|
|
392
|
+
return undefined;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
case "BMAP": {
|
|
396
|
+
const response = await serverInterface.bmap(request);
|
|
397
|
+
|
|
398
|
+
return {
|
|
399
|
+
...response,
|
|
400
|
+
unique: request.unique,
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
case "IOCTL": {
|
|
405
|
+
const response = await serverInterface.ioctl(request);
|
|
406
|
+
|
|
407
|
+
return {
|
|
408
|
+
...response,
|
|
409
|
+
unique: request.unique,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
case "POLL": {
|
|
414
|
+
const response = await serverInterface.poll(request);
|
|
415
|
+
|
|
416
|
+
return {
|
|
417
|
+
...response,
|
|
418
|
+
unique: request.unique,
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
case "NOTIFY_REPLY": {
|
|
423
|
+
await serverInterface.notifyReply(request);
|
|
424
|
+
return undefined;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
case "FALLOCATE": {
|
|
428
|
+
const response = await serverInterface.fallocate(request);
|
|
429
|
+
|
|
430
|
+
return {
|
|
431
|
+
...response,
|
|
432
|
+
unique: request.unique,
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
case "READDIRPLUS": {
|
|
437
|
+
const response = await serverInterface.readdirplus(request);
|
|
438
|
+
|
|
439
|
+
return {
|
|
440
|
+
...response,
|
|
441
|
+
unique: request.unique,
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
default: {
|
|
446
|
+
// @ts-expect-error exhaustive check
|
|
447
|
+
throw Error(`unsupported opcode: ${request.opcode}`);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
return {
|
|
453
|
+
handleRequest
|
|
454
|
+
};
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
export {
|
|
458
|
+
createConvenienceRequestHandler
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
/*export type {
|
|
462
|
+
TFuseServerInterface,
|
|
463
|
+
};*/
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
type TIncomingRequest = {
|
|
2
|
+
header: {
|
|
3
|
+
opcode: bigint;
|
|
4
|
+
unique: bigint;
|
|
5
|
+
nodeid: bigint;
|
|
6
|
+
uid: bigint;
|
|
7
|
+
gid: bigint;
|
|
8
|
+
pid: bigint;
|
|
9
|
+
};
|
|
10
|
+
payload: Uint8Array;
|
|
11
|
+
};
|
|
12
|
+
type TOutgoingResponse = {
|
|
13
|
+
header: {
|
|
14
|
+
error: bigint;
|
|
15
|
+
unique: bigint;
|
|
16
|
+
};
|
|
17
|
+
payload: Uint8Array;
|
|
18
|
+
};
|
|
19
|
+
type TTryReadIncomingMessageResult = {
|
|
20
|
+
error: Error;
|
|
21
|
+
incomingMessage: undefined;
|
|
22
|
+
end: undefined;
|
|
23
|
+
} | {
|
|
24
|
+
error: undefined;
|
|
25
|
+
incomingMessage: Uint8Array;
|
|
26
|
+
end: false;
|
|
27
|
+
} | {
|
|
28
|
+
error: undefined;
|
|
29
|
+
incomingMessage: undefined;
|
|
30
|
+
end: false | true;
|
|
31
|
+
};
|
|
32
|
+
declare const createFuseLowLevel: ({ fuseFd, maxMessageSize }: {
|
|
33
|
+
fuseFd: number;
|
|
34
|
+
maxMessageSize: number;
|
|
35
|
+
}) => {
|
|
36
|
+
tryReadIncomingMessage: () => TTryReadIncomingMessageResult;
|
|
37
|
+
writeOutgoingMessage: ({ rawMessage }: {
|
|
38
|
+
rawMessage: Uint8Array;
|
|
39
|
+
}) => void;
|
|
40
|
+
};
|
|
41
|
+
export { createFuseLowLevel };
|
|
42
|
+
export type { TIncomingRequest, TOutgoingResponse };
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { read, write } from "./syscalls.js";
|
|
2
|
+
|
|
3
|
+
/*type TIncomingRequest = {
|
|
4
|
+
header: {
|
|
5
|
+
opcode: bigint;
|
|
6
|
+
unique: bigint;
|
|
7
|
+
nodeid: bigint;
|
|
8
|
+
uid: bigint;
|
|
9
|
+
gid: bigint;
|
|
10
|
+
pid: bigint;
|
|
11
|
+
},
|
|
12
|
+
payload: Uint8Array
|
|
13
|
+
};*/
|
|
14
|
+
|
|
15
|
+
/*type TOutgoingResponse = {
|
|
16
|
+
header: {
|
|
17
|
+
error: bigint;
|
|
18
|
+
unique: bigint;
|
|
19
|
+
},
|
|
20
|
+
payload: Uint8Array
|
|
21
|
+
};*/
|
|
22
|
+
|
|
23
|
+
/*type TTryReadIncomingMessageResult = {
|
|
24
|
+
error: Error;
|
|
25
|
+
incomingMessage: undefined;
|
|
26
|
+
end: undefined;
|
|
27
|
+
} | {
|
|
28
|
+
error: undefined;
|
|
29
|
+
incomingMessage: Uint8Array;
|
|
30
|
+
end: false;
|
|
31
|
+
} | {
|
|
32
|
+
error: undefined;
|
|
33
|
+
incomingMessage: undefined;
|
|
34
|
+
end: false | true;
|
|
35
|
+
};*/
|
|
36
|
+
|
|
37
|
+
const EPERM = 1;
|
|
38
|
+
const EAGAIN = 11;
|
|
39
|
+
const ENODEV = 19;
|
|
40
|
+
|
|
41
|
+
const createFuseLowLevel = ({
|
|
42
|
+
fuseFd,
|
|
43
|
+
maxMessageSize
|
|
44
|
+
}/*: {
|
|
45
|
+
fuseFd: number;
|
|
46
|
+
maxMessageSize: number;
|
|
47
|
+
}*/) => {
|
|
48
|
+
|
|
49
|
+
const incomingBuffer = new Uint8Array(maxMessageSize);
|
|
50
|
+
|
|
51
|
+
// eslint-disable-next-line complexity
|
|
52
|
+
const tryReadIncomingMessage = ()/*: TTryReadIncomingMessageResult*/ => {
|
|
53
|
+
|
|
54
|
+
const { errno, ret } = read({
|
|
55
|
+
fd: fuseFd,
|
|
56
|
+
buffer: incomingBuffer
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
if (errno !== undefined) {
|
|
60
|
+
|
|
61
|
+
if (errno === EPERM) {
|
|
62
|
+
|
|
63
|
+
// most likely the filesystem hasn't been mounted yet
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
error: undefined,
|
|
67
|
+
incomingMessage: undefined,
|
|
68
|
+
end: false
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (errno === EAGAIN) {
|
|
73
|
+
// no message to read
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
error: undefined,
|
|
77
|
+
incomingMessage: undefined,
|
|
78
|
+
end: false
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (errno === ENODEV) {
|
|
83
|
+
// the filesystem has been unmounted
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
error: undefined,
|
|
87
|
+
incomingMessage: undefined,
|
|
88
|
+
end: true
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
throw Error(`errno ${errno} not implemented yet`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const incomingMessage = incomingBuffer.slice(0, Number(ret));
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
error: undefined,
|
|
99
|
+
incomingMessage,
|
|
100
|
+
end: false
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const writeOutgoingMessage = ({ rawMessage }/*: { rawMessage: Uint8Array }*/) => {
|
|
105
|
+
|
|
106
|
+
const { errno, ret } = write({
|
|
107
|
+
fd: fuseFd,
|
|
108
|
+
buffer: rawMessage
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
if (errno !== undefined) {
|
|
112
|
+
throw Error(`write syscall failed with errno ${errno}`);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (ret !== BigInt(rawMessage.length)) {
|
|
116
|
+
throw Error(`short write not supported yet`);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
tryReadIncomingMessage,
|
|
122
|
+
writeOutgoingMessage,
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export {
|
|
127
|
+
createFuseLowLevel
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/*export type {
|
|
131
|
+
TIncomingRequest,
|
|
132
|
+
TOutgoingResponse
|
|
133
|
+
};*/
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type TRequestHandler } from "./server.js";
|
|
2
|
+
import { openFuseFd, defaultFusePath } from "./linux.js";
|
|
3
|
+
import { createConvenienceRequestHandler } from "./convenience.js";
|
|
4
|
+
import { moveMount, unmount, type TMountAttributes, type TRequiredFuseMountOptions } from "./mount.js";
|
|
5
|
+
import type { TFuseResponse } from "./protocol.js";
|
|
6
|
+
declare const createFuseFileSystem: ({ fuseFd, requestHandler, sniff, }: {
|
|
7
|
+
fuseFd: number;
|
|
8
|
+
requestHandler: TRequestHandler;
|
|
9
|
+
sniff?: {
|
|
10
|
+
rawMessageFromKernel: (args: {
|
|
11
|
+
data: Uint8Array;
|
|
12
|
+
}) => void;
|
|
13
|
+
rawMessageToKernel: (args: {
|
|
14
|
+
data: Uint8Array;
|
|
15
|
+
}) => void;
|
|
16
|
+
};
|
|
17
|
+
}) => {
|
|
18
|
+
mountDetached: ({ otherOptions, requiredOptions, mountAttributes, }: {
|
|
19
|
+
otherOptions: {
|
|
20
|
+
default_permissions?: boolean;
|
|
21
|
+
allow_other?: boolean;
|
|
22
|
+
allow_root?: boolean;
|
|
23
|
+
} | Record<string, string | boolean>;
|
|
24
|
+
requiredOptions: TRequiredFuseMountOptions;
|
|
25
|
+
mountAttributes: TMountAttributes;
|
|
26
|
+
}) => {
|
|
27
|
+
error: Error;
|
|
28
|
+
mountFd: undefined;
|
|
29
|
+
} | {
|
|
30
|
+
error: undefined;
|
|
31
|
+
mountFd: number;
|
|
32
|
+
};
|
|
33
|
+
close: () => void;
|
|
34
|
+
};
|
|
35
|
+
declare const createDefaultInitResult: () => Extract<TFuseResponse, {
|
|
36
|
+
forOpcode: "INIT";
|
|
37
|
+
errorCode: undefined;
|
|
38
|
+
}>["result"];
|
|
39
|
+
export { createFuseFileSystem, openFuseFd, defaultFusePath, createConvenienceRequestHandler, moveMount, unmount, createDefaultInitResult };
|
|
40
|
+
export type { TRequiredFuseMountOptions, TMountAttributes, };
|