[インデックス 18584] ファイルの概要
コミット
- コミットハッシュ:
58a9268f265843e2720adbcbdaf0bc1d367046a1
- 作者: David du Colombier (
0intro@gmail.com
) - コミット日時: 2014年2月20日 木曜日 07:59:38 +0100
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/58a9268f265843e2720adbcbdaf0bc1d367046a1
元コミット内容
os: fix Rename on Plan 9
Rename should fail when the directory doesn't match.
It will fix the newly introduced test from cmd/pack
on Plan 9.
LGTM=r
R=golang-codereviews, r
CC=golang-codereviews
https://golang.org/cl/65270044
変更の背景
このコミットは、Go言語のos
パッケージにおけるRename
関数のPlan 9オペレーティングシステム上での挙動を修正することを目的としています。具体的には、Rename
関数が、移動元と移動先のディレクトリが一致しない場合に正しくエラーを返すように変更されました。
この修正が必要となった背景には、cmd/pack
というGoのツール(おそらくアーカイブ関連のツール)で新しく導入されたテストがPlan 9上で失敗するという問題がありました。Rename
関数が期待されるエラーを返さないために、このテストが誤った結果を出していたと考えられます。このコミットは、Rename
の挙動をOSのセマンティクスに合わせ、テストの失敗を解消するために行われました。
前提知識の解説
- Plan 9 from Bell Labs: Plan 9は、ベル研究所で開発された分散オペレーティングシステムです。Unixの後継として設計され、ファイルシステムを中心とした設計思想が特徴です。すべてのリソース(プロセス、ネットワーク接続、デバイスなど)がファイルとして表現され、標準的なファイルシステムインターフェースを通じてアクセスされます。Go言語は、その設計思想の一部をPlan 9から継承しており、Goの初期開発者の中にはPlan 9の開発者が多く含まれています。
os.Rename
関数: Go言語の標準ライブラリos
パッケージに含まれる関数で、ファイルまたはディレクトリの名前を変更したり、移動したりするために使用されます。通常、os.Rename(oldpath, newpath string)
という形式で呼び出され、oldpath
で指定されたパスのファイルまたはディレクトリをnewpath
に移動または名前変更します。LinkError
: Go言語のos
パッケージで定義されているエラー型の一つです。ファイルシステム操作(リンク、名前変更など)が失敗した場合に返されることがあります。このエラー型は、操作の種類(Op)、古いパス(Old)、新しいパス(New)、そして根本的なエラー(Err)の情報を持ちます。ErrInvalid
: Go言語のos
パッケージで定義されているエラー変数の一つで、無効な引数や操作が指定された場合に返されることがあります。
技術的詳細
このコミットは、src/pkg/os/file_plan9.go
ファイル内のrename
関数に焦点を当てています。このファイルは、Goのos
パッケージがPlan 9オペレーティングシステム上で動作するための特定の実装を含んでいます。
rename
関数は、oldname
(元のパス)とnewname
(新しいパス)を受け取ります。変更前のコードでは、newname
がoldname
のディレクトリ部分をプレフィックスとして持っている場合、そのプレフィックスを取り除いて相対パスに変換していました。しかし、newname
がoldname
と同じディレクトリにない場合(つまり、ディレクトリをまたぐ移動の場合)、この処理はnewname
を適切に処理せず、Rename
が期待されるエラーを返さない可能性がありました。
Plan 9のファイルシステムセマンティクスでは、Rename
操作は、移動元と移動先のディレクトリが一致しない場合に失敗すべきです。このコミットは、このセマンティクスを強制するために、newname
がoldname
のディレクトリ部分をプレフィックスとして持たない場合に、即座にLinkError
を返すように修正を加えました。これにより、ディレクトリをまたぐ不適切なRename
操作が早期に検出され、エラーとして報告されるようになります。
コアとなるコードの変更箇所
diff --git a/src/pkg/os/file_plan9.go b/src/pkg/os/file_plan9.go
index e6496558ca..a804b81973 100644
--- a/src/pkg/os/file_plan9.go
+++ b/src/pkg/os/file_plan9.go
@@ -332,6 +332,8 @@ func rename(oldname, newname string) error {
dirname := oldname[:lastIndex(oldname, '/')+1]
if hasPrefix(newname, dirname) {
newname = newname[len(dirname):]
+ } else {
+ return &LinkError{"rename", oldname, newname, ErrInvalid}
}
// If newname still contains slashes after removing the oldname
コアとなるコードの解説
変更はsrc/pkg/os/file_plan9.go
ファイルのrename
関数内で行われています。
元のコードでは、以下の部分がありました。
dirname := oldname[:lastIndex(oldname, '/')+1]
if hasPrefix(newname, dirname) {
newname = newname[len(dirname):]
}
ここで、oldname
のディレクトリ部分(例: /a/b/c
の場合の/a/b/
)をdirname
として抽出し、newname
がそのdirname
で始まるかどうかをチェックしています。もしnewname
がdirname
で始まる場合、newname
からdirname
を取り除き、相対パスに変換しています。これは、同じディレクトリ内での名前変更を効率的に処理するためのロジックです。
このコミットで追加されたのは、else
ブロックです。
+ } else {
+ return &LinkError{"rename", oldname, newname, ErrInvalid}
}
このelse
ブロックは、newname
がoldname
のdirname
をプレフィックスとして持たない場合に実行されます。つまり、oldname
とnewname
が異なるディレクトリに属している場合です。このような状況は、Plan 9のRename
セマンティクスではエラーと見なされるべきです。
したがって、このelse
ブロックでは、LinkError
を生成して返しています。
Op
: "rename" (操作の種類)Old
:oldname
(元のパス)New
:newname
(新しいパス)Err
:ErrInvalid
(無効な操作であることを示すエラー)
この変更により、os.Rename
関数はPlan 9上で、ディレクトリをまたぐ不適切な名前変更/移動操作に対して、より正確なエラーを返すようになりました。これにより、cmd/pack
のテストが期待通りに失敗し、問題が修正されたと考えられます。
関連リンク
- Go CL (Code Review) へのリンク: https://golang.org/cl/65270044
参考にした情報源リンク
- (特になし。コミットメッセージとGoの標準ライブラリの知識に基づいています。)