TARFS 0.1.5
Read-only TAR filesystem for ESP32
Loading...
Searching...
No Matches
fs.c
Go to the documentation of this file.
1/*
2 * TARFS - Immutable (read-only) filesystem for embedded systems.
3 *
4 * Copyright (c) 2026 Viacheslav Logunov
5 * SPDX-License-Identifier: MMIT
6 *
7 * Author:
8 * Viacheslav Logunov <vvb333007@gmail.com>
9 *
10 * Project:
11 * https://github.com/vvb333007/tarfs
12 */
13
14
15#include <stdint.h>
16#include <stdlib.h>
17#include <string.h>
18#include <stdio.h>
19#include <stdbool.h>
20#include <stdatomic.h>
21
22#include <unistd.h>
23#include <dirent.h>
24#include <sys/errno.h>
25#include <sys/fcntl.h>
26
27#include "config.h"
28#include "os.h"
29#include "refc.h"
30#include "fs.h"
31#include "file.h"
32#include "inode.h"
33
34
35
39static _Atomic int s_numfs = 0;
40static struct tarfs_fs *s_tarfs[TARFS_MAX_FS] = { 0 };
41
42#if CONFIG_TARFS_LOG
43bool g_tarfs_log = true;
44#endif
45
46#if CONFIG_TARFS_INTEGRITY
47static bool s_tarfs_crc64 = true;
48#endif
49
54struct tarfs_fs *tarfs_getfs(int i) {
55
56 if (i>=0 && i < TARFS_MAX_FS)
57 return s_tarfs[i];
58
59 log("filesystem #%d does not exist!\r\n",i);
60
61 return NULL;
62
63}
64
71
72 struct tarfs_fs *fs;
73
74 tarfs_lock(); /* concurrent commit_unmount() fired */
75
76 if (i>=0 && i < TARFS_MAX_FS) {
77 fs = s_tarfs[i];
78 if (!tarfs_addref(fs))
79 fs = NULL;
80 }
81 else
82 fs = NULL;
83
84 tarfs_unlock();
85
86 if (fs == NULL)
87 log("filesystem #%d does not exist!\r\n",i);
88
89 return fs;
90}
91
92
93
100static int findfs(const char *mountpoint) {
101
102 for (int i = 0; i < TARFS_MAX_FS; i++) {
103
104 /* We are interested in empty slots only if mountpoint is NULL */
105 if (s_tarfs[i] == NULL) {
106 if (mountpoint == NULL) {
107 log("empty slot #%d found\r\n", i);
108 return i;
109 }
110
111 continue;
112 }
113
114 /* We are not interested in occupied slots if mountpoint is NULL */
115 if (mountpoint == NULL)
116 continue;
117
118 /* Exact name match? Return slot number */
119 if (!strcmp(s_tarfs[i]->fs_mountpoint, mountpoint)) {
120 log("mountpoint %s slot #%d found\r\n", mountpoint, i);
121 return i;
122 }
123 }
124
125 /* Log, set errno and return -1 */
126
127 if (mountpoint == NULL) {
128 log("can not find empty slot\r\n");
129 errno = EBUSY;
130 return -1;
131 }
132
133 log("can not find slot (%s)\r\n", mountpoint);
134 errno = ENOENT;
135 return -1;
136}
137
138
147int tarfs_fsindex(const char *path) {
148
149 int best = -1;
150 size_t best_len = 0;
151
152 tarfs_lock();
153 for (int i = 0; i < TARFS_MAX_FS; i++) {
154
155 if (s_tarfs[i] != NULL) {
156 const char *mp = s_tarfs[i]->fs_mountpoint; /* can't be NULL, it is an inplace array */
157 size_t len = strlen(mp);
158
159 if (len <= best_len)
160 continue;
161
162 if (strncmp(path, mp, len) != 0)
163 continue;
164
165 /* Match exactly "/foo" or "/foo/..." */
166 if (path[len] != '\0' &&
167 path[len] != '/' &&
168 mp[len - 1] != '/')
169 continue;
170
171 best = i;
172 best_len = len;
173 }
174 }
175 tarfs_unlock();
176
177 return best;
178}
179
180
181
190static void commit_unmount(void *ctx) {
191
192 int i;
193 struct tarfs_fs *fs = (struct tarfs_fs *)ctx;
194
195 if (fs == NULL)
196 return ;
197
198 log("unmounting FS '%s' started\r\n", fs->fs_mountpoint);
199
200
201 log("unregistering VFS\r\n");
202
203 /* If we can not properly unregister our FS we don't remove tarfs_fs entry
204 * to prevent crashes: unregistered fs can still call read()/write()/open()
205 */
207
208 log(" failed to unregister '%s', memory leaked!\r\n", fs->fs_mountpoint);
209 /* This will create a memory leak, but prevents crashes */
210 return ;
211 }
212
213 /* Once FS is unregistered, no handlers with ctx==fs will be called.
214 * Now we can start data structures removal
215 */
216 /* Clear slot: pointer is going to become invalid
217 */
218 log("clearing slot..\r\n");
219 tarfs_lock();
220 for (i = 0; i< TARFS_MAX_FS; i++)
221 if (s_tarfs[i] == fs) {
222 s_numfs--;
223 s_tarfs[i] = NULL;
224 log("FS slot %d cleared\r\n", i);
225 break;
226 }
227 tarfs_unlock();
228
229 /* Release all associated memory: inodes, inode index*/
230 if (fs->fs_ino != NULL && fs->fs_nino > 0) {
231
232 log(" deleting inodes (%u)\r\n", (unsigned int)fs->fs_nino);
233 inode_unmount(fs, (const void *)fs->fs_vaddr, fs->fs_size);
234 fs->fs_ino = NULL;
235 }
236
237 /* Release the FS image */
238 if (fs->fs_vaddr != NULL) {
239 if (fs->fs_handle != 0) {
240 log(" unmapping filesystem image, vaddr=%p, size=%u\r\n", (const void *)fs->fs_vaddr, (unsigned int)fs->fs_size);
241 tarfs_os_unmap_tarfile((void *)fs->fs_handle, (void *)fs->fs_vaddr, fs->fs_size);
242 }
243 fs->fs_vaddr = NULL;
244 }
245
246 log("deleting FS descriptor %p\r\n", (void *)fs);
247 tarfs_os_free(fs);
248}
249
250/*
251 *
252 */
253int tarfs_addref(struct tarfs_fs *fs) {
254 return fs == NULL ? 0 : addref(&fs->fs_ref);
255}
256
257/*
258 *
259 */
260int tarfs_unref(struct tarfs_fs *fs) {
261 return fs == NULL ? 0 : unrefx(&fs->fs_ref, fs, commit_unmount);
262}
263
267int tarfs_unmount(const char *mountpoint) {
268
269 int slot,
270 err = 0;
271
272 struct tarfs_fs *fs;
273
274 refc_type_t prev_refc;
275
276 if (mountpoint == NULL) {
277 errno = EFAULT;
278 return -1;
279 }
280
281 tarfs_lock(); /* protect s_tarfs[] array, protects from a concurrent tarfs_unmount/mount */
282
283 if ((slot = findfs(mountpoint)) >= 0) {
284
285 fs = s_tarfs[slot];
286
287 prev_refc = tarfs_unref(fs);
288
289 if (prev_refc > 1) {
290 log("Filesystem %s is in use (%u open fds), unmount delayed\r\n", mountpoint, prev_refc - 1);
291 err = EAGAIN;
292 }
293
294 } else
295 err = ENOENT;
296
297 tarfs_unlock();
298
299 if (err != 0) {
300 errno = err;
301 return -1;
302 }
303
304 return 0;
305}
306
307/* Mount TARfile which is already mmaped/loaded into RAM
308 *
309 */
310int tarfs_mount_memory(const void *map, size_t size, const char *mountpoint, const char *link_rebase, const char *path_rebase) {
311
312 int len;
313
314
315 int slot = -1;
316 struct tarfs_fs *fs = NULL;
317
318 char base_dir[128] = { '/' };
319
320 if (link_rebase == NULL)
321 link_rebase = "";
322
323 if (path_rebase) {
324 strncpy(&base_dir[1], path_rebase, sizeof(base_dir)-1);
325 } else {
326 if (false == tar_rootdir(map, size, &base_dir[1], sizeof(base_dir) - 1))
327 base_dir[0] = '\0';
328 }
329
330 if (mountpoint == NULL)
331 mountpoint = base_dir;
332 else {
333 log("detected MP '%s' is overriden with '%s'\r\n", base_dir, mountpoint);
334 }
335
336 len = strlen(mountpoint);
337
338#if CONFIG_TARFS_INTEGRITY
339 if (tarfs_integrity(-1) > 0)
340 log("TAR-CRC64 filesystem is expected\r\n");
341#endif
342
343 if (false == (len > 1 && mountpoint[0] == '/' && mountpoint[len - 1] != '/')) {
344 log("mountpoint is too short or invalid '%s'\r\n", mountpoint);
345 errno = EINVAL;
346unmap_and_return_error:
347
348 return -1;
349 }
350
351 log("mountpoint: '%s'\r\n", mountpoint);
352
353 if (base_dir[1] == '\0') {
354 log("WARN: tarfile has no root directory\r\n");
355 } else {
356 log("common prefix: '%s' (will be stripped)\r\n", &base_dir[1]);
357 }
358
359 if (*link_rebase != '\0') {
360 log("absolute path rewrite: '%s'\r\n",link_rebase);
361 } else {
362 log("preserving absolute paths in hardlinks/symlinks\r\n");
363 }
364
365 /* Allocate FS descriptor */
366 if ( NULL == (fs = tarfs_calloc(1, sizeof(struct tarfs_fs) + len + 1))) {
367 /* errno is set in memory backend */
368 goto unmap_and_return_error;
369 }
370
371 /* Allocate free FS slot */
372 /* ------- locked -------*/
373 tarfs_lock();
374 if (0 > (slot = findfs( NULL ))) {
375 tarfs_unlock();
376 tarfs_os_free(fs);
377 log("too many mounted filesystems (%u)\r\n",s_numfs);
378 errno = EBUSY;
379 goto unmap_and_return_error;
380 }
381
382 /* Occupy FS slot and release the lock ASAP */
383 s_tarfs[slot] = fs;
384 s_numfs++;
385 tarfs_unlock();
386 /* ------- unlocked -------*/
387
388 log("allocated new FS descriptor s_tarfs[%d] = %p\r\n", slot, (void *)fs);
389
390 /* set refcounter to 1 */
391 initref(&fs->fs_ref);
392
393 /* Store tarfile mapping parameters in the FS descriptor */
394 fs->fs_vaddr = map;
395 fs->fs_handle = 0; /* populated by tarfs_mount() if required */
396 fs->fs_size = size;
397
398 /* Copy mountpoint. Trailing zero is there already */
399 memcpy(fs->fs_mountpoint, mountpoint, len);
400
401 log("mounting..\r\n");
402 if (inode_mount(fs, map, size, link_rebase, &base_dir[1]) < 0) {
403 if (fs->fs_ino == NULL) {
404 log("filesystem is unusable, no valid inodes were found\r\n");
405 tarfs_lock();
406 s_tarfs[slot] = NULL;
407 s_numfs--;
408 tarfs_unlock();
409 /* errno must be set in inode_mount() */
410 goto unmap_and_return_error;
411 }
412 log("WARN: running in degraded mode\r\n");
413 }
414
415// log("addr %p:%u --> %u inodes successfully mounted\r\n", map, (unsigned int)size, (unsigned int)fs->fs_nino);
416
417 /* Registering VFS */
418 log("registering TARFS in VFS..\r\n");
419 if (tarfs_os_register_fs(mountpoint, (void *)(intptr_t)slot) == false) {
420 log("Can not register POSIX handlers, only native tarfs API is available\r\n");
421 } else {
422 log("VFS registered. (prefix '%s' in VFS)\r\n", mountpoint);
423 }
424
425 log("mount is done. filesystem slot is %d\r\n", slot);
426
427 log("-----------\r\n%u blocks (%u bytes) were skipped as BAD\n"
428 "TAR archive has %u files, %u links and %u dirs\r\n"
429 "TAR data/headers ratio: %u data bytes, %u header bytes\r\n"
430 "RAM overhead (total RAM used by the FS): %u bytes\r\n-----------\r\n",
431 fs->fs_stats.badblocks,
432 fs->fs_stats.badblocks * 512,
433 fs->fs_stats.files,
434 fs->fs_stats.links,
435 fs->fs_stats.dirs,
436 (unsigned int)fs->fs_dsize,
437 (unsigned int)(fs->fs_size - fs->fs_dsize),
438 fs->fs_stats.ram);
439
440 return slot;
441}
442
443
449int tarfs_mount(const char *label, const char *mountpoint, const char *link_rebase, const char *path_rebase) {
450
451 int slot;
452 size_t size;
453 void const *map;
454 void *os_handle;
455
456
457 /* Actual memory mapping */
458 log("loading OS-specific resource '%s'..\r\n", label);
459
460 if (NULL != (map = tarfs_os_map_tarfile( label, &os_handle, &size))) {
461
462 log("resource is available at %p, %u bytes. mounting from memory..\r\n", map, (unsigned int)size);
463
464 slot = tarfs_mount_memory(map, size, mountpoint, link_rebase, path_rebase);
465 if (slot >= 0) {
466
467 log("success, filesystem slot %d was assigned\r\n", slot);
468
469 struct tarfs_fs *fs = tarfs_getfs(slot);
470
471 log("resource handle is %p, commit_unmount() will do tarfs_os_unmap_tarfile()\r\n", (void *)os_handle);
472
473 fs->fs_handle = (uintptr_t)os_handle;
474
475 return slot;
476 }
477 tarfs_os_unmap_tarfile(os_handle, map, size);
478 }
479
480 if (errno == 0)
481 errno = EIO;
482
483 log("failed to mmap() the FS image (errno=%d, label=%s)\r\n", errno, label);
484
485 return -1;
486}
487
492void *tarfs_calloc(size_t count, size_t size) {
493
494 void *buffer;
495
496 if ((buffer = tarfs_os_malloc(size * count)) != NULL)
497 memset(buffer, 0, size);
498
499 return buffer;
500}
501
502/*
503 * strdup() based on a memory backend
504 */
505char *tarfs_strdup(char const *str) {
506
507 if (str != NULL) {
508
509 size_t len = strlen(str);
510 char *dst = tarfs_os_malloc(len + 1);
511
512 if (dst != NULL) {
513
514 memcpy(dst, str, len);
515 dst[len] = '\0';
516
517 return dst;
518 }
519 }
520 return NULL;
521}
522
523
524
533int tarfs_info(const char *mp, size_t *raw_size, size_t *data_size) {
534
535 int fs_idx = tarfs_fsindex(mp);
536
537 if (fs_idx >= 0) {
538
539 struct tarfs_fs *fs = tarfs_getfs_addref(fs_idx);
540
541 if (fs != NULL) {
542
543 if (raw_size)
544 *raw_size = fs->fs_size;
545
546 if (data_size)
547 *data_size = fs->fs_dsize;
548 tarfs_unref(fs);
549
550 return 0;
551 }
552 }
553
554 errno = ENODEV;
555 return -1;
556}
557
558
559
569unsigned int tarfs_fsck(const char *label) {
570
571 size_t tar_length;
572 void const *map;
573 void *os_handle;
574
575
576 printf("Checking filesystem '%s'..\r\n", label);
577
578 if (NULL != (map = tarfs_os_map_tarfile( label, &os_handle, &tar_length))) {
579 int num = 0;
580 do {
581
582 uintptr_t tar_start = (uintptr_t )map;
583 uint32_t size;
584 size_t off = 0;
585 int bad = 0, files = 0, dirs = 0, links = 0, bad_total = 0, hdr_no = 0, bad_files = 0;
586 uintptr_t tar_end = (uintptr_t )((const uint8_t *)map + tar_length);
587
588 while (off + sizeof(tarhdr_t) <= tar_length) {
589
590 const tarhdr_t *hdr = (const tarhdr_t *)(tar_start + off);
591
592 if (tar_badhdr(hdr)) {
593
594 if (!bad) {
595bad_header:
596 printf("Inode#%u : bad metadata, switching to scan\r\n", hdr_no);
597 }
598 bad++;
599
600 off += sizeof(tarhdr_t);
601 continue;
602 }
603
604 if (bad) {
605 bad_total += bad;
606 printf("Inode#%u : %u headers were skipped, continuing to mount..\r\n", hdr_no, bad);
607 bad = 0;
608 }
609
610 size = tar_octal(hdr->size, sizeof(hdr->size));
611
612 /* Check if size is sane: current pointer + 512 bytes + size must be < tar_end */
613 if (((uintptr_t)(hdr + 1)) + size >= tar_end) {
614 printf("Inode#%u : element extends beyond the end of the archive\r\n", hdr_no);
615 goto bad_header;
616 }
617
618 switch(hdr->type) {
619 case TART_AFILE:
620 case TART_CONT:
621 case TART_FILE: files++; break;
622
623 case TART_SYMLINK:
624 case TART_HARDLINK: links++; break;
625
626 case TART_DIR: dirs++; break;
627 case TART_PAX:
628 case TART_PAX_G: break;
629
630 /* Unrecognized entry */
631 default:
632 printf("Unrecognized entry #%u, type=0x%02x\r\n",hdr_no, hdr->type);
633 };
634
635
636 if (tar_baddata(hdr, size)) {
637 printf("Inode#%u : bad data\r\n", hdr_no);
638 bad_files++;
639 }
640
641
642 off += sizeof(tarhdr_t);
643
644
645 /* Real size is 512 bytes aligned */
646 off += ((size_t)size + 511) & ~511u;
647
648 hdr_no++;
649 }
650
651 bad_total += bad;
652
653 unsigned int total = files + links + dirs;
654
655 printf("Check finished.\r\n\r\n"
656 "Inodes processed: %u, number of bad metadata headers: %u\r\n\r\n", hdr_no, bad_total);
657 printf("Trailing garbage: %u blocks, ~%u bytes\r\n", bad, bad * 512);
658 printf("Damaged data: (%u files / pax headers)\r\n",bad_files);
659 printf("Available: %u entries (%u files, %u dirs, %u links)\r\n",total, files, dirs, links);
660
661 num = bad_total + bad_files;
662 } while (0);
663
664 tarfs_os_unmap_tarfile(os_handle, map, tar_length);
665
666 /* fsck() returns total number of unrecognized/bad headers */
667 return num;
668 }
669
670 /* all headers are bad */
671 return -1;
672}
673
674
686int tarfs_statvfs(void *ctx, struct statvfs *st) {
687
688 int fs_idx;
689 struct tarfs_fs *fs;
690
691 if (!st) {
692 errno = EFAULT; /* Linux sets EFAULT instead of EINVAL so we do the same */
693 return -1;
694 }
695
696 fs_idx = (int)(uintptr_t)ctx;
697 fs = tarfs_getfs_addref( fs_idx );
698
699 if (fs == NULL) {
700 errno = EIO;
701 return -1;
702 }
703
704 memset(st, 0, sizeof(*st));
705
706 /* FS ID*/
707 st->f_fsid = fs_idx;
708
709 /* Logical block size and total filesystem size */
710 st->f_bsize = 512;
711 st->f_frsize = 512;
712 st->f_blocks = ((fs->fs_dsize + 511) & ~511) / 512;
713
714 /* Number of files (ROFS!) */
715 st->f_files = fs->fs_stats.files;
716
717 /* Maximum filename length and flags
718 * We do support longer filenames but we are limited to the size of dirent's d_name
719 */
720 st->f_namemax = sizeof(((struct dirent *) 0)->d_name) - 1;
722
723 /* Cygwin does not have these: */
724#ifdef ST_NOATIME
725 st->f_flag |= ST_NOATIME;
726#endif
727#ifdef ST_NODIRATIME
728 st->f_flag |= ST_NODIRATIME;
729#endif
730#ifdef ST_NODEV
731 st->f_flag |= ST_NODEV;
732#endif
733
734 /* TARFS extensions. These are not part of the standart, and only can be
735 * added to statvfs structure when platform lacks statvfs.h;
736 */
737#if CONFIG_TARFS_HAVE_STATVFS_H
738/* For systems with their own sys/statvfs.h file, we stop here */
739#else
740# if CONFIG_TARFS_COUNTERS
741 /* Runtime counters */
742 st->f_bread = fs->fs_bread;
743 st->f_bmmap = fs->fs_bmmap;
744 st->f_nfail = fs->fs_nfail;
745# endif
746# if CONFIG_TARFS_INTEGRITY
747 /* Number of bad files (if CRC64 is enabled at compile tiem)*/
748 st->f_badcrc = fs->fs_stats.badcrc;
749# endif
750 /* Mount-time statistics, immutable */
751 st->f_dirs = fs->fs_stats.dirs;
752 st->f_links = fs->fs_stats.links;
754 st->f_ram = fs->fs_stats.ram;
755#endif /* #if CONFIG_TARFS_HAVE_STATVFS_H */
756
757 tarfs_unref(fs);
758
759 return 0;
760}
761
770int tarfs_integrity_on_open(int fs_idx, int en) {
771
772#if CONFIG_TARFS_INTEGRITY
773 struct tarfs_fs *fs = tarfs_getfs_addref(fs_idx);
774
775 if (fs == NULL) {
776
777 log("no such filesystem: %d\r\n", fs_idx);
778 errno = ENODEV;
779
780 return -1;
781 }
782
783 int ret = fs->fs_opencrc;
784
785 if (en >= 0)
786 fs->fs_opencrc = (int)(bool)en;
787 tarfs_unref(fs);
788
789 log(" CRC64 on each open() : %s\r\n", en < 0 ? "unchanged" : (en ? "enabled (slow open)" : "disabled"));
790 return ret;
791#else
792 log("CONFIG_TARFS_INTEGRITY is disabled, flag ignored\r\n");
793 return 0;
794#endif
795}
796
797
798
803int tarfs_integrity(int en) {
804
805#if CONFIG_TARFS_INTEGRITY
806
807 int ret = s_tarfs_crc64;
808
809 if (en >= 0) {
810 log(" CRC64 on mount : %s\r\n", en < 0 ? "unchanged" : (en ? "enabled (slow mount)" : "disabled"));
811 s_tarfs_crc64 = en;
812 }
813
814 return ret;
815
816#else
817
818 if (en >= 0)
819 log("CONFIG_TARFS_INTEGRITY is disabled, flag ignored\r\n");
820
821 return 0;
822
823#endif
824}
825
826
827
832int tarfs_dump(int fs_idx) {
833
834 struct statvfs st;
835
836 if (tarfs_statvfs((void *)(intptr_t)fs_idx, &st) == 0) {
837
838 printf(" Filesystem ID: %u\r\n",(unsigned int)st.f_fsid);
839 printf("----------------\r\n");
840 printf(" Filesystem block size: %u\r\n",(unsigned int)st.f_bsize);
841 printf(" Fragment size: %u\r\n",(unsigned int)st.f_frsize);
842 printf(" Number of blocks: %u\r\n",(unsigned int)st.f_blocks);
843 printf(" Maximum filename length: %u\r\n",(unsigned int)st.f_namemax);
844
845#if CONFIG_TARFS_HAVE_STATVFS_H
846 /* Platform provides its own statvfs.h so we can not add TARFS-specific information
847 * Instead, direct lookup into tarfs_fs.fs_stats should be made
848 */
849#else
850 printf(" Number of bad/unrecognized 512-byte blocks: %u\r\n",(unsigned int)st.f_badblocks);
851 printf(" Number of bad CRC64 files: %u\r\n",(unsigned int)st.f_badcrc);
852
853 printf(" Number of files: %u\r\n",(unsigned int)st.f_files);
854 printf(" Number of links: %u\r\n",(unsigned int)st.f_links);
855 printf(" Number of directories: %u\r\n",(unsigned int)st.f_dirs);
856
857 printf(" Total bytes read()+pread(): %llu\r\n",(unsigned long long)st.f_bread);
858 printf(" Total bytes mmap(): %llu\r\n",(unsigned long long)st.f_bmmap);
859 printf(" Total number of failures: %u\r\n",(unsigned int)st.f_nfail);
860
861 printf(" Total RAM used by the FS: %u \r\n",(unsigned int)st.f_ram);
862#endif
863 } else
864 printf("failed to statvfs()\r\n");
865
866 return -1;
867}
int tarfs_statvfs(void *ctx, struct statvfs *st)
Obtain filesystem statistics.
Definition fs.c:686
int tarfs_fsindex(const char *path)
Find the filesystem responsible for a given path.
Definition fs.c:147
int tarfs_unref(struct tarfs_fs *fs)
Definition fs.c:260
int tarfs_integrity_on_open(int fs_idx, int en)
Enable/Disable/Get fs_opencrc flag for a filesystem with index fs_idx This flag enable optinal CRC64 ...
Definition fs.c:770
unsigned int tarfs_fsck(const char *label)
Perform a deep filesystem integrity check.
Definition fs.c:569
int tarfs_unmount(const char *mountpoint)
Unmount tar file system.
Definition fs.c:267
void * tarfs_calloc(size_t count, size_t size)
calloc() based on a memory backend; Memory backend must set errno if there were errors
Definition fs.c:492
char * tarfs_strdup(char const *str)
Definition fs.c:505
struct tarfs_fs * tarfs_getfs(int i)
Lockless, not thread safe, does not increase refcounters.
Definition fs.c:54
int tarfs_mount(const char *label, const char *mountpoint, const char *link_rebase, const char *path_rebase)
Actual mount procedure We expect sane label pointer (ASCIIZ) and a sane mountpoint (i....
Definition fs.c:449
int tarfs_addref(struct tarfs_fs *fs)
Filesystem reference counting.
Definition fs.c:253
int tarfs_dump(int fs_idx)
Dump FS statistics and content This functions is for debugging only and MUST NOT be used in productio...
Definition fs.c:832
int tarfs_integrity(int en)
Enables or disables CRC64 integrity verification for TARFS archives.
Definition fs.c:803
struct tarfs_fs * tarfs_getfs_addref(int i)
Thread safe, increases refcounter, uses mutex!
Definition fs.c:70
int tarfs_mount_memory(const void *map, size_t size, const char *mountpoint, const char *link_rebase, const char *path_rebase)
Mount a TARFS filesystem from an already mapped memory buffer.
Definition fs.c:310
int tarfs_info(const char *mp, size_t *raw_size, size_t *data_size)
Get size information for TARFS.
Definition fs.c:533
#define TARFS_MAX_FS
Definition fs.h:29
#define log(Format_,...)
Definition fs.h:445
@ ST_NODEV
Definition fs.h:129
@ ST_NOATIME
Definition fs.h:128
@ ST_RDONLY
Definition fs.h:133
@ ST_NOSUID
Definition fs.h:132
@ ST_NODIRATIME
Definition fs.h:130
void inode_unmount(struct tarfs_fs *fs, const void *tar_start, size_t tar_size)
Unmount a TAR image.
Definition inode.c:921
int inode_mount(struct tarfs_fs *fs, const unsigned char *buf, size_t size, const char *rebase_link, const char *base_dir)
Build an inode index for a TAR image.
Definition inode.c:932
void const * tarfs_os_map_tarfile(const char *name, void **os_handle_out, size_t *size_out)
Map a ESP32 flash partition to a virtual address space.
Definition os_esp32.c:222
void tarfs_os_unmap_tarfile(void *os_handle, const void *ptr, size_t size)
Opposite of tarfs_os_map_tarfile().
Definition os_esp32.c:279
bool tarfs_os_register_fs(const char *prefix, void *context)
Tell the VFS that TARFS is now handle all the paths starting from 'prefix'.
Definition os_esp32.c:319
void * tarfs_os_malloc(size_t size)
Memory allocation backend.
Definition os_esp32.c:187
void tarfs_os_free(void *buffer)
Definition os_esp32.c:207
bool tarfs_os_unregister_fs(const char *prefix)
Tell the VFS that path 'prefix' is not handled by tarfs anymore.
Definition os_esp32.c:306
typedef _Atomic(refc_type_t) refc_t
Atomic reference counter type.
unsigned int refc_type_t
Use case:
Definition refc.h:47
The statvfs structure for systems without it (e.g.
Definition fs.h:142
size_t f_badcrc
Definition fs.h:167
size_t f_frsize
Definition fs.h:147
size_t f_ram
Definition fs.h:166
size_t f_dirs
Definition fs.h:165
uint64_t f_bmmap
Definition fs.h:161
size_t f_bsize
Definition fs.h:146
size_t f_links
Definition fs.h:164
int f_flag
Definition fs.h:155
size_t f_files
Definition fs.h:151
size_t f_namemax
Definition fs.h:156
uint32_t f_nfail
Definition fs.h:162
size_t f_badblocks
Definition fs.h:163
size_t f_fsid
Definition fs.h:154
uint64_t f_bread
Definition fs.h:160
size_t f_blocks
Definition fs.h:148
This descriptor holds all file descriptors opened.
Definition fs.h:94
refc_t fs_ref
Definition fs.h:96
uintptr_t fs_handle
Definition fs.h:97
uint32_t fs_nfail
Definition fs.h:114
struct tarfs_stats fs_stats
Definition fs.h:110
uint64_t fs_bread
Definition fs.h:113
tarfs_inode_t const *const * fs_ino
Definition fs.h:102
uint64_t fs_bmmap
Definition fs.h:112
uint16_t fs_opencrc
Definition fs.h:108
uint32_t fs_nino
Definition fs.h:101
size_t fs_dsize
Definition fs.h:99
void const * fs_vaddr
Definition fs.h:98
char fs_mountpoint[]
Definition fs.h:116
size_t fs_size
Definition fs.h:100
unsigned int ram
Definition fs.h:73
unsigned int links
Definition fs.h:71
unsigned int dirs
Definition fs.h:72
unsigned int badblocks
Definition fs.h:69
unsigned int files
Definition fs.h:70
uint32_t tar_octal(const char *p, size_t max_len)
Definition tar.c:193
bool tar_badhdr(tarhdr_t const *hdr)
Validate a TAR header.
Definition tar.c:249
bool tar_baddata(struct tarhdr const *hdr, size_t size)
Verify CRC64 checksum stored in a TAR archive, if present.
Definition tar.c:529
bool tar_rootdir(const uint8_t *tar_start, size_t tar_length, char *base_dir, size_t out_len)
Detect the archive root directory.
Definition tar.c:372
const char size[12]
Definition tar.h:5