]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
hfsplus: Report case sensitivity in fileattr_get
authorChuck Lever <chuck.lever@oracle.com>
Thu, 7 May 2026 08:53:00 +0000 (04:53 -0400)
committerChristian Brauner <brauner@kernel.org>
Mon, 11 May 2026 14:50:28 +0000 (16:50 +0200)
Add case sensitivity reporting to the existing hfsplus_fileattr_get()
function via the FS_XFLAG_CASEFOLD flag. HFS+ always preserves case
at rest.

Case sensitivity depends on how the volume was formatted: HFSX
volumes may be either case-sensitive or case-insensitive, indicated
by the HFSPLUS_SB_CASEFOLD superblock flag.

FS_XFLAG_CASEFOLD is read-only: FS_XFLAG_RDONLY_MASK ensures
FS_IOC_FSSETXATTR strips it. The legacy FS_IOC_SETFLAGS path in
hfsplus_fileattr_set() also allows FS_CASEFOLD_FL through its
allowlist on case-insensitive volumes so that a chattr
read-modify-write cycle does not fail with EOPNOTSUPP.

Reviewed-by: Viacheslav Dubeyko <slava@dubeyko.com>
Reviewed-by: Roland Mainz <roland.mainz@nrubsig.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Link: https://patch.msgid.link/20260507-case-sensitivity-v14-7-e62cc8200435@oracle.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/hfsplus/inode.c

index d05891ec492e3a5de80b2055c75ec51193cc3f78..5565c14b4bf692610a2549653cba66e29cd398bc 100644 (file)
@@ -740,6 +740,7 @@ int hfsplus_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
 {
        struct inode *inode = d_inode(dentry);
        struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
        unsigned int flags = 0;
 
        if (inode->i_flags & S_IMMUTABLE)
@@ -748,6 +749,8 @@ int hfsplus_fileattr_get(struct dentry *dentry, struct file_kattr *fa)
                flags |= FS_APPEND_FL;
        if (hip->userflags & HFSPLUS_FLG_NODUMP)
                flags |= FS_NODUMP_FL;
+       if (test_bit(HFSPLUS_SB_CASEFOLD, &sbi->flags))
+               flags |= FS_CASEFOLD_FL;
 
        fileattr_fill_flags(fa, flags);
 
@@ -759,13 +762,24 @@ int hfsplus_fileattr_set(struct mnt_idmap *idmap,
 {
        struct inode *inode = d_inode(dentry);
        struct hfsplus_inode_info *hip = HFSPLUS_I(inode);
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb);
+       unsigned int allowed = FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL;
        unsigned int new_fl = 0;
 
        if (fileattr_has_fsx(fa))
                return -EOPNOTSUPP;
 
+       /*
+        * FS_CASEFOLD_FL reflects HFSPLUS_SB_CASEFOLD, a mount-time
+        * property. Accept it as a no-op so chattr's RMW round-trip
+        * succeeds; reject any attempt to enable it on a volume that
+        * was not formatted case-insensitive.
+        */
+       if (test_bit(HFSPLUS_SB_CASEFOLD, &sbi->flags))
+               allowed |= FS_CASEFOLD_FL;
+
        /* don't silently ignore unsupported ext2 flags */
-       if (fa->flags & ~(FS_IMMUTABLE_FL|FS_APPEND_FL|FS_NODUMP_FL))
+       if (fa->flags & ~allowed)
                return -EOPNOTSUPP;
 
        if (fa->flags & FS_IMMUTABLE_FL)