vfsi-c 0.3.0

C API for VFSI vectorized filesystem interfaces
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
#ifndef VFSI_H
#define VFSI_H

#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>

/**
 * ABI version implemented by this library.
 */
#define VFSI_ABI_VERSION 3

/**
 * No error occurred.
 */
#define VFSI_ERROR_NONE 0

/**
 * A filesystem/backend status was returned.
 */
#define VFSI_ERROR_FILESYSTEM 1

/**
 * The transport failed without a filesystem status.
 */
#define VFSI_ERROR_TRANSPORT 2

/**
 * The selected backend does not implement the requested operation.
 */
#define VFSI_ERROR_UNSUPPORTED 3

/**
 * The C request itself was malformed.
 */
#define VFSI_ERROR_INVALID_ARGUMENT 4

/**
 * The operation was not submitted because an earlier request was invalid.
 */
#define VFSI_ERROR_NOT_ATTEMPTED 5

/**
 * The backend batch failed and this element's final state cannot be proven.
 */
#define VFSI_ERROR_INDETERMINATE 6

/**
 * Fixed capacity of [`vfsi_result::message`], including its trailing NUL.
 */
#define VFSI_RESULT_MESSAGE_SIZE 160

#define VFSI_ATTR_MODE (1 << 0)

#define VFSI_ATTR_SIZE (1 << 1)

#define VFSI_ATTR_NLINK (1 << 2)

#define VFSI_ATTR_FILEID (1 << 3)

#define VFSI_ATTR_BLOCKS (1 << 4)

#define VFSI_ATTR_UID (1 << 5)

#define VFSI_ATTR_GID (1 << 6)

#define VFSI_ATTR_RDEV (1 << 7)

#define VFSI_ATTR_ATIME (1 << 8)

#define VFSI_ATTR_MTIME (1 << 9)

#define VFSI_ATTR_CTIME (1 << 10)

/**
 * The backend will currently attempt server-side COPY.
 */
#define VFSI_CAP_SERVER_COPY (1 << 0)

/**
 * The backend reports and honors Unix metadata such as modes and ownership.
 */
#define VFSI_CAP_POSIX_METADATA (1 << 1)

/**
 * The backend supports symbolic links.
 */
#define VFSI_CAP_SYMLINKS (1 << 2)

/**
 * The backend supports hard links.
 */
#define VFSI_CAP_HARDLINKS (1 << 3)

/**
 * The backend accepts arbitrary non-UTF-8 Unix path bytes.
 */
#define VFSI_CAP_NON_UTF8_PATHS (1 << 4)

/**
 * The backend implements no-follow metadata operations.
 */
#define VFSI_CAP_LSTAT (1 << 5)

/**
 * Opaque filesystem handle owned by C.
 */
typedef struct vfsi_fs vfsi_fs;

/**
 * Attributes returned by [`vfsi_stat`] and passed to listdir callbacks.
 */
typedef struct vfsi_attrs {
  /**
   * Size of this structure, for forward-compatible extension.
   */
  uint32_t struct_size;
  /**
   * ABI version used to populate this structure.
   */
  uint32_t abi_version;
  uint32_t ftype;
  uint32_t mode;
  uint64_t size;
  uint32_t nlink;
  uint64_t fileid;
  uint32_t uid;
  uint32_t gid;
  uint64_t blocks;
  int64_t atime_sec;
  uint32_t atime_nsec;
  int64_t mtime_sec;
  uint32_t mtime_nsec;
  int64_t ctime_sec;
  uint32_t ctime_nsec;
} vfsi_attrs;

/**
 * Uniform ABI-v3 result for scalar and vector operations.
 *
 * `index` is the completed count on success and the failing operation index
 * on error. Vector calls also populate a caller-owned result per element;
 * after a submitted concurrent batch fails, every non-failing element is
 * marked indeterminate because it may already have completed. `err_no`
 * retains the backend status while `category` is portable across protocols.
 */
typedef struct vfsi_result {
  uint32_t struct_size;
  uint32_t abi_version;
  size_t index;
  uint32_t category;
  uint32_t err_no;
  char message[VFSI_RESULT_MESSAGE_SIZE];
} vfsi_result;

typedef struct vfsi_open_op {
  const char *path;
  int flags;
  uint32_t mode;
  int fd;
} vfsi_open_op;

typedef struct vfsi_stat_op {
  const char *path;
  struct vfsi_attrs attrs;
} vfsi_stat_op;

typedef struct vfsi_setattr_op {
  const char *path;
  uint32_t mask;
  uint32_t mode;
  uint64_t size;
  int64_t atime_sec;
  uint32_t atime_nsec;
  int64_t mtime_sec;
  uint32_t mtime_nsec;
} vfsi_setattr_op;

typedef struct vfsi_pread_op {
  int fd;
  void *buf;
  size_t len;
  uint64_t offset;
  size_t got;
} vfsi_pread_op;

typedef struct vfsi_pwrite_op {
  int fd;
  const void *buf;
  size_t len;
  uint64_t offset;
  size_t wrote;
} vfsi_pwrite_op;

typedef struct vfsi_mkdir_op {
  const char *path;
  uint32_t mode;
} vfsi_mkdir_op;

typedef struct vfsi_rename_op {
  const char *oldpath;
  const char *newpath;
} vfsi_rename_op;

typedef struct vfsi_copy_op {
  const char *src;
  uint64_t src_offset;
  const char *dst;
  uint64_t dst_offset;
  uint64_t length;
  bool to_eof;
} vfsi_copy_op;

typedef bool (*vfsi_read_stream_cb)(const char *path,
                                    size_t index,
                                    uint64_t offset,
                                    const uint8_t *data,
                                    size_t len,
                                    bool eof,
                                    void *userdata);

typedef bool (*vfsi_listdir_cb)(const char *name, const struct vfsi_attrs *attrs, void *userdata);

typedef bool (*vfsi_listdirv_cb)(const char *dir,
                                 const char *name,
                                 const struct vfsi_attrs *attrs,
                                 void *userdata);

typedef bool (*vfsi_read_paths_cb)(const char *path, const uint8_t *data, size_t len, void *userdata);

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

/**
 * Return the ABI version implemented by the loaded library.
 */
uint32_t vfsi_abi_version(void);

/**
 * Return the negotiated NFS minor version, or zero for a non-NFS/invalid
 * handle.
 */
uint32_t vfsi_nfs_minorversion(const struct vfsi_fs *fs);

/**
 * Return the negotiated SMB dialect revision (`0x0202` through `0x0311`),
 * or zero for a non-SMB/invalid handle.
 */
uint16_t vfsi_smb_dialect(const struct vfsi_fs *fs);

/**
 * Return the current `VFSI_CAP_*` capability bitset.
 */
uint64_t vfsi_capabilities(const struct vfsi_fs *fs);

/**
 * Create a local-directory vfsi backend rooted at `root`.
 */
int vfsi_dummy_open(const char *root, struct vfsi_fs **out);

/**
 * Create a local-directory vfsi backend rooted at `root`, treating
 * `mountpoint` as the kernel-visible root of the same directory. Callers can
 * pass ordinary kernel paths under `mountpoint`, which are mapped to `/`-rooted
 * vfsi paths before they reach the backend.
 */
int vfsi_dummy_open_mount(const char *root, const char *mountpoint, struct vfsi_fs **out);

/**
 * Connect to an NFSv4.1 server at `host` and open the export root.
 */
int vfsi_nfs_open(const char *host, struct vfsi_fs **out);

/**
 * Connect using an explicit supported NFS minor version (1 or 2).
 */
int vfsi_nfs_open_minor(const char *host, uint32_t minorversion, struct vfsi_fs **out);

/**
 * Connect to an NFSv4.1 server and treat `mountpoint` (a local kernel mount
 * path) as the vfsi root. Callers can then pass ordinary kernel paths.
 */
int vfsi_nfs_open_mount(const char *host, const char *mountpoint, struct vfsi_fs **out);

/**
 * Connect to an NFSv4.1 server, mapping a local kernel `mountpoint` to the
 * server-side `export_root` beneath the NFSv4 pseudo-root.
 */
int vfsi_nfs_open_mount_export(const char *host,
                               const char *export_root,
                               const char *mountpoint,
                               struct vfsi_fs **out);

/**
 * Connect to an SMB2/3 share. `server` may omit port 445; empty username and
 * password strings request guest access. Paths are rooted at the share root.
 */
int vfsi_smb_open(const char *server,
                  const char *share,
                  const char *username,
                  const char *password,
                  const char *domain,
                  struct vfsi_fs **out);

/**
 * Connect to an SMB2/3 share and map a kernel-visible `mountpoint` onto
 * `share_root` within that share. Both paths must be absolute and may not
 * contain parent-directory components.
 */
int vfsi_smb_open_mount(const char *server,
                        const char *share,
                        const char *username,
                        const char *password,
                        const char *domain,
                        const char *share_root,
                        const char *mountpoint,
                        struct vfsi_fs **out);

/**
 * Destroy a filesystem handle returned by one of the `vfsi_*_open*`
 * functions.
 */
void vfsi_free(struct vfsi_fs *fs);

/**
 * Stat `path`, following a final symlink.
 */
int vfsi_stat(struct vfsi_fs *fs, const char *path, struct vfsi_attrs *out);

/**
 * Open a file and return a vfsi descriptor (`>= 0`), or a negative errno.
 */
int vfsi_open(struct vfsi_fs *fs, const char *path, int flags, uint32_t mode);

/**
 * Close a descriptor opened by [`vfsi_open`].
 */
int vfsi_close(struct vfsi_fs *fs, int fd);

/**
 * Read up to `len` bytes at `offset` into `buf`; writes the actual count to
 * `*got` when non-NULL.
 */
int vfsi_pread(struct vfsi_fs *fs, int fd, void *buf, size_t len, uint64_t offset, size_t *got);

/**
 * Write `len` bytes at `offset`; writes the actual count to `*wrote`.
 */
int vfsi_pwrite(struct vfsi_fs *fs,
                int fd,
                const void *buf,
                size_t len,
                uint64_t offset,
                size_t *wrote);

/**
 * Create a directory (`create_parents != 0` behaves like `mkdir -p`).
 */
int vfsi_mkdir(struct vfsi_fs *fs, const char *path, uint32_t mode, int create_parents);

/**
 * Remove a path (directories must be empty).
 */
int vfsi_remove(struct vfsi_fs *fs, const char *path);

/**
 * Rename `oldpath` to `newpath`.
 */
int vfsi_rename(struct vfsi_fs *fs, const char *oldpath, const char *newpath);

/**
 * Copy one extent. When `to_eof` is true, `length` is ignored and copying
 * continues to the source EOF. The backend uses NFSv4.2 COPY or SMB
 * server-side copy when available and falls back to client-side I/O.
 */
int vfsi_copy(struct vfsi_fs *fs,
              const char *src,
              uint64_t src_offset,
              const char *dst,
              uint64_t dst_offset,
              uint64_t length,
              bool to_eof);

/**
 * Open `count` files in one backend vector call. ABI-v2 functions remain
 * available; this and the other `*v` entry points use the uniform ABI-v3
 * overall and per-element result contract.
 */
struct vfsi_result vfsi_openv(struct vfsi_fs *fs,
                              struct vfsi_open_op *ops,
                              size_t count,
                              struct vfsi_result *item_results);

/**
 * Close a descriptor array in one backend vector call.
 */
struct vfsi_result vfsi_closev(struct vfsi_fs *fs,
                               const int *fds,
                               size_t count,
                               struct vfsi_result *item_results);

/**
 * Stat a path array in one backend vector call.
 */
struct vfsi_result vfsi_statv(struct vfsi_fs *fs,
                              struct vfsi_stat_op *ops,
                              size_t count,
                              struct vfsi_result *item_results);

/**
 * Set selected attributes for a path array in one backend vector call.
 */
struct vfsi_result vfsi_setattrv(struct vfsi_fs *fs,
                                 const struct vfsi_setattr_op *ops,
                                 size_t count,
                                 struct vfsi_result *item_results);

/**
 * Positioned vector read using caller-owned buffers.
 */
struct vfsi_result vfsi_preadv(struct vfsi_fs *fs,
                               struct vfsi_pread_op *ops,
                               size_t count,
                               struct vfsi_result *item_results);

/**
 * Positioned vector write using caller-owned buffers.
 */
struct vfsi_result vfsi_pwritev(struct vfsi_fs *fs,
                                struct vfsi_pwrite_op *ops,
                                size_t count,
                                struct vfsi_result *item_results);

/**
 * Create a directory array in one backend vector call.
 */
struct vfsi_result vfsi_mkdirv(struct vfsi_fs *fs,
                               const struct vfsi_mkdir_op *ops,
                               size_t count,
                               struct vfsi_result *item_results);

/**
 * Remove a path array in one backend vector call.
 */
struct vfsi_result vfsi_removev(struct vfsi_fs *fs,
                                const char *const *paths,
                                size_t count,
                                struct vfsi_result *item_results);

/**
 * Rename a path-pair array in one backend vector call.
 */
struct vfsi_result vfsi_renamev(struct vfsi_fs *fs,
                                const struct vfsi_rename_op *ops,
                                size_t count,
                                struct vfsi_result *item_results);

/**
 * Copy an extent-pair array in one backend vector call.
 */
struct vfsi_result vfsi_copyv(struct vfsi_fs *fs,
                              const struct vfsi_copy_op *ops,
                              size_t count,
                              struct vfsi_result *item_results);

/**
 * Stream several paths in bounded vectorized chunks. Returning `false` from
 * `cb` cancels successfully. The callback provides backpressure and must not
 * reenter the same filesystem handle.
 */
struct vfsi_result vfsi_read_streamv(struct vfsi_fs *fs,
                                     const char *const *paths,
                                     size_t count,
                                     size_t chunk_size,
                                     size_t memory_limit,
                                     vfsi_read_stream_cb cb,
                                     void *userdata);

/**
 * List `dir` and call `cb` for each entry. Returning `false` from `cb`
 * stops the listing.
 */
int vfsi_listdir(struct vfsi_fs *fs, const char *dir, vfsi_listdir_cb cb, void *userdata);

/**
 * List several directories in one vectorized batch, calling `cb` for each
 * entry with the directory the entry came from.
 */
int vfsi_listdirv(struct vfsi_fs *fs,
                  const char *const *dirs,
                  size_t count,
                  size_t max_entries,
                  bool recursive,
                  vfsi_listdirv_cb cb,
                  void *userdata);

/**
 * Read the full contents of several files in one vectorized batch, calling
 * `cb` for each file after its data has been fetched.
 */
int vfsi_read_paths(struct vfsi_fs *fs,
                    const char *const *paths,
                    size_t count,
                    vfsi_read_paths_cb cb,
                    void *userdata);

#ifdef __cplusplus
}  // extern "C"
#endif  // __cplusplus

#endif  /* VFSI_H */