ユーザーが所有していないディレクトリで、「chown」コマンドが「-R」フラグで繰り返し機能しないのはなぜですか?

ユーザーが所有していないディレクトリで、「chown」コマンドが「-R」フラグで繰り返し機能しないのはなぜですか?

システム:x86_64 Linux 5.13.19-2-MANJARO。

ユーザーが所有するいくつかのディレクトリを含む "~/.local/share/Trash/expunged"に奇妙なディレクトリがあります。誰も。 rootで次のコマンドを実行してみました。

rm -rf pathToWeirdDirectory

これにより、次のエラーメッセージが生成されます。

rm: 'pathToWeirdDirectory' を削除できません。定義されたデータ型と比較して値が大きすぎます。

以下を使用してディレクトリの所有権を変更した後

chown me:me pathToWeirdDirectory

最後にディレクトリを正常に削除しました。複数のファイルを含む複数のサブディレクトリを持つこの種類のディレクトリもあります。次のコマンドを実行しようとしています。

chown -R me:me pathToSecondWeirdDirectory

これにより、次のエラーメッセージが生成されます。

chown: 'pathToSeconWeirdDirectory/subdirectory1/subdirectory2' ディレクトリを読み込めません。権限が拒否されました。

私の場合、「-R」フラグは特定のディレクトリの所有権を再帰的に変更したため、次のテストケースを作成しました。

directory/
    file
    subdirectory/
    file2

ユーザーが所有。 "chown -R root:root" を使用して、期待どおりにすべてのサブディレクトリとファイルを含む所有権を正常に変更しました。

質問:ユーザーが所有するディレクトリに対して「-R」フラグを使用して、「chown」コマンドが繰り返し機能しないのはなぜですか?誰も?ユーザーが所有しているファイルを削除できないのはなぜですか?誰も〜のように

編集する:コメントに応じて「pathToSecondWeirdDirectory」のフルネームを提供したいと思います。

~/.local/share/Trash/expunged/294376611/5e5a7b41-3df4-4b2f-b7ac-f57d09ed1823/.sage/matplotlib-1.5.1

他の例

~/.local/share/Trash/expunged/294376611/5e5a7b41-3df4-4b2f-b7ac-f57d09ed1823/.sage/R

編集2:Marcusが優れた答えを提供した後、同じ技術を使用してさらにデバッグを実行しました。単一のディレクトリを chown することは期待どおりに機能します。 chown に -R を使用すると失敗します。出力を比較しましたが、最後の数行まで同じでした。彼らは次のとおりです。

:

close(8)                                = 0
close(5)                                = 0
close(6)                                = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
newfstatat(AT_FDCWD, "security", {st_mode=S_IFDIR|0700, st_size=4096, ...}, AT_SYMLINK_NOFOLLOW) = 0
fchownat(AT_FDCWD, "security", 60202, 60202, 0) = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++

ジョン-R

close(8)                                = 0
close(5)                                = 0
close(6)                                = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
newfstatat(AT_FDCWD, "startup", {st_mode=S_IFDIR|0700, st_size=4096, ...}, AT_SYMLINK_NOFOLLOW) = 0
openat(AT_FDCWD, "startup", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = -1 EACCES (Permission denied)
openat(AT_FDCWD, "/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=2998, ...}, AT_EMPTY_PATH) = 0
read(3, "# Locale name alias data base.\n#"..., 4096) = 2998
read(3, "", 4096)                       = 0
close(3)                                = 0
openat(AT_FDCWD, "/usr/share/locale/en_US.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, "chown: ", 7)                  = 7
write(2, "cannot read directory 'startup'", 31) = 31
openat(AT_FDCWD, "/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, ": Permission denied", 19)     = 19
write(2, "\n", 1)                       = 1
close(1)                                = 0
close(2)                                = 0
exit_group(1)                           = ?
+++ exited with 1 +++

ベストアンサー1

追加のデバッグがなければはっきりわかりませんが、これはLinuxで以前に遭遇した(そして今も起こっている)stat / stat64の問題のようです。

デフォルトでは、fstatシステムコールは「このファイルはディレクトリですか?」などの質問に使用されます。 (再帰的に削除したい場合は知ることが非常に重要です)、「シンボリックリンクですか?」、「サイズはいくらですか?」。

最後の部分が面白くなる部分です。システムコールには、struct statこのすべてのタイプ情報のフィールドを含むaへのポインターが必要です。最初はファイルサイズ整数は32ビットです。これで、ファイルがこれより大きくなる可能性があります。したがって、64ビット情報を提供するには新しい呼び出しが必要です。

32ビット変数を含むことができるよりも大きいファイルに32ビット統計バリアントを使用する場合はどうなりますか?明らかに、誤って65 GBのファイルのサイズが1 GBにすぎないとは思わないように、エラー条件が必要です。このエラーがerror// に渡されると、表示されるエラーメッセージがstrerror正しく印刷されます。perror

もちろん、ファイル統計の他の部分が返すタイプに合わない場合(または最大ページ数を超える場合、および他の多くの場合)にも同じメカニズムが適用されます。

今楽しい部分が出てきます。これは比較的現代的なものではありません。

/usr/bin/rm: ELF 64 ビット LSB パイ実行可能ファイル、x86-64、バージョン 1(SYSV)、動的にリンクされた、i​​nterpreter/lib64/ld-linux-x86-64.so.2, BuildID[sha1] = 5d1d8b77d21f9362855e93f8cff5fc685127a26f 、GNU/Linux 4.4.0では削除されました

使用中古い fstat[at]システムコール。あなたは試すことができます:

cd /tmp
touch base
strace -o log.strace -e /stat rm base
grep '"base"' log.strace

しなければならないおそらくYield callを使用newfstatatすると、確かに64ビット数を処理します。

したがって、これらの知識に基づいて、奇妙なディレクトリを削除してみましょう。

strace -o /tmp/log.strace rm -r /path/to/one/single_one/of/the/undeletable_directories

そして、ログの一番下までスクロールします。エラーメッセージを印刷するには数行の呼び出しが必要ですが、上記の呼び出しは結果呼び出しでなければなりませんEOVERFLOW(ヒント:その文字列を検索してください)。私の仮定はこれです。いいえこれは一般的な統計呼び出しですが、呼び出しである可能性openatがあり、他の理由で失敗する可能性があります。


¹を実行し、すべての呼び出しにブレークポイントを設定し、それでも機能しない場合は、すべての呼び出しにブレークポイントを設定しgdb --args rm /path/to/weirddirectoryます。errorwrite

² CoreutilsもありますFAQポータルarchive.orgリンクこれは、FSFが安定したインフラを永遠に運営できると信じていないからです。

おすすめ記事