@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.
@@ -0,0 +1,3783 @@
1
+ /* eslint-disable max-statements, complexity */
2
+
3
+ import {
4
+ decodeCString,
5
+ decodeCStringPair,
6
+ fuseAccessInParser,
7
+ fuseAttrOutParser,
8
+ fuseBatchForgetInParser,
9
+ fuseBmapInParser,
10
+ fuseBmapOutParser,
11
+ fuseCreateInParser,
12
+ fuseEntryOutParser,
13
+ fuseFallocateInParser,
14
+ fuseFsyncInParser,
15
+ fuseFlushInParser,
16
+ fuseForgetInParser,
17
+ fuseForgetOneParser,
18
+ fuseGetattrInParser,
19
+ fuseGetxattrInParser,
20
+ fuseGetxattrOutParser,
21
+ fuseInitInParser,
22
+ fuseInitOutParser,
23
+ fuseInterruptInParser,
24
+ fuseIoctlInParser,
25
+ fuseIoctlOutParser,
26
+ fuseLinkInParser,
27
+ fuseLkInParser,
28
+ fuseLkOutParser,
29
+ fuseMkdirInParser,
30
+ fuseMknodInParser,
31
+ fuseOpenInParser,
32
+ fuseOpenOutParser,
33
+ fusePollInParser,
34
+ fusePollOutParser,
35
+ fuseReadInParser,
36
+ fuseReleaseInParser,
37
+ fuseRename2InParser,
38
+ fuseRenameInParser,
39
+ fuseSetattrInParser,
40
+ fuseSetxattrInParser,
41
+ fuseStatfsOutParser,
42
+ fuseWriteInParser,
43
+ fuseWriteOutParser,
44
+ } from "./abi.js";
45
+ import { FOPEN_DIRECT_IO, FOPEN_KEEP_CACHE, FOPEN_NONSEEKABLE, FUSE_GETATTR_FH, opcode } from "./constants.js";
46
+ /*import type { TParsedMessageFromKernel, TParsedMessageToKernel } from "./message.ts";*/
47
+
48
+ /*type TRequesterInfo = {
49
+ uid: bigint;
50
+ gid: bigint;
51
+ pid: bigint;
52
+ };*/
53
+
54
+ /*type TOpenFlagsToKernel = {
55
+ directIo: boolean;
56
+ keepCache: boolean;
57
+ nonSeekable: boolean;
58
+ };*/
59
+
60
+ /*type TFuseAttr = {
61
+ ino: bigint;
62
+ mode: bigint;
63
+ nlink: bigint;
64
+ uid: bigint;
65
+ gid: bigint;
66
+ rdev: bigint;
67
+ size: bigint;
68
+ blksize: bigint;
69
+ blocks: bigint;
70
+ atimeNsec: bigint;
71
+ mtimeNsec: bigint;
72
+ ctimeNsec: bigint;
73
+ };*/
74
+
75
+ /*type TFuseEntry = {
76
+ nodeId: bigint;
77
+ generation: bigint;
78
+ entryValidNsec: bigint;
79
+ attrValidNsec: bigint;
80
+ attr: TFuseAttr;
81
+ };*/
82
+
83
+ /*type TFuseXAttrResult = {
84
+ data: Uint8Array;
85
+ } | {
86
+ size: bigint;
87
+ };*/
88
+
89
+ /*type TFuseRequest = {
90
+ unique: bigint;
91
+ requester: TRequesterInfo;
92
+ } & ({
93
+ opcode: "INIT";
94
+ major: bigint;
95
+ minor: bigint;
96
+ } | {
97
+ opcode: "FORGET";
98
+ nodeId: bigint;
99
+ lookupCount: bigint;
100
+ } | {
101
+ opcode: "BATCH_FORGET";
102
+ forgets: Array<{
103
+ nodeId: bigint;
104
+ lookupCount: bigint;
105
+ }>;
106
+ } | {
107
+ opcode: "GETATTR";
108
+ getattrMode: "node";
109
+ nodeId: bigint;
110
+ } | {
111
+ opcode: "GETATTR";
112
+ getattrMode: "fileHandle";
113
+ fh: bigint;
114
+ } | {
115
+ opcode: "LISTXATTR";
116
+ nodeId: bigint;
117
+ size: bigint;
118
+ } | {
119
+ opcode: "GETXATTR";
120
+ nodeId: bigint;
121
+ size: bigint;
122
+ name: string;
123
+ } | {
124
+ opcode: "SETATTR";
125
+ nodeId: bigint;
126
+ valid: bigint;
127
+ fh: bigint;
128
+ size: bigint;
129
+ lockOwner: bigint;
130
+ atimeNsec: bigint;
131
+ mtimeNsec: bigint;
132
+ ctimeNsec: bigint;
133
+ mode: bigint;
134
+ uid: bigint;
135
+ gid: bigint;
136
+ } | {
137
+ opcode: "READLINK";
138
+ nodeId: bigint;
139
+ } | {
140
+ opcode: "SYMLINK";
141
+ parentNodeId: bigint;
142
+ name: string;
143
+ target: string;
144
+ } | {
145
+ opcode: "MKNOD";
146
+ parentNodeId: bigint;
147
+ name: string;
148
+ mode: bigint;
149
+ rdev: bigint;
150
+ umask: bigint;
151
+ } | {
152
+ opcode: "MKDIR";
153
+ parentNodeId: bigint;
154
+ name: string;
155
+ mode: bigint;
156
+ umask: bigint;
157
+ } | {
158
+ opcode: "UNLINK";
159
+ parentNodeId: bigint;
160
+ name: string;
161
+ } | {
162
+ opcode: "RMDIR";
163
+ parentNodeId: bigint;
164
+ name: string;
165
+ } | {
166
+ opcode: "RENAME";
167
+ parentNodeId: bigint;
168
+ newParentNodeId: bigint;
169
+ oldName: string;
170
+ newName: string;
171
+ flags: bigint;
172
+ } | {
173
+ opcode: "LINK";
174
+ oldNodeId: bigint;
175
+ newParentNodeId: bigint;
176
+ name: string;
177
+ } | {
178
+ opcode: "OPENDIR";
179
+ nodeId: bigint;
180
+ flags: bigint;
181
+ } | {
182
+ opcode: "READDIR";
183
+ nodeId: bigint;
184
+ fh: bigint;
185
+ offset: bigint;
186
+ size: bigint;
187
+ readFlags: bigint;
188
+ lockOwner: bigint;
189
+ flags: bigint;
190
+ } | {
191
+ opcode: "RELEASE";
192
+ nodeId: bigint;
193
+ fh: bigint;
194
+ flags: bigint;
195
+ releaseFlags: bigint;
196
+ lockOwner: bigint;
197
+ } | {
198
+ opcode: "RELEASEDIR";
199
+ nodeId: bigint;
200
+ fh: bigint;
201
+ flags: bigint;
202
+ releaseFlags: bigint;
203
+ lockOwner: bigint;
204
+ } | {
205
+ opcode: "FSYNCDIR";
206
+ nodeId: bigint;
207
+ fh: bigint;
208
+ fsyncFlags: bigint;
209
+ } | {
210
+ opcode: "STATFS";
211
+ } | {
212
+ opcode: "LOOKUP";
213
+ parentNodeId: bigint;
214
+ name: string;
215
+ } | {
216
+ opcode: "OPEN",
217
+ nodeId: bigint;
218
+ flags: bigint;
219
+ } | {
220
+ opcode: "READ";
221
+ nodeId: bigint;
222
+ fh: bigint;
223
+ offset: bigint;
224
+ size: bigint;
225
+ readFlags: bigint;
226
+ lockOwner: bigint;
227
+ } | {
228
+ opcode: "WRITE";
229
+ nodeId: bigint;
230
+ fh: bigint;
231
+ offset: bigint;
232
+ data: Uint8Array;
233
+ writeFlags: bigint;
234
+ lockOwner: bigint;
235
+ } | {
236
+ opcode: "FLUSH";
237
+ nodeId: bigint;
238
+ fh: bigint;
239
+ lockOwner: bigint;
240
+ } | {
241
+ opcode: "FSYNC";
242
+ nodeId: bigint;
243
+ fh: bigint;
244
+ fsyncFlags: bigint;
245
+ } | {
246
+ opcode: "ACCESS";
247
+ nodeId: bigint;
248
+ mask: bigint;
249
+ } | {
250
+ opcode: "SETXATTR";
251
+ nodeId: bigint;
252
+ name: string;
253
+ data: Uint8Array;
254
+ flags: bigint;
255
+ setxattrFlags: bigint;
256
+ } | {
257
+ opcode: "REMOVEXATTR";
258
+ nodeId: bigint;
259
+ name: string;
260
+ } | {
261
+ opcode: "CREATE";
262
+ parentNodeId: bigint;
263
+ name: string;
264
+ flags: bigint;
265
+ mode: bigint;
266
+ umask: bigint;
267
+ } | {
268
+ opcode: "DESTROY";
269
+ } | {
270
+ opcode: "GETLK";
271
+ nodeId: bigint;
272
+ fh: bigint;
273
+ owner: bigint;
274
+ lockStart: bigint;
275
+ lockEnd: bigint;
276
+ lockType: bigint;
277
+ lockPid: bigint;
278
+ lkFlags: bigint;
279
+ } | {
280
+ opcode: "SETLK";
281
+ nodeId: bigint;
282
+ fh: bigint;
283
+ owner: bigint;
284
+ lockStart: bigint;
285
+ lockEnd: bigint;
286
+ lockType: bigint;
287
+ lockPid: bigint;
288
+ lkFlags: bigint;
289
+ } | {
290
+ opcode: "SETLKW";
291
+ nodeId: bigint;
292
+ fh: bigint;
293
+ owner: bigint;
294
+ lockStart: bigint;
295
+ lockEnd: bigint;
296
+ lockType: bigint;
297
+ lockPid: bigint;
298
+ lkFlags: bigint;
299
+ } | {
300
+ opcode: "INTERRUPT";
301
+ targetUnique: bigint;
302
+ } | {
303
+ opcode: "BMAP";
304
+ nodeId: bigint;
305
+ block: bigint;
306
+ blocksize: bigint;
307
+ } | {
308
+ opcode: "IOCTL";
309
+ nodeId: bigint;
310
+ fh: bigint;
311
+ flags: bigint;
312
+ cmd: bigint;
313
+ arg: bigint;
314
+ inData: Uint8Array;
315
+ outSize: bigint;
316
+ } | {
317
+ opcode: "POLL";
318
+ nodeId: bigint;
319
+ fh: bigint;
320
+ kh: bigint;
321
+ flags: bigint;
322
+ events: bigint;
323
+ } | {
324
+ opcode: "NOTIFY_REPLY";
325
+ data: Uint8Array;
326
+ } | {
327
+ opcode: "FALLOCATE";
328
+ nodeId: bigint;
329
+ fh: bigint;
330
+ offset: bigint;
331
+ length: bigint;
332
+ mode: bigint;
333
+ } | {
334
+ opcode: "READDIRPLUS";
335
+ nodeId: bigint;
336
+ fh: bigint;
337
+ offset: bigint;
338
+ size: bigint;
339
+ readFlags: bigint;
340
+ lockOwner: bigint;
341
+ flags: bigint;
342
+ });*/
343
+
344
+
345
+ /*type TFuseResponse = {
346
+ forOpcode: "INIT";
347
+ unique: bigint;
348
+ errorCode: number;
349
+ result: undefined;
350
+ } | {
351
+ forOpcode: "INIT";
352
+ unique: bigint;
353
+ errorCode: undefined;
354
+ result: {
355
+ major: bigint,
356
+ minor: bigint,
357
+ maxReadahead: bigint,
358
+ flags: bigint,
359
+ maxBackground: bigint,
360
+ congestionThreshold: bigint,
361
+ maxWrite: bigint,
362
+ timeGran: bigint,
363
+ maxPages: bigint,
364
+ mapAlignment: bigint,
365
+ flags2: bigint,
366
+ maxStackDepth: bigint,
367
+ requestTimeout: bigint,
368
+ };
369
+ } | {
370
+ forOpcode: "GETATTR";
371
+ unique: bigint;
372
+ errorCode: number;
373
+ result: undefined;
374
+ } | {
375
+ forOpcode: "GETATTR";
376
+ unique: bigint;
377
+ errorCode: undefined;
378
+ result: {
379
+ attrValidNsec: bigint;
380
+ attr: TFuseAttr
381
+ };
382
+ } | {
383
+ forOpcode: "SETATTR";
384
+ unique: bigint;
385
+ errorCode: number;
386
+ result: undefined;
387
+ } | {
388
+ forOpcode: "SETATTR";
389
+ unique: bigint;
390
+ errorCode: undefined;
391
+ result: {
392
+ attrValidNsec: bigint;
393
+ attr: TFuseAttr;
394
+ };
395
+ } | {
396
+ forOpcode: "LISTXATTR";
397
+ unique: bigint;
398
+ errorCode: number;
399
+ result: undefined;
400
+ } | {
401
+ forOpcode: "LISTXATTR";
402
+ unique: bigint;
403
+ errorCode: undefined;
404
+ result: TFuseXAttrResult;
405
+ } | {
406
+ forOpcode: "GETXATTR";
407
+ unique: bigint;
408
+ errorCode: number;
409
+ result: undefined;
410
+ } | {
411
+ forOpcode: "GETXATTR";
412
+ unique: bigint;
413
+ errorCode: undefined;
414
+ result: TFuseXAttrResult;
415
+ } | {
416
+ forOpcode: "READLINK";
417
+ unique: bigint;
418
+ errorCode: number;
419
+ result: undefined;
420
+ } | {
421
+ forOpcode: "READLINK";
422
+ unique: bigint;
423
+ errorCode: undefined;
424
+ result: {
425
+ target: string;
426
+ };
427
+ } | {
428
+ forOpcode: "MKNOD";
429
+ unique: bigint;
430
+ errorCode: number;
431
+ result: undefined;
432
+ } | {
433
+ forOpcode: "MKNOD";
434
+ unique: bigint;
435
+ errorCode: undefined;
436
+ result: TFuseEntry;
437
+ } | {
438
+ forOpcode: "OPENDIR";
439
+ unique: bigint;
440
+ errorCode: number;
441
+ result: undefined;
442
+ } | {
443
+ forOpcode: "OPENDIR";
444
+ unique: bigint;
445
+ errorCode: undefined;
446
+ result: {
447
+ fh: bigint;
448
+ openFlagsToKernel: TOpenFlagsToKernel;
449
+ };
450
+ } | {
451
+ forOpcode: "READDIR";
452
+ unique: bigint;
453
+ errorCode: number;
454
+ result: undefined;
455
+ } | {
456
+ forOpcode: "READDIR";
457
+ unique: bigint;
458
+ errorCode: undefined;
459
+ result: {
460
+ data: Uint8Array;
461
+ };
462
+ } | {
463
+ forOpcode: "RELEASEDIR";
464
+ unique: bigint;
465
+ errorCode: number;
466
+ result: undefined;
467
+ } | {
468
+ forOpcode: "RELEASEDIR";
469
+ unique: bigint;
470
+ errorCode: undefined;
471
+ result: Record<string, never>;
472
+ } | {
473
+ forOpcode: "FSYNCDIR";
474
+ unique: bigint;
475
+ errorCode: number;
476
+ result: undefined;
477
+ } | {
478
+ forOpcode: "FSYNCDIR";
479
+ unique: bigint;
480
+ errorCode: undefined;
481
+ result: Record<string, never>;
482
+ } | {
483
+ forOpcode: "RELEASE";
484
+ unique: bigint;
485
+ errorCode: number;
486
+ result: undefined;
487
+ } | {
488
+ forOpcode: "RELEASE";
489
+ unique: bigint;
490
+ errorCode: undefined;
491
+ result: Record<string, never>;
492
+ } | {
493
+ forOpcode: "STATFS";
494
+ unique: bigint;
495
+ errorCode: number;
496
+ result: undefined;
497
+ } | {
498
+ forOpcode: "STATFS";
499
+ unique: bigint;
500
+ errorCode: undefined;
501
+ result: {
502
+ blocks: bigint;
503
+ bfree: bigint;
504
+ bavail: bigint;
505
+ files: bigint;
506
+ ffree: bigint;
507
+ bsize: bigint;
508
+ namelen: bigint;
509
+ frsize: bigint;
510
+ }
511
+ } | {
512
+ forOpcode: "LOOKUP";
513
+ unique: bigint;
514
+ errorCode: number;
515
+ result: undefined;
516
+ } | {
517
+ forOpcode: "LOOKUP";
518
+ unique: bigint;
519
+ errorCode: undefined;
520
+ result: TFuseEntry;
521
+ } | {
522
+ forOpcode: "SYMLINK";
523
+ unique: bigint;
524
+ errorCode: number;
525
+ result: undefined;
526
+ } | {
527
+ forOpcode: "SYMLINK";
528
+ unique: bigint;
529
+ errorCode: undefined;
530
+ result: TFuseEntry;
531
+ } | {
532
+ forOpcode: "MKDIR";
533
+ unique: bigint;
534
+ errorCode: number;
535
+ result: undefined;
536
+ } | {
537
+ forOpcode: "MKDIR";
538
+ unique: bigint;
539
+ errorCode: undefined;
540
+ result: TFuseEntry;
541
+ } | {
542
+ forOpcode: "LINK";
543
+ unique: bigint;
544
+ errorCode: number;
545
+ result: undefined;
546
+ } | {
547
+ forOpcode: "LINK";
548
+ unique: bigint;
549
+ errorCode: undefined;
550
+ result: TFuseEntry;
551
+ } | {
552
+ forOpcode: "UNLINK";
553
+ unique: bigint;
554
+ errorCode: number;
555
+ result: undefined;
556
+ } | {
557
+ forOpcode: "UNLINK";
558
+ unique: bigint;
559
+ errorCode: undefined;
560
+ result: Record<string, never>;
561
+ } | {
562
+ forOpcode: "RMDIR";
563
+ unique: bigint;
564
+ errorCode: number;
565
+ result: undefined;
566
+ } | {
567
+ forOpcode: "RMDIR";
568
+ unique: bigint;
569
+ errorCode: undefined;
570
+ result: Record<string, never>;
571
+ } | {
572
+ forOpcode: "RENAME";
573
+ unique: bigint;
574
+ errorCode: number;
575
+ result: undefined;
576
+ } | {
577
+ forOpcode: "RENAME";
578
+ unique: bigint;
579
+ errorCode: undefined;
580
+ result: Record<string, never>;
581
+ } | {
582
+ forOpcode: "OPEN";
583
+ unique: bigint;
584
+ errorCode: number;
585
+ result: undefined;
586
+ } | {
587
+ forOpcode: "OPEN";
588
+ unique: bigint;
589
+ errorCode: undefined;
590
+ result: {
591
+ fh: bigint;
592
+ openFlagsToKernel: TOpenFlagsToKernel;
593
+ }
594
+ } | {
595
+ forOpcode: "READ";
596
+ unique: bigint;
597
+ errorCode: number;
598
+ result: undefined;
599
+ } | {
600
+ forOpcode: "READ";
601
+ unique: bigint;
602
+ errorCode: undefined;
603
+ result: {
604
+ data: Uint8Array;
605
+ }
606
+ } | {
607
+ forOpcode: "WRITE";
608
+ unique: bigint;
609
+ errorCode: number;
610
+ result: undefined;
611
+ } | {
612
+ forOpcode: "WRITE";
613
+ unique: bigint;
614
+ errorCode: undefined;
615
+ result: {
616
+ bytesWritten: bigint;
617
+ }
618
+ } | {
619
+ forOpcode: "FLUSH";
620
+ unique: bigint;
621
+ errorCode: number;
622
+ result: undefined;
623
+ } | {
624
+ forOpcode: "FLUSH";
625
+ unique: bigint;
626
+ errorCode: undefined;
627
+ result: Record<string, never>;
628
+ } | {
629
+ forOpcode: "FSYNC";
630
+ unique: bigint;
631
+ errorCode: number;
632
+ result: undefined;
633
+ } | {
634
+ forOpcode: "FSYNC";
635
+ unique: bigint;
636
+ errorCode: undefined;
637
+ result: Record<string, never>;
638
+ } | {
639
+ forOpcode: "ACCESS";
640
+ unique: bigint;
641
+ errorCode: number;
642
+ result: undefined;
643
+ } | {
644
+ forOpcode: "ACCESS";
645
+ unique: bigint;
646
+ errorCode: undefined;
647
+ result: Record<string, never>;
648
+ } | {
649
+ forOpcode: "SETXATTR";
650
+ unique: bigint;
651
+ errorCode: number;
652
+ result: undefined;
653
+ } | {
654
+ forOpcode: "SETXATTR";
655
+ unique: bigint;
656
+ errorCode: undefined;
657
+ result: Record<string, never>;
658
+ } | {
659
+ forOpcode: "REMOVEXATTR";
660
+ unique: bigint;
661
+ errorCode: number;
662
+ result: undefined;
663
+ } | {
664
+ forOpcode: "REMOVEXATTR";
665
+ unique: bigint;
666
+ errorCode: undefined;
667
+ result: Record<string, never>;
668
+ } | {
669
+ forOpcode: "CREATE";
670
+ unique: bigint;
671
+ errorCode: number;
672
+ result: undefined;
673
+ } | {
674
+ forOpcode: "CREATE";
675
+ unique: bigint;
676
+ errorCode: undefined;
677
+ result: TFuseEntry & {
678
+ fh: bigint;
679
+ openFlagsToKernel: TOpenFlagsToKernel;
680
+ };
681
+ } | {
682
+ forOpcode: "DESTROY";
683
+ unique: bigint;
684
+ errorCode: number;
685
+ result: undefined;
686
+ } | {
687
+ forOpcode: "DESTROY";
688
+ unique: bigint;
689
+ errorCode: undefined;
690
+ result: Record<string, never>;
691
+ } | {
692
+ forOpcode: "GETLK";
693
+ unique: bigint;
694
+ errorCode: number;
695
+ result: undefined;
696
+ } | {
697
+ forOpcode: "GETLK";
698
+ unique: bigint;
699
+ errorCode: undefined;
700
+ result: {
701
+ lockStart: bigint;
702
+ lockEnd: bigint;
703
+ lockType: bigint;
704
+ lockPid: bigint;
705
+ };
706
+ } | {
707
+ forOpcode: "SETLK";
708
+ unique: bigint;
709
+ errorCode: number;
710
+ result: undefined;
711
+ } | {
712
+ forOpcode: "SETLK";
713
+ unique: bigint;
714
+ errorCode: undefined;
715
+ result: Record<string, never>;
716
+ } | {
717
+ forOpcode: "SETLKW";
718
+ unique: bigint;
719
+ errorCode: number;
720
+ result: undefined;
721
+ } | {
722
+ forOpcode: "SETLKW";
723
+ unique: bigint;
724
+ errorCode: undefined;
725
+ result: Record<string, never>;
726
+ } | {
727
+ forOpcode: "BMAP";
728
+ unique: bigint;
729
+ errorCode: number;
730
+ result: undefined;
731
+ } | {
732
+ forOpcode: "BMAP";
733
+ unique: bigint;
734
+ errorCode: undefined;
735
+ result: {
736
+ block: bigint;
737
+ };
738
+ } | {
739
+ forOpcode: "IOCTL";
740
+ unique: bigint;
741
+ errorCode: number;
742
+ result: undefined;
743
+ } | {
744
+ forOpcode: "IOCTL";
745
+ unique: bigint;
746
+ errorCode: undefined;
747
+ result: {
748
+ ioctlResult: bigint;
749
+ flags: bigint;
750
+ data: Uint8Array;
751
+ };
752
+ } | {
753
+ forOpcode: "POLL";
754
+ unique: bigint;
755
+ errorCode: number;
756
+ result: undefined;
757
+ } | {
758
+ forOpcode: "POLL";
759
+ unique: bigint;
760
+ errorCode: undefined;
761
+ result: {
762
+ revents: bigint;
763
+ };
764
+ } | {
765
+ forOpcode: "FALLOCATE";
766
+ unique: bigint;
767
+ errorCode: number;
768
+ result: undefined;
769
+ } | {
770
+ forOpcode: "FALLOCATE";
771
+ unique: bigint;
772
+ errorCode: undefined;
773
+ result: Record<string, never>;
774
+ } | {
775
+ forOpcode: "READDIRPLUS";
776
+ unique: bigint;
777
+ errorCode: number;
778
+ result: undefined;
779
+ } | {
780
+ forOpcode: "READDIRPLUS";
781
+ unique: bigint;
782
+ errorCode: undefined;
783
+ result: {
784
+ data: Uint8Array;
785
+ };
786
+ };*/
787
+
788
+ /*type TGenericInterpretResult<T> = {
789
+ error: Error;
790
+ interpreted: undefined;
791
+ } | {
792
+ error: undefined;
793
+ interpreted: T;
794
+ };*/
795
+
796
+ const hasFlag = ({ bitmask, flag }/*: { bitmask: bigint; flag: bigint }*/)/*: boolean*/ => {
797
+ return (bitmask & flag) === flag;
798
+ };
799
+
800
+ const fuseAttrToPayloadValue = ({ attr }/*: { attr: TFuseAttr }*/) => {
801
+ return {
802
+ ino: attr.ino,
803
+ mode: attr.mode,
804
+ nlink: attr.nlink,
805
+ uid: attr.uid,
806
+ gid: attr.gid,
807
+ rdev: attr.rdev,
808
+ size: attr.size,
809
+ blksize: attr.blksize,
810
+ blocks: attr.blocks,
811
+ atime: attr.atimeNsec / 1_000_000_000n,
812
+ atimensec: attr.atimeNsec % 1_000_000_000n,
813
+ mtime: attr.mtimeNsec / 1_000_000_000n,
814
+ mtimensec: attr.mtimeNsec % 1_000_000_000n,
815
+ ctime: attr.ctimeNsec / 1_000_000_000n,
816
+ ctimensec: attr.ctimeNsec % 1_000_000_000n,
817
+ padding: 0n,
818
+ };
819
+ };
820
+
821
+ const payloadValueToFuseAttr = ({ attr }/*: { attr: ReturnType<typeof fuseAttrOutParser.parse>["attr"] }*/)/*: TFuseAttr*/ => {
822
+ return {
823
+ ino: attr.ino,
824
+ mode: attr.mode,
825
+ nlink: attr.nlink,
826
+ uid: attr.uid,
827
+ gid: attr.gid,
828
+ rdev: attr.rdev,
829
+ size: attr.size,
830
+ blksize: attr.blksize,
831
+ blocks: attr.blocks,
832
+ atimeNsec: attr.atime * 1_000_000_000n + attr.atimensec,
833
+ mtimeNsec: attr.mtime * 1_000_000_000n + attr.mtimensec,
834
+ ctimeNsec: attr.ctime * 1_000_000_000n + attr.ctimensec,
835
+ };
836
+ };
837
+
838
+ const openFlagsToKernelToBitmask = ({ openFlagsToKernel }/*: { openFlagsToKernel: TOpenFlagsToKernel }*/)/*: bigint*/ => {
839
+ let bitmask = 0n;
840
+
841
+ if (openFlagsToKernel.directIo) {
842
+ bitmask |= FOPEN_DIRECT_IO;
843
+ }
844
+
845
+ if (openFlagsToKernel.keepCache) {
846
+ bitmask |= FOPEN_KEEP_CACHE;
847
+ }
848
+
849
+ if (openFlagsToKernel.nonSeekable) {
850
+ bitmask |= FOPEN_NONSEEKABLE;
851
+ }
852
+
853
+ return bitmask;
854
+ };
855
+
856
+ const openFlagsToKernelFromBitmask = ({ bitmask }/*: { bitmask: bigint }*/)/*: TOpenFlagsToKernel*/ => {
857
+ return {
858
+ directIo: hasFlag({ bitmask, flag: FOPEN_DIRECT_IO }),
859
+ keepCache: hasFlag({ bitmask, flag: FOPEN_KEEP_CACHE }),
860
+ nonSeekable: hasFlag({ bitmask, flag: FOPEN_NONSEEKABLE }),
861
+ };
862
+ };
863
+
864
+ const encodeAttrPayload = (
865
+ { unique, result }/*: {
866
+ unique: bigint;
867
+ forOpcode: "GETATTR" | "SETATTR";
868
+ result: { attrValidNsec: bigint; attr: TFuseAttr };
869
+ }*/,
870
+ )/*: Extract<TParsedMessageToKernel, { header: { unique: bigint } }>*/ => {
871
+ const payload = fuseAttrOutParser.format({
872
+ value: {
873
+ dummy: 0n,
874
+ attr_valid: result.attrValidNsec / 1_000_000_000n,
875
+ attr_valid_nsec: result.attrValidNsec % 1_000_000_000n,
876
+ attr: fuseAttrToPayloadValue({ attr: result.attr }),
877
+ }
878
+ });
879
+
880
+ return {
881
+ header: {
882
+ unique,
883
+ error: 0n,
884
+ },
885
+ payload,
886
+ };
887
+ };
888
+
889
+ const interpretAttrPayload = /*<TForOpcode extends "GETATTR" | "SETATTR">*/(
890
+ { unique, forOpcode, payload }/*: { unique: bigint; forOpcode: TForOpcode; payload: Uint8Array }*/
891
+ )/*: TGenericInterpretResult<Extract<TFuseResponse, { forOpcode: TForOpcode }>>*/ => {
892
+ if (payload.length !== fuseAttrOutParser.size) {
893
+ return {
894
+ error: new Error(
895
+ `Invalid payload size for ${forOpcode} response. Expected ${fuseAttrOutParser.size} bytes, got ${payload.length} bytes.`
896
+ ),
897
+ interpreted: undefined,
898
+ };
899
+ }
900
+
901
+ const parsed = fuseAttrOutParser.parse({ data: payload });
902
+
903
+ return {
904
+ error: undefined,
905
+ interpreted: {
906
+ forOpcode,
907
+ unique,
908
+ errorCode: undefined,
909
+ result: {
910
+ attrValidNsec: parsed.attr_valid * 1_000_000_000n + parsed.attr_valid_nsec,
911
+ attr: payloadValueToFuseAttr({ attr: parsed.attr }),
912
+ }
913
+ } /*as Extract<TFuseResponse, { forOpcode: TForOpcode }>*/,
914
+ };
915
+ };
916
+
917
+ const encodeEntryPayload = (
918
+ { unique, result }/*: {
919
+ unique: bigint;
920
+ forOpcode: "LOOKUP" | "SYMLINK" | "MKNOD" | "MKDIR" | "LINK";
921
+ result: TFuseEntry;
922
+ }*/,
923
+ )/*: TParsedMessageToKernel*/ => {
924
+ const payload = fuseEntryOutParser.format({
925
+ value: {
926
+ nodeid: result.nodeId,
927
+ generation: result.generation,
928
+ entry_valid: result.entryValidNsec / 1_000_000_000n,
929
+ attr_valid: result.attrValidNsec / 1_000_000_000n,
930
+ entry_valid_nsec: result.entryValidNsec % 1_000_000_000n,
931
+ attr_valid_nsec: result.attrValidNsec % 1_000_000_000n,
932
+ attr: fuseAttrToPayloadValue({ attr: result.attr }),
933
+ }
934
+ });
935
+
936
+ return {
937
+ header: {
938
+ unique,
939
+ error: 0n,
940
+ },
941
+ payload,
942
+ };
943
+ };
944
+
945
+ const interpretEntryPayload = /*<TForOpcode extends "LOOKUP" | "SYMLINK" | "MKNOD" | "MKDIR" | "LINK">*/(
946
+ { unique, forOpcode, payload }/*: { unique: bigint; forOpcode: TForOpcode; payload: Uint8Array }*/
947
+ )/*: TGenericInterpretResult<Extract<TFuseResponse, { forOpcode: TForOpcode }>>*/ => {
948
+ if (payload.length !== fuseEntryOutParser.size) {
949
+ return {
950
+ error: new Error(
951
+ `Invalid payload size for ${forOpcode} response. Expected ${fuseEntryOutParser.size} bytes, got ${payload.length} bytes.`
952
+ ),
953
+ interpreted: undefined,
954
+ };
955
+ }
956
+
957
+ const parsed = fuseEntryOutParser.parse({ data: payload });
958
+
959
+ return {
960
+ error: undefined,
961
+ interpreted: {
962
+ forOpcode,
963
+ unique,
964
+ errorCode: undefined,
965
+ result: {
966
+ nodeId: parsed.nodeid,
967
+ generation: parsed.generation,
968
+ entryValidNsec: parsed.entry_valid * 1_000_000_000n + parsed.entry_valid_nsec,
969
+ attrValidNsec: parsed.attr_valid * 1_000_000_000n + parsed.attr_valid_nsec,
970
+ attr: payloadValueToFuseAttr({ attr: parsed.attr }),
971
+ },
972
+ } /*as Extract<TFuseResponse, { forOpcode: TForOpcode }>*/,
973
+ };
974
+ };
975
+
976
+ const encodeOpenPayload = (
977
+ { unique, result }/*: { unique: bigint; result: { fh: bigint; openFlagsToKernel: TOpenFlagsToKernel } }*/
978
+ )/*: TParsedMessageToKernel*/ => {
979
+ const payload = fuseOpenOutParser.format({
980
+ value: {
981
+ fh: result.fh,
982
+ open_flags: openFlagsToKernelToBitmask({ openFlagsToKernel: result.openFlagsToKernel }),
983
+ backing_id: 0n,
984
+ }
985
+ });
986
+
987
+ return {
988
+ header: {
989
+ unique,
990
+ error: 0n,
991
+ },
992
+ payload,
993
+ };
994
+ };
995
+
996
+ const interpretOpenPayload = /*<TForOpcode extends "OPEN" | "OPENDIR">*/(
997
+ { unique, forOpcode, payload }/*: { unique: bigint; forOpcode: TForOpcode; payload: Uint8Array }*/
998
+ )/*: TGenericInterpretResult<Extract<TFuseResponse, { forOpcode: TForOpcode }>>*/ => {
999
+ if (payload.length !== fuseOpenOutParser.size) {
1000
+ return {
1001
+ error: new Error(
1002
+ `Invalid payload size for ${forOpcode} response. Expected ${fuseOpenOutParser.size} bytes, got ${payload.length} bytes.`
1003
+ ),
1004
+ interpreted: undefined,
1005
+ };
1006
+ }
1007
+
1008
+ const parsed = fuseOpenOutParser.parse({ data: payload });
1009
+
1010
+ return {
1011
+ error: undefined,
1012
+ interpreted: {
1013
+ forOpcode,
1014
+ unique,
1015
+ errorCode: undefined,
1016
+ result: {
1017
+ fh: parsed.fh,
1018
+ openFlagsToKernel: openFlagsToKernelFromBitmask({ bitmask: parsed.open_flags }),
1019
+ }
1020
+ } /*as Extract<TFuseResponse, { forOpcode: TForOpcode }>*/,
1021
+ };
1022
+ };
1023
+
1024
+ const encodeEmptyPayload = ({ unique }/*: { unique: bigint }*/)/*: TParsedMessageToKernel*/ => {
1025
+ return {
1026
+ header: {
1027
+ unique,
1028
+ error: 0n,
1029
+ },
1030
+ payload: new Uint8Array(0),
1031
+ };
1032
+ };
1033
+
1034
+ const interpretEmptyPayload = /*<T extends Extract<TFuseResponse, { result: Record<string, never> }>["forOpcode"]>*/(
1035
+ { unique, forOpcode }/*: { unique: bigint; forOpcode: T }*/,
1036
+ )/*: TGenericInterpretResult<Extract<TFuseResponse, { forOpcode: T }>>*/ => {
1037
+ return {
1038
+ error: undefined,
1039
+ interpreted: {
1040
+ forOpcode,
1041
+ unique,
1042
+ errorCode: undefined,
1043
+ result: {},
1044
+ } /*as Extract<TFuseResponse, { forOpcode: T }>*/,
1045
+ };
1046
+ };
1047
+
1048
+ const encodeXAttrPayload = ({ unique, result }/*: { unique: bigint; result: TFuseXAttrResult }*/)/*: TParsedMessageToKernel*/ => {
1049
+ const payload = "size" in result
1050
+ ? fuseGetxattrOutParser.format({ value: { size: result.size, padding: 0n } })
1051
+ : result.data;
1052
+
1053
+ return {
1054
+ header: {
1055
+ unique,
1056
+ error: 0n,
1057
+ },
1058
+ payload,
1059
+ };
1060
+ };
1061
+
1062
+ const interpretXAttrPayload = /*<TForOpcode extends "GETXATTR" | "LISTXATTR">*/(
1063
+ { unique, forOpcode, payload, requestedSize }/*:
1064
+ { unique: bigint; forOpcode: TForOpcode; payload: Uint8Array; requestedSize: bigint }*/
1065
+ )/*: TGenericInterpretResult<Extract<TFuseResponse, { forOpcode: TForOpcode }>>*/ => {
1066
+ if (requestedSize === 0n) {
1067
+ if (payload.length !== fuseGetxattrOutParser.size) {
1068
+ return {
1069
+ error: new Error(
1070
+ `Invalid payload size for ${forOpcode} size response. Expected ${fuseGetxattrOutParser.size} bytes, got ${payload.length} bytes.`
1071
+ ),
1072
+ interpreted: undefined,
1073
+ };
1074
+ }
1075
+
1076
+ const parsed = fuseGetxattrOutParser.parse({ data: payload });
1077
+
1078
+ return {
1079
+ error: undefined,
1080
+ interpreted: {
1081
+ forOpcode,
1082
+ unique,
1083
+ errorCode: undefined,
1084
+ result: { size: parsed.size },
1085
+ } /*as Extract<TFuseResponse, { forOpcode: TForOpcode }>*/,
1086
+ };
1087
+ }
1088
+
1089
+ return {
1090
+ error: undefined,
1091
+ interpreted: {
1092
+ forOpcode,
1093
+ unique,
1094
+ errorCode: undefined,
1095
+ result: { data: payload },
1096
+ } /*as Extract<TFuseResponse, { forOpcode: TForOpcode }>*/,
1097
+ };
1098
+ };
1099
+
1100
+ const createMessageFromKernelInterpreter = () => {
1101
+
1102
+ /*type TInterpretFunc<T extends string> = (
1103
+ args: { unique: bigint, nodeId: bigint, requester: TRequesterInfo, payload: Uint8Array }
1104
+ ) => TGenericInterpretResult<Extract<TFuseRequest, { opcode: T }>>;*/
1105
+
1106
+ const interpretInit/*: TInterpretFunc<"INIT">*/ = ({ unique, requester, payload }) => {
1107
+
1108
+ if (payload.length !== fuseInitInParser.size) {
1109
+ return {
1110
+ error: new Error(`Invalid payload size for INIT request. Expected ${fuseInitInParser.size} bytes, got ${payload.length} bytes.`),
1111
+ interpreted: undefined,
1112
+ };
1113
+ }
1114
+
1115
+ const { major, minor } = fuseInitInParser.parse({ data: payload });
1116
+
1117
+ return {
1118
+ error: undefined,
1119
+ interpreted: {
1120
+ unique,
1121
+ requester,
1122
+ opcode: "INIT",
1123
+ major,
1124
+ minor,
1125
+ }
1126
+ };
1127
+ };
1128
+
1129
+ const interpretGetAttr/*: TInterpretFunc<"GETATTR">*/ = ({ unique, nodeId, requester, payload }) => {
1130
+ if (payload.length !== fuseGetattrInParser.size) {
1131
+ return {
1132
+ error: new Error(
1133
+ `Invalid payload size for GETATTR request. Expected ${fuseGetattrInParser.size} bytes, got ${payload.length} bytes.`
1134
+ ),
1135
+ interpreted: undefined,
1136
+ };
1137
+ }
1138
+
1139
+ const { getattr_flags, fh } = fuseGetattrInParser.parse({ data: payload });
1140
+
1141
+ if (hasFlag({ bitmask: getattr_flags, flag: FUSE_GETATTR_FH })) {
1142
+ return {
1143
+ error: undefined,
1144
+ interpreted: {
1145
+ unique,
1146
+ requester,
1147
+ opcode: "GETATTR",
1148
+ getattrMode: "fileHandle",
1149
+ fh,
1150
+ }
1151
+ };
1152
+ }
1153
+
1154
+ return {
1155
+ error: undefined,
1156
+ interpreted: {
1157
+ unique,
1158
+ requester,
1159
+ opcode: "GETATTR",
1160
+ getattrMode: "node",
1161
+ nodeId,
1162
+ }
1163
+ };
1164
+ };
1165
+
1166
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-underscore-dangle
1167
+ const _interpretListXAttr/*: TInterpretFunc<"LISTXATTR">*/ = ({ unique, nodeId, requester }) => {
1168
+ return {
1169
+ error: undefined,
1170
+ interpreted: {
1171
+ unique,
1172
+ requester,
1173
+ opcode: "LISTXATTR",
1174
+ nodeId,
1175
+ size: 0n,
1176
+ }
1177
+ };
1178
+ };
1179
+
1180
+ const interpretForget/*: TInterpretFunc<"FORGET">*/ = ({ unique, nodeId, requester, payload }) => {
1181
+ if (payload.length !== fuseForgetInParser.size) {
1182
+ return {
1183
+ error: new Error(
1184
+ `Invalid payload size for FORGET request. Expected ${fuseForgetInParser.size} bytes, got ${payload.length} bytes.`
1185
+ ),
1186
+ interpreted: undefined,
1187
+ };
1188
+ }
1189
+
1190
+ const { nlookup } = fuseForgetInParser.parse({ data: payload });
1191
+
1192
+ return {
1193
+ error: undefined,
1194
+ interpreted: {
1195
+ unique,
1196
+ requester,
1197
+ opcode: "FORGET",
1198
+ nodeId,
1199
+ lookupCount: nlookup,
1200
+ }
1201
+ };
1202
+ };
1203
+
1204
+ const interpretBatchForget/*: TInterpretFunc<"BATCH_FORGET">*/ = ({ unique, requester, payload }) => {
1205
+ if (payload.length < fuseBatchForgetInParser.size) {
1206
+ return {
1207
+ error: new Error(
1208
+ `Invalid payload size for BATCH_FORGET request. ` +
1209
+ `Expected at least ${fuseBatchForgetInParser.size} bytes, got ${payload.length} bytes.`
1210
+ ),
1211
+ interpreted: undefined,
1212
+ };
1213
+ }
1214
+
1215
+ const header = fuseBatchForgetInParser.parse({ data: payload.subarray(0, fuseBatchForgetInParser.size) });
1216
+ const count = Number(header.count);
1217
+ const expectedSize = fuseBatchForgetInParser.size + (count * fuseForgetOneParser.size);
1218
+ if (payload.length !== expectedSize) {
1219
+ return {
1220
+ error: new Error(`Invalid payload size for BATCH_FORGET request. Expected ${expectedSize} bytes, got ${payload.length} bytes.`),
1221
+ interpreted: undefined,
1222
+ };
1223
+ }
1224
+
1225
+ let forgets/*: Array<{ nodeId: bigint; lookupCount: bigint }>*/ = [];
1226
+ for (let index = 0; index < count; index += 1) {
1227
+ const start = fuseBatchForgetInParser.size + (index * fuseForgetOneParser.size);
1228
+ const parsed = fuseForgetOneParser.parse({ data: payload.subarray(start, start + fuseForgetOneParser.size) });
1229
+ forgets = [...forgets, {
1230
+ nodeId: parsed.nodeid,
1231
+ lookupCount: parsed.nlookup,
1232
+ }];
1233
+ }
1234
+
1235
+ return {
1236
+ error: undefined,
1237
+ interpreted: {
1238
+ unique,
1239
+ requester,
1240
+ opcode: "BATCH_FORGET",
1241
+ forgets,
1242
+ }
1243
+ };
1244
+ };
1245
+
1246
+ const interpretListXAttrRequest/*: TInterpretFunc<"LISTXATTR">*/ = ({ unique, nodeId, requester, payload }) => {
1247
+ if (payload.length !== fuseGetxattrInParser.size) {
1248
+ return {
1249
+ error: new Error(
1250
+ `Invalid payload size for LISTXATTR request. Expected ${fuseGetxattrInParser.size} bytes, got ${payload.length} bytes.`
1251
+ ),
1252
+ interpreted: undefined,
1253
+ };
1254
+ }
1255
+
1256
+ const { size } = fuseGetxattrInParser.parse({ data: payload });
1257
+
1258
+ return {
1259
+ error: undefined,
1260
+ interpreted: {
1261
+ unique,
1262
+ requester,
1263
+ opcode: "LISTXATTR",
1264
+ nodeId,
1265
+ size,
1266
+ }
1267
+ };
1268
+ };
1269
+
1270
+ const interpretGetXAttr/*: TInterpretFunc<"GETXATTR">*/ = ({ unique, nodeId, requester, payload }) => {
1271
+ if (payload.length < fuseGetxattrInParser.size) {
1272
+ return {
1273
+ error: new Error(
1274
+ `Invalid payload size for GETXATTR request. Expected at least ${fuseGetxattrInParser.size} bytes, got ${payload.length} bytes.`
1275
+ ),
1276
+ interpreted: undefined,
1277
+ };
1278
+ }
1279
+
1280
+ const { size } = fuseGetxattrInParser.parse({ data: payload.subarray(0, fuseGetxattrInParser.size) });
1281
+
1282
+ return {
1283
+ error: undefined,
1284
+ interpreted: {
1285
+ unique,
1286
+ requester,
1287
+ opcode: "GETXATTR",
1288
+ nodeId,
1289
+ size,
1290
+ name: decodeCString(payload.subarray(fuseGetxattrInParser.size)),
1291
+ }
1292
+ };
1293
+ };
1294
+
1295
+ const interpretSetAttr/*: TInterpretFunc<"SETATTR">*/ = ({ unique, nodeId, requester, payload }) => {
1296
+ if (payload.length !== fuseSetattrInParser.size) {
1297
+ return {
1298
+ error: new Error(
1299
+ `Invalid payload size for SETATTR request. Expected ${fuseSetattrInParser.size} bytes, got ${payload.length} bytes.`
1300
+ ),
1301
+ interpreted: undefined,
1302
+ };
1303
+ }
1304
+
1305
+ const parsed = fuseSetattrInParser.parse({ data: payload });
1306
+
1307
+ return {
1308
+ error: undefined,
1309
+ interpreted: {
1310
+ unique,
1311
+ requester,
1312
+ opcode: "SETATTR",
1313
+ nodeId,
1314
+ valid: parsed.valid,
1315
+ fh: parsed.fh,
1316
+ size: parsed.size,
1317
+ lockOwner: parsed.lock_owner,
1318
+ atimeNsec: parsed.atime * 1_000_000_000n + parsed.atimensec,
1319
+ mtimeNsec: parsed.mtime * 1_000_000_000n + parsed.mtimensec,
1320
+ ctimeNsec: parsed.ctime * 1_000_000_000n + parsed.ctimensec,
1321
+ mode: parsed.mode,
1322
+ uid: parsed.uid,
1323
+ gid: parsed.gid,
1324
+ }
1325
+ };
1326
+ };
1327
+
1328
+ const interpretReadLink/*: TInterpretFunc<"READLINK">*/ = ({ unique, nodeId, requester }) => {
1329
+ return {
1330
+ error: undefined,
1331
+ interpreted: {
1332
+ unique,
1333
+ requester,
1334
+ opcode: "READLINK",
1335
+ nodeId,
1336
+ }
1337
+ };
1338
+ };
1339
+
1340
+ const interpretSymlink/*: TInterpretFunc<"SYMLINK">*/ = ({ unique, nodeId, requester, payload }) => {
1341
+ const { first: name, second: target } = decodeCStringPair(payload);
1342
+
1343
+ return {
1344
+ error: undefined,
1345
+ interpreted: {
1346
+ unique,
1347
+ requester,
1348
+ opcode: "SYMLINK",
1349
+ parentNodeId: nodeId,
1350
+ name,
1351
+ target,
1352
+ }
1353
+ };
1354
+ };
1355
+
1356
+ const interpretMknod/*: TInterpretFunc<"MKNOD">*/ = ({ unique, nodeId, requester, payload }) => {
1357
+ if (payload.length < fuseMknodInParser.size) {
1358
+ return {
1359
+ error: new Error(
1360
+ `Invalid payload size for MKNOD request. Expected at least ${fuseMknodInParser.size} bytes, got ${payload.length} bytes.`
1361
+ ),
1362
+ interpreted: undefined,
1363
+ };
1364
+ }
1365
+
1366
+ const { mode, rdev, umask } = fuseMknodInParser.parse({ data: payload.subarray(0, fuseMknodInParser.size) });
1367
+
1368
+ return {
1369
+ error: undefined,
1370
+ interpreted: {
1371
+ unique,
1372
+ requester,
1373
+ opcode: "MKNOD",
1374
+ parentNodeId: nodeId,
1375
+ name: decodeCString(payload.subarray(fuseMknodInParser.size)),
1376
+ mode,
1377
+ rdev,
1378
+ umask,
1379
+ }
1380
+ };
1381
+ };
1382
+
1383
+ const interpretMkdir/*: TInterpretFunc<"MKDIR">*/ = ({ unique, nodeId, requester, payload }) => {
1384
+ if (payload.length < fuseMkdirInParser.size) {
1385
+ return {
1386
+ error: new Error(
1387
+ `Invalid payload size for MKDIR request. Expected at least ${fuseMkdirInParser.size} bytes, got ${payload.length} bytes.`
1388
+ ),
1389
+ interpreted: undefined,
1390
+ };
1391
+ }
1392
+
1393
+ const { mode, umask } = fuseMkdirInParser.parse({ data: payload.subarray(0, fuseMkdirInParser.size) });
1394
+
1395
+ return {
1396
+ error: undefined,
1397
+ interpreted: {
1398
+ unique,
1399
+ requester,
1400
+ opcode: "MKDIR",
1401
+ parentNodeId: nodeId,
1402
+ name: decodeCString(payload.subarray(fuseMkdirInParser.size)),
1403
+ mode,
1404
+ umask,
1405
+ }
1406
+ };
1407
+ };
1408
+
1409
+ const interpretUnlink/*: TInterpretFunc<"UNLINK">*/ = ({ unique, nodeId, requester, payload }) => {
1410
+ return {
1411
+ error: undefined,
1412
+ interpreted: {
1413
+ unique,
1414
+ requester,
1415
+ opcode: "UNLINK",
1416
+ parentNodeId: nodeId,
1417
+ name: decodeCString(payload),
1418
+ }
1419
+ };
1420
+ };
1421
+
1422
+ const interpretRmDir/*: TInterpretFunc<"RMDIR">*/ = ({ unique, nodeId, requester, payload }) => {
1423
+ return {
1424
+ error: undefined,
1425
+ interpreted: {
1426
+ unique,
1427
+ requester,
1428
+ opcode: "RMDIR",
1429
+ parentNodeId: nodeId,
1430
+ name: decodeCString(payload),
1431
+ }
1432
+ };
1433
+ };
1434
+
1435
+ const interpretRename = (
1436
+ { unique, nodeId, requester, payload, supportsFlags }/*:
1437
+ { unique: bigint; nodeId: bigint; requester: TRequesterInfo; payload: Uint8Array; supportsFlags: boolean }*/
1438
+ )/*: TGenericInterpretResult<Extract<TFuseRequest, { opcode: "RENAME" }>>*/ => {
1439
+ const headerSize = supportsFlags ? fuseRename2InParser.size : fuseRenameInParser.size;
1440
+ if (payload.length < headerSize) {
1441
+ return {
1442
+ error: new Error(
1443
+ `Invalid payload size for ${supportsFlags ? "RENAME2" : "RENAME"} request. ` +
1444
+ `Expected at least ${headerSize} bytes, got ${payload.length} bytes.`
1445
+ ),
1446
+ interpreted: undefined,
1447
+ };
1448
+ }
1449
+
1450
+ const { newdir, flags } = supportsFlags
1451
+ ? fuseRename2InParser.parse({ data: payload.subarray(0, fuseRename2InParser.size) })
1452
+ : { ...fuseRenameInParser.parse({ data: payload.subarray(0, fuseRenameInParser.size) }), flags: 0n };
1453
+ const { first: oldName, second: newName } = decodeCStringPair(payload.subarray(headerSize));
1454
+
1455
+ return {
1456
+ error: undefined,
1457
+ interpreted: {
1458
+ unique,
1459
+ requester,
1460
+ opcode: "RENAME",
1461
+ parentNodeId: nodeId,
1462
+ newParentNodeId: newdir,
1463
+ oldName,
1464
+ newName,
1465
+ flags,
1466
+ }
1467
+ };
1468
+ };
1469
+
1470
+ const interpretOpenDir/*: TInterpretFunc<"OPENDIR">*/ = ({ unique, nodeId, requester, payload }) => {
1471
+ if (payload.length !== fuseOpenInParser.size) {
1472
+ return {
1473
+ error: new Error(`Invalid payload size for OPENDIR request. Expected ${fuseOpenInParser.size} bytes, got ${payload.length} bytes.`),
1474
+ interpreted: undefined,
1475
+ };
1476
+ }
1477
+
1478
+ const { flags } = fuseOpenInParser.parse({ data: payload });
1479
+
1480
+ return {
1481
+ error: undefined,
1482
+ interpreted: {
1483
+ unique,
1484
+ requester,
1485
+ opcode: "OPENDIR",
1486
+ nodeId,
1487
+ flags,
1488
+ }
1489
+ };
1490
+ };
1491
+
1492
+ const interpretLink/*: TInterpretFunc<"LINK">*/ = ({ unique, nodeId, requester, payload }) => {
1493
+ if (payload.length < fuseLinkInParser.size) {
1494
+ return {
1495
+ error: new Error(
1496
+ `Invalid payload size for LINK request. Expected at least ${fuseLinkInParser.size} bytes, got ${payload.length} bytes.`
1497
+ ),
1498
+ interpreted: undefined,
1499
+ };
1500
+ }
1501
+
1502
+ const { oldnodeid } = fuseLinkInParser.parse({ data: payload.subarray(0, fuseLinkInParser.size) });
1503
+
1504
+ return {
1505
+ error: undefined,
1506
+ interpreted: {
1507
+ unique,
1508
+ requester,
1509
+ opcode: "LINK",
1510
+ oldNodeId: oldnodeid,
1511
+ newParentNodeId: nodeId,
1512
+ name: decodeCString(payload.subarray(fuseLinkInParser.size)),
1513
+ }
1514
+ };
1515
+ };
1516
+
1517
+ const interpretReadDir/*: TInterpretFunc<"READDIR">*/ = ({ unique, nodeId, requester, payload }) => {
1518
+ if (payload.length !== fuseReadInParser.size) {
1519
+ return {
1520
+ error: new Error(`Invalid payload size for READDIR request. Expected ${fuseReadInParser.size} bytes, got ${payload.length} bytes.`),
1521
+ interpreted: undefined,
1522
+ };
1523
+ }
1524
+
1525
+ const { fh, offset, size, flags, lock_owner, read_flags } = fuseReadInParser.parse({ data: payload });
1526
+
1527
+ return {
1528
+ error: undefined,
1529
+ interpreted: {
1530
+ unique,
1531
+ requester,
1532
+ opcode: "READDIR",
1533
+ nodeId,
1534
+ fh,
1535
+ offset,
1536
+ size,
1537
+ flags,
1538
+ lockOwner: lock_owner,
1539
+ readFlags: read_flags,
1540
+ }
1541
+ };
1542
+ };
1543
+
1544
+ const interpretReleaseDir/*: TInterpretFunc<"RELEASEDIR">*/ = ({ unique, nodeId, requester, payload }) => {
1545
+ if (payload.length !== fuseReleaseInParser.size) {
1546
+ return {
1547
+ error: new Error(
1548
+ `Invalid payload size for RELEASEDIR request. Expected ${fuseReleaseInParser.size} bytes, got ${payload.length} bytes.`
1549
+ ),
1550
+ interpreted: undefined,
1551
+ };
1552
+ }
1553
+
1554
+ const { fh, flags, release_flags, lock_owner } = fuseReleaseInParser.parse({ data: payload });
1555
+
1556
+ return {
1557
+ error: undefined,
1558
+ interpreted: {
1559
+ unique,
1560
+ requester,
1561
+ opcode: "RELEASEDIR",
1562
+ nodeId,
1563
+ fh,
1564
+ flags,
1565
+ releaseFlags: release_flags,
1566
+ lockOwner: lock_owner,
1567
+ }
1568
+ };
1569
+ };
1570
+
1571
+ const interpretRelease/*: TInterpretFunc<"RELEASE">*/ = ({ unique, nodeId, requester, payload }) => {
1572
+ if (payload.length !== fuseReleaseInParser.size) {
1573
+ return {
1574
+ error: new Error(
1575
+ `Invalid payload size for RELEASE request. Expected ${fuseReleaseInParser.size} bytes, got ${payload.length} bytes.`
1576
+ ),
1577
+ interpreted: undefined,
1578
+ };
1579
+ }
1580
+
1581
+ const { fh, flags, release_flags, lock_owner } = fuseReleaseInParser.parse({ data: payload });
1582
+
1583
+ return {
1584
+ error: undefined,
1585
+ interpreted: {
1586
+ unique,
1587
+ requester,
1588
+ opcode: "RELEASE",
1589
+ nodeId,
1590
+ fh,
1591
+ flags,
1592
+ releaseFlags: release_flags,
1593
+ lockOwner: lock_owner,
1594
+ }
1595
+ };
1596
+ };
1597
+
1598
+ const interpretStatFs/*: TInterpretFunc<"STATFS">*/ = ({ unique, requester }) => {
1599
+ return {
1600
+ error: undefined,
1601
+ interpreted: {
1602
+ unique,
1603
+ requester,
1604
+ opcode: "STATFS",
1605
+ }
1606
+ };
1607
+ };
1608
+
1609
+ const interpretLookup/*: TInterpretFunc<"LOOKUP">*/ = ({ unique, nodeId, requester, payload }) => {
1610
+ const name = decodeCString(payload);
1611
+
1612
+ return {
1613
+ error: undefined,
1614
+ interpreted: {
1615
+ unique,
1616
+ requester,
1617
+ opcode: "LOOKUP",
1618
+ parentNodeId: nodeId,
1619
+ name,
1620
+ }
1621
+ };
1622
+ };
1623
+
1624
+ const interpretOpen/*: TInterpretFunc<"OPEN">*/ = ({ unique, nodeId, requester, payload }) => {
1625
+ if (payload.length !== fuseOpenInParser.size) {
1626
+ return {
1627
+ error: new Error(`Invalid payload size for OPEN request. Expected ${fuseOpenInParser.size} bytes, got ${payload.length} bytes.`),
1628
+ interpreted: undefined,
1629
+ };
1630
+ }
1631
+
1632
+ const { flags } = fuseOpenInParser.parse({ data: payload });
1633
+
1634
+ return {
1635
+ error: undefined,
1636
+ interpreted: {
1637
+ unique,
1638
+ requester,
1639
+ opcode: "OPEN",
1640
+ nodeId,
1641
+ flags,
1642
+ }
1643
+ };
1644
+ };
1645
+
1646
+ const interpretRead/*: TInterpretFunc<"READ">*/ = ({ unique, nodeId, requester, payload }) => {
1647
+ if (payload.length !== fuseReadInParser.size) {
1648
+ return {
1649
+ error: new Error(`Invalid payload size for READ request. Expected ${fuseReadInParser.size} bytes, got ${payload.length} bytes.`),
1650
+ interpreted: undefined,
1651
+ };
1652
+ }
1653
+
1654
+ const { fh, offset, size, lock_owner, read_flags } = fuseReadInParser.parse({ data: payload });
1655
+
1656
+ return {
1657
+ error: undefined,
1658
+ interpreted: {
1659
+ unique,
1660
+ requester,
1661
+ opcode: "READ",
1662
+ nodeId,
1663
+ fh,
1664
+ offset,
1665
+ size,
1666
+ lockOwner: lock_owner,
1667
+ readFlags: read_flags,
1668
+ }
1669
+ };
1670
+ };
1671
+
1672
+ const interpretWrite/*: TInterpretFunc<"WRITE">*/ = ({ unique, nodeId, requester, payload }) => {
1673
+ if (payload.length < fuseWriteInParser.size) {
1674
+ return {
1675
+ error: new Error(
1676
+ `Invalid payload size for WRITE request. Expected at least ${fuseWriteInParser.size} bytes, got ${payload.length} bytes.`
1677
+ ),
1678
+ interpreted: undefined,
1679
+ };
1680
+ }
1681
+
1682
+ const { fh, offset, write_flags, lock_owner } = fuseWriteInParser.parse({ data: payload.subarray(0, fuseWriteInParser.size) });
1683
+ const data = payload.subarray(fuseWriteInParser.size);
1684
+
1685
+ return {
1686
+ error: undefined,
1687
+ interpreted: {
1688
+ unique,
1689
+ requester,
1690
+ opcode: "WRITE",
1691
+ nodeId,
1692
+ fh,
1693
+ offset,
1694
+ data,
1695
+ writeFlags: write_flags,
1696
+ lockOwner: lock_owner,
1697
+ }
1698
+ };
1699
+ };
1700
+
1701
+ const interpretFlush/*: TInterpretFunc<"FLUSH">*/ = ({ unique, nodeId, requester, payload }) => {
1702
+ if (payload.length !== fuseFlushInParser.size) {
1703
+ return {
1704
+ error: new Error(`Invalid payload size for FLUSH request. Expected ${fuseFlushInParser.size} bytes, got ${payload.length} bytes.`),
1705
+ interpreted: undefined,
1706
+ };
1707
+ }
1708
+
1709
+ const { fh, lock_owner } = fuseFlushInParser.parse({ data: payload });
1710
+
1711
+ return {
1712
+ error: undefined,
1713
+ interpreted: {
1714
+ unique,
1715
+ requester,
1716
+ opcode: "FLUSH",
1717
+ nodeId,
1718
+ fh,
1719
+ lockOwner: lock_owner,
1720
+ }
1721
+ };
1722
+ };
1723
+
1724
+ const interpretFsync = (
1725
+ { unique, nodeId, requester, payload, forOpcode }/*:
1726
+ { unique: bigint; nodeId: bigint; requester: TRequesterInfo; payload: Uint8Array; forOpcode: "FSYNC" | "FSYNCDIR" }*/
1727
+ )/*: TGenericInterpretResult<Extract<TFuseRequest, { opcode: typeof forOpcode }>>*/ => {
1728
+ if (payload.length !== fuseFsyncInParser.size) {
1729
+ return {
1730
+ error: new Error(
1731
+ `Invalid payload size for ${forOpcode} request. Expected ${fuseFsyncInParser.size} bytes, got ${payload.length} bytes.`
1732
+ ),
1733
+ interpreted: undefined,
1734
+ };
1735
+ }
1736
+
1737
+ const { fh, fsync_flags } = fuseFsyncInParser.parse({ data: payload });
1738
+
1739
+ return {
1740
+ error: undefined,
1741
+ interpreted: {
1742
+ unique,
1743
+ requester,
1744
+ opcode: forOpcode,
1745
+ nodeId,
1746
+ fh,
1747
+ fsyncFlags: fsync_flags,
1748
+ } /*as Extract<TFuseRequest, { opcode: typeof forOpcode }>*/,
1749
+ };
1750
+ };
1751
+
1752
+ const interpretAccess/*: TInterpretFunc<"ACCESS">*/ = ({ unique, nodeId, requester, payload }) => {
1753
+ if (payload.length !== fuseAccessInParser.size) {
1754
+ return {
1755
+ error: new Error(
1756
+ `Invalid payload size for ACCESS request. Expected ${fuseAccessInParser.size} bytes, got ${payload.length} bytes.`
1757
+ ),
1758
+ interpreted: undefined,
1759
+ };
1760
+ }
1761
+
1762
+ const { mask } = fuseAccessInParser.parse({ data: payload });
1763
+
1764
+ return {
1765
+ error: undefined,
1766
+ interpreted: {
1767
+ unique,
1768
+ requester,
1769
+ opcode: "ACCESS",
1770
+ nodeId,
1771
+ mask,
1772
+ }
1773
+ };
1774
+ };
1775
+
1776
+ const interpretSetXAttr/*: TInterpretFunc<"SETXATTR">*/ = ({ unique, nodeId, requester, payload }) => {
1777
+ if (payload.length < fuseSetxattrInParser.size) {
1778
+ return {
1779
+ error: new Error(
1780
+ `Invalid payload size for SETXATTR request. Expected at least ${fuseSetxattrInParser.size} bytes, got ${payload.length} bytes.`
1781
+ ),
1782
+ interpreted: undefined,
1783
+ };
1784
+ }
1785
+
1786
+ const { size, flags, setxattr_flags } = fuseSetxattrInParser.parse({ data: payload.subarray(0, fuseSetxattrInParser.size) });
1787
+ const trailing = payload.subarray(fuseSetxattrInParser.size);
1788
+ const nameTerminator = trailing.indexOf(0);
1789
+ if (nameTerminator === -1) {
1790
+ return {
1791
+ error: new Error("Invalid payload for SETXATTR request. Expected a nul-terminated attribute name."),
1792
+ interpreted: undefined,
1793
+ };
1794
+ }
1795
+
1796
+ const name = decodeCString(trailing);
1797
+ const data = trailing.subarray(nameTerminator + 1);
1798
+ if (BigInt(data.length) !== size) {
1799
+ return {
1800
+ error: new Error(`Invalid payload size for SETXATTR request data. Expected ${size} bytes, got ${data.length} bytes.`),
1801
+ interpreted: undefined,
1802
+ };
1803
+ }
1804
+
1805
+ return {
1806
+ error: undefined,
1807
+ interpreted: {
1808
+ unique,
1809
+ requester,
1810
+ opcode: "SETXATTR",
1811
+ nodeId,
1812
+ name,
1813
+ data,
1814
+ flags,
1815
+ setxattrFlags: setxattr_flags,
1816
+ }
1817
+ };
1818
+ };
1819
+
1820
+ const interpretRemoveXAttr/*: TInterpretFunc<"REMOVEXATTR">*/ = ({ unique, nodeId, requester, payload }) => {
1821
+ return {
1822
+ error: undefined,
1823
+ interpreted: {
1824
+ unique,
1825
+ requester,
1826
+ opcode: "REMOVEXATTR",
1827
+ nodeId,
1828
+ name: decodeCString(payload),
1829
+ }
1830
+ };
1831
+ };
1832
+
1833
+ const interpretCreate/*: TInterpretFunc<"CREATE">*/ = ({ unique, nodeId, requester, payload }) => {
1834
+ if (payload.length < fuseCreateInParser.size) {
1835
+ return {
1836
+ error: new Error(
1837
+ `Invalid payload size for CREATE request. Expected at least ${fuseCreateInParser.size} bytes, got ${payload.length} bytes.`
1838
+ ),
1839
+ interpreted: undefined,
1840
+ };
1841
+ }
1842
+
1843
+ const { flags, mode, umask } = fuseCreateInParser.parse({ data: payload.subarray(0, fuseCreateInParser.size) });
1844
+
1845
+ return {
1846
+ error: undefined,
1847
+ interpreted: {
1848
+ unique,
1849
+ requester,
1850
+ opcode: "CREATE",
1851
+ parentNodeId: nodeId,
1852
+ name: decodeCString(payload.subarray(fuseCreateInParser.size)),
1853
+ flags,
1854
+ mode,
1855
+ umask,
1856
+ }
1857
+ };
1858
+ };
1859
+
1860
+ const interpretDestroy/*: TInterpretFunc<"DESTROY">*/ = ({ unique, requester }) => {
1861
+ return {
1862
+ error: undefined,
1863
+ interpreted: {
1864
+ unique,
1865
+ requester,
1866
+ opcode: "DESTROY",
1867
+ }
1868
+ };
1869
+ };
1870
+
1871
+ const interpretLk = (
1872
+ { unique, nodeId, requester, payload, forOpcode }/*:
1873
+ { unique: bigint; nodeId: bigint; requester: TRequesterInfo; payload: Uint8Array; forOpcode: "GETLK" | "SETLK" | "SETLKW" }*/
1874
+ )/*: TGenericInterpretResult<Extract<TFuseRequest, { opcode: typeof forOpcode }>>*/ => {
1875
+ if (payload.length !== fuseLkInParser.size) {
1876
+ return {
1877
+ error: new Error(
1878
+ `Invalid payload size for ${forOpcode} request. Expected ${fuseLkInParser.size} bytes, got ${payload.length} bytes.`
1879
+ ),
1880
+ interpreted: undefined,
1881
+ };
1882
+ }
1883
+
1884
+ const { fh, owner, lk, lk_flags } = fuseLkInParser.parse({ data: payload });
1885
+
1886
+ return {
1887
+ error: undefined,
1888
+ interpreted: {
1889
+ unique,
1890
+ requester,
1891
+ opcode: forOpcode,
1892
+ nodeId,
1893
+ fh,
1894
+ owner,
1895
+ lockStart: lk.start,
1896
+ lockEnd: lk.end,
1897
+ lockType: lk.type,
1898
+ lockPid: lk.pid,
1899
+ lkFlags: lk_flags,
1900
+ } /*as Extract<TFuseRequest, { opcode: typeof forOpcode }>*/,
1901
+ };
1902
+ };
1903
+
1904
+ const interpretInterrupt/*: TInterpretFunc<"INTERRUPT">*/ = ({ unique, requester, payload }) => {
1905
+ if (payload.length !== fuseInterruptInParser.size) {
1906
+ return {
1907
+ error: new Error(
1908
+ `Invalid payload size for INTERRUPT request. Expected ${fuseInterruptInParser.size} bytes, got ${payload.length} bytes.`
1909
+ ),
1910
+ interpreted: undefined,
1911
+ };
1912
+ }
1913
+
1914
+ const parsed = fuseInterruptInParser.parse({ data: payload });
1915
+
1916
+ return {
1917
+ error: undefined,
1918
+ interpreted: {
1919
+ unique,
1920
+ requester,
1921
+ opcode: "INTERRUPT",
1922
+ targetUnique: parsed.unique,
1923
+ }
1924
+ };
1925
+ };
1926
+
1927
+ const interpretBmap/*: TInterpretFunc<"BMAP">*/ = ({ unique, nodeId, requester, payload }) => {
1928
+ if (payload.length !== fuseBmapInParser.size) {
1929
+ return {
1930
+ error: new Error(`Invalid payload size for BMAP request. Expected ${fuseBmapInParser.size} bytes, got ${payload.length} bytes.`),
1931
+ interpreted: undefined,
1932
+ };
1933
+ }
1934
+
1935
+ const { block, blocksize } = fuseBmapInParser.parse({ data: payload });
1936
+
1937
+ return {
1938
+ error: undefined,
1939
+ interpreted: {
1940
+ unique,
1941
+ requester,
1942
+ opcode: "BMAP",
1943
+ nodeId,
1944
+ block,
1945
+ blocksize,
1946
+ }
1947
+ };
1948
+ };
1949
+
1950
+ const interpretIoctl/*: TInterpretFunc<"IOCTL">*/ = ({ unique, nodeId, requester, payload }) => {
1951
+ if (payload.length < fuseIoctlInParser.size) {
1952
+ return {
1953
+ error: new Error(
1954
+ `Invalid payload size for IOCTL request. Expected at least ${fuseIoctlInParser.size} bytes, got ${payload.length} bytes.`
1955
+ ),
1956
+ interpreted: undefined,
1957
+ };
1958
+ }
1959
+
1960
+ const { fh, flags, cmd, arg, out_size } = fuseIoctlInParser.parse({ data: payload.subarray(0, fuseIoctlInParser.size) });
1961
+
1962
+ return {
1963
+ error: undefined,
1964
+ interpreted: {
1965
+ unique,
1966
+ requester,
1967
+ opcode: "IOCTL",
1968
+ nodeId,
1969
+ fh,
1970
+ flags,
1971
+ cmd,
1972
+ arg,
1973
+ inData: payload.subarray(fuseIoctlInParser.size),
1974
+ outSize: out_size,
1975
+ }
1976
+ };
1977
+ };
1978
+
1979
+ const interpretPoll/*: TInterpretFunc<"POLL">*/ = ({ unique, nodeId, requester, payload }) => {
1980
+ if (payload.length !== fusePollInParser.size) {
1981
+ return {
1982
+ error: new Error(`Invalid payload size for POLL request. Expected ${fusePollInParser.size} bytes, got ${payload.length} bytes.`),
1983
+ interpreted: undefined,
1984
+ };
1985
+ }
1986
+
1987
+ const { fh, kh, flags, events } = fusePollInParser.parse({ data: payload });
1988
+
1989
+ return {
1990
+ error: undefined,
1991
+ interpreted: {
1992
+ unique,
1993
+ requester,
1994
+ opcode: "POLL",
1995
+ nodeId,
1996
+ fh,
1997
+ kh,
1998
+ flags,
1999
+ events,
2000
+ }
2001
+ };
2002
+ };
2003
+
2004
+ const interpretNotifyReply/*: TInterpretFunc<"NOTIFY_REPLY">*/ = ({ unique, requester, payload }) => {
2005
+ return {
2006
+ error: undefined,
2007
+ interpreted: {
2008
+ unique,
2009
+ requester,
2010
+ opcode: "NOTIFY_REPLY",
2011
+ data: payload,
2012
+ }
2013
+ };
2014
+ };
2015
+
2016
+ const interpretFallocate/*: TInterpretFunc<"FALLOCATE">*/ = ({ unique, nodeId, requester, payload }) => {
2017
+ if (payload.length !== fuseFallocateInParser.size) {
2018
+ return {
2019
+ error: new Error(
2020
+ `Invalid payload size for FALLOCATE request. Expected ${fuseFallocateInParser.size} bytes, got ${payload.length} bytes.`
2021
+ ),
2022
+ interpreted: undefined,
2023
+ };
2024
+ }
2025
+
2026
+ const { fh, offset, length, mode } = fuseFallocateInParser.parse({ data: payload });
2027
+
2028
+ return {
2029
+ error: undefined,
2030
+ interpreted: {
2031
+ unique,
2032
+ requester,
2033
+ opcode: "FALLOCATE",
2034
+ nodeId,
2035
+ fh,
2036
+ offset,
2037
+ length,
2038
+ mode,
2039
+ }
2040
+ };
2041
+ };
2042
+
2043
+ const interpretReadDirPlus/*: TInterpretFunc<"READDIRPLUS">*/ = ({ unique, nodeId, requester, payload }) => {
2044
+ if (payload.length !== fuseReadInParser.size) {
2045
+ return {
2046
+ error: new Error(
2047
+ `Invalid payload size for READDIRPLUS request. Expected ${fuseReadInParser.size} bytes, got ${payload.length} bytes.`
2048
+ ),
2049
+ interpreted: undefined,
2050
+ };
2051
+ }
2052
+
2053
+ const { fh, offset, size, flags, lock_owner, read_flags } = fuseReadInParser.parse({ data: payload });
2054
+
2055
+ return {
2056
+ error: undefined,
2057
+ interpreted: {
2058
+ unique,
2059
+ requester,
2060
+ opcode: "READDIRPLUS",
2061
+ nodeId,
2062
+ fh,
2063
+ offset,
2064
+ size,
2065
+ flags,
2066
+ lockOwner: lock_owner,
2067
+ readFlags: read_flags,
2068
+ }
2069
+ };
2070
+ };
2071
+
2072
+ const interpretMessageFromKernel = (
2073
+ { parsedMessageFromKernel }/*: { parsedMessageFromKernel: TParsedMessageFromKernel }*/
2074
+ )/*: TGenericInterpretResult<TFuseRequest>*/ => {
2075
+
2076
+ const unique = parsedMessageFromKernel.header.unique;
2077
+ const nodeId = parsedMessageFromKernel.header.nodeid;
2078
+ const requester = {
2079
+ uid: parsedMessageFromKernel.header.uid,
2080
+ gid: parsedMessageFromKernel.header.gid,
2081
+ pid: parsedMessageFromKernel.header.pid,
2082
+ };
2083
+
2084
+ switch (parsedMessageFromKernel.header.opcode) {
2085
+ case BigInt(opcode.INIT): {
2086
+ return interpretInit({
2087
+ unique,
2088
+ nodeId,
2089
+ requester,
2090
+ payload: parsedMessageFromKernel.payload,
2091
+ });
2092
+ }
2093
+
2094
+ case BigInt(opcode.FORGET): {
2095
+ return interpretForget({
2096
+ unique,
2097
+ nodeId,
2098
+ requester,
2099
+ payload: parsedMessageFromKernel.payload,
2100
+ });
2101
+ }
2102
+
2103
+ case BigInt(opcode.BATCH_FORGET): {
2104
+ return interpretBatchForget({
2105
+ unique,
2106
+ nodeId,
2107
+ requester,
2108
+ payload: parsedMessageFromKernel.payload,
2109
+ });
2110
+ }
2111
+
2112
+ case BigInt(opcode.GETATTR): {
2113
+ return interpretGetAttr({
2114
+ unique,
2115
+ nodeId,
2116
+ requester,
2117
+ payload: parsedMessageFromKernel.payload,
2118
+ });
2119
+ }
2120
+
2121
+ case BigInt(opcode.SETATTR): {
2122
+ return interpretSetAttr({
2123
+ unique,
2124
+ nodeId,
2125
+ requester,
2126
+ payload: parsedMessageFromKernel.payload,
2127
+ });
2128
+ }
2129
+
2130
+ case BigInt(opcode.LISTXATTR): {
2131
+ return interpretListXAttrRequest({
2132
+ unique,
2133
+ nodeId,
2134
+ requester,
2135
+ payload: parsedMessageFromKernel.payload,
2136
+ });
2137
+ }
2138
+
2139
+ case BigInt(opcode.GETXATTR): {
2140
+ return interpretGetXAttr({
2141
+ unique,
2142
+ nodeId,
2143
+ requester,
2144
+ payload: parsedMessageFromKernel.payload,
2145
+ });
2146
+ }
2147
+
2148
+ case BigInt(opcode.READLINK): {
2149
+ return interpretReadLink({
2150
+ unique,
2151
+ nodeId,
2152
+ requester,
2153
+ payload: parsedMessageFromKernel.payload,
2154
+ });
2155
+ }
2156
+
2157
+ case BigInt(opcode.SYMLINK): {
2158
+ return interpretSymlink({
2159
+ unique,
2160
+ nodeId,
2161
+ requester,
2162
+ payload: parsedMessageFromKernel.payload,
2163
+ });
2164
+ }
2165
+
2166
+ case BigInt(opcode.MKNOD): {
2167
+ return interpretMknod({
2168
+ unique,
2169
+ nodeId,
2170
+ requester,
2171
+ payload: parsedMessageFromKernel.payload,
2172
+ });
2173
+ }
2174
+
2175
+ case BigInt(opcode.MKDIR): {
2176
+ return interpretMkdir({
2177
+ unique,
2178
+ nodeId,
2179
+ requester,
2180
+ payload: parsedMessageFromKernel.payload,
2181
+ });
2182
+ }
2183
+
2184
+ case BigInt(opcode.UNLINK): {
2185
+ return interpretUnlink({
2186
+ unique,
2187
+ nodeId,
2188
+ requester,
2189
+ payload: parsedMessageFromKernel.payload,
2190
+ });
2191
+ }
2192
+
2193
+ case BigInt(opcode.RMDIR): {
2194
+ return interpretRmDir({
2195
+ unique,
2196
+ nodeId,
2197
+ requester,
2198
+ payload: parsedMessageFromKernel.payload,
2199
+ });
2200
+ }
2201
+
2202
+ case BigInt(opcode.RENAME): {
2203
+ return interpretRename({
2204
+ unique,
2205
+ nodeId,
2206
+ requester,
2207
+ payload: parsedMessageFromKernel.payload,
2208
+ supportsFlags: false,
2209
+ });
2210
+ }
2211
+
2212
+ case BigInt(opcode.RENAME2): {
2213
+ return interpretRename({
2214
+ unique,
2215
+ nodeId,
2216
+ requester,
2217
+ payload: parsedMessageFromKernel.payload,
2218
+ supportsFlags: true,
2219
+ });
2220
+ }
2221
+
2222
+ case BigInt(opcode.OPENDIR): {
2223
+ return interpretOpenDir({
2224
+ unique,
2225
+ nodeId,
2226
+ requester,
2227
+ payload: parsedMessageFromKernel.payload,
2228
+ });
2229
+ }
2230
+
2231
+ case BigInt(opcode.LINK): {
2232
+ return interpretLink({
2233
+ unique,
2234
+ nodeId,
2235
+ requester,
2236
+ payload: parsedMessageFromKernel.payload,
2237
+ });
2238
+ }
2239
+
2240
+ case BigInt(opcode.READDIR): {
2241
+ return interpretReadDir({
2242
+ unique,
2243
+ nodeId,
2244
+ requester,
2245
+ payload: parsedMessageFromKernel.payload,
2246
+ });
2247
+ }
2248
+
2249
+ case BigInt(opcode.RELEASE): {
2250
+ return interpretRelease({
2251
+ unique,
2252
+ nodeId,
2253
+ requester,
2254
+ payload: parsedMessageFromKernel.payload,
2255
+ });
2256
+ }
2257
+
2258
+ case BigInt(opcode.RELEASEDIR): {
2259
+ return interpretReleaseDir({
2260
+ unique,
2261
+ nodeId,
2262
+ requester,
2263
+ payload: parsedMessageFromKernel.payload,
2264
+ });
2265
+ }
2266
+
2267
+ case BigInt(opcode.FSYNCDIR): {
2268
+ return interpretFsync({
2269
+ unique,
2270
+ nodeId,
2271
+ requester,
2272
+ payload: parsedMessageFromKernel.payload,
2273
+ forOpcode: "FSYNCDIR",
2274
+ });
2275
+ }
2276
+
2277
+ case BigInt(opcode.STATFS): {
2278
+ return interpretStatFs({
2279
+ unique,
2280
+ nodeId,
2281
+ requester,
2282
+ payload: parsedMessageFromKernel.payload,
2283
+ });
2284
+ }
2285
+
2286
+ case BigInt(opcode.LOOKUP): {
2287
+ return interpretLookup({
2288
+ unique,
2289
+ nodeId,
2290
+ requester,
2291
+ payload: parsedMessageFromKernel.payload,
2292
+ });
2293
+ }
2294
+
2295
+ case BigInt(opcode.OPEN): {
2296
+ return interpretOpen({
2297
+ unique,
2298
+ nodeId,
2299
+ requester,
2300
+ payload: parsedMessageFromKernel.payload,
2301
+ });
2302
+ }
2303
+
2304
+ case BigInt(opcode.READ): {
2305
+ return interpretRead({
2306
+ unique,
2307
+ nodeId,
2308
+ requester,
2309
+ payload: parsedMessageFromKernel.payload,
2310
+ });
2311
+ }
2312
+
2313
+ case BigInt(opcode.WRITE): {
2314
+ return interpretWrite({
2315
+ unique,
2316
+ nodeId,
2317
+ requester,
2318
+ payload: parsedMessageFromKernel.payload,
2319
+ });
2320
+ }
2321
+
2322
+ case BigInt(opcode.FLUSH): {
2323
+ return interpretFlush({
2324
+ unique,
2325
+ nodeId,
2326
+ requester,
2327
+ payload: parsedMessageFromKernel.payload,
2328
+ });
2329
+ }
2330
+
2331
+ case BigInt(opcode.FSYNC): {
2332
+ return interpretFsync({
2333
+ unique,
2334
+ nodeId,
2335
+ requester,
2336
+ payload: parsedMessageFromKernel.payload,
2337
+ forOpcode: "FSYNC",
2338
+ });
2339
+ }
2340
+
2341
+ case BigInt(opcode.ACCESS): {
2342
+ return interpretAccess({
2343
+ unique,
2344
+ nodeId,
2345
+ requester,
2346
+ payload: parsedMessageFromKernel.payload,
2347
+ });
2348
+ }
2349
+
2350
+ case BigInt(opcode.SETXATTR): {
2351
+ return interpretSetXAttr({
2352
+ unique,
2353
+ nodeId,
2354
+ requester,
2355
+ payload: parsedMessageFromKernel.payload,
2356
+ });
2357
+ }
2358
+
2359
+ case BigInt(opcode.REMOVEXATTR): {
2360
+ return interpretRemoveXAttr({
2361
+ unique,
2362
+ nodeId,
2363
+ requester,
2364
+ payload: parsedMessageFromKernel.payload,
2365
+ });
2366
+ }
2367
+
2368
+ case BigInt(opcode.CREATE): {
2369
+ return interpretCreate({
2370
+ unique,
2371
+ nodeId,
2372
+ requester,
2373
+ payload: parsedMessageFromKernel.payload,
2374
+ });
2375
+ }
2376
+
2377
+ case BigInt(opcode.DESTROY): {
2378
+ return interpretDestroy({
2379
+ unique,
2380
+ nodeId,
2381
+ requester,
2382
+ payload: parsedMessageFromKernel.payload,
2383
+ });
2384
+ }
2385
+
2386
+ case BigInt(opcode.GETLK): {
2387
+ return interpretLk({
2388
+ unique,
2389
+ nodeId,
2390
+ requester,
2391
+ payload: parsedMessageFromKernel.payload,
2392
+ forOpcode: "GETLK",
2393
+ });
2394
+ }
2395
+
2396
+ case BigInt(opcode.SETLK): {
2397
+ return interpretLk({
2398
+ unique,
2399
+ nodeId,
2400
+ requester,
2401
+ payload: parsedMessageFromKernel.payload,
2402
+ forOpcode: "SETLK",
2403
+ });
2404
+ }
2405
+
2406
+ case BigInt(opcode.SETLKW): {
2407
+ return interpretLk({
2408
+ unique,
2409
+ nodeId,
2410
+ requester,
2411
+ payload: parsedMessageFromKernel.payload,
2412
+ forOpcode: "SETLKW",
2413
+ });
2414
+ }
2415
+
2416
+ case BigInt(opcode.INTERRUPT): {
2417
+ return interpretInterrupt({
2418
+ unique,
2419
+ nodeId,
2420
+ requester,
2421
+ payload: parsedMessageFromKernel.payload,
2422
+ });
2423
+ }
2424
+
2425
+ case BigInt(opcode.BMAP): {
2426
+ return interpretBmap({
2427
+ unique,
2428
+ nodeId,
2429
+ requester,
2430
+ payload: parsedMessageFromKernel.payload,
2431
+ });
2432
+ }
2433
+
2434
+ case BigInt(opcode.IOCTL): {
2435
+ return interpretIoctl({
2436
+ unique,
2437
+ nodeId,
2438
+ requester,
2439
+ payload: parsedMessageFromKernel.payload,
2440
+ });
2441
+ }
2442
+
2443
+ case BigInt(opcode.POLL): {
2444
+ return interpretPoll({
2445
+ unique,
2446
+ nodeId,
2447
+ requester,
2448
+ payload: parsedMessageFromKernel.payload,
2449
+ });
2450
+ }
2451
+
2452
+ case BigInt(opcode.NOTIFY_REPLY): {
2453
+ return interpretNotifyReply({
2454
+ unique,
2455
+ nodeId,
2456
+ requester,
2457
+ payload: parsedMessageFromKernel.payload,
2458
+ });
2459
+ }
2460
+
2461
+ case BigInt(opcode.FALLOCATE): {
2462
+ return interpretFallocate({
2463
+ unique,
2464
+ nodeId,
2465
+ requester,
2466
+ payload: parsedMessageFromKernel.payload,
2467
+ });
2468
+ }
2469
+
2470
+ case BigInt(opcode.READDIRPLUS): {
2471
+ return interpretReadDirPlus({
2472
+ unique,
2473
+ nodeId,
2474
+ requester,
2475
+ payload: parsedMessageFromKernel.payload,
2476
+ });
2477
+ }
2478
+
2479
+ default: {
2480
+ break;
2481
+ }
2482
+ }
2483
+
2484
+ return {
2485
+ error: new Error(`Unsupported opcode: ${parsedMessageFromKernel.header.opcode}`),
2486
+ interpreted: undefined,
2487
+ };
2488
+ };
2489
+
2490
+ return {
2491
+ interpretMessageFromKernel,
2492
+ };
2493
+ };
2494
+
2495
+
2496
+ const createMessageToKernelInterpreter = () => {
2497
+
2498
+ /*type TInterpretFunc<T extends string> = (
2499
+ args: { unique: bigint, payload: Uint8Array }
2500
+ ) => TGenericInterpretResult<Extract<TFuseResponse, { forOpcode: T }>>;*/
2501
+
2502
+ const encodeInitResponse = (
2503
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "INIT", errorCode: undefined }> }*/
2504
+ )/*: TParsedMessageToKernel*/ => {
2505
+
2506
+ const initResult = response.result;
2507
+
2508
+ const initResultPayload = fuseInitOutParser.format({
2509
+ value: {
2510
+ major: initResult.major,
2511
+ minor: initResult.minor,
2512
+ max_readahead: initResult.maxReadahead,
2513
+ flags: initResult.flags,
2514
+ max_background: initResult.maxBackground,
2515
+ congestion_threshold: initResult.congestionThreshold,
2516
+ max_write: initResult.maxWrite,
2517
+ time_gran: initResult.timeGran,
2518
+ max_pages: initResult.maxPages,
2519
+ map_alignment: initResult.mapAlignment,
2520
+ flags2: initResult.flags2,
2521
+ max_stack_depth: initResult.maxStackDepth,
2522
+ request_timeout: initResult.requestTimeout,
2523
+ unused: [0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n, 0n],
2524
+ }
2525
+ });
2526
+
2527
+ return {
2528
+ header: {
2529
+ unique: response.unique,
2530
+ error: 0n,
2531
+ },
2532
+ payload: initResultPayload,
2533
+ };
2534
+ };
2535
+
2536
+ const encodeGetAttrResponse = (
2537
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "GETATTR", errorCode: undefined }> }*/
2538
+ )/*: TParsedMessageToKernel*/ => {
2539
+ return encodeAttrPayload({ unique: response.unique, forOpcode: "GETATTR", result: response.result });
2540
+ };
2541
+
2542
+ const encodeSetAttrResponse = (
2543
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "SETATTR", errorCode: undefined }> }*/
2544
+ )/*: TParsedMessageToKernel*/ => {
2545
+ return encodeAttrPayload({ unique: response.unique, forOpcode: "SETATTR", result: response.result });
2546
+ };
2547
+
2548
+ const encodeOpenDirResponse = (
2549
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "OPENDIR", errorCode: undefined }> }*/
2550
+ )/*: TParsedMessageToKernel*/ => {
2551
+ return encodeOpenPayload({ unique: response.unique, result: response.result });
2552
+ };
2553
+
2554
+ const encodeReadDirResponse = (
2555
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "READDIR", errorCode: undefined }> }*/
2556
+ )/*: TParsedMessageToKernel*/ => {
2557
+ return {
2558
+ header: {
2559
+ unique: response.unique,
2560
+ error: 0n,
2561
+ },
2562
+ payload: response.result.data,
2563
+ };
2564
+ };
2565
+
2566
+ const encodeReleaseDirResponse = (
2567
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "RELEASEDIR", errorCode: undefined }> }*/
2568
+ )/*: TParsedMessageToKernel*/ => {
2569
+ return encodeEmptyPayload({ unique: response.unique });
2570
+ };
2571
+
2572
+ const encodeReleaseResponse = (
2573
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "RELEASE", errorCode: undefined }> }*/
2574
+ )/*: TParsedMessageToKernel*/ => {
2575
+ return encodeEmptyPayload({ unique: response.unique });
2576
+ };
2577
+
2578
+ const encodeOpenResponse = (
2579
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "OPEN", errorCode: undefined }> }*/
2580
+ )/*: TParsedMessageToKernel*/ => {
2581
+ return encodeOpenPayload({ unique: response.unique, result: response.result });
2582
+ };
2583
+
2584
+ const encodeReadResponse = (
2585
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "READ", errorCode: undefined }> }*/
2586
+ )/*: TParsedMessageToKernel*/ => {
2587
+ return {
2588
+ header: {
2589
+ unique: response.unique,
2590
+ error: 0n,
2591
+ },
2592
+ payload: response.result.data,
2593
+ };
2594
+ };
2595
+
2596
+ const encodeWriteResponse = (
2597
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "WRITE", errorCode: undefined }> }*/
2598
+ )/*: TParsedMessageToKernel*/ => {
2599
+ const writeResultPayload = fuseWriteOutParser.format({
2600
+ value: {
2601
+ size: response.result.bytesWritten,
2602
+ padding: 0n,
2603
+ }
2604
+ });
2605
+
2606
+ return {
2607
+ header: {
2608
+ unique: response.unique,
2609
+ error: 0n,
2610
+ },
2611
+ payload: writeResultPayload,
2612
+ };
2613
+ };
2614
+
2615
+ const encodeLookupResponse = (
2616
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "LOOKUP", errorCode: undefined }> }*/
2617
+ )/*: TParsedMessageToKernel*/ => {
2618
+ return encodeEntryPayload({ unique: response.unique, forOpcode: "LOOKUP", result: response.result });
2619
+ };
2620
+
2621
+ const encodeSymlinkResponse = (
2622
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "SYMLINK", errorCode: undefined }> }*/
2623
+ )/*: TParsedMessageToKernel*/ => {
2624
+ return encodeEntryPayload({ unique: response.unique, forOpcode: "SYMLINK", result: response.result });
2625
+ };
2626
+
2627
+ const encodeMkdirResponse = (
2628
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "MKDIR", errorCode: undefined }> }*/
2629
+ )/*: TParsedMessageToKernel*/ => {
2630
+ return encodeEntryPayload({ unique: response.unique, forOpcode: "MKDIR", result: response.result });
2631
+ };
2632
+
2633
+ const encodeStatFsResponse = (
2634
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "STATFS", errorCode: undefined }> }*/
2635
+ )/*: TParsedMessageToKernel*/ => {
2636
+ const statFsResult = response.result;
2637
+
2638
+ const statFsResultPayload = fuseStatfsOutParser.format({
2639
+ value: {
2640
+ st: {
2641
+ blocks: statFsResult.blocks,
2642
+ bfree: statFsResult.bfree,
2643
+ bavail: statFsResult.bavail,
2644
+ files: statFsResult.files,
2645
+ ffree: statFsResult.ffree,
2646
+ bsize: statFsResult.bsize,
2647
+ namelen: statFsResult.namelen,
2648
+ frsize: statFsResult.frsize,
2649
+ padding: 0n,
2650
+ spare: [0n, 0n, 0n, 0n, 0n, 0n],
2651
+ }
2652
+ }
2653
+ });
2654
+
2655
+ return {
2656
+ header: {
2657
+ unique: response.unique,
2658
+ error: 0n,
2659
+ },
2660
+ payload: statFsResultPayload,
2661
+ };
2662
+ };
2663
+
2664
+ const encodeGetXAttrResponse = (
2665
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "GETXATTR", errorCode: undefined }> }*/
2666
+ )/*: TParsedMessageToKernel*/ => {
2667
+ return encodeXAttrPayload({ unique: response.unique, result: response.result });
2668
+ };
2669
+
2670
+ const encodeListXAttrResponse = (
2671
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "LISTXATTR", errorCode: undefined }> }*/
2672
+ )/*: TParsedMessageToKernel*/ => {
2673
+ return encodeXAttrPayload({ unique: response.unique, result: response.result });
2674
+ };
2675
+
2676
+ const encodeReadLinkResponse = (
2677
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "READLINK", errorCode: undefined }> }*/
2678
+ )/*: TParsedMessageToKernel*/ => {
2679
+ return {
2680
+ header: {
2681
+ unique: response.unique,
2682
+ error: 0n,
2683
+ },
2684
+ payload: new TextEncoder().encode(response.result.target),
2685
+ };
2686
+ };
2687
+
2688
+ const encodeUnlinkResponse = (
2689
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "UNLINK", errorCode: undefined }> }*/
2690
+ )/*: TParsedMessageToKernel*/ => {
2691
+ return encodeEmptyPayload({ unique: response.unique });
2692
+ };
2693
+
2694
+ const encodeRmDirResponse = (
2695
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "RMDIR", errorCode: undefined }> }*/
2696
+ )/*: TParsedMessageToKernel*/ => {
2697
+ return encodeEmptyPayload({ unique: response.unique });
2698
+ };
2699
+
2700
+ const encodeRenameResponse = (
2701
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "RENAME", errorCode: undefined }> }*/
2702
+ )/*: TParsedMessageToKernel*/ => {
2703
+ return encodeEmptyPayload({ unique: response.unique });
2704
+ };
2705
+
2706
+ const encodeFsyncResponse = (
2707
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "FSYNC", errorCode: undefined }> }*/
2708
+ )/*: TParsedMessageToKernel*/ => {
2709
+ return encodeEmptyPayload({ unique: response.unique });
2710
+ };
2711
+
2712
+ const encodeSetXAttrResponse = (
2713
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "SETXATTR", errorCode: undefined }> }*/
2714
+ )/*: TParsedMessageToKernel*/ => {
2715
+ return encodeEmptyPayload({ unique: response.unique });
2716
+ };
2717
+
2718
+ const encodeRemoveXAttrResponse = (
2719
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "REMOVEXATTR", errorCode: undefined }> }*/
2720
+ )/*: TParsedMessageToKernel*/ => {
2721
+ return encodeEmptyPayload({ unique: response.unique });
2722
+ };
2723
+
2724
+ const encodeMknodResponse = (
2725
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "MKNOD", errorCode: undefined }> }*/
2726
+ )/*: TParsedMessageToKernel*/ => {
2727
+ return encodeEntryPayload({ unique: response.unique, forOpcode: "MKNOD", result: response.result });
2728
+ };
2729
+
2730
+ const encodeLinkResponse = (
2731
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "LINK", errorCode: undefined }> }*/
2732
+ )/*: TParsedMessageToKernel*/ => {
2733
+ return encodeEntryPayload({ unique: response.unique, forOpcode: "LINK", result: response.result });
2734
+ };
2735
+
2736
+ const encodeFsyncDirResponse = (
2737
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "FSYNCDIR", errorCode: undefined }> }*/
2738
+ )/*: TParsedMessageToKernel*/ => {
2739
+ return encodeEmptyPayload({ unique: response.unique });
2740
+ };
2741
+
2742
+ const encodeFlushResponse = (
2743
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "FLUSH", errorCode: undefined }> }*/
2744
+ )/*: TParsedMessageToKernel*/ => {
2745
+ return encodeEmptyPayload({ unique: response.unique });
2746
+ };
2747
+
2748
+ const encodeAccessResponse = (
2749
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "ACCESS", errorCode: undefined }> }*/
2750
+ )/*: TParsedMessageToKernel*/ => {
2751
+ return encodeEmptyPayload({ unique: response.unique });
2752
+ };
2753
+
2754
+ const encodeCreateResponse = (
2755
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "CREATE", errorCode: undefined }> }*/
2756
+ )/*: TParsedMessageToKernel*/ => {
2757
+ const entryPayload = fuseEntryOutParser.format({
2758
+ value: {
2759
+ nodeid: response.result.nodeId,
2760
+ generation: response.result.generation,
2761
+ entry_valid: response.result.entryValidNsec / 1_000_000_000n,
2762
+ attr_valid: response.result.attrValidNsec / 1_000_000_000n,
2763
+ entry_valid_nsec: response.result.entryValidNsec % 1_000_000_000n,
2764
+ attr_valid_nsec: response.result.attrValidNsec % 1_000_000_000n,
2765
+ attr: fuseAttrToPayloadValue({ attr: response.result.attr }),
2766
+ }
2767
+ });
2768
+ const openPayload = fuseOpenOutParser.format({
2769
+ value: {
2770
+ fh: response.result.fh,
2771
+ open_flags: openFlagsToKernelToBitmask({ openFlagsToKernel: response.result.openFlagsToKernel }),
2772
+ backing_id: 0n,
2773
+ }
2774
+ });
2775
+
2776
+ const payload = new Uint8Array(entryPayload.length + openPayload.length);
2777
+ payload.set(entryPayload, 0);
2778
+ payload.set(openPayload, entryPayload.length);
2779
+
2780
+ return {
2781
+ header: {
2782
+ unique: response.unique,
2783
+ error: 0n,
2784
+ },
2785
+ payload,
2786
+ };
2787
+ };
2788
+
2789
+ const encodeDestroyResponse = (
2790
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "DESTROY", errorCode: undefined }> }*/
2791
+ )/*: TParsedMessageToKernel*/ => {
2792
+ return encodeEmptyPayload({ unique: response.unique });
2793
+ };
2794
+
2795
+ const encodeGetLkResponse = (
2796
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "GETLK", errorCode: undefined }> }*/
2797
+ )/*: TParsedMessageToKernel*/ => {
2798
+ const payload = fuseLkOutParser.format({
2799
+ value: {
2800
+ lk: {
2801
+ start: response.result.lockStart,
2802
+ end: response.result.lockEnd,
2803
+ type: response.result.lockType,
2804
+ pid: response.result.lockPid,
2805
+ },
2806
+ }
2807
+ });
2808
+
2809
+ return {
2810
+ header: {
2811
+ unique: response.unique,
2812
+ error: 0n,
2813
+ },
2814
+ payload,
2815
+ };
2816
+ };
2817
+
2818
+ const encodeSetLkResponse = (
2819
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "SETLK", errorCode: undefined }> }*/
2820
+ )/*: TParsedMessageToKernel*/ => {
2821
+ return encodeEmptyPayload({ unique: response.unique });
2822
+ };
2823
+
2824
+ const encodeSetLkWResponse = (
2825
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "SETLKW", errorCode: undefined }> }*/
2826
+ )/*: TParsedMessageToKernel*/ => {
2827
+ return encodeEmptyPayload({ unique: response.unique });
2828
+ };
2829
+
2830
+ const encodeBmapResponse = (
2831
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "BMAP", errorCode: undefined }> }*/
2832
+ )/*: TParsedMessageToKernel*/ => {
2833
+ const payload = fuseBmapOutParser.format({
2834
+ value: {
2835
+ block: response.result.block,
2836
+ }
2837
+ });
2838
+
2839
+ return {
2840
+ header: {
2841
+ unique: response.unique,
2842
+ error: 0n,
2843
+ },
2844
+ payload,
2845
+ };
2846
+ };
2847
+
2848
+ const encodeIoctlResponse = (
2849
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "IOCTL", errorCode: undefined }> }*/
2850
+ )/*: TParsedMessageToKernel*/ => {
2851
+ const headerPayload = fuseIoctlOutParser.format({
2852
+ value: {
2853
+ result: response.result.ioctlResult,
2854
+ flags: response.result.flags,
2855
+ in_iovs: 0n,
2856
+ out_iovs: 0n,
2857
+ }
2858
+ });
2859
+
2860
+ const payload = new Uint8Array(headerPayload.length + response.result.data.length);
2861
+ payload.set(headerPayload, 0);
2862
+ payload.set(response.result.data, headerPayload.length);
2863
+
2864
+ return {
2865
+ header: {
2866
+ unique: response.unique,
2867
+ error: 0n,
2868
+ },
2869
+ payload,
2870
+ };
2871
+ };
2872
+
2873
+ const encodePollResponse = (
2874
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "POLL", errorCode: undefined }> }*/
2875
+ )/*: TParsedMessageToKernel*/ => {
2876
+ const payload = fusePollOutParser.format({
2877
+ value: {
2878
+ revents: response.result.revents,
2879
+ padding: 0n,
2880
+ }
2881
+ });
2882
+
2883
+ return {
2884
+ header: {
2885
+ unique: response.unique,
2886
+ error: 0n,
2887
+ },
2888
+ payload,
2889
+ };
2890
+ };
2891
+
2892
+ const encodeFallocateResponse = (
2893
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "FALLOCATE", errorCode: undefined }> }*/
2894
+ )/*: TParsedMessageToKernel*/ => {
2895
+ return encodeEmptyPayload({ unique: response.unique });
2896
+ };
2897
+
2898
+ const encodeReadDirPlusResponse = (
2899
+ { response }/*: { response: Extract<TFuseResponse, { forOpcode: "READDIRPLUS", errorCode: undefined }> }*/
2900
+ )/*: TParsedMessageToKernel*/ => {
2901
+ return {
2902
+ header: {
2903
+ unique: response.unique,
2904
+ error: 0n,
2905
+ },
2906
+ payload: response.result.data,
2907
+ };
2908
+ };
2909
+
2910
+ const encodeMessageToKernel = ({ response }/*: { response: TFuseResponse }*/)/*: TParsedMessageToKernel*/ => {
2911
+
2912
+ if (response.errorCode !== undefined) {
2913
+
2914
+ if (response.errorCode > 0) {
2915
+ throw Error(`fuse expects error codes to be negative numbers. Got ${response.errorCode}`);
2916
+ }
2917
+
2918
+ return {
2919
+ header: {
2920
+ unique: response.unique,
2921
+ error: BigInt(response.errorCode),
2922
+ },
2923
+ payload: new Uint8Array(0),
2924
+ };
2925
+ }
2926
+
2927
+ switch (response.forOpcode) {
2928
+ case "INIT": {
2929
+ return encodeInitResponse({ response });
2930
+ }
2931
+
2932
+ case "GETATTR": {
2933
+ return encodeGetAttrResponse({ response });
2934
+ }
2935
+
2936
+ case "SETATTR": {
2937
+ return encodeSetAttrResponse({ response });
2938
+ }
2939
+
2940
+ case "LISTXATTR": {
2941
+ return encodeListXAttrResponse({ response });
2942
+ }
2943
+
2944
+ case "GETXATTR": {
2945
+ return encodeGetXAttrResponse({ response });
2946
+ }
2947
+
2948
+ case "READLINK": {
2949
+ return encodeReadLinkResponse({ response });
2950
+ }
2951
+
2952
+ case "MKNOD": {
2953
+ return encodeMknodResponse({ response });
2954
+ }
2955
+
2956
+ case "OPENDIR": {
2957
+ return encodeOpenDirResponse({ response });
2958
+ }
2959
+
2960
+ case "READDIR": {
2961
+ return encodeReadDirResponse({ response });
2962
+ }
2963
+
2964
+ case "RELEASEDIR": {
2965
+ return encodeReleaseDirResponse({ response });
2966
+ }
2967
+
2968
+ case "FSYNCDIR": {
2969
+ return encodeFsyncDirResponse({ response });
2970
+ }
2971
+
2972
+ case "RELEASE": {
2973
+ return encodeReleaseResponse({ response });
2974
+ }
2975
+
2976
+ case "STATFS": {
2977
+ return encodeStatFsResponse({ response });
2978
+ }
2979
+
2980
+ case "LOOKUP": {
2981
+ return encodeLookupResponse({ response });
2982
+ }
2983
+
2984
+ case "SYMLINK": {
2985
+ return encodeSymlinkResponse({ response });
2986
+ }
2987
+
2988
+ case "MKDIR": {
2989
+ return encodeMkdirResponse({ response });
2990
+ }
2991
+
2992
+ case "LINK": {
2993
+ return encodeLinkResponse({ response });
2994
+ }
2995
+
2996
+ case "UNLINK": {
2997
+ return encodeUnlinkResponse({ response });
2998
+ }
2999
+
3000
+ case "RMDIR": {
3001
+ return encodeRmDirResponse({ response });
3002
+ }
3003
+
3004
+ case "RENAME": {
3005
+ return encodeRenameResponse({ response });
3006
+ }
3007
+
3008
+ case "OPEN": {
3009
+ return encodeOpenResponse({ response });
3010
+ }
3011
+
3012
+ case "READ": {
3013
+ return encodeReadResponse({ response });
3014
+ }
3015
+
3016
+ case "WRITE": {
3017
+ return encodeWriteResponse({ response });
3018
+ }
3019
+
3020
+ case "FLUSH": {
3021
+ return encodeFlushResponse({ response });
3022
+ }
3023
+
3024
+ case "FSYNC": {
3025
+ return encodeFsyncResponse({ response });
3026
+ }
3027
+
3028
+ case "ACCESS": {
3029
+ return encodeAccessResponse({ response });
3030
+ }
3031
+
3032
+ case "SETXATTR": {
3033
+ return encodeSetXAttrResponse({ response });
3034
+ }
3035
+
3036
+ case "REMOVEXATTR": {
3037
+ return encodeRemoveXAttrResponse({ response });
3038
+ }
3039
+
3040
+ case "CREATE": {
3041
+ return encodeCreateResponse({ response });
3042
+ }
3043
+
3044
+ case "DESTROY": {
3045
+ return encodeDestroyResponse({ response });
3046
+ }
3047
+
3048
+ case "GETLK": {
3049
+ return encodeGetLkResponse({ response });
3050
+ }
3051
+
3052
+ case "SETLK": {
3053
+ return encodeSetLkResponse({ response });
3054
+ }
3055
+
3056
+ case "SETLKW": {
3057
+ return encodeSetLkWResponse({ response });
3058
+ }
3059
+
3060
+ case "BMAP": {
3061
+ return encodeBmapResponse({ response });
3062
+ }
3063
+
3064
+ case "IOCTL": {
3065
+ return encodeIoctlResponse({ response });
3066
+ }
3067
+
3068
+ case "POLL": {
3069
+ return encodePollResponse({ response });
3070
+ }
3071
+
3072
+ case "FALLOCATE": {
3073
+ return encodeFallocateResponse({ response });
3074
+ }
3075
+
3076
+ case "READDIRPLUS": {
3077
+ return encodeReadDirPlusResponse({ response });
3078
+ }
3079
+
3080
+ default: {
3081
+ // @ts-expect-error exhaustiveness check
3082
+ throw new Error(`Unsupported opcode: ${response.forOpcode}`);
3083
+ }
3084
+ }
3085
+ };
3086
+
3087
+ const interpretInitResponse/*: TInterpretFunc<"INIT">*/ = ({ unique, payload }) => {
3088
+ if (payload.length !== fuseInitOutParser.size) {
3089
+ return {
3090
+ error: new Error(`Invalid payload size for INIT response. Expected ${fuseInitOutParser.size} bytes, got ${payload.length} bytes.`),
3091
+ interpreted: undefined,
3092
+ };
3093
+ }
3094
+
3095
+ const initResult = fuseInitOutParser.parse({ data: payload });
3096
+
3097
+ return {
3098
+ error: undefined,
3099
+ interpreted: {
3100
+ forOpcode: "INIT",
3101
+ unique,
3102
+ errorCode: undefined,
3103
+ result: {
3104
+ major: initResult.major,
3105
+ minor: initResult.minor,
3106
+ maxReadahead: initResult.max_readahead,
3107
+ flags: initResult.flags,
3108
+ maxBackground: initResult.max_background,
3109
+ congestionThreshold: initResult.congestion_threshold,
3110
+ maxWrite: initResult.max_write,
3111
+ timeGran: initResult.time_gran,
3112
+ maxPages: initResult.max_pages,
3113
+ mapAlignment: initResult.map_alignment,
3114
+ flags2: initResult.flags2,
3115
+ maxStackDepth: initResult.max_stack_depth,
3116
+ requestTimeout: initResult.request_timeout,
3117
+ }
3118
+ }
3119
+ };
3120
+ };
3121
+
3122
+ const interpretGetAttrResponse/*: TInterpretFunc<"GETATTR">*/ = ({ unique, payload }) => {
3123
+ return interpretAttrPayload({ unique, forOpcode: "GETATTR", payload });
3124
+ };
3125
+
3126
+ const interpretSetAttrResponse/*: TInterpretFunc<"SETATTR">*/ = ({ unique, payload }) => {
3127
+ return interpretAttrPayload({ unique, forOpcode: "SETATTR", payload });
3128
+ };
3129
+
3130
+ const interpretOpenDirResponse/*: TInterpretFunc<"OPENDIR">*/ = ({ unique, payload }) => {
3131
+ return interpretOpenPayload({ unique, forOpcode: "OPENDIR", payload });
3132
+ };
3133
+
3134
+ const interpretReadDirResponse/*: TInterpretFunc<"READDIR">*/ = ({ unique, payload }) => {
3135
+ return {
3136
+ error: undefined,
3137
+ interpreted: {
3138
+ forOpcode: "READDIR",
3139
+ unique,
3140
+ errorCode: undefined,
3141
+ result: {
3142
+ data: payload,
3143
+ }
3144
+ }
3145
+ };
3146
+ };
3147
+
3148
+ const interpretReleaseDirResponse/*: TInterpretFunc<"RELEASEDIR">*/ = ({ unique }) => {
3149
+ return interpretEmptyPayload({ unique, forOpcode: "RELEASEDIR" });
3150
+ };
3151
+
3152
+ const interpretReleaseResponse/*: TInterpretFunc<"RELEASE">*/ = ({ unique }) => {
3153
+ return interpretEmptyPayload({ unique, forOpcode: "RELEASE" });
3154
+ };
3155
+
3156
+ const interpretLookupResponse/*: TInterpretFunc<"LOOKUP">*/ = ({ unique, payload }) => {
3157
+ return interpretEntryPayload({ unique, forOpcode: "LOOKUP", payload });
3158
+ };
3159
+
3160
+ const interpretSymlinkResponse/*: TInterpretFunc<"SYMLINK">*/ = ({ unique, payload }) => {
3161
+ return interpretEntryPayload({ unique, forOpcode: "SYMLINK", payload });
3162
+ };
3163
+
3164
+ const interpretMknodResponse/*: TInterpretFunc<"MKNOD">*/ = ({ unique, payload }) => {
3165
+ return interpretEntryPayload({ unique, forOpcode: "MKNOD", payload });
3166
+ };
3167
+
3168
+ const interpretMkdirResponse/*: TInterpretFunc<"MKDIR">*/ = ({ unique, payload }) => {
3169
+ return interpretEntryPayload({ unique, forOpcode: "MKDIR", payload });
3170
+ };
3171
+
3172
+ const interpretLinkResponse/*: TInterpretFunc<"LINK">*/ = ({ unique, payload }) => {
3173
+ return interpretEntryPayload({ unique, forOpcode: "LINK", payload });
3174
+ };
3175
+
3176
+ const interpretOpenResponse/*: TInterpretFunc<"OPEN">*/ = ({ unique, payload }) => {
3177
+ return interpretOpenPayload({ unique, forOpcode: "OPEN", payload });
3178
+ };
3179
+
3180
+ const interpretReadResponse/*: TInterpretFunc<"READ">*/ = ({ unique, payload }) => {
3181
+ return {
3182
+ error: undefined,
3183
+ interpreted: {
3184
+ forOpcode: "READ",
3185
+ unique,
3186
+ errorCode: undefined,
3187
+ result: {
3188
+ data: payload,
3189
+ }
3190
+ }
3191
+ };
3192
+ };
3193
+
3194
+ const interpretWriteResponse/*: TInterpretFunc<"WRITE">*/ = ({ unique, payload }) => {
3195
+ if (payload.length !== fuseWriteOutParser.size) {
3196
+ return {
3197
+ error: new Error(
3198
+ `Invalid payload size for WRITE response. Expected ${fuseWriteOutParser.size} bytes, got ${payload.length} bytes.`
3199
+ ),
3200
+ interpreted: undefined,
3201
+ };
3202
+ }
3203
+
3204
+ const writeResult = fuseWriteOutParser.parse({ data: payload });
3205
+
3206
+ return {
3207
+ error: undefined,
3208
+ interpreted: {
3209
+ forOpcode: "WRITE",
3210
+ unique,
3211
+ errorCode: undefined,
3212
+ result: {
3213
+ bytesWritten: writeResult.size,
3214
+ }
3215
+ }
3216
+ };
3217
+ };
3218
+
3219
+ const interpretGetXAttrResponse = (
3220
+ { unique, payload, request }/*:
3221
+ { unique: bigint; payload: Uint8Array; request: Extract<TFuseRequest, { opcode: "GETXATTR" }> }*/
3222
+ )/*: TGenericInterpretResult<Extract<TFuseResponse, { forOpcode: "GETXATTR" }>>*/ => {
3223
+ return interpretXAttrPayload({ unique, forOpcode: "GETXATTR", payload, requestedSize: request.size });
3224
+ };
3225
+
3226
+ const interpretListXAttrResponse = (
3227
+ { unique, payload, request }/*:
3228
+ { unique: bigint; payload: Uint8Array; request: Extract<TFuseRequest, { opcode: "LISTXATTR" }> }*/
3229
+ )/*: TGenericInterpretResult<Extract<TFuseResponse, { forOpcode: "LISTXATTR" }>>*/ => {
3230
+ return interpretXAttrPayload({ unique, forOpcode: "LISTXATTR", payload, requestedSize: request.size });
3231
+ };
3232
+
3233
+ const interpretReadLinkResponse/*: TInterpretFunc<"READLINK">*/ = ({ unique, payload }) => {
3234
+ return {
3235
+ error: undefined,
3236
+ interpreted: {
3237
+ forOpcode: "READLINK",
3238
+ unique,
3239
+ errorCode: undefined,
3240
+ result: {
3241
+ target: new TextDecoder().decode(payload),
3242
+ }
3243
+ }
3244
+ };
3245
+ };
3246
+
3247
+ const interpretUnlinkResponse/*: TInterpretFunc<"UNLINK">*/ = ({ unique }) => {
3248
+ return interpretEmptyPayload({ unique, forOpcode: "UNLINK" });
3249
+ };
3250
+
3251
+ const interpretRmDirResponse/*: TInterpretFunc<"RMDIR">*/ = ({ unique }) => {
3252
+ return interpretEmptyPayload({ unique, forOpcode: "RMDIR" });
3253
+ };
3254
+
3255
+ const interpretRenameResponse/*: TInterpretFunc<"RENAME">*/ = ({ unique }) => {
3256
+ return interpretEmptyPayload({ unique, forOpcode: "RENAME" });
3257
+ };
3258
+
3259
+ const interpretFlushResponse/*: TInterpretFunc<"FLUSH">*/ = ({ unique }) => {
3260
+ return interpretEmptyPayload({ unique, forOpcode: "FLUSH" });
3261
+ };
3262
+
3263
+ const interpretFsyncResponse/*: TInterpretFunc<"FSYNC">*/ = ({ unique }) => {
3264
+ return interpretEmptyPayload({ unique, forOpcode: "FSYNC" });
3265
+ };
3266
+
3267
+ const interpretAccessResponse/*: TInterpretFunc<"ACCESS">*/ = ({ unique }) => {
3268
+ return interpretEmptyPayload({ unique, forOpcode: "ACCESS" });
3269
+ };
3270
+
3271
+ const interpretSetXAttrResponse/*: TInterpretFunc<"SETXATTR">*/ = ({ unique }) => {
3272
+ return interpretEmptyPayload({ unique, forOpcode: "SETXATTR" });
3273
+ };
3274
+
3275
+ const interpretRemoveXAttrResponse/*: TInterpretFunc<"REMOVEXATTR">*/ = ({ unique }) => {
3276
+ return interpretEmptyPayload({ unique, forOpcode: "REMOVEXATTR" });
3277
+ };
3278
+
3279
+ const interpretFsyncDirResponse/*: TInterpretFunc<"FSYNCDIR">*/ = ({ unique }) => {
3280
+ return interpretEmptyPayload({ unique, forOpcode: "FSYNCDIR" });
3281
+ };
3282
+
3283
+ const interpretCreateResponse/*: TInterpretFunc<"CREATE">*/ = ({ unique, payload }) => {
3284
+ const expectedSize = fuseEntryOutParser.size + fuseOpenOutParser.size;
3285
+ if (payload.length !== expectedSize) {
3286
+ return {
3287
+ error: new Error(`Invalid payload size for CREATE response. Expected ${expectedSize} bytes, got ${payload.length} bytes.`),
3288
+ interpreted: undefined,
3289
+ };
3290
+ }
3291
+
3292
+ const entry = fuseEntryOutParser.parse({ data: payload.subarray(0, fuseEntryOutParser.size) });
3293
+ const open = fuseOpenOutParser.parse({ data: payload.subarray(fuseEntryOutParser.size) });
3294
+
3295
+ return {
3296
+ error: undefined,
3297
+ interpreted: {
3298
+ forOpcode: "CREATE",
3299
+ unique,
3300
+ errorCode: undefined,
3301
+ result: {
3302
+ nodeId: entry.nodeid,
3303
+ generation: entry.generation,
3304
+ entryValidNsec: entry.entry_valid * 1_000_000_000n + entry.entry_valid_nsec,
3305
+ attrValidNsec: entry.attr_valid * 1_000_000_000n + entry.attr_valid_nsec,
3306
+ attr: payloadValueToFuseAttr({ attr: entry.attr }),
3307
+ fh: open.fh,
3308
+ openFlagsToKernel: openFlagsToKernelFromBitmask({ bitmask: open.open_flags }),
3309
+ }
3310
+ }
3311
+ };
3312
+ };
3313
+
3314
+ const interpretDestroyResponse/*: TInterpretFunc<"DESTROY">*/ = ({ unique }) => {
3315
+ return interpretEmptyPayload({ unique, forOpcode: "DESTROY" });
3316
+ };
3317
+
3318
+ const interpretGetLkResponse/*: TInterpretFunc<"GETLK">*/ = ({ unique, payload }) => {
3319
+ if (payload.length !== fuseLkOutParser.size) {
3320
+ return {
3321
+ error: new Error(`Invalid payload size for GETLK response. Expected ${fuseLkOutParser.size} bytes, got ${payload.length} bytes.`),
3322
+ interpreted: undefined,
3323
+ };
3324
+ }
3325
+
3326
+ const parsed = fuseLkOutParser.parse({ data: payload });
3327
+
3328
+ return {
3329
+ error: undefined,
3330
+ interpreted: {
3331
+ forOpcode: "GETLK",
3332
+ unique,
3333
+ errorCode: undefined,
3334
+ result: {
3335
+ lockStart: parsed.lk.start,
3336
+ lockEnd: parsed.lk.end,
3337
+ lockType: parsed.lk.type,
3338
+ lockPid: parsed.lk.pid,
3339
+ }
3340
+ }
3341
+ };
3342
+ };
3343
+
3344
+ const interpretSetLkResponse/*: TInterpretFunc<"SETLK">*/ = ({ unique }) => {
3345
+ return interpretEmptyPayload({ unique, forOpcode: "SETLK" });
3346
+ };
3347
+
3348
+ const interpretSetLkWResponse/*: TInterpretFunc<"SETLKW">*/ = ({ unique }) => {
3349
+ return interpretEmptyPayload({ unique, forOpcode: "SETLKW" });
3350
+ };
3351
+
3352
+ const interpretBmapResponse/*: TInterpretFunc<"BMAP">*/ = ({ unique, payload }) => {
3353
+ if (payload.length !== fuseBmapOutParser.size) {
3354
+ return {
3355
+ error: new Error(`Invalid payload size for BMAP response. Expected ${fuseBmapOutParser.size} bytes, got ${payload.length} bytes.`),
3356
+ interpreted: undefined,
3357
+ };
3358
+ }
3359
+
3360
+ const parsed = fuseBmapOutParser.parse({ data: payload });
3361
+
3362
+ return {
3363
+ error: undefined,
3364
+ interpreted: {
3365
+ forOpcode: "BMAP",
3366
+ unique,
3367
+ errorCode: undefined,
3368
+ result: {
3369
+ block: parsed.block,
3370
+ }
3371
+ }
3372
+ };
3373
+ };
3374
+
3375
+ const interpretIoctlResponse/*: TInterpretFunc<"IOCTL">*/ = ({ unique, payload }) => {
3376
+ if (payload.length < fuseIoctlOutParser.size) {
3377
+ return {
3378
+ error: new Error(
3379
+ `Invalid payload size for IOCTL response. Expected at least ${fuseIoctlOutParser.size} bytes, got ${payload.length} bytes.`
3380
+ ),
3381
+ interpreted: undefined,
3382
+ };
3383
+ }
3384
+
3385
+ const parsed = fuseIoctlOutParser.parse({ data: payload.subarray(0, fuseIoctlOutParser.size) });
3386
+
3387
+ return {
3388
+ error: undefined,
3389
+ interpreted: {
3390
+ forOpcode: "IOCTL",
3391
+ unique,
3392
+ errorCode: undefined,
3393
+ result: {
3394
+ ioctlResult: parsed.result,
3395
+ flags: parsed.flags,
3396
+ data: payload.subarray(fuseIoctlOutParser.size),
3397
+ }
3398
+ }
3399
+ };
3400
+ };
3401
+
3402
+ const interpretPollResponse/*: TInterpretFunc<"POLL">*/ = ({ unique, payload }) => {
3403
+ if (payload.length !== fusePollOutParser.size) {
3404
+ return {
3405
+ error: new Error(`Invalid payload size for POLL response. Expected ${fusePollOutParser.size} bytes, got ${payload.length} bytes.`),
3406
+ interpreted: undefined,
3407
+ };
3408
+ }
3409
+
3410
+ const parsed = fusePollOutParser.parse({ data: payload });
3411
+
3412
+ return {
3413
+ error: undefined,
3414
+ interpreted: {
3415
+ forOpcode: "POLL",
3416
+ unique,
3417
+ errorCode: undefined,
3418
+ result: {
3419
+ revents: parsed.revents,
3420
+ }
3421
+ }
3422
+ };
3423
+ };
3424
+
3425
+ const interpretFallocateResponse/*: TInterpretFunc<"FALLOCATE">*/ = ({ unique }) => {
3426
+ return interpretEmptyPayload({ unique, forOpcode: "FALLOCATE" });
3427
+ };
3428
+
3429
+ const interpretReadDirPlusResponse/*: TInterpretFunc<"READDIRPLUS">*/ = ({ unique, payload }) => {
3430
+ return {
3431
+ error: undefined,
3432
+ interpreted: {
3433
+ forOpcode: "READDIRPLUS",
3434
+ unique,
3435
+ errorCode: undefined,
3436
+ result: {
3437
+ data: payload,
3438
+ }
3439
+ }
3440
+ };
3441
+ };
3442
+
3443
+ const interpretStatFsResponse/*: TInterpretFunc<"STATFS">*/ = ({ unique, payload }) => {
3444
+ if (payload.length !== fuseStatfsOutParser.size) {
3445
+ return {
3446
+ error: new Error(
3447
+ `Invalid payload size for STATFS response. Expected ${fuseStatfsOutParser.size} bytes, got ${payload.length} bytes.`
3448
+ ),
3449
+ interpreted: undefined,
3450
+ };
3451
+ }
3452
+
3453
+ const statFsResult = fuseStatfsOutParser.parse({ data: payload });
3454
+
3455
+ return {
3456
+ error: undefined,
3457
+ interpreted: {
3458
+ forOpcode: "STATFS",
3459
+ unique,
3460
+ errorCode: undefined,
3461
+ result: {
3462
+ blocks: statFsResult.st.blocks,
3463
+ bfree: statFsResult.st.bfree,
3464
+ bavail: statFsResult.st.bavail,
3465
+ files: statFsResult.st.files,
3466
+ ffree: statFsResult.st.ffree,
3467
+ bsize: statFsResult.st.bsize,
3468
+ namelen: statFsResult.st.namelen,
3469
+ frsize: statFsResult.st.frsize,
3470
+ }
3471
+ }
3472
+ };
3473
+ };
3474
+
3475
+ const interpretMessageToKernel = (
3476
+ { request, parsedMessageToKernel }/*: { request: TFuseRequest, parsedMessageToKernel: TParsedMessageToKernel }*/
3477
+ )/*: TGenericInterpretResult<TFuseResponse>*/ => {
3478
+
3479
+ const unique = parsedMessageToKernel.header.unique;
3480
+ const forOpcode = request.opcode /*as TFuseResponse["forOpcode"]*/;
3481
+
3482
+ if (parsedMessageToKernel.header.error !== 0n) {
3483
+ return {
3484
+ error: undefined,
3485
+ interpreted: {
3486
+ forOpcode,
3487
+ unique,
3488
+ errorCode: Number(parsedMessageToKernel.header.error),
3489
+ result: undefined,
3490
+ } /*as Extract<TFuseResponse, { forOpcode: typeof forOpcode; errorCode: number }>*/,
3491
+ };
3492
+ }
3493
+
3494
+ switch (forOpcode) {
3495
+ case "INIT": {
3496
+ return interpretInitResponse({
3497
+ unique,
3498
+ payload: parsedMessageToKernel.payload,
3499
+ });
3500
+ }
3501
+
3502
+ case "GETATTR": {
3503
+ return interpretGetAttrResponse({
3504
+ unique,
3505
+ payload: parsedMessageToKernel.payload,
3506
+ });
3507
+ }
3508
+
3509
+ case "SETATTR": {
3510
+ return interpretSetAttrResponse({
3511
+ unique,
3512
+ payload: parsedMessageToKernel.payload,
3513
+ });
3514
+ }
3515
+
3516
+ case "LISTXATTR": {
3517
+ return interpretListXAttrResponse({
3518
+ unique,
3519
+ payload: parsedMessageToKernel.payload,
3520
+ request: request /*as Extract<TFuseRequest, { opcode: "LISTXATTR" }>*/,
3521
+ });
3522
+ }
3523
+
3524
+ case "GETXATTR": {
3525
+ return interpretGetXAttrResponse({
3526
+ unique,
3527
+ payload: parsedMessageToKernel.payload,
3528
+ request: request /*as Extract<TFuseRequest, { opcode: "GETXATTR" }>*/,
3529
+ });
3530
+ }
3531
+
3532
+ case "READLINK": {
3533
+ return interpretReadLinkResponse({
3534
+ unique,
3535
+ payload: parsedMessageToKernel.payload,
3536
+ });
3537
+ }
3538
+
3539
+ case "MKNOD": {
3540
+ return interpretMknodResponse({
3541
+ unique,
3542
+ payload: parsedMessageToKernel.payload,
3543
+ });
3544
+ }
3545
+
3546
+ case "OPENDIR": {
3547
+ return interpretOpenDirResponse({
3548
+ unique,
3549
+ payload: parsedMessageToKernel.payload,
3550
+ });
3551
+ }
3552
+
3553
+ case "READDIR": {
3554
+ return interpretReadDirResponse({
3555
+ unique,
3556
+ payload: parsedMessageToKernel.payload,
3557
+ });
3558
+ }
3559
+
3560
+ case "RELEASEDIR": {
3561
+ return interpretReleaseDirResponse({
3562
+ unique,
3563
+ payload: parsedMessageToKernel.payload,
3564
+ });
3565
+ }
3566
+
3567
+ case "FSYNCDIR": {
3568
+ return interpretFsyncDirResponse({
3569
+ unique,
3570
+ payload: parsedMessageToKernel.payload,
3571
+ });
3572
+ }
3573
+
3574
+ case "RELEASE": {
3575
+ return interpretReleaseResponse({
3576
+ unique,
3577
+ payload: parsedMessageToKernel.payload,
3578
+ });
3579
+ }
3580
+
3581
+ case "STATFS": {
3582
+ return interpretStatFsResponse({
3583
+ unique,
3584
+ payload: parsedMessageToKernel.payload,
3585
+ });
3586
+ }
3587
+
3588
+ case "LOOKUP": {
3589
+ return interpretLookupResponse({
3590
+ unique,
3591
+ payload: parsedMessageToKernel.payload,
3592
+ });
3593
+ }
3594
+
3595
+ case "SYMLINK": {
3596
+ return interpretSymlinkResponse({
3597
+ unique,
3598
+ payload: parsedMessageToKernel.payload,
3599
+ });
3600
+ }
3601
+
3602
+ case "LINK": {
3603
+ return interpretLinkResponse({
3604
+ unique,
3605
+ payload: parsedMessageToKernel.payload,
3606
+ });
3607
+ }
3608
+
3609
+ case "MKDIR": {
3610
+ return interpretMkdirResponse({
3611
+ unique,
3612
+ payload: parsedMessageToKernel.payload,
3613
+ });
3614
+ }
3615
+
3616
+ case "UNLINK": {
3617
+ return interpretUnlinkResponse({
3618
+ unique,
3619
+ payload: parsedMessageToKernel.payload,
3620
+ });
3621
+ }
3622
+
3623
+ case "RMDIR": {
3624
+ return interpretRmDirResponse({
3625
+ unique,
3626
+ payload: parsedMessageToKernel.payload,
3627
+ });
3628
+ }
3629
+
3630
+ case "RENAME": {
3631
+ return interpretRenameResponse({
3632
+ unique,
3633
+ payload: parsedMessageToKernel.payload,
3634
+ });
3635
+ }
3636
+
3637
+ case "OPEN": {
3638
+ return interpretOpenResponse({
3639
+ unique,
3640
+ payload: parsedMessageToKernel.payload,
3641
+ });
3642
+ }
3643
+
3644
+ case "READ": {
3645
+ return interpretReadResponse({
3646
+ unique,
3647
+ payload: parsedMessageToKernel.payload,
3648
+ });
3649
+ }
3650
+
3651
+ case "WRITE": {
3652
+ return interpretWriteResponse({
3653
+ unique,
3654
+ payload: parsedMessageToKernel.payload,
3655
+ });
3656
+ }
3657
+
3658
+ case "FLUSH": {
3659
+ return interpretFlushResponse({
3660
+ unique,
3661
+ payload: parsedMessageToKernel.payload,
3662
+ });
3663
+ }
3664
+
3665
+ case "FSYNC": {
3666
+ return interpretFsyncResponse({
3667
+ unique,
3668
+ payload: parsedMessageToKernel.payload,
3669
+ });
3670
+ }
3671
+
3672
+ case "ACCESS": {
3673
+ return interpretAccessResponse({
3674
+ unique,
3675
+ payload: parsedMessageToKernel.payload,
3676
+ });
3677
+ }
3678
+
3679
+ case "SETXATTR": {
3680
+ return interpretSetXAttrResponse({
3681
+ unique,
3682
+ payload: parsedMessageToKernel.payload,
3683
+ });
3684
+ }
3685
+
3686
+ case "REMOVEXATTR": {
3687
+ return interpretRemoveXAttrResponse({
3688
+ unique,
3689
+ payload: parsedMessageToKernel.payload,
3690
+ });
3691
+ }
3692
+
3693
+ case "CREATE": {
3694
+ return interpretCreateResponse({
3695
+ unique,
3696
+ payload: parsedMessageToKernel.payload,
3697
+ });
3698
+ }
3699
+
3700
+ case "DESTROY": {
3701
+ return interpretDestroyResponse({
3702
+ unique,
3703
+ payload: parsedMessageToKernel.payload,
3704
+ });
3705
+ }
3706
+
3707
+ case "GETLK": {
3708
+ return interpretGetLkResponse({
3709
+ unique,
3710
+ payload: parsedMessageToKernel.payload,
3711
+ });
3712
+ }
3713
+
3714
+ case "SETLK": {
3715
+ return interpretSetLkResponse({
3716
+ unique,
3717
+ payload: parsedMessageToKernel.payload,
3718
+ });
3719
+ }
3720
+
3721
+ case "SETLKW": {
3722
+ return interpretSetLkWResponse({
3723
+ unique,
3724
+ payload: parsedMessageToKernel.payload,
3725
+ });
3726
+ }
3727
+
3728
+ case "BMAP": {
3729
+ return interpretBmapResponse({
3730
+ unique,
3731
+ payload: parsedMessageToKernel.payload,
3732
+ });
3733
+ }
3734
+
3735
+ case "IOCTL": {
3736
+ return interpretIoctlResponse({
3737
+ unique,
3738
+ payload: parsedMessageToKernel.payload,
3739
+ });
3740
+ }
3741
+
3742
+ case "POLL": {
3743
+ return interpretPollResponse({
3744
+ unique,
3745
+ payload: parsedMessageToKernel.payload,
3746
+ });
3747
+ }
3748
+
3749
+ case "FALLOCATE": {
3750
+ return interpretFallocateResponse({
3751
+ unique,
3752
+ payload: parsedMessageToKernel.payload,
3753
+ });
3754
+ }
3755
+
3756
+ case "READDIRPLUS": {
3757
+ return interpretReadDirPlusResponse({
3758
+ unique,
3759
+ payload: parsedMessageToKernel.payload,
3760
+ });
3761
+ }
3762
+
3763
+ default: {
3764
+ throw Error(`unsupported opcode for interpretation: ${forOpcode}`);
3765
+ }
3766
+ }
3767
+ };
3768
+
3769
+ return {
3770
+ encodeMessageToKernel,
3771
+ interpretMessageToKernel,
3772
+ };
3773
+ };
3774
+
3775
+ export {
3776
+ createMessageFromKernelInterpreter,
3777
+ createMessageToKernelInterpreter,
3778
+ };
3779
+
3780
+ /*export type {
3781
+ TFuseRequest,
3782
+ TFuseResponse,
3783
+ };*/