Why I hate HFS+
August 5, 2011HFS+, the filesystem used on modern versions of Mac OS, is long past its prime. It’s actually a remarkable feat of engineering: the same filesystem has been extended and improved upon for over ten years despite technical limitations inherent in its original design. However, sometimes its limitations are a little too much.
I have kept a checkout of the linux 2.6 git repository on my Mac for some time
now – it’s sometimes fun to go sourcediving through the kernel, even though I
grok very little of it. A few months ago, however, I noticed that after a pull,
git said I had unstaged changes in my working directory. This was curious
since I hadn’t changed anything, but I didn’t think much of it, and after a few
failed git reset --hards, I forgot about it.
Today, however, I got frustrated at git and decided to dig further into the
problem. I tried everything – first I tried adding and committing the unstaged
changes, but git add refused to add any of the supposedly untracked files.
git reset --hard and git clean were similarly ineffective. git rm -f was
the only command that I could actually get to function properly, but that put
git in some odd state in which the files were both staged and not staged for
deletion.
But then I looked closer at the filenames. Turns out they weren’t quite the same. The set of files that was staged for deletion were partially uppercase, while the unstaged ones were entirely lowercase:
# On branch master
# Changes to be committed:
# deleted: include/linux/netfilter/xt_CONNMARK.h
# deleted: include/linux/netfilter/xt_DSCP.h
# deleted: include/linux/netfilter/xt_MARK.h
# deleted: include/linux/netfilter/xt_RATEEST.h
# deleted: include/linux/netfilter/xt_TCPMSS.h
# deleted: include/linux/netfilter_ipv4/ipt_ECN.h
# deleted: include/linux/netfilter_ipv4/ipt_TTL.h
# deleted: include/linux/netfilter_ipv6/ip6t_HL.h
# deleted: net/ipv4/netfilter/ipt_ECN.c
# deleted: net/netfilter/xt_DSCP.c
# deleted: net/netfilter/xt_HL.c
# deleted: net/netfilter/xt_RATEEST.c
# deleted: net/netfilter/xt_TCPMSS.c
#
# Changes not staged for commit:
# deleted: include/linux/netfilter/xt_connmark.h
# deleted: include/linux/netfilter/xt_dscp.h
# deleted: include/linux/netfilter/xt_mark.h
# deleted: include/linux/netfilter/xt_rateest.h
# deleted: include/linux/netfilter/xt_tcpmss.h
# deleted: include/linux/netfilter_ipv4/ipt_ecn.h
# deleted: include/linux/netfilter_ipv4/ipt_ttl.h
# deleted: include/linux/netfilter_ipv6/ip6t_hl.h
# deleted: net/ipv4/netfilter/ipt_ecn.c
# deleted: net/netfilter/xt_dscp.c
# deleted: net/netfilter/xt_hl.c
# deleted: net/netfilter/xt_rateest.c
# deleted: net/netfilter/xt_tcpmss.c
#
# Untracked files:
# samples/hidraw/
Suddenly it clicked. HFS+, by default, is a case-insensitve filesystem. At some point in the last few months, the Linux repo added multiple files with different capitalizations, pretty much screwing over anyone still stuck with this miserable excuse for a filesystem.
Hey Apple. How’s that ZFS support coming along?