[インデックス 10719] ファイルの概要
このコミットは、Go言語のos
パッケージにおけるFileInfo
APIの変更に対応するため、Plan 9オペレーティングシステム向けのビルドを修正するものです。具体的には、FileInfo
が構造体からインターフェースに変更されたことに伴い、関連するファイル操作やファイル情報の取得ロジックが更新されています。
コミット
commit 2c2a582ae9555845b359a089704e17a299aa40b0
Author: Anthony Martin <ality@pbrane.org>
Date: Mon Dec 12 16:14:00 2011 -0500
os: fix Plan 9 build for new FileInfo API
R=lucio.dere, rsc
CC=golang-dev
https://golang.org/cl/5440073
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/2c2a582ae9555845b359a089704e17a299aa40b0
元コミット内容
os: fix Plan 9 build for new FileInfo API
R=lucio.dere, rsc
CC=golang-dev
https://golang.org/cl/5440073
変更の背景
このコミットは、Go言語の標準ライブラリであるos
パッケージにおけるFileInfo
APIの重要な変更に対応するために行われました。2011年頃、Go 1.0のリリースに向けて、os.FileInfo
はそれまでの具体的な構造体(struct)からインターフェース(interface)へと再定義されました。この変更の主な目的は、ファイル情報の表現に柔軟性を持たせ、オペレーティングシステムのネイティブな構造体だけでなく、より多様なファイル情報の実装を可能にすることでした。
FileInfo
がインターフェースになったことで、以前はフィールドとして直接アクセスできたName
, Size
, Mode
, ModTime
, IsDir
, Sys
といった属性が、インターフェースのメソッドとして提供されるようになりました。これにより、FileInfo
を扱うコードは、具体的な実装に依存せず、インターフェースが提供するメソッドを通じてファイル情報にアクセスする形に修正する必要が生じました。
このコミットは、特にPlan 9オペレーティングシステム向けのGoのビルドにおいて、このAPI変更によって発生した互換性の問題を解決することを目的としています。Plan 9固有のファイルシステム操作やシステムコールを扱う部分が、新しいFileInfo
インターフェースの仕様に合わせて更新されています。
前提知識の解説
os.FileInfo
: Go言語のos
パッケージで提供されるインターフェースで、ファイルやディレクトリのメタデータ(名前、サイズ、パーミッション、更新時刻など)を抽象的に表現します。このコミットが行われた時期に、具体的な構造体からインターフェースへと変更されました。- Plan 9: ベル研究所で開発された分散オペレーティングシステムです。Go言語は、Unix系OSだけでなく、Plan 9も公式にサポートしており、Goの標準ライブラリにはPlan 9固有のシステムコールやファイルシステム操作を扱うコードが含まれています。
syscall
パッケージ: Go言語のsyscall
パッケージは、低レベルのオペレーティングシステムプリミティブへのアクセスを提供します。ファイルシステム操作やプロセス管理など、OS固有の機能に直接アクセスするために使用されます。このコミットでは、Plan 9のシステムコール(syscall.Stat
,syscall.Fstat
など)を介して取得したファイル情報を、新しいFileInfo
インターフェースに適合させるための変換ロジックが変更されています。Dir
構造体 (Plan 9固有): Plan 9のファイルシステムでは、ファイルのメタデータはDir
という構造体で表現されます。これはUnix系のstat
構造体に相当します。Goのos
パッケージのPlan 9固有の実装では、このDir
構造体からos.FileInfo
インターフェースを実装するオブジェクトを生成します。Mode
とパーミッション: ファイルのモード(種類とパーミッション)は、os.FileMode
型で表現されます。Plan 9のDir
構造体にはMode
フィールドがあり、これにはファイルの種類(ディレクトリ、通常ファイルなど)やアクセス権限がビットフラグとして含まれています。syscall.DMDIR
などの定数は、Plan 9固有のモードビットを表します。
技術的詳細
このコミットの核心は、os.FileInfo
が構造体からインターフェースに変わったことによる影響を、Plan 9固有のコードベースで吸収することです。
以前のFileInfo
が構造体であった頃は、fileInfoFromStat
のような関数は*FileInfo
ポインタを受け取り、そのフィールドに直接値を設定していました。しかし、FileInfo
がインターフェースになったことで、この関数はFileInfo
インターフェースを実装する具体的な型(このコミットでは*FileStat
)のインスタンスを生成し、それを返すように変更されました。
具体的には、以下の点が変更されています。
-
FileInfo
の返り値の変更:fileInfoFromStat
関数は、以前は*FileInfo
ポインタを引数に取り、そのポインタを返していましたが、変更後は*Dir
構造体を受け取り、FileInfo
インターフェースを実装する*FileStat
型の値を直接返すようになりました。File.Stat()
およびStat()
,Lstat()
関数も、以前は*FileInfo
ポインタとエラーを返していましたが、変更後はFileInfo
インターフェースとエラーを返すようになりました。これにより、呼び出し側はインターフェースを通じてファイル情報にアクセスすることになります。
-
FileInfo
メソッドの呼び出し:Readdirnames
関数では、fi[i].Name
という直接フィールドアクセスから、fi[i].Name()
というインターフェースメソッドの呼び出しに変更されました。これは、Name
がFileInfo
インターフェースのメソッドになったためです。
-
ファイルモードのチェック:
findExecutable
関数では、以前はd.IsRegular()
とd.Permission()
というFileInfo
構造体のフィールドとメソッドを組み合わせていましたが、新しいFileInfo
インターフェースではMode()
メソッドがos.FileMode
を返すため、m := d.Mode(); !m.IsDir() && m&0111 != 0
という形式に変更されました。これは、os.FileMode
が提供するヘルパーメソッド(IsDir()
など)やビット演算子を使って、ファイルの種類と実行権限をチェックする方法です。
-
dirstat
関数のバッファサイズ調整:dirstat
関数は、Plan 9のstat
システムコールから返されるファイル情報を格納するためのバッファを扱います。以前はsyscall.STATFIXLEN + 16*4
という固定サイズでバッファを確保していましたが、stat
メッセージの実際のサイズがこれより大きい場合に備え、ループ内でバッファサイズを動的に調整するロジックが改善されました。size := (syscall.STATFIXLEN + 16*4 + 128) &^ 128
という行は、バッファサイズを128バイトの倍数に丸めることで、アライメントを考慮しつつ効率的なメモリ確保を行うためのものです。
-
FileStat
構造体の導入:stat_plan9.go
では、FileInfo
インターフェースを実装するための具体的な型としてFileStat
構造体が導入されています。この構造体は、ファイル名、サイズ、更新時刻、モード、そして基となるPlan 9のDir
構造体(Sys
フィールド)を保持します。
コアとなるコードの変更箇所
このコミットでは、以下の4つのファイルが変更されています。
-
src/pkg/os/dir_plan9.go
:File.Readdir
関数内で、fileInfoFromStat
の呼び出し方が変更されました。以前はvar f FileInfo; fileInfoFromStat(&f, dir); result = append(result, f)
のように、FileInfo
構造体のポインタを渡していましたが、変更後はresult = append(result, fileInfoFromStat(dir))
のように、fileInfoFromStat
が直接FileInfo
インターフェースを返すようになったため、その返り値を直接append
しています。File.Readdirnames
関数内で、fi[i].Name
という直接フィールドアクセスがfi[i].Name()
というメソッド呼び出しに変更されました。
-
src/pkg/os/exec/lp_plan9.go
:findExecutable
関数内で、ファイルの実行可能属性をチェックするロジックが変更されました。以前のd.IsRegular() && d.Permission()&0111 != 0
から、m := d.Mode(); !m.IsDir() && m&0111 != 0
に変更され、FileInfo
インターフェースのMode()
メソッドが返すos.FileMode
型を利用するようになりました。
-
src/pkg/os/file_plan9.go
:File.Stat()
関数のシグネチャが変更されました。以前はfunc (f *File) Stat() (fi *FileInfo, err error)
でしたが、変更後はfunc (f *File) Stat() (FileInfo, error)
となり、*FileInfo
ポインタではなくFileInfo
インターフェースを返すようになりました。fileInfoFromStat
の呼び出し方も、return fileInfoFromStat(new(FileInfo), d), err
からreturn fileInfoFromStat(d), nil
に変更されました。
-
src/pkg/os/stat_plan9.go
:fileInfoFromStat
関数のシグネチャが変更されました。以前はfunc fileInfoFromStat(fi *FileInfo, d *Dir) *FileInfo
でしたが、変更後はfunc fileInfoFromStat(d *Dir) FileInfo
となり、*FileInfo
ポインタを引数に取らず、FileInfo
インターフェースを直接返すようになりました。FileStat
構造体が導入され、fileInfoFromStat
はこのFileStat
のインスタンスを生成して返します。sameFile
関数が追加され、2つのFileStat
が同じファイルを参照しているかを比較するロジックが実装されました。dirstat
関数内で、syscall.Stat
やsyscall.Fstat
のバッファサイズ計算ロジックが改善され、より堅牢になりました。Stat()
およびLstat()
関数のシグネチャもFile.Stat()
と同様に変更され、FileInfo
インターフェースを返すようになりました。Lstat
はPlan 9ではシンボリックリンクがないため、Stat
を呼び出すように簡略化されました。
コアとなるコードの解説
このコミットの主要な変更は、Go言語のos.FileInfo
が構造体からインターフェースに移行したことへの対応です。
-
fileInfoFromStat
関数の役割変更: この関数は、Plan 9のシステムコールから取得した生のファイル情報(*Dir
構造体)を、Goのos.FileInfo
インターフェースに適合する形式に変換する役割を担っています。以前は既存のFileInfo
構造体にデータを埋め込む形でしたが、インターフェース化に伴い、FileStat
という新しい構造体を内部で定義し、そのインスタンスを生成してFileInfo
インターフェースとして返すように変更されました。これにより、os
パッケージの他の部分がFileInfo
インターフェースを通じてファイル情報にアクセスできるようになります。 -
File.Stat()
、Stat()
、Lstat()
の返り値の統一: これらの関数は、ファイルやパスのFileInfo
を取得するGoの標準的な方法です。インターフェースへの変更により、これらの関数が返す型が*FileInfo
からFileInfo
インターフェースに統一されました。これは、GoのAPI設計における抽象化の原則に従ったもので、具体的な実装の詳細を隠蔽し、より柔軟なコードを記述できるようにします。 -
ファイルモードの扱い:
os/exec/lp_plan9.go
における実行可能ファイルのチェックロジックの変更は、os.FileMode
型が提供するメソッド(IsDir()
など)やビットフラグを直接利用することで、よりGoらしい(idiomaticな)方法でファイルモードを扱うようになったことを示しています。これは、FileInfo
インターフェースが提供する情報へのアクセス方法が洗練された結果です。 -
dirstat
の堅牢性向上:dirstat
関数におけるバッファサイズ計算の改善は、Plan 9のstat
システムコールが返すメッセージのサイズが可変であることへの対応です。これにより、予期せぬ短いバッファによるエラーを防ぎ、より信頼性の高いファイル情報取得を実現しています。
これらの変更は、Go言語のos
パッケージが、異なるオペレーティングシステム(この場合はPlan 9)の特性を吸収しつつ、統一された抽象化されたAPI(os.FileInfo
)を提供するための重要なステップでした。
関連リンク
- Go CL 5440073: https://golang.org/cl/5440073
参考にした情報源リンク
- Go
os.FileInfo
API changes 2011:- https://stackoverflow.com/questions/7900970/go-os-fileinfo-interface-vs-struct
- https://go.dev/doc/go1.html#os_fileinfo
- https://go.dev/blog/go1
- https://www.geeksforgeeks.org/go-os-fileinfo-interface/
- https://vld.bg/go-os-fileinfo-interface/
- https://go.dev/doc/effective_go#interface_types
- https://stackoverflow.com/questions/7900970/go-os-fileinfo-interface-vs-struct
- https://www.google.com/search?q=Go+FileInfo+API+changes+2011