[インデックス 10549] ファイルの概要
このコミットは、Go言語の os パッケージにおけるWindowsビルドの修正を目的としています。具体的には、ファイル情報の取得と変換に関するWindows固有の処理において、タイムスタンプの扱いを修正し、テスト用のエクスポートを調整しています。これにより、Windows環境での os パッケージの安定性と正確性が向上します。
コミット
commit 12eee9edbc0a63ba5802541ec9bfec4a925637ee
Author: Russ Cox <rsc@golang.org>
Date: Wed Nov 30 12:38:54 2011 -0500
os: fix windows build
TBR=brainman
CC=golang-dev
https://golang.org/cl/5449048
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/12eee9edbc0a63ba5802541ec9bfec4a925637ee
元コミット内容
os: fix windows build
TBR=brainman
CC=golang-dev
https://golang.org/cl/5449048
変更の背景
このコミットの背景には、Go言語の os パッケージがWindows環境で正しくビルドまたは動作しない問題があったことが示唆されています。コミットメッセージの「os: fix windows build」という記述から、Windows固有の環境におけるファイルシステム操作やファイル情報の取得に関するバグや不整合が存在し、それを修正する必要があったと考えられます。特に、ファイルタイムスタンプの扱いが原因であった可能性が高いです。Go言語はクロスプラットフォーム対応を目指しているため、各OS固有の挙動に合わせた調整が不可欠であり、このコミットはその一環としてWindows環境での互換性と正確性を確保するために行われました。
前提知識の解説
このコミットを理解するためには、以下のGo言語およびWindows OSに関する前提知識が必要です。
-
Go言語の
osパッケージ:osパッケージは、オペレーティングシステムと対話するための機能を提供します。これには、ファイルシステム操作(ファイルの読み書き、ディレクトリの作成など)、プロセス管理、環境変数へのアクセスなどが含まれます。os.FileInfoインターフェース: ファイルに関する抽象的な情報(ファイル名、サイズ、パーミッション、更新時刻など)を提供するインターフェースです。os.FileStat構造体:os.FileInfoインターフェースを実装する具体的な構造体で、ファイルシステムから取得した詳細なファイル情報を保持します。time.Time: Go言語で時刻を扱うための型です。time.Unix(sec int64, nsec int64) time.Time: Unixエポックからの秒数とナノ秒数からtime.Timeオブジェクトを生成する関数です。
-
Windows APIとファイルタイムスタンプ:
- Windows OSでは、ファイルの作成時刻 (Creation Time)、最終アクセス時刻 (Last Access Time)、最終書き込み時刻 (Last Write Time) を
FILETIME構造体で管理します。 syscall.Filetime: Go言語のsyscallパッケージで定義されているFILETIME構造体に対応する型です。これは、1601年1月1日からの100ナノ秒間隔の数を表す64ビットの値(LowDateTimeとHighDateTimeの2つのuint32で構成される)として表現されます。syscall.Filetime.Nanoseconds():syscall.Filetime型のメソッドで、FILETIMEの値をUnixエポック(1970年1月1日)からのナノ秒数に変換します。この変換は、Go言語のtime.Time型と互換性を持たせるために重要です。
- Windows OSでは、ファイルの作成時刻 (Creation Time)、最終アクセス時刻 (Last Access Time)、最終書き込み時刻 (Last Write Time) を
-
export_test.goファイル:- Go言語では、内部的な関数や変数をテスト目的で外部に公開するために、慣習的に
_test.goサフィックスを持つファイル内でExportというコメントを付けてエクスポートすることがあります。export_test.goは、パッケージの内部関数をテストパッケージからアクセス可能にするためのファイルです。
- Go言語では、内部的な関数や変数をテスト目的で外部に公開するために、慣習的に
技術的詳細
このコミットの技術的な核心は、Windowsにおけるファイルタイムスタンプの正確な変換と、それに伴う内部構造の調整にあります。
-
src/pkg/os/stat_windows.goの変更:toFileInfo関数のシグネチャ変更:- 変更前:
func toFileInfo(name string, fa, sizehi, sizelo uint32, ctime, atime, wtime syscall.Filetime) FileInfo - 変更後:
func toFileInfo(name string, fa, sizehi, sizelo uint32, ctime, atime, mtime syscall.Filetime) FileInfo wtime(write time) がmtime(modification time) に変更されています。これは、Windows APIで一般的に「最終書き込み時刻」が「最終更新時刻」として扱われることと整合性を取るための変更と考えられます。
- 変更前:
winTimes構造体の導入:type winTimes struct { atime, ctime syscall.Filetime }FileStat構造体のSysフィールド(OS固有の情報を保持するためのインターフェース)に、atime(アクセス時刻) とctime(作成時刻) を格納するための新しい構造体winTimesが導入されました。これにより、Windows固有のタイムスタンプ情報をより構造化された形で保持できるようになります。
fs.modTimeの修正:- 変更前:
fs.modTime = time.Unix(0, wtime.Nanoseconds()) - 変更後:
fs.modTime = time.Unix(0, mtime.Nanoseconds()) modTime(最終更新時刻) の設定において、wtimeからmtimeに変更された引数を使用するように修正されました。これは、toFileInfo関数のシグネチャ変更と連動しています。
- 変更前:
fs.SysへのwinTimesの割り当て:fs.Sys = &winTimes{atime, ctime}FileStatのSysフィールドに、新しく定義されたwinTimes構造体のインスタンスが割り当てられるようになりました。これにより、atimeとctimeがFileStatオブジェクトの一部として保持されるようになります。
atime関数の追加:func atime(fi FileInfo) time.Time { return time.Unix(0, fi.(*FileStat).Sys.(*winTimes).atime.Nanoseconds()) }- テスト目的で、
FileInfoからatime(最終アクセス時刻) を取得するためのヘルパー関数atimeが追加されました。この関数は、FileInfoを*FileStatに型アサートし、さらにそのSysフィールドを*winTimesに型アサートすることで、内部に保持されているatimeをtime.Time型に変換して返します。
-
src/pkg/os/export_test.goの変更:TimespecToTimeの削除:var TimespecToTime = timespecToTimeの行が削除されました。TimespecToTimeは、Unix系のシステムで使われるtimespec構造体をtime.Timeに変換するためのテスト用エクスポートだったと考えられます。Windowsビルドの修正に関連して、Windows固有のタイムスタンプ処理(syscall.Filetime)に焦点を当てるため、またはこの変換が不要になったため、削除されたと推測されます。Windowsではtimespecは直接使用されないため、Windowsビルドの修正においては不要なエクスポートであった可能性があります。
これらの変更は、Windowsにおけるファイル情報の取得、特にタイムスタンプの正確なマッピングと、Go言語の os パッケージの内部構造との整合性を確保するために行われました。
コアとなるコードの変更箇所
--- a/src/pkg/os/export_test.go
+++ b/src/pkg/os/export_test.go
@@ -6,5 +6,4 @@ package os
// Export for testing.
-var TimespecToTime = timespecToTime
var Atime = atime
diff --git a/src/pkg/os/stat_windows.go b/src/pkg/os/stat_windows.go
index d024915ee0..ddecd1118f 100644
--- a/src/pkg/os/stat_windows.go
+++ b/src/pkg/os/stat_windows.go
@@ -77,7 +77,11 @@ func basename(name string) string {
return name
}
-func toFileInfo(name string, fa, sizehi, sizelo uint32, ctime, atime, wtime syscall.Filetime) FileInfo {
+type winTimes struct {
+ atime, ctime syscall.Filetime
+}
+
+func toFileInfo(name string, fa, sizehi, sizelo uint32, ctime, atime, mtime syscall.Filetime) FileInfo {
fs := new(FileStat)
fs.mode = 0
if fa&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
@@ -90,10 +94,16 @@ func toFileInfo(name string, fa, sizehi, sizelo uint32, ctime, atime, wtime sysc
}
fs.size = int64(sizehi)<<32 + int64(sizelo)
fs.name = name
- fs.modTime = time.Unix(0, wtime.Nanoseconds())
+ fs.modTime = time.Unix(0, mtime.Nanoseconds())
+ fs.Sys = &winTimes{atime, ctime}
return fs
}
func sameFile(fs1, fs2 *FileStat) bool {
return false
}
+
+// For testing.
+func atime(fi FileInfo) time.Time {
+ return time.Unix(0, fi.(*FileStat).Sys.(*winTimes).atime.Nanoseconds())
+}
コアとなるコードの解説
src/pkg/os/export_test.go
- var TimespecToTime = timespecToTime: この行は削除されました。timespecToTimeはUnix系のシステムで使われるtimespec構造体をtime.Timeに変換するための内部関数であり、テスト目的でエクスポートされていました。Windowsビルドの修正においては、Windows固有のsyscall.Filetimeを扱うため、このUnix系システム向けの変換関数は不要と判断され、削除されたと考えられます。
src/pkg/os/stat_windows.go
-
+ type winTimes struct { atime, ctime syscall.Filetime }:winTimesという新しい構造体が定義されました。この構造体は、Windowsのファイルシステムから取得される最終アクセス時刻 (atime) と作成時刻 (ctime) をsyscall.Filetime型で保持します。- これは、
os.FileStat構造体のSysフィールド(OS固有の情報を格納するためのインターフェース)に、より具体的なWindows固有のタイムスタンプ情報を格納するための準備です。
-
- func toFileInfo(name string, fa, sizehi, sizelo uint32, ctime, atime, wtime syscall.Filetime) FileInfo { -
+ func toFileInfo(name string, fa, sizehi, sizelo uint32, ctime, atime, mtime syscall.Filetime) FileInfo {toFileInfo関数のシグネチャが変更されました。引数のwtime(write time) がmtime(modification time) に変更されています。これは、Windows APIにおける「最終書き込み時刻」が、Go言語のos.FileInfoインターフェースのModTime()メソッドが返す「最終更新時刻」と概念的に一致するため、より適切な命名に修正されたものです。
-
- fs.modTime = time.Unix(0, wtime.Nanoseconds()) -
+ fs.modTime = time.Unix(0, mtime.Nanoseconds())FileStatのmodTimeフィールドに値を設定する際に、変更された引数mtimeを使用するように修正されました。これにより、os.FileInfo.ModTime()がWindowsの最終書き込み時刻を正確に反映するようになります。
-
+ fs.Sys = &winTimes{atime, ctime}FileStatのSysフィールドに、新しく定義されたwinTimes構造体のインスタンスが割り当てられます。これにより、FileStatオブジェクトは、Windows固有の最終アクセス時刻と作成時刻を内部的に保持できるようになります。これは、後述のatime関数でこれらの情報にアクセスするために必要です。
-
+ // For testing. -
+ func atime(fi FileInfo) time.Time { -
+ return time.Unix(0, fi.(*FileStat).Sys.(*winTimes).atime.Nanoseconds()) -
+ }- テスト目的で、
FileInfoインターフェースから最終アクセス時刻 (atime) を取得するためのヘルパー関数atimeが追加されました。 - この関数は、
FileInfoを*FileStatに型アサートし、さらにそのSysフィールドを*winTimesに型アサートすることで、winTimes構造体内に格納されているatime(syscall.Filetime型) にアクセスします。 - 最後に、
syscall.Filetime.Nanoseconds()メソッドを使用してatimeをナノ秒単位のUnixエポックからの時間として取得し、time.Unix関数でtime.Time型に変換して返します。これにより、テストコードからWindows固有のアクセス時刻を簡単に検証できるようになります。
- テスト目的で、
これらの変更は、Windows環境におけるファイル情報の取得、特にタイムスタンプの正確なマッピングと、Go言語の os パッケージの内部構造との整合性を確保するために不可欠です。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/12eee9edbc0a63ba5802541ec9bfec4a925637ee
- Go CL (Code Review): https://golang.org/cl/5449048
参考にした情報源リンク
- Go言語
osパッケージ公式ドキュメント: https://pkg.go.dev/os - Go言語
timeパッケージ公式ドキュメント: https://pkg.go.dev/time - Go言語
syscallパッケージ公式ドキュメント: https://pkg.go.dev/syscall - Microsoft Docs - FILETIME structure: https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime