Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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)のインスタンスを生成し、それを返すように変更されました。

具体的には、以下の点が変更されています。

  1. FileInfoの返り値の変更:

    • fileInfoFromStat関数は、以前は*FileInfoポインタを引数に取り、そのポインタを返していましたが、変更後は*Dir構造体を受け取り、FileInfoインターフェースを実装する*FileStat型の値を直接返すようになりました。
    • File.Stat()およびStat(), Lstat()関数も、以前は*FileInfoポインタとエラーを返していましたが、変更後はFileInfoインターフェースとエラーを返すようになりました。これにより、呼び出し側はインターフェースを通じてファイル情報にアクセスすることになります。
  2. FileInfoメソッドの呼び出し:

    • Readdirnames関数では、fi[i].Nameという直接フィールドアクセスから、fi[i].Name()というインターフェースメソッドの呼び出しに変更されました。これは、NameFileInfoインターフェースのメソッドになったためです。
  3. ファイルモードのチェック:

    • findExecutable関数では、以前はd.IsRegular()d.Permission()というFileInfo構造体のフィールドとメソッドを組み合わせていましたが、新しいFileInfoインターフェースではMode()メソッドがos.FileModeを返すため、m := d.Mode(); !m.IsDir() && m&0111 != 0という形式に変更されました。これは、os.FileModeが提供するヘルパーメソッド(IsDir()など)やビット演算子を使って、ファイルの種類と実行権限をチェックする方法です。
  4. dirstat関数のバッファサイズ調整:

    • dirstat関数は、Plan 9のstatシステムコールから返されるファイル情報を格納するためのバッファを扱います。以前はsyscall.STATFIXLEN + 16*4という固定サイズでバッファを確保していましたが、statメッセージの実際のサイズがこれより大きい場合に備え、ループ内でバッファサイズを動的に調整するロジックが改善されました。size := (syscall.STATFIXLEN + 16*4 + 128) &^ 128という行は、バッファサイズを128バイトの倍数に丸めることで、アライメントを考慮しつつ効率的なメモリ確保を行うためのものです。
  5. FileStat構造体の導入:

    • stat_plan9.goでは、FileInfoインターフェースを実装するための具体的な型としてFileStat構造体が導入されています。この構造体は、ファイル名、サイズ、更新時刻、モード、そして基となるPlan 9のDir構造体(Sysフィールド)を保持します。

コアとなるコードの変更箇所

このコミットでは、以下の4つのファイルが変更されています。

  1. 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()というメソッド呼び出しに変更されました。
  2. 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型を利用するようになりました。
  3. 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に変更されました。
  4. 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.Statsyscall.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)を提供するための重要なステップでした。

関連リンク

参考にした情報源リンク