Skip to content

Commit

Permalink
hfsuser: treat orphaned hard links as regular files
Browse files Browse the repository at this point in the history
Fixes an odd case where files may have the hard link file type code but
which are otherwise regular files, with data in their own catalog record
and no associated inode entry.
Previously files like this appeared in directory listings but would not
exist when read from.

This change matches the behavior of Apple's driver.
  • Loading branch information
0x09 committed Apr 21, 2024
1 parent af0062d commit 80b9302
Showing 1 changed file with 7 additions and 9 deletions.
16 changes: 7 additions & 9 deletions lib/libhfsuser/hfsuser.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ int hfs_lookup(hfs_volume* vol, const char* path, hfs_catalog_keyed_record_t* re
if(alt_fork_lookup)
pathcpy[pathlen - dev->rsrc_len] = '\0';

hfs_catalog_keyed_record_t inode_rec; //for resolving hard links

// lookup normally ends when either the path is exhasuted or a file is found, however there are exactly two cases
// where a file is permitted as part of the path: hard links to other directories, or when accessing a file's
// resource fork via the special /rsrc suffix
Expand All @@ -306,12 +308,10 @@ int hfs_lookup(hfs_volume* vol, const char* path, hfs_catalog_keyed_record_t* re

if(record->type == HFS_REC_FILE) {
if(record->file.user_info.file_creator == HFS_MACS_CREATOR &&
record->file.user_info.file_type == HFS_DIR_HARD_LINK_FILE_TYPE) {
record->file.user_info.file_type == HFS_DIR_HARD_LINK_FILE_TYPE &&
!hfslib_get_directory_hardlink(vol, record->file.bsd.special.inode_num, &inode_rec, NULL)) {
// resolve directory hard links and resume path traversal
if(hfslib_get_directory_hardlink(vol, record->file.bsd.special.inode_num, record, NULL)) {
ret = -ENOENT;
goto end;
}
*record = inode_rec;
continue;
}

Expand All @@ -330,10 +330,8 @@ int hfs_lookup(hfs_volume* vol, const char* path, hfs_catalog_keyed_record_t* re
if(record->type == HFS_REC_FILE &&
record->file.user_info.file_creator == HFS_HFSPLUS_CREATOR &&
record->file.user_info.file_type == HFS_HARD_LINK_FILE_TYPE &&
hfslib_get_hardlink(vol, record->file.bsd.special.inode_num, record, NULL)) {
ret = -ENOENT;
goto end;
}
!hfslib_get_hardlink(vol, record->file.bsd.special.inode_num, &inode_rec, NULL))
*record = inode_rec;

if(!alt_fork_lookup) // don't cache alternate fork lookups
hfs_record_cache_add(cache,path,pathlen,record,key);
Expand Down

0 comments on commit 80b9302

Please sign in to comment.