### EXT4FUSE_VERSION usage example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md Example of how to print the EXT4FUSE_VERSION at runtime. ```c fprintf(stderr, "Version: %s\n", EXT4FUSE_VERSION); ``` -------------------------------- ### INFO Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Example usage of the INFO macro. ```c INFO("Block size: %u bytes", block_size); INFO("Inode size: %u bytes", inode_size); ``` -------------------------------- ### NOTICE Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Example usage of the NOTICE macro. ```c NOTICE("Mounting filesystem with %d block groups", n_groups); ``` -------------------------------- ### logging_open Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Example usage of the logging_open function. ```c if (logging_open("/tmp/ext4fuse.log") < 0) { fprintf(stderr, "Failed to open log file\n"); return -1; } INFO("Logging started"); ``` -------------------------------- ### WARNING Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Example usage of the WARNING macro. ```c WARNING("Inode %d has invalid size %lld", n, size); ``` -------------------------------- ### DEBUG Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Example usage of the DEBUG macro. ```c DEBUG("Reading inode %d from offset 0x%lx", inode_num, offset); DEBUG("Disk read: 0x%jx +0x%zx", where, size); ``` -------------------------------- ### dcache_init_root Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/directory-cache.md Example usage of dcache_init_root. ```c int ret = dcache_init_root(ROOT_INODE_N); /* ROOT_INODE_N = 2 */ if (ret != 0) { fprintf(stderr, "Failed to initialize dcache\n"); return -1; } ``` -------------------------------- ### Logging Initialization Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Example of how to initialize the logging system during program startup. ```c /* Set up logging during program start */ if (logging_open("/var/log/ext4fuse.log") < 0) { perror("logging_open"); return EXIT_FAILURE; } logging_setlevel(LOG_DEBUG); /* Be verbose */ INFO("ext4fuse starting"); ``` -------------------------------- ### Example of basic ext4fuse usage Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md An example demonstrating how to mount an ext4 filesystem using ext4fuse. ```bash ext4fuse /dev/sda1 /mnt/ext4 ``` -------------------------------- ### Installation Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/overview.md Instructions for installing ext4fuse via Homebrew or from source. ```bash # Via Homebrew (macOS) brew install ext4fuse # From source make && sudo cp ext4fuse /usr/local/bin/ ``` -------------------------------- ### ALERT Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Example usage of the ALERT macro. ```c ALERT("Filesystem inconsistency detected"); ``` -------------------------------- ### logging_setlevel Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Example usage of the logging_setlevel function. ```c logging_setlevel(LOG_DEBUG); /* Show all messages */ logging_setlevel(LOG_WARNING); /* Show only warnings and errors */ ``` -------------------------------- ### dcache_lookup Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/directory-cache.md Example usage of dcache_lookup. ```c struct dcache_entry *home = dcache_lookup(NULL, "home", 4); if (home) { struct dcache_entry *user = dcache_lookup(home, "user", 4); } ``` -------------------------------- ### dcache_insert Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/directory-cache.md Example usage of dcache_insert. ```c struct dcache_entry *home_entry = dcache_insert(NULL, "home", 4, 123); struct dcache_entry *user_entry = dcache_insert(home_entry, "user", 4, 456); ``` -------------------------------- ### Debugging Command Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/README.md Example command to enable logging for debugging. ```bash ext4fuse /dev/sda1 /mnt -o logfile=/tmp/debug.log ``` -------------------------------- ### ERR Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Example usage of the ERR macro. ```c ERR("Failed to read inode %d: %s", inode_num, strerror(errno)); ``` -------------------------------- ### dcache_get_inode Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/directory-cache.md Example usage of dcache_get_inode. ```c struct dcache_entry *entry = dcache_lookup(parent, "file", 4); uint32_t inode_num = dcache_get_inode(entry); /* Returns 0 (root) if entry is NULL, otherwise entry's inode */ ``` -------------------------------- ### Disk Context Reading for Sequential Blocks Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md Bash example demonstrating the use of a disk_ctx structure for efficient sequential reading of multiple blocks, avoiding repeated lseek calls. ```bash struct disk_ctx ctx; disk_ctx_create(&ctx, BLOCKS2BYTES(start), BLOCK_SIZE, count); while (disk_ctx_read(&ctx, size, buf) > 0) { ... } ``` -------------------------------- ### Install ext4fuse on FreeBSD Source: https://github.com/gerard/ext4fuse/blob/master/README.md Command to install ext4fuse through the FreeBSD ports tree. ```bash $ cd /usr/ports/sysutils/fusefs-ext4fuse && make install clean ``` -------------------------------- ### op_readdir example usage Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/fuse-operations.md An example of how to call the op_readdir function in C. ```c int result = op_readdir("/path/to/dir", buf, filler, 0, NULL); if (result == 0) { /* Directory listing populated via filler callbacks */ } ``` -------------------------------- ### inode_init Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/inode-operations.md Example of calling inode_init during FUSE initialization. ```c /* Called during FUSE initialization */ if (inode_init() != 0) { fprintf(stderr, "Failed to initialize inodes\n"); return -1; } ``` -------------------------------- ### CRIT Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Example usage of the CRIT macro. ```c CRIT("Superblock magic number invalid: 0x%x", magic); ``` -------------------------------- ### Installing ext4fuse on macOS via Homebrew Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md Commands to install osxfuse and ext4fuse using Homebrew on macOS. ```bash brew install osxfuse brew install ext4fuse ``` -------------------------------- ### EMERG Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Example usage of the EMERG macro. ```c EMERG("Out of memory, cannot continue"); ``` -------------------------------- ### op_init Example Usage Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/fuse-operations.md Example of how op_init is registered with FUSE operations. ```c /* Called automatically by FUSE on mount */ struct fuse_operations ops = { .init = op_init, /* ... other operations ... */ }; fuse_main(argc, argv, &ops, NULL); ``` -------------------------------- ### Setting runtime logging level Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md Examples of using the logging_setlevel() function to control runtime log verbosity. ```c logging_setlevel(LOG_DEBUG); /* Most verbose */ logging_setlevel(LOG_WARNING); /* Warnings and errors */ logging_setlevel(LOG_ERR); /* Errors only */ ``` -------------------------------- ### inode_get_size Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/inode-operations.md Example showing how to retrieve the 64-bit file size from an inode. ```c struct ext4_inode inode; inode_get_by_number(42, &inode); uint64_t size = inode_get_size(&inode); printf("File size: %lld bytes\n", size); ``` -------------------------------- ### Install ext4fuse on OS X using Homebrew Source: https://github.com/gerard/ext4fuse/blob/master/README.md Commands to install osxfuse and ext4fuse via Homebrew. ```bash $ brew cask install osxfuse $ brew install ext4fuse ``` -------------------------------- ### inode_dentry_get Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/inode-operations.md Example demonstrating how to iterate through directory entries using inode_dentry_get. ```c struct ext4_inode inode; struct inode_dir_ctx *ctx = inode_dir_ctx_get(); inode_get_by_path("/home", &inode); inode_dir_ctx_reset(ctx, &inode); off_t offset = 0; struct ext4_dir_entry_2 *entry; while ((entry = inode_dentry_get(&inode, offset, ctx))) { if (entry->inode) { char name[256]; strncpy(name, entry->name, entry->name_len); name[entry->name_len] = 0; printf("Entry: %s (inode %d)\n", name, entry->inode); } offset += entry->rec_len; } inode_dir_ctx_put(ctx); ``` -------------------------------- ### ext4fuse with allow_other option Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md Example of using the 'allow_other' FUSE option to permit non-root user access. ```bash ext4fuse /dev/sda1 /mnt/ext4 -o allow_other ``` -------------------------------- ### Logging During Operation Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Example of using logging macros for informational messages during normal operation. ```c DEBUG("Reading inode %d", inode_num); int ret = inode_get_by_number(inode_num, &inode); if (ret < 0) { ERR("Failed to read inode %d", inode_num); return ret; } DEBUG("Inode read successfully"); ``` -------------------------------- ### disk_ctx_read Example Usage Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/disk-operations.md Example demonstrating how to use disk_ctx_read to read data from a disk context. ```c struct disk_ctx ctx; disk_ctx_create(&ctx, BLOCKS2BYTES(100), BLOCK_SIZE, 8); char buf[8192]; int bytes = disk_ctx_read(&ctx, 8192, buf); /* Read next 8KB - advances position to second block */ bytes = disk_ctx_read(&ctx, 8192, buf); ``` -------------------------------- ### op_readlink example usage Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/fuse-operations.md An example of how to call the op_readlink function in C and print the target. ```c char link_target[256]; int ret = op_readlink("/path/to/symlink", link_target, sizeof(link_target)); if (ret == 0) { printf("Symlink points to: %s\n", link_target); } ``` -------------------------------- ### Error Reporting Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Example of using the ERR macro to report critical errors. ```c if (disk_magic != 0xEF53) { ERR("Invalid filesystem signature: 0x%04x (expected 0xEF53)", disk_magic); return -EINVAL; } ``` -------------------------------- ### op_open Example Usage Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/fuse-operations.md Example of calling op_open and retrieving the inode number from the file handle. ```c struct fuse_file_info fi = {0}; int ret = op_open("/path/to/file", &fi); if (ret == 0) { uint32_t inode_num = fi->fh; /* Can now use this inode_num in op_read */ } ``` -------------------------------- ### Architecture Overview - Data Flow Example: Reading File Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/overview.md Diagram showing the data flow when reading a file, from user application to disk I/O. ```text User Application ↓ FUSE read(path, offset, size) ↓ op_read() [op_read.c] ↓ inode_get_by_number() [inode.c] - Retrieve inode via fi->fh ↓ inode_get_data_pblock() [inode.c] - Map logical → physical blocks ├─ extent_get_pblock() [extents.c] (if EXT4_EXTENTS_FL set) └─ Indirect block lookup (if traditional layout) ↓ disk_read() [disk.c] - Read physical blocks ↓ pread() system call on device/image ``` -------------------------------- ### inode_dir_ctx_put Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/inode-operations.md Example demonstrating how to free a directory read context after use. ```c struct inode_dir_ctx *ctx = inode_dir_ctx_get(); /* ... use ctx ... */ inode_dir_ctx_put(ctx); /* Release resources */ ``` -------------------------------- ### inode_dir_ctx_reset Example Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/inode-operations.md Example showing how to reset a directory read context to load the first block of directory data. ```c struct ext4_inode dir_inode; struct inode_dir_ctx *ctx = inode_dir_ctx_get(); inode_get_by_path("/home/user", &dir_inode); inode_dir_ctx_reset(ctx, &dir_inode); /* Ready to read entries */ ``` -------------------------------- ### Path Lookup with Cache Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/directory-cache.md Example C function demonstrating how to look up a path within the directory cache. ```c struct dcache_entry *lookup_path(const char *path) { struct dcache_entry *current = NULL; /* Start at root */ while (*path) { if (*path == '/') path++; /* Skip slashes */ const char *end = strchr(path, '/'); int namelen = end ? (end - path) : strlen(path); /* Look up component in cache */ struct dcache_entry *next = dcache_lookup(current, path, namelen); if (!next) { return NULL; /* Not in cache */ } current = next; path += namelen; } return current; } ``` -------------------------------- ### op_getattr Example Usage Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/fuse-operations.md Example of calling op_getattr and printing file size and owner information. ```c struct stat stbuf; int ret = op_getattr("/path/to/file", &stbuf); if (ret == 0) { printf("File size: %ld bytes\n", stbuf.st_size); printf("Owner: %d:%d\n", stbuf.st_uid, stbuf.st_gid); } ``` -------------------------------- ### op_read Example Usage Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/fuse-operations.md Example of calling op_read to read file contents into a buffer. ```c char buffer[4096]; int bytes_read = op_read("/path/to/file", buffer, 4096, 0, &fi); if (bytes_read > 0) { /* buffer now contains up to 'bytes_read' bytes from file */ } ``` -------------------------------- ### FUSE Command-Line Logging Option Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Example of how to enable logging to a file using the '-o logfile=PATH' FUSE option. ```bash ext4fuse /dev/sda1 /mnt/ext4 -o logfile=/tmp/ext4fuse.log ``` -------------------------------- ### Example Usage of extent_get_pblock Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/extents-api.md Demonstrates how to use extent_get_pblock to find the physical block for a given logical block. ```c struct ext4_inode inode; inode_get_by_number(42, &inode); if (inode.i_flags & EXT4_EXTENTS_FL) { uint32_t extent_len; uint64_t pblock = extent_get_pblock(&inode.i_block, 100, &extent_len); if (pblock) { printf("Logical block 100 -> physical block %lld (%d consecutive)\n", pblock, extent_len); } } ``` -------------------------------- ### Basic ext4fuse command-line usage Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md The basic syntax for using ext4fuse to mount an ext4 device. ```bash ext4fuse [options] ``` -------------------------------- ### Execution Flow: mount → read file - 2. op_init Phase Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/overview.md Step-by-step flow for the op_init phase of ext4fuse. ```text op_init() [op_init.c] ↓ super_fill() [super.c] - Read and cache superblock ↓ super_group_fill() [super.c] - Read and cache group descriptors ↓ inode_init() [inode.c] - Initialize directory cache with root (inode 2) ↓ Return NULL (no private data) ``` -------------------------------- ### Calculating block size from superblock Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md C code snippet demonstrating how to calculate the filesystem block size from the superblock structure. ```c uint32_t block_size = 1024 << superblock.s_log_block_size; ``` -------------------------------- ### Initialization Steps Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/README.md Sequence of operations for initializing ext4fuse. ```c 1. logging_open(logfile) - Enable debug logging 2. disk_open(device) - Open device/image 3. super_fill() - Load and cache superblock 4. super_group_fill() - Load and cache group descriptors 5. inode_init() - Initialize directory cache ``` -------------------------------- ### Directory Context Management for Block Loading Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/implementation-details.md C code snippet demonstrating the context management for loading directory blocks during iteration, including updating the context when crossing block boundaries. ```c // inode_dentry_get(): uint32_t lblock = offset / BLOCK_SIZE; uint32_t blk_offset = offset % BLOCK_SIZE; if (lblock == ctx->lblock) { return (struct ext4_dir_entry_2 *)&ctx->buf[blk_offset]; } else { dir_ctx_update(inode, lblock, ctx); // Load new block return inode_dentry_get(inode, offset, ctx); // Retry (recursive) } ``` -------------------------------- ### Enabling Verbose Logging Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md Bash commands to clean, build, and run ext4fuse with verbose logging enabled, redirecting output to a file. ```bash make clean && make # Debug build by default ./ext4fuse /dev/sda1 /mnt -o logfile=/tmp/debug.log tail -f /tmp/debug.log ``` -------------------------------- ### Execution Flow: mount → read file - 3. File Access Phase (e.g., read /home/user/file.txt) - a. File Open Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/overview.md Step-by-step flow for opening a file during the file access phase. ```text op_open("/home/user/file.txt", &fi) [op_open.c] ↓ Verify read-only access (fi->flags & 3 == O_RDONLY) ↓ inode_get_idx_by_path("/home/user/file.txt") [inode.c] ├─ Walk path components: /home, /user, /file.txt ├─ Use dcache to cache /home and /user inodes └─ Return inode number (e.g., 456) ↓ Store inode number in fi->fh ↓ Return 0 (success) ``` -------------------------------- ### Loading FUSE module on FreeBSD Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md Command to load the FUSE kernel module on FreeBSD. ```bash kldload fuse ``` -------------------------------- ### Super Block Loading Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/implementation-details.md C code snippet demonstrating the loading and parsing of the ext4 super block, extracting key filesystem metadata. ```c super_fill() { disk_read(BOOT_SECTOR_SIZE, sizeof(struct ext4_super_block), &super); // Static variable 'super' now contains filesystem metadata INFO("BLOCK SIZE: %i", super_block_size()); // Typically 4096 INFO("BLOCK GROUP SIZE: %i", super_block_group_size()); INFO("N BLOCK GROUPS: %i", super_n_block_groups()); INFO("INODE SIZE: %i", super_inode_size()); // Typically 256 INFO("INODES PER GROUP: %i", super_inodes_per_group()); } ``` -------------------------------- ### Create a filesystem backup Source: https://github.com/gerard/ext4fuse/blob/master/README.md Command to create a compressed backup of an ext4 partition. ```bash $ dd if= bs=64K | gzip -c > filesystem.backup.gz ``` -------------------------------- ### Compile ext4fuse from source Source: https://github.com/gerard/ext4fuse/blob/master/README.md Commands to compile ext4fuse from source on Linux and FreeBSD. ```bash $ make ``` ```bash $ gmake ``` -------------------------------- ### Mount a filesystem with ext4fuse Source: https://github.com/gerard/ext4fuse/blob/master/README.md Basic command to mount an ext4 partition using ext4fuse. ```bash $ ext4fuse ``` -------------------------------- ### Makefile CFLAGS for FreeBSD Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md Makefile snippet for platform-specific CFLAGS on FreeBSD. ```makefile CFLAGS += -I/usr/local/include -L/usr/local/lib LDFLAGS += -lexecinfo ``` -------------------------------- ### Execution Flow: mount → read file - 1. Mount Phase Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/overview.md Step-by-step flow for the mount phase of ext4fuse. ```text main() [fuse-main.c] ↓ Parse arguments (device, mountpoint, -o options) ↓ logging_open() [logging.c] - Set up debug output ↓ disk_open() [disk.c] - Open device/image file ↓ Verify ext4 magic (0xEF53 at offset 0x400 + 0x38) ↓ fuse_main() - Hand off to FUSE ↓ FUSE calls op_init() on first connection ``` -------------------------------- ### Mount a filesystem with ext4fuse (compiled from source) Source: https://github.com/gerard/ext4fuse/blob/master/README.md Command to mount an ext4 partition using ext4fuse when compiled from source and not in PATH. ```bash $ ./ext4fuse ``` -------------------------------- ### Directory Listing Usage Pattern Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/README.md Steps involved in listing a directory using ext4fuse. ```c 1. op_readdir("/path/to/dir", buf, filler, offset, fi) → List directory 2. inode_get_by_path(path, &inode) → Resolve directory inode 3. inode_dir_ctx_get() → Allocate directory buffer 4. inode_dentry_get(&inode, offset, ctx) → Get directory entry 5. filler(buf, name, NULL, offset) → Call FUSE callback for each entry ``` -------------------------------- ### Compilation Commands Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/overview.md Commands for compiling, testing, and cleaning the ext4fuse build. ```bash make # Compile ext4fuse binary make test # Run unit tests (faster) make test-slow # Run all tests make clean # Clean build artifacts ``` -------------------------------- ### Makefile LDFLAGS for FUSE Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md Makefile snippet for linking against the FUSE library. ```makefile LDFLAGS += $(shell pkg-config fuse --libs) ``` -------------------------------- ### op_init Function Signature Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/fuse-operations.md Initializes the FUSE filesystem and loads filesystem metadata on first connection. ```c void *op_init(struct fuse_conn_info *info); ``` -------------------------------- ### FreeBSD Block Alignment Wrapper Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/implementation-details.md A wrapper function for pread that handles block alignment requirements on FreeBSD systems. ```c static int pread_wrapper(int disk_fd, void *p, size_t size, off_t where) { #if defined(__FreeBSD__) && !defined(__APPLE__) #define PREAD_BLOCK_SIZE 1024 // Handle unaligned start if (first_offset = where % PREAD_BLOCK_SIZE) { int pread_ret = pread(disk_fd, block, PREAD_BLOCK_SIZE, where - first_offset); ASSERT(pread_ret == PREAD_BLOCK_SIZE); // Copy only requested bytes size_t first_size = MIN(size, PREAD_BLOCK_SIZE - first_offset); memcpy(p, block + first_offset, first_size); // Advance and continue... } // Handle aligned middle // Handle unaligned end #else return pread(disk_fd, p, size, where); // Direct call on other systems #endif } ``` -------------------------------- ### Logging Output Format Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/implementation-details.md Illustrates the format of log messages, including severity level, function, line number, and the message itself. ```text [level][function:line] message ``` ```text [debug][op_read:82] read(/path/to/file, buf, 4096, 0, fi->fh=42) [info] [super_fill:59] BLOCK SIZE: 4096 [warn] [disk.c:108] Read operation with 0 size [err] [inode.c:146] Failed to read inode ``` -------------------------------- ### disk_ctx_create Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/disk-operations.md Creates a disk read context for sequential reading. ```c int disk_ctx_create(struct disk_ctx *ctx, off_t where, size_t size, uint32_t len); ``` ```c struct disk_ctx { off_t cur; /* Current read offset */ size_t size; /* Remaining bytes to read */ }; struct disk_ctx ctx; /* Read 8 consecutive blocks starting at block 100 */ disk_ctx_create(&ctx, BLOCKS2BYTES(100), BLOCK_SIZE, 8); char buf[4096]; while (disk_ctx_read(&ctx, 4096, buf) > 0) { /* Process 4KB chunk */ } ``` -------------------------------- ### Reading a File Usage Pattern Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/README.md Steps involved in reading a file using ext4fuse. ```c 1. op_open("/path/to/file", &fi) → Stores inode number in fi->fh 2. op_read(path, buf, size, offset, &fi) → Reads data using inode from fi->fh 3. inode_get_by_number(fi->fh, &inode) → Retrieve inode 4. inode_get_data_pblock(&inode, lblock, &extent_len) → Map logical to physical block 5. disk_read(BLOCKS2BYTES(pblock), BLOCK_SIZE, buf) → Read from disk ``` -------------------------------- ### Sparse File Block Reading Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/implementation-details.md C code snippet demonstrating how sparse file regions are handled during read operations, filling with zeros. ```c // In op_read(): if (pblock) { // Read from disk disk_ctx_create(&read_ctx, BLOCKS2BYTES(pblock), BLOCK_SIZE, extent_len); bytes = disk_ctx_read(&read_ctx, size - ret, buf); } else { // Fill with zeros for sparse regions bytes = size - ret; if (bytes > BLOCK_SIZE) { bytes = BLOCK_SIZE; // Cap per iteration } memset(buf, 0, bytes); DEBUG("sparse file, skipping %d bytes", bytes); } ``` -------------------------------- ### WARNING Macro Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Logs a warning. ```c #define WARNING(...) __LOG(LOG_WARNING, __FUNCTION__, __LINE__, __VA_ARGS__); ``` -------------------------------- ### Generate a log file with ext4fuse Source: https://github.com/gerard/ext4fuse/blob/master/README.md Command to run ext4fuse and output the log to stdout. ```bash $ ext4fuse -o logfile=/dev/stdout ``` -------------------------------- ### Directory Entry Iteration Offset Calculation Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/implementation-details.md C code snippet showing how to advance the offset during directory entry iteration using the rec_len field. ```c // In op_readdir(): while ((dentry = inode_dentry_get(&inode, offset, dctx))) { offset += dentry->rec_len; // Advance by entry's record length if (!dentry->inode) { // Skip dummy/unused entries continue; } } ``` -------------------------------- ### Logging API Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/README.md API functions and macros for logging. ```c int logging_open(const char *path) void logging_setlevel(int new_level) Macros: DEBUG(), INFO(), WARNING(), ERR(), CRIT(), ALERT(), EMERG(), ASSERT() ``` -------------------------------- ### Extent Entry Ordering Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/implementation-details.md Shows how the extent entries are iterated to find a block, assuming they are ordered by ee_block ascending. ```c // In extent_get_block_from_ees(): for (i = 0; i < n_ee; i++) { if (ee[i].ee_block + ee[i].ee_len > lblock) { // Found extent containing or starting before lblock return ee[i].ee_start_lo + block_ext_offset; } } ``` -------------------------------- ### Architecture Quick Reference Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/README.md A diagram illustrating the flow of operations within the ext4fuse filesystem. ```text FUSE Kernel Interface ↓ [fuse-main.c] Entry Point & FUSE Setup ↓ [FUSE Operations] op_init, op_getattr, op_open, op_read, op_readdir, op_readlink ↓ [Inode Subsystem] inode.c, dcache.c, extents.c ↓ [Filesystem Metadata] super.c (superblock, group descriptors) ↓ [Disk I/O] disk.c (mutex-protected pread) ↓ [Device/Image File] ``` -------------------------------- ### Directory Cache Structure Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md Description of the directory cache entry structure (dcache_entry) and its linked list implementation. -------------------------------- ### Makefile CFLAGS for FUSE and version Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md Makefile snippet showing CFLAGS for FUSE integration and version definition. ```makefile CFLAGS += $(shell pkg-config fuse --cflags) CFLAGS += -DFUSE_USE_VERSION=26 CFLAGS += -std=gnu99 -g3 -Wall -Wextra CFLAGS += -DEXT4FUSE_VERSION=\"$(VERSION)\" ``` -------------------------------- ### Filesystem Detection Magic Number Check Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md C code snippet to validate the ext4 filesystem magic number (0xEF53) at the boot sector offset. ```c off_t disk_magic_offset = BOOT_SECTOR_SIZE + offsetof(struct ext4_super_block, s_magic); uint16_t disk_magic; disk_read(disk_magic_offset, sizeof(disk_magic), &disk_magic); if (disk_magic != 0xEF53) { fprintf(stderr, "Partition doesn't contain EXT4 filesystem\n"); return EXIT_FAILURE; } ``` -------------------------------- ### EXT4FUSE_VERSION definition Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md C preprocessor definition for the ext4fuse version string, typically set from git tags. ```c #define EXT4FUSE_VERSION "version_string" ``` -------------------------------- ### File Read Operation Flow Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/overview.md Illustrates the steps involved in reading a file, from the initial operation call to disk read and byte accumulation. ```pseudocode op_read(path, buf, 4096, 0, &fi) [op_read.c] ↓ Retrieve inode by number fi->fh [inode.c] ↓ Truncate read size to file size bounds ↓ For each block in read range: inode_get_data_pblock(inode, lblock, &extent_len) ├─ If EXT4_EXTENTS_FL set: │ extent_get_pblock() - Traverse extent tree [extents.c] └─ Else: Indirect block lookup (direct, single, double, triple) [inode.c] ↓ disk_read(physical_offset, BLOCK_SIZE, buffer) [disk.c] ↓ Accumulate bytes and return total read ``` -------------------------------- ### Group Descriptor Loading Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/implementation-details.md C code snippet illustrating the calculation of the offset for group descriptor loading and considerations for variable descriptor sizes. ```c super_group_fill() { // Allocates array: sizeof(struct ext4_group_desc) * super_n_block_groups() // Reads descriptor table immediately after superblock // Aligned to block boundary off_t bg_off = ALIGN_TO_BLOCKSIZE(BOOT_SECTOR_SIZE + sizeof(ext4_super_block)); bg_off += i * super_group_desc_size(); // Each descriptor may have variable size } ``` -------------------------------- ### NOTICE Macro Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Logs a normal but significant event. ```c #define NOTICE(...) __LOG(LOG_NOTICE, __FUNCTION__, __LINE__, __VA_ARGS__); ``` -------------------------------- ### Cache Population for Directory Inodes Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/implementation-details.md C code snippet showing how directory entries are added to a circular sibling list in the cache. ```c if (!parent->childs) { new_entry->siblings = new_entry; parent->childs = new_entry; } else { new_entry->siblings = parent->childs->siblings; parent->childs->siblings = new_entry; parent->childs = new_entry; // New entry becomes first child } ``` -------------------------------- ### Makefile CFLAGS for macOS Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md Makefile snippet for platform-specific CFLAGS on macOS. ```makefile CFLAGS += -mmacosx-version-min=10.5 CFLAGS += -D_FILE_OFFSET_BITS=64 ``` -------------------------------- ### GDB Debugging Session Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md GDB commands to attach to and debug a running ext4fuse process, including setting arguments and obtaining a backtrace. ```bash gdb --args ./ext4fuse /dev/sda1 /mnt (gdb) run (gdb) bt # Backtrace on crash ``` -------------------------------- ### Inline Symlink Handling Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/implementation-details.md C code snippet showing how to handle inline symlinks, where the target path is stored directly within the inode's i_block if it fits. ```c if (inode_size <= 60) { /* Link destination fits in inode */ memcpy(buf, inode->i_block, inode_size); buf[inode_size] = 0; // Null-terminate } ``` -------------------------------- ### Logical Block to Physical Block Calculation (Extents) Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/overview.md Explains how to find the physical block address for a given logical block when using extents. ```pseudocode **For extents**: 1. Read extent header from inode.i_block 2. If depth == 0: array contains ext4_extent entries - Search for extent covering lblock - Return extent.ee_start + offset 3. If depth > 0: array contains ext4_extent_idx entries - Find index entry with ei_block <= lblock - Load child block recursively ``` -------------------------------- ### INFO Macro Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Logs informational message. ```c #define INFO(...) __LOG(LOG_INFO, __FUNCTION__, __LINE__, __VA_ARGS__); ``` -------------------------------- ### dcache_init_root Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/directory-cache.md Initializes the directory cache with the root directory. ```c int dcache_init_root(uint32_t n); ``` -------------------------------- ### logging_open Function Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/logging-api.md Opens a file for logging output. ```c int logging_open(const char *path); ``` -------------------------------- ### Extent Tree Traversal for Block Mapping Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/implementation-details.md C code snippet illustrating the traversal logic within an extent tree to find the appropriate extent for a given logical block. ```c // For depth > 0 (internal node): for (int i = 0; i < eh->eh_entries; i++) { if (ei_array[i].ei_block > lblock) { break; // Found index that exceeds target } recurse_ei = &ei_array[i]; // Keep most recent index } ASSERT(recurse_ei); // Must have found something ``` -------------------------------- ### NDEBUG effect on logging and assertions (Release build) Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/configuration.md Configuration for release builds with NDEBUG defined, reducing logging and disabling assertions. ```c #define DEFAULT_LOG_LEVEL LOG_ERR /* Errors only */ #define ASSERT(e) do { } while(0) /* No-op */ ``` -------------------------------- ### Directory Lookup Performance Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/overview.md Analyzes the performance characteristics of directory lookups, considering the first component, subsequent components, and caching. ```markdown ### Directory Lookup - **First component**: O(1) - root cached - **Subsequent components**: O(n) per level where n = sibling count - **Caching**: Directories cached after first lookup - **Typical case**: O(path_depth) for cached paths ``` -------------------------------- ### Lock-Free Components for Thread Safety Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/overview.md Describes components that are designed to be lock-free, such as the directory cache, and the trade-offs involved. ```markdown ### Lock-Free Components - **Directory cache**: Atomic pointer updates for insertions - May result in duplicate entries (accepted tradeoff) - No locks held during lookups (fast path) ``` -------------------------------- ### Block Mapping Performance Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/overview.md Compares the performance of different block mapping strategies, including direct blocks, indirect blocks, and extents. ```markdown ### Block Mapping - **Direct blocks**: O(1) - **Single indirect**: O(1) - single block lookup - **Double indirect**: O(1) - two block lookups - **Extents**: O(tree_depth) - usually 1-2 ``` -------------------------------- ### File Read Performance Source: https://github.com/gerard/ext4fuse/blob/master/_autodocs/overview.md Discusses the performance aspects of file reads, differentiating between sequential and random read patterns. ```markdown ### File Read - **Sequential**: Optimized via extent_len returning consecutive blocks - **Random**: Block-by-block lookups via inode_get_data_pblock ```