本の虫

著者:江添亮
ブログ: http://cpplover.blogspot.jp/
メール: boostcpp@gmail.com
Twitter: https://twitter.com/EzoeRyou
GitHub: https://github.com/EzoeRyou

アマゾンの江添のほしい物リストを著者に送るとブログ記事のネタになる

筆者にブログのネタになる品物を直接送りたい場合、住所をメールで質問してください。

Mac OS Xで削除がとても難しいファイルを作成する方法

2013年の記事だが、Mac OS XとそのHFS+はこの上なくクソなので何があっても驚きはしないが、Mac OS Xで削除しにくいシンボリックリンクファイルを作成する方法があるらしい

OS X and the Unremovable File - galvanist

HFS+上で、削除しにくいシンボリックリンクを作成できる。

# be root, for example with: sudo -i
str1=$(python -c "print '1' * 255")
str2=$(python -c "print '2' * 255")
str3=$(python -c "print '3' * 255")
str4=$(python -c "print '4' * 253")
mkdir -p  $str1/$str2/$str3/$str4
ln -s ftw $str1/$str2/$str3/$str4/L

さて、このように作った以上、OS X v10.9では以下のコマンドでは削除できない。


# still as root...
unlink 1*/2*/3*/4*/L
unlink $str1/$str2/$str3/$str4/L
rm -rf 1*
rm -rf $str1
rm -rf $str1/$str2/$str3/$str4
rm -rf $str1/$str2/$str3/$str4/L
(cd $str1/$str2/$str3/$str4; unlink L)
(cd $str1/$str2/$str3/$str4; rm -rf L)

すべて、以下のようなエラーとなる。(読みやすさのために[...]で省略)

root# pwd
/private/tmp/111[ ... ]111/222[ ... ]222/333[ ... ]333/444[ ... ]444
root# ls
L
root# rm -f L
rm: L: No space left on device
root# df -H
Filesystem      Size   Used  Avail Capacity   iused     ifree %iused  Mounted on
/dev/disk1      250G   108G   142G    44%  26385563  34601956   43%   /
[...]

念の為、システムコールを直接呼び出すコードを書いてみる。/tmp/fixit.cにおいてあるとする。

#include <unistd.h>
#include <stdio.h>
#include <errno.h>

int main(int argc, char* argv[]) {
    printf("Unlink returned %i\n", unlink("L"));
    perror("Error was");
    return 0;
}

実行してみるが、

root# pwd
/private/tmp/111[ ... ]111/222[ ... ]222/333[ ... ]333/444[ ... ]444
root# gcc -o /tmp/fixit /tmp/fixit.c 
root# /tmp/fixit 
Unlink returned -1
Error was: No space left on device

ENOSPCだと。unlink(2) Mac OS X Developer Tools Manual Pageに返すとは書かれていないエラーだぞ。

状況は複雑だ。

Workaround

なぜか、パスはシンボリックリンクを作るには短いが、削除するには長すぎるようだ。パスを短縮すれば消せる。

root# pwd
/private/tmp/111[ ... ]111/222[ ... ]222/333[ ... ]333/444[ ... ]444
root# ls
L
root# mv /private/tmp/1* /private/tmp/one
root# pwd
/private/tmp/one/222[ ... ]222/333[ ... ]333/444[ ... ]444
root# rm L
root# ls
root# rm -rf /tmp/one
root# 

workaroundは十分なのか。

そういうわけで、一応workaroundはあるのだが、しかし疑問がある。

ちなみに、これは2013年の記事だが、Yosemiteまでは同じ問題があるそうだ。El Capitainだと、ファイルパスが長すぎて作成できないエラーが返るらしい。そもそも、Mac OS XのカーネルであるXNUのファイルパスの上限が2024文字なのに2025文字のファイルパスを作成できてしまうのがおかしいようだ。