Skip to content

Commit

Permalink
hfsfuse: add mount option to present symlinks as regular files
Browse files Browse the repository at this point in the history
With `-o disable_symlinks` these will not act as symbolic links but
regular files with the link destination as their content.

Offers an alternative means for viewing xattrs of these on systems that
don't support user xattrs on symlinks.
  • Loading branch information
0x09 committed May 11, 2024
1 parent 3984ff8 commit 44e18ec
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 1 deletion.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,14 @@ hfsfuse-specific options are shown below
you should only set this if you are sure it is being misdetected
-o rsrc_ext=suffix special suffix for filenames which can be used to access their resource fork
or alternatively their data fork if mounted in rsrc_only mode

-o default_file_mode=N octal filesystem permissions for Mac OS Classic files (755)
-o default_dir_mode=N octal filesystem permissions for Mac OS Classic directories (777)
-o default_uid=N unix user ID for Mac OS Classic files (0)
-o default_gid=N unix group ID for Mac OS Classic files (0)

-o disable_symlinks treat symbolic links as regular files. may be used to view extended attributes
of these on systems that don't support symlink xattrs

-o noublio disable ublio read layer
-o ublio_items=N number of ublio cache entries, 0 for no caching (64)
Expand Down Expand Up @@ -127,6 +130,8 @@ Because of this, the more familiar `/rsrc` suffix used by previous releases of m
Finally, the entire volume may be mounted in resource-fork only mode using the `rsrc_only` option. In this mode, all entries on the filesystem are presented using the size and contents of their resource fork. Files with no resource fork will appear as empty, 0 size entries.
This option may be combined with the `rsrc_ext` option described above, in which case the special suffix will instead be used to access the regular data fork.

### OS-specific extended attribute behavior

On Linux you may encounter the following error when inspecting xattrs: `user.com.apple.ResourceFork: Argument list too long`
This occurs when the resource fork is larger than the maximum allowed extended attribute size of 64kb. In this case you can still access the resource fork as described above by setting the `rsrc_ext` option or mounting in `rsrc_only` mode.

Expand All @@ -139,6 +144,9 @@ catattr -r user.com.apple.ResourceFork file | xxd -r -p
Extended attributes are presented in the preferred namespace for the OS, typically `user.`. Alternate namespaces may be chosen when building hfsfuse by setting the `XATTR_NAMESPACE` make var.
This should include the trailing `.` as an empty value indicates no namespacing (such as on macOS.)

HFS+ symbolic links may contain extended attributes of their own separate from their link destination.
For systems such as Linux that do not support reading user-namespace extended attributes of symlinks, these can be viewed by using the `-o disable_symlinks` mount option, which will cause hfsfuse to display all symlinks as regular files.

## Mac OS Classic file permissions
HFS+ filesystems created on Mac OS Classic do not contain the typical set of Unix ownership and permission information for files and folders.
For these hfsfuse provides the options default_file_mode, default_dir_mode, default_uid, and default_gid to specify fallback values if needed.
Expand Down
6 changes: 6 additions & 0 deletions lib/libhfsuser/hfsuser.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ struct hfs_device {
gid_t default_gid;
void* read_buf;
pthread_mutex_t read_mutex;
bool disable_symlinks;
#ifdef HAVE_UBLIO
bool use_ublio;
ublio_filehandle_t ubfh;
Expand Down Expand Up @@ -393,6 +394,9 @@ void hfs_stat(hfs_volume* vol, hfs_catalog_keyed_record_t* key, struct stat* st,
HFS_IFMODES
#undef X

if(dev->disable_symlinks && S_ISLNK(st->st_mode))
st->st_mode = (st->st_mode & ~S_IFLNK) | S_IFREG;

if(key->file.bsd.owner_id > UID_MAX) {
hfslib_error("hfs_stat: owner_id %" PRIu32 " too large for CNID %" PRIu32 ", using default",NULL,0,key->file.bsd.owner_id,key->file.cnid);
st->st_uid = dev->default_uid;
Expand Down Expand Up @@ -590,6 +594,8 @@ int hfs_open(hfs_volume* vol, const char* name, hfs_callback_args* cbargs) {
BAIL(ERANGE);
dev->default_gid = cfg.default_gid;

dev->disable_symlinks = cfg.disable_symlinks;

#ifdef HAVE_UBLIO
dev->use_ublio = !cfg.noublio;
if(dev->use_ublio) {
Expand Down
2 changes: 2 additions & 0 deletions lib/libhfsuser/hfsuser.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ struct hfs_volume_config {

uint16_t default_file_mode, default_dir_mode;
uint32_t default_uid, default_gid;

int disable_symlinks;
};

// HFS+ compression support
Expand Down
4 changes: 4 additions & 0 deletions src/hfsfuse.c
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,7 @@ static struct fuse_opt hfsfuse_opts[] = {
HFS_OPTION("default_dir_mode=%"SCNo16,default_dir_mode),
HFS_OPTION("default_uid=%" SCNu32,default_uid),
HFS_OPTION("default_gid=%" SCNu32,default_gid),
HFS_OPTION("disable_symlinks", disable_symlinks),
FUSE_OPT_END
};

Expand Down Expand Up @@ -606,6 +607,9 @@ static void help(const char* self, struct hfsfuse_config* cfg) {
" -o default_dir_mode=N octal filesystem permissions for Mac OS Classic directories (%" PRIo16 ")\n"
" -o default_uid=N unix user ID for Mac OS Classic files (%" PRIu32 ")\n"
" -o default_gid=N unix group ID for Mac OS Classic files (%" PRIu32 ")\n"
"\n"
" -o disable_symlinks treat symbolic links as regular files. may be used to view extended attributes\n"
" of these on systems that don't support symlink xattrs\n"
"\n",
cfg->volume_config.cache_size,
cfg->volume_config.default_file_mode,
Expand Down

0 comments on commit 44e18ec

Please sign in to comment.