diff --git a/doc/dwarfs.md b/doc/dwarfs.md index bc6e83fe..2de48d59 100644 --- a/doc/dwarfs.md +++ b/doc/dwarfs.md @@ -64,6 +64,16 @@ options: will also consume more memory to hold the hardlink count table. This will be 4 bytes for every regular file inode. + * `-o readonly` + Show all file system entries as read-only. By default, DwarFS + will preserve the original writeability, which is obviously a + lie as it's a read-only file system. However, this is needed + for overlays to work correctly, as otherwise directories are + seen as read-only by the overlay and it'll be impossible to + create new files even in a writeable overlay. If you don't use + overlays and want the file system to reflect its read-only + state, you can set this option. + * `-o (no_)cache_image` By default, `dwarfs` tries to ensure that the compressed file system image will not be cached by the kernel (i.e. the default diff --git a/include/dwarfs/options.h b/include/dwarfs/options.h index 0f272c39..20d08c8e 100644 --- a/include/dwarfs/options.h +++ b/include/dwarfs/options.h @@ -38,6 +38,7 @@ struct block_cache_options { struct metadata_options { bool enable_nlink{false}; + bool readonly{false}; }; struct filesystem_options { diff --git a/src/dwarfs.cpp b/src/dwarfs.cpp index 65e9afd2..80d84e9a 100644 --- a/src/dwarfs.cpp +++ b/src/dwarfs.cpp @@ -53,6 +53,7 @@ struct options { const char* mlock_str; // TODO: const?? -> use string? const char* decompress_ratio_str; // TODO: const?? -> use string? int enable_nlink; + int readonly; int cache_image; int cache_files; size_t cachesize; @@ -79,6 +80,7 @@ const struct fuse_opt dwarfs_opts[] = { DWARFS_OPT("mlock=%s", mlock_str, 0), DWARFS_OPT("decratio=%s", decompress_ratio_str, 0), DWARFS_OPT("enable_nlink", enable_nlink, 1), + DWARFS_OPT("readonly", readonly, 1), DWARFS_OPT("cache_image", cache_image, 1), DWARFS_OPT("no_cache_image", cache_image, 0), DWARFS_OPT("cache_files", cache_files, 1), @@ -105,6 +107,7 @@ void op_init(void* /*userdata*/, struct fuse_conn_info* /*conn*/) { fsopts.block_cache.decompress_ratio = s_opts.decompress_ratio; fsopts.block_cache.mm_release = !s_opts.cache_image; fsopts.metadata.enable_nlink = bool(s_opts.enable_nlink); + fsopts.metadata.readonly = bool(s_opts.readonly); s_fs = std::make_shared( s_lgr, std::make_shared(s_opts.fsimage), fsopts, &s_opts.stat_defaults, FUSE_ROOT_ID); @@ -400,6 +403,7 @@ void usage(const char* progname) { << " -o mlock=NAME mlock mode: (none), try, must\n" << " -o decratio=NUM ratio for full decompression (0.8)\n" << " -o enable_nlink show correct hardlink numbers\n" + << " -o readonly show read-only file system\n" << " -o (no_)cache_image (don't) keep image in kernel cache\n" << " -o (no_)cache_files (don't) keep files in kernel cache\n" << " -o debuglevel=NAME error, warn, (info), debug, trace\n" diff --git a/src/dwarfs/metadata_v2.cpp b/src/dwarfs/metadata_v2.cpp index c3a99164..0c2273dd 100644 --- a/src/dwarfs/metadata_v2.cpp +++ b/src/dwarfs/metadata_v2.cpp @@ -95,6 +95,8 @@ void analyze_frozen(std::ostream& os, os << '\n'; } +const uint16_t READ_ONLY_MASK = ~(S_IWUSR | S_IWGRP | S_IWOTH); + } // namespace template @@ -637,6 +639,10 @@ int metadata_::getattr(entry_view entry, stbuf->st_mode = mode; + if (options_.readonly) { + stbuf->st_mode &= READ_ONLY_MASK; + } + stbuf->st_size = S_ISDIR(mode) ? make_directory_view(entry).entry_count() : file_size(entry, mode); stbuf->st_ino = inode + inode_offset_;