Cthulhu  0.2.10
Cthulhu compiler collection
fs.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: LGPL-3.0-only
2 
3 #include "common.h"
4 
5 #include "arena/arena.h"
6 
7 #include "os/os.h"
8 
9 #include "io/impl.h"
10 #include "io/io.h"
11 
12 #include "std/vector.h"
13 #include "std/str.h"
14 #include "std/map.h"
15 
16 #include "base/util.h"
17 #include "base/panic.h"
18 
19 static vector_t *path_split(const char *path, arena_t *arena)
20 {
21  return str_split(path, "/", arena);
22 }
23 
24 // fs interface api
25 
26 static fs_inode_t *impl_query_inode(fs_t *fs, fs_inode_t *node, const char *name)
27 {
28  CTASSERT(fs != NULL);
29  CTASSERT(node != NULL);
30  CTASSERT(name != NULL);
31 
32  CTASSERT(inode_is(node, eOsNodeDir));
33  CTASSERT(fs->cb->pfn_query_node != NULL);
34 
35  return fs->cb->pfn_query_node(fs, node, name);
36 }
37 
38 static io_t *impl_query_file(fs_t *fs, fs_inode_t *node, os_access_t flags)
39 {
40  CTASSERT(fs != NULL);
41  CTASSERT(node != NULL);
42 
43  CTASSERT(inode_is(node, eOsNodeFile));
44  CTASSERT(fs->cb->pfn_query_file != NULL);
45 
46  return fs->cb->pfn_query_file(fs, node, flags);
47 }
48 
49 static inode_result_t impl_create_file(fs_t *fs, fs_inode_t *node, const char *name)
50 {
51  CTASSERT(fs != NULL);
52  CTASSERT(node != NULL);
53  CTASSERT(name != NULL);
54 
55  CTASSERT(inode_is(node, eOsNodeDir));
56  CTASSERT(fs->cb->pfn_create_file != NULL);
57 
58  return fs->cb->pfn_create_file(fs, node, name);
59 }
60 
61 static os_error_t impl_delete_file(fs_t *fs, fs_inode_t *node, const char *name)
62 {
63  CTASSERT(fs != NULL);
64  CTASSERT(node != NULL);
65  CTASSERT(name != NULL);
66 
67  CTASSERT(inode_is(node, eOsNodeDir));
68  CTASSERT(fs->cb->pfn_delete_file != NULL);
69 
70  return fs->cb->pfn_delete_file(fs, node, name);
71 }
72 
73 static fs_inode_t *impl_create_dir(fs_t *fs, fs_inode_t *node, const char *name)
74 {
75  CTASSERT(fs != NULL);
76  CTASSERT(node != NULL);
77  CTASSERT(name != NULL);
78 
79  CTASSERT(inode_is(node, eOsNodeDir));
80  CTASSERT(fs->cb->pfn_create_dir != NULL);
81 
82  inode_result_t result = fs->cb->pfn_create_dir(fs, node, name);
83 
84  return result.node;
85 }
86 
87 static os_error_t impl_delete_dir(fs_t *fs, fs_inode_t *node, const char *name)
88 {
89  CTASSERT(fs != NULL);
90  CTASSERT(node != NULL);
91  CTASSERT(name != NULL);
92 
93  CTASSERT(inode_is(node, eOsNodeDir));
94  CTASSERT(fs->cb->pfn_delete_dir != NULL);
95 
96  return fs->cb->pfn_delete_dir(fs, node, name);
97 }
98 
99 static os_error_t impl_iter_begin(fs_t *fs, const fs_inode_t *dir, fs_iter_t *iter)
100 {
101  CTASSERT(fs != NULL);
102  CTASSERT(dir != NULL);
103  CTASSERT(iter != NULL);
104 
105  CTASSERT(fs_inode_is(dir, eOsNodeDir));
106  CTASSERT(fs->cb->pfn_iter_begin != NULL);
107 
108  return fs->cb->pfn_iter_begin(fs, dir, iter);
109 }
110 
111 static os_error_t impl_iter_next(fs_iter_t *iter)
112 {
113  CTASSERT(iter != NULL);
114  CTASSERT(iter->fs != NULL);
115 
116  CTASSERT(iter->fs->cb->pfn_iter_next != NULL);
117 
118  return iter->fs->cb->pfn_iter_next(iter);
119 }
120 
121 static os_error_t impl_iter_end(fs_iter_t *iter)
122 {
123  CTASSERT(iter != NULL);
124  CTASSERT(iter->fs != NULL);
125 
126  CTASSERT(iter->fs->cb->pfn_iter_end != NULL);
127 
128  return iter->fs->cb->pfn_iter_end(iter);
129 }
130 
131 // private impl
132 
133 static fs_inode_t *find_inode(fs_t *fs, fs_inode_t *start, const char *path)
134 {
135  vector_t *parts = path_split(path, fs->arena);
136  size_t len = vector_len(parts);
137  fs_inode_t *current = start;
138 
139  CTASSERT(len > 0);
140 
141  for (size_t i = 0; i < len - 1; i++)
142  {
143  const char *part = vector_get(parts, i);
144  fs_inode_t *node = impl_query_inode(fs, current, part);
145  switch (node->type)
146  {
147  case eOsNodeDir:
148  current = node;
149  break;
150 
151  case eOsNodeNone:
152  case eOsNodeFile:
153  return NULL;
154 
155  default:
156  CT_NEVER("invalid inode type (%s)", os_dirent_string(node->type));
157  }
158  }
159 
160  return impl_query_inode(fs, current, vector_tail(parts));
161 }
162 
163 // fs delete
164 
165 STA_DECL
166 void fs_delete(fs_t *fs)
167 {
168  CTASSERT(fs != NULL);
169 
171 }
172 
173 // fs file api
174 
175 STA_DECL
176 void fs_file_create(fs_t *fs, const char *path)
177 {
178  vector_t *parts = path_split(path, fs->arena);
179  size_t len = vector_len(parts);
180  fs_inode_t *current = fs->root;
181 
182  for (size_t i = 0; i < len - 1; i++)
183  {
184  const char *part = vector_get(parts, i);
185  fs_inode_t *node = impl_query_inode(fs, current, part);
186  switch (node->type)
187  {
188  case eOsNodeDir: current = node; break;
189  default: return;
190  }
191  }
192 
193  impl_create_file(fs, current, vector_tail(parts));
194 }
195 
196 STA_DECL
197 bool fs_file_exists(fs_t *fs, const char *path)
198 {
199  vector_t *parts = path_split(path, fs->arena);
200  size_t len = vector_len(parts);
201  fs_inode_t *current = fs->root;
202 
203  for (size_t i = 0; i < len - 1; i++)
204  {
205  const char *part = vector_get(parts, i);
206  fs_inode_t *node = impl_query_inode(fs, current, part);
207  switch (node->type)
208  {
209  case eOsNodeDir: current = node; break;
210  default: return false;
211  }
212  }
213 
214  fs_inode_t *file = impl_query_inode(fs, current, vector_tail(parts));
215  return inode_is(file, eOsNodeFile);
216 }
217 
218 STA_DECL
219 os_error_t fs_file_delete(fs_t *fs, const char *path)
220 {
221  vector_t *parts = path_split(path, fs->arena);
222  size_t len = vector_len(parts);
223  fs_inode_t *current = fs->root;
224 
225  for (size_t i = 0; i < len - 1; i++)
226  {
227  const char *part = vector_get(parts, i);
228  fs_inode_t *node = impl_query_inode(fs, current, part);
229  switch (node->type)
230  {
231  case eOsNodeDir: current = node; break;
232  default: return eOsNotFound;
233  }
234  }
235 
236  return impl_delete_file(fs, current, vector_tail(parts));
237 }
238 
239 static const io_callbacks_t kInvalidIo = { 0 };
240 
241 static io_t *make_error_file(const char *name, os_access_t flags, os_error_t error, arena_t *arena)
242 {
243  io_t *io = io_new(&kInvalidIo, flags, name, NULL, arena);
244  io->error = error;
245  return io;
246 }
247 
248 static io_t *make_missing_file(const char *name, os_access_t flags, arena_t *arena)
249 {
250  return make_error_file(name, flags, eOsNotFound, arena);
251 }
252 
253 STA_DECL
254 io_t *fs_open(fs_t *fs, const char *path, os_access_t flags)
255 {
256  // create a file if it doesn't exist then open it
257 
258  vector_t *parts = path_split(path, fs->arena);
259  size_t len = vector_len(parts);
260  fs_inode_t *current = fs->root;
261 
262  for (size_t i = 0; i < len - 1; i++)
263  {
264  const char *part = vector_get(parts, i);
265  fs_inode_t *node = impl_query_inode(fs, current, part);
266  switch (node->type)
267  {
268  case eOsNodeDir: current = node; break;
269  case eOsNodeNone: current = impl_create_dir(fs, current, part); break;
270  default: return make_missing_file(path, flags, fs->arena);
271  }
272  }
273 
274  CTASSERTF(current != NULL, "current is NULL (path = %s)", path);
275 
276  fs_inode_t *file = impl_query_inode(fs, current, vector_tail(parts));
277  if (inode_is(file, eOsNodeFile))
278  {
279  return impl_query_file(fs, file, flags);
280  }
281 
282  if (inode_is(file, eOsNodeNone))
283  {
284  inode_result_t result = impl_create_file(fs, current, vector_tail(parts));
285  if (result.error != eOsSuccess)
286  {
287  return make_error_file(path, eOsAccessNone, result.error, fs->arena);
288  }
289 
290  return impl_query_file(fs, result.node, flags);
291  }
292 
293  return make_missing_file(path, flags, fs->arena);
294 }
295 
296 // fs dir api
297 
298 static fs_inode_t *get_dir_or_create(fs_t *fs, fs_inode_t *node, const char *name)
299 {
300  fs_inode_t *dir = impl_query_inode(fs, node, name);
301  switch (dir->type)
302  {
303  case eOsNodeDir: return dir;
304  case eOsNodeNone: return impl_create_dir(fs, node, name);
305 
306  default: return NULL;
307  }
308 }
309 
310 static fs_inode_t *get_file_or_create(fs_t *fs, fs_inode_t *node, const char *name)
311 {
312  fs_inode_t *file = impl_query_inode(fs, node, name);
313  switch (file->type)
314  {
315  case eOsNodeFile: return file;
316  case eOsNodeNone: return impl_create_file(fs, node, name).node;
317 
318  default: return NULL;
319  }
320 }
321 
322 static fs_inode_t *get_inode_for(fs_t *fs, fs_inode_t *node, const char *name, os_dirent_t type)
323 {
324  switch (type)
325  {
326  case eOsNodeDir: return get_dir_or_create(fs, node, name);
327  case eOsNodeFile: return get_file_or_create(fs, node, name);
328  default: CT_NEVER("invalid inode type for %s", name);
329  }
330 }
331 
332 STA_DECL
333 os_error_t fs_dir_create(fs_t *fs, const char *path)
334 {
335  CTASSERT(fs != NULL);
336  CTASSERT(path != NULL);
337  CT_PARANOID_ASSERTF(ctu_strlen(path) > 0, "path cannot be empty");
338 
339  vector_t *parts = path_split(path, fs->arena);
340  size_t len = vector_len(parts);
341  fs_inode_t *current = fs->root;
342 
343  for (size_t i = 0; i < len; i++)
344  {
345  const char *part = vector_get(parts, i);
346  fs_inode_t *node = impl_query_inode(fs, current, part);
347  switch (node->type)
348  {
349  case eOsNodeDir:
350  current = node;
351  break;
352  case eOsNodeNone:
353  current = impl_create_dir(fs, current, part);
354  break;
355 
356  case eOsNodeFile:
357  return eOsExists;
358 
359  default:
360  CT_NEVER("invalid inode type (type = %d)", node->type);
361  }
362  }
363 
364  return eOsSuccess;
365 }
366 
367 STA_DECL
368 bool fs_dir_exists(fs_t *fs, const char *path)
369 {
370  vector_t *parts = path_split(path, fs->arena);
371  size_t len = vector_len(parts);
372  fs_inode_t *current = fs->root;
373 
374  for (size_t i = 0; i < len; i++)
375  {
376  const char *part = vector_get(parts, i);
377  fs_inode_t *node = impl_query_inode(fs, current, part);
378  switch (node->type)
379  {
380  case eOsNodeDir:
381  current = node;
382  break;
383 
384  case eOsNodeNone:
385  case eOsNodeFile:
386  return false;
387 
388  default:
389  CT_NEVER("invalid inode type (type = %d)", node->type);
390  }
391  }
392 
393  return inode_is(current, eOsNodeDir);
394 }
395 
396 STA_DECL
397 os_error_t fs_dir_delete(fs_t *fs, const char *path)
398 {
399  vector_t *parts = path_split(path, fs->arena);
400  size_t len = vector_len(parts);
401  fs_inode_t *current = fs->root;
402 
403  CTASSERT(len > 0);
404 
405  for (size_t i = 0; i < len - 1; i++)
406  {
407  const char *part = vector_get(parts, i);
408  fs_inode_t *node = impl_query_inode(fs, current, part);
409  switch (node->type)
410  {
411  case eOsNodeDir:
412  current = node;
413  break;
414 
415  case eOsNodeNone:
416  case eOsNodeFile:
417  return eOsNotFound;
418 
419  default:
420  CT_NEVER("invalid inode type (type = %d)", node->type);
421  }
422  }
423 
424  // TODO: recursively delete all files and directories inside the directory
425  return impl_delete_dir(fs, current, vector_tail(parts));
426 }
427 
428 // fs sync
429 
430 static os_error_t sync_file(fs_t *dst_fs, fs_t *src_fs, fs_inode_t *dst_node, fs_inode_t *src_node)
431 {
432  CTASSERT(inode_is(dst_node, eOsNodeFile));
433  CTASSERT(inode_is(src_node, eOsNodeFile));
434 
435  os_error_t err = eOsSuccess;
436  io_t *src_io = impl_query_file(src_fs, src_node, eOsAccessRead);
437  io_t *dst_io = impl_query_file(dst_fs, dst_node, eOsAccessWrite | eOsAccessTruncate);
438 
439  if ((err = io_error(src_io)) != eOsSuccess)
440  {
441  goto cleanup;
442  }
443 
444  if ((err = io_error(dst_io)) != eOsSuccess)
445  {
446  goto cleanup;
447  }
448 
449  size_t size = io_size(src_io);
450  if (size > 0)
451  {
452  const void *data = io_map(src_io, eOsProtectRead);
453  CTASSERTF(data != NULL, "failed to map file during sync (path = %s)", io_name(src_io));
454  io_write(dst_io, data, size);
455  }
456 
457 cleanup:
458  // TODO: do we care about the error from closing the io?
459  io_close(dst_io);
460  io_close(src_io);
461  return err;
462 }
463 
464 static sync_result_t sync_dir(fs_t *dst, fs_t *src, fs_inode_t *dst_node, fs_inode_t *src_node)
465 {
466  fs_iter_t *iter;
467  os_error_t err = eOsSuccess;
468 
469  err = fs_iter_begin(src, src_node, &iter);
470  if (err != eOsSuccess)
471  {
472  sync_result_t result = { .path = NULL };
473  return result;
474  }
475 
476  fs_inode_t *child;
477  while (fs_iter_next(iter, &child) == eOsSuccess)
478  {
479  fs_inode_t *other = get_inode_for(dst, dst_node, child->name, child->type);
480  if (other == NULL)
481  {
482  sync_result_t result = { .path = child->name };
483  return result;
484  }
485 
486  if (child->type == eOsNodeDir)
487  {
488  sync_dir(dst, src, other, child);
489  }
490  else if (child->type == eOsNodeFile)
491  {
492  if (sync_file(dst, src, other, child) != eOsSuccess)
493  {
494  sync_result_t result = { .path = child->name };
495  return result;
496  }
497  }
498  else
499  {
500  CT_NEVER("invalid inode type (type = %d)", child->type);
501  }
502  }
503 
504  fs_iter_end(iter);
505 
506  sync_result_t result = { .path = NULL };
507  return result;
508 }
509 
510 STA_DECL
512 {
513  CTASSERT(dst != NULL);
514  CTASSERT(src != NULL);
515 
516  return sync_dir(dst, src, dst->root, src->root);
517 }
518 
519 STA_DECL
521 {
522  CTASSERT(inode != NULL);
523 
524  return inode->type;
525 }
526 
527 STA_DECL
528 bool fs_inode_is(const fs_inode_t *inode, os_dirent_t type)
529 {
530  CT_ASSERT_RANGE(type, 0, eOsNodeCount - 1);
531 
532  return fs_inode_type(inode) == type;
533 }
534 
535 STA_DECL
536 const char *fs_inode_name(const fs_inode_t *inode)
537 {
538  CTASSERT(inode != NULL);
539 
540  return inode->name;
541 }
542 
543 STA_DECL
544 fs_inode_t *fs_find_inode(fs_t *fs, const char *path)
545 {
546  CTASSERT(fs != NULL);
547  CTASSERT(path != NULL);
548 
549  return find_inode(fs, fs->root, path);
550 }
551 
552 STA_DECL
554 {
555  CTASSERT(fs != NULL);
556 
557  return fs->root;
558 }
559 
560 STA_DECL
561 os_error_t fs_iter_begin(fs_t *fs, const fs_inode_t *node, fs_iter_t **iter)
562 {
563  CTASSERT(fs != NULL);
564  CTASSERT(node != NULL);
565  CTASSERT(iter != NULL);
566 
567  if (!fs_inode_is(node, eOsNodeDir))
568  {
569  return eOsExists;
570  }
571  const size_t sz = sizeof(fs_iter_t) + fs->cb->iter_size;
572 
573  fs_iter_t *data = ARENA_MALLOC(sz, "fs_iter", node, fs->arena);
574  data->fs = fs;
575  data->dir = node;
576  data->current = NULL;
577 
578  os_error_t err = impl_iter_begin(fs, node, data);
579  if (err != eOsSuccess)
580  {
581  arena_free(data, sz, fs->arena);
582  return err;
583  }
584 
585  *iter = data;
586  return eOsSuccess;
587 }
588 
589 STA_DECL
590 os_error_t fs_iter_end(fs_iter_t *iter)
591 {
592  CTASSERT(iter != NULL);
593  const size_t sz = sizeof(fs_iter_t) + iter->fs->cb->iter_size;
594 
595  os_error_t err = impl_iter_end(iter);
596  arena_free(iter, sz, iter->fs->arena);
597 
598  return err;
599 }
600 
601 STA_DECL
602 os_error_t fs_iter_next(fs_iter_t *iter, fs_inode_t **inode)
603 {
604  CTASSERT(iter != NULL);
605  CTASSERT(inode != NULL);
606 
607  os_error_t err = impl_iter_next(iter);
608  if (err == eOsSuccess)
609  {
610  *inode = iter->current;
611  }
612 
613  return err;
614 }
bool inode_is(const fs_inode_t *inode, os_dirent_t type)
Definition: common.c:55
CT_NODISCARD size_t size
Definition: scan.h:128
CT_NODISCARD CT_CONSTFN STA_RET_STRING CT_OS_API const char * os_dirent_string(os_dirent_t type)
get the string representation of a directory entry type
Definition: os_common.c:13
os_dirent_t
directory entry type
Definition: core.h:56
@ eOsNodeCount
Definition: core.h:60
os_access_t
file access mode
Definition: core.h:38
STA_DECL void fs_delete(fs_t *fs)
Definition: fs.c:166
STA_DECL os_error_t fs_iter_next(fs_iter_t *iter, fs_inode_t **inode)
Definition: fs.c:602
STA_DECL os_error_t fs_iter_begin(fs_t *fs, const fs_inode_t *node, fs_iter_t **iter)
Definition: fs.c:561
#define STA_DECL
sal2 annotation on function implementations to copy annotations from the declaration
CT_NODISCARD CT_PUREFN CT_BASE_API size_t ctu_strlen(const char *str)
get the length of a string not including the null terminator equivalent to strlen but with safety che...
Definition: util.c:87
STA_DECL os_dirent_t fs_inode_type(const fs_inode_t *inode)
get the type of an inode
Definition: fs.c:520
STA_DECL bool fs_dir_exists(fs_t *fs, const char *path)
query if a directory exists
Definition: fs.c:368
STA_DECL os_error_t fs_file_delete(fs_t *fs, const char *path)
delete a file
Definition: fs.c:219
STA_DECL bool fs_file_exists(fs_t *fs, const char *path)
query if a file exists
Definition: fs.c:197
STA_DECL os_error_t fs_dir_delete(fs_t *fs, const char *path)
delete a directory delete a directory and all contained files and folders
Definition: fs.c:397
STA_DECL os_error_t fs_dir_create(fs_t *fs, const char *path)
create a directory create a directory and all child directories inside a filesystem
Definition: fs.c:333
STA_DECL fs_inode_t * fs_find_inode(fs_t *fs, const char *path)
find an inode in a filesystem
Definition: fs.c:544
STA_DECL io_t * fs_open(fs_t *fs, const char *path, os_access_t flags)
open a file at a given location in the filesystem
Definition: fs.c:254
STA_DECL os_error_t fs_iter_end(fs_iter_t *iter)
end an iteration
Definition: fs.c:590
STA_DECL void fs_file_create(fs_t *fs, const char *path)
create a file
Definition: fs.c:176
STA_DECL bool fs_inode_is(const fs_inode_t *inode, os_dirent_t type)
check if a given inode is of a certain type
Definition: fs.c:528
STA_DECL const char * fs_inode_name(const fs_inode_t *inode)
get the name of an inode
Definition: fs.c:536
STA_DECL sync_result_t fs_sync(fs_t *dst, fs_t *src)
synchronize 2 filesystems copies all folders and files from src to dst
Definition: fs.c:511
STA_DECL fs_inode_t * fs_root_inode(fs_t *fs)
get the root inode of a filesystem
Definition: fs.c:553
CT_IO_API io_t * io_new(const io_callbacks_t *cb, os_access_t flags, const char *name, STA_READS(cb->size) const void *data, arena_t *arena)
create a new IO object for a given interface
CT_IO_API size_t io_write(io_t *io, STA_READS(size) const void *src, size_t size)
write to an io object
CT_NODISCARD CT_IO_API os_error_t io_error(const io_t *io)
get the last error from the io object
Definition: io.c:144
CT_IO_API os_error_t io_close(INOUT_NOTNULL io_t *io)
destroy an IO object
CT_NODISCARD CT_IO_API size_t io_size(io_t *io)
get the total size of an io objects contents
Definition: io.c:94
CT_NODISCARD CT_IO_API const char * io_name(const io_t *io)
get the name of an io object
Definition: io.c:112
CT_NODISCARD CT_IO_API void * io_map(io_t *io, os_protect_t protect)
map an io object into memory maps an io objects entire contents into memory.
Definition: io.c:120
#define CT_ALLOC_SIZE_UNKNOWN
unknown allocation size constant when freeing or reallocating memory, this can be used as the size to...
Definition: arena.h:37
#define ARENA_MALLOC(size, name, parent, arena)
allocate memory from a custom allocator
Definition: arena.h:392
CT_ARENA_API void arena_free(STA_RELEASE void *ptr, size_t size, arena_t *arena)
release memory from a custom allocator
#define CT_ASSERT_RANGE(value, min, max)
assert that a value is in a range inclusive bounds check
Definition: panic.h:148
#define CT_NEVER(...)
assert that a code path is never reached
Definition: panic.h:136
#define CTASSERT(expr)
assert a condition, prints the condition as a message
Definition: panic.h:130
#define CTASSERTF(expr,...)
assert a condition with a message and optional format arguments
Definition: panic.h:116
#define CT_PARANOID_ASSERTF(expr,...)
assert a condition with a message and optional format arguments
CT_NODISCARD CT_STD_API vector_t * str_split(const char *str, const char *sep, arena_t *arena)
split a string into a vector by a separator
Definition: str.c:557
CT_NODISCARD CT_PUREFN CT_STD_API void * vector_get(const vector_t *vector, size_t index)
get a value from a vector
Definition: vector.c:134
CT_NODISCARD CT_PUREFN CT_STD_API void * vector_tail(const vector_t *vector)
get the last element of a vector
Definition: vector.c:143
CT_NODISCARD CT_PUREFN CT_STD_API size_t vector_len(const vector_t *vector)
get the length of a vector
Definition: vector.c:152
CT_NODISCARD OUT_NOTNULL os_inode_t * dir
Definition: os.h:245
@ eOsNotFound
Definition: posix.h:25
@ eOsExists
Definition: posix.h:26
@ eOsSuccess
Definition: posix.h:24
an allocator object
Definition: arena.h:86
fs_dir_create_t pfn_create_dir
Definition: common.h:57
fs_iter_next_t pfn_iter_next
Definition: common.h:64
size_t iter_size
Definition: common.h:67
fs_file_create_t pfn_create_file
Definition: common.h:60
fs_iter_begin_t pfn_iter_begin
Definition: common.h:63
fs_query_file_t pfn_query_file
Definition: common.h:55
fs_dir_delete_t pfn_delete_dir
Definition: common.h:58
fs_file_delete_t pfn_delete_file
Definition: common.h:61
fs_iter_end_t pfn_iter_end
Definition: common.h:65
fs_query_node_t pfn_query_node
Definition: common.h:53
os_dirent_t type
Definition: common.h:14
const char * name
Definition: common.h:15
fs_inode_t * current
Definition: common.h:23
fs_t * fs
Definition: common.h:21
Definition: common.h:72
arena_t * arena
Definition: common.h:74
const fs_callbacks_t * cb
callbacks
Definition: common.h:73
fs_inode_t * root
root inode
Definition: common.h:75
fs_inode_t * node
Definition: common.h:29
os_error_t error
Definition: common.h:30
io callback interface
Definition: impl.h:86
io object implementation
Definition: impl.h:122
os_error_t error
the last error set on this object
Definition: impl.h:127
os_dirent_t type
Definition: os.h:54
the result of a fs_sync call this is here because we cant use Compiler message notification in the fs...
Definition: fs.h:116
a generic vector of pointers
Definition: vector.c:16