[インデックス 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