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 --hard
s, 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?