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

[インデックス 18192] ファイルの概要

このコミットは、Go言語の標準ライブラリsrc/pkg/net/lookup_plan9.goファイルに対する変更です。具体的には、Plan 9オペレーティングシステム上でのネットワークルックアップ処理において、/net/dnsまたは/net/csファイルへの読み書きを行う前に、ファイルオフセットを0にシークする処理を追加しています。

コミット

commit a03e8a5be017f4741c029c04a3333bb655ab8059
Author: Jeff Sickel <jas@corpus-callosum.com>
Date:   Wed Jan 8 21:22:18 2014 +0100

    plan9: lookup query must seek to offset 0 before reading or
           writing /net/dns or /net/cs (see nbd(8)).
    
    R=golang-codereviews
    CC=0intro, golang-codereviews, rsc
    https://golang.org/cl/49060043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/a03e8a5be017f4741c029c04a3333bb655ab8059

元コミット内容

diff --git a/src/pkg/net/lookup_plan9.go b/src/pkg/net/lookup_plan9.go
index a755ff2aac..95c0f0b068 100644
--- a/src/pkg/net/lookup_plan9.go
+++ b/src/pkg/net/lookup_plan9.go
@@ -16,6 +16,10 @@ func query(filename, query string, bufSize int) (res []string, err error) {
 	}\n \tdefer file.Close()\n \n+\t_, err = file.Seek(0, 0)\n+\tif err != nil {\n+\t\treturn\n+\t}\n \t_, err = file.WriteString(query)\n \tif err != nil {\n \t\treturn\n```

## 変更の背景

この変更は、Plan 9オペレーティングシステムにおけるネットワークルックアップの挙動に関するものです。Plan 9では、「すべてがファイルである」という哲学に基づき、ネットワークサービスもファイルシステム上の特殊なファイルとして表現されます。具体的には、DNS解決には`/net/dns`が、接続情報の解決には`/net/cs`が使用されます。

これらのファイルは、クエリを書き込み、その結果を読み取ることでネットワーク操作を行います。しかし、以前の操作がファイルのオフセットを変更したままになっていると、次の読み書き操作が意図しない位置から開始されてしまい、正しく機能しない可能性がありました。

コミットメッセージにある`nbd(8)`は、Plan 9のネットワークデータベース(`ndb`)に関連する可能性が高いです。`ndb`は、ネットワークに関する管理情報を格納する中央データベースであり、`/net/dns`や`/net/cs`のような特殊なファイルがこのデータベースと連携して動作することがあります。この文脈では、`nbd(8)`が、これらのファイルへのアクセス規約、特にオフセットの管理について言及していると考えられます。

このコミットは、このようなオフセットの問題を解決し、`/net/dns`や`/net/cs`へのアクセスが常にファイルの先頭(オフセット0)から行われるようにすることで、ネットワークルックアップの信頼性を向上させることを目的としています。

## 前提知識の解説

*   **Plan 9 from Bell Labs**: Unixの哲学をさらに推し進めた分散オペレーティングシステムです。その最大の特徴は「すべてがファイルである」という設計思想で、プロセス、ネットワーク接続、デバイスなど、あらゆるシステムリソースがファイルシステム上のファイルとして表現されます。これにより、一貫したインターフェースでシステム全体を操作できます。Go言語の設計者の一部はPlan 9の開発にも携わっており、Go言語の設計にもその影響が見られます。
*   **/net/dns**: Plan 9におけるDNS(Domain Name System)リゾルバへのファイルインターフェースです。ユーザーレベルのプロセスがDNSサーバーとして機能し、クライアントは`/net/dns`ファイルにDNSクエリ(例: ドメイン名とレコードタイプ)を書き込み、その後ファイルを読み取ることで対応するDNSリソースレコードを取得します。
*   **/net/cs**: Plan 9における接続サーバー(connection server)へのファイルインターフェースです。`/net/dns`と同様に、ユーザーレベルのプロセスによって提供されるファイルです。その主な機能は、シンボリックなネットワーク名をネットワークアドレスや接続情報に変換することです。アプリケーションは`/net/cs`にシンボリック名を書き込み、その名前のリソースへの接続を確立する方法に関する情報を読み取ります。これには、新しい接続を開始するための「クローン」ファイルへのパスが含まれることがよくあります。
*   **ファイルオフセット**: ファイル内の現在の読み書き位置を示すポインタです。ファイル操作(読み込み、書き込み)を行うと、このオフセットは自動的に進みます。明示的にオフセットを変更するには、`seek`のような操作が必要です。
*   **`file.Seek(offset, whence)`**: ファイルの読み書き位置(オフセット)を変更するための関数です。
    *   `offset`: どこに移動するかを示すバイト数です。
    *   `whence`: `offset`の基準位置を指定します。
        *   `0` (または `io.SeekStart`): ファイルの先頭からのオフセット。
        *   `1` (または `io.SeekCurrent`): 現在のオフセットからのオフセット。
        *   `2` (または `io.SeekEnd`): ファイルの末尾からのオフセット。
    このコミットでは`file.Seek(0, 0)`が使用されており、これはファイルの先頭(オフセット0)に移動することを意味します。

## 技術的詳細

Go言語の`net`パッケージは、様々なオペレーティングシステムに対応するために、OS固有のネットワークルックアップ実装を持っています。`src/pkg/net/lookup_plan9.go`は、Plan 9システムにおけるこの機能を提供します。

Plan 9の「すべてがファイル」という設計は、ネットワーク操作を通常のファイルI/O操作として扱うことを可能にします。しかし、この抽象化には、ファイルオフセットの管理という課題が伴います。一般的なファイルでは、一度書き込みや読み込みを行うと、その操作のバイト数分だけオフセットが進みます。次に同じファイルに対して操作を行う場合、そのオフセットから開始されます。

`/net/dns`や`/net/cs`のような特殊なファイルは、単なるデータストレージではなく、特定のプロトコルに従って対話するインターフェースです。これらのファイルにクエリを書き込み、その結果を読み取るというシーケンスは、多くの場合、常にファイルの「論理的な先頭」から開始されることを期待します。もし以前の操作によってオフセットがファイルの途中に残っていると、新しいクエリの書き込みが正しく解釈されなかったり、結果の読み込みが期待通りに行われなかったりする可能性があります。

このコミットは、この問題を解決するために、`file.WriteString(query)`の前に`file.Seek(0, 0)`を呼び出すことで、明示的にファイルのオフセットを先頭にリセットしています。これにより、常にクエリがファイルの先頭から書き込まれ、その後の読み込みも正しく行われることが保証されます。これは、Plan 9の特殊なファイルインターフェースのセマンティクスに合わせた、堅牢な実装のための重要な修正です。

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

`src/pkg/net/lookup_plan9.go`ファイルの`query`関数内に、以下の4行が追加されました。

```go
	_, err = file.Seek(0, 0)
	if err != nil {
		return
	}

コアとなるコードの解説

この変更は、query関数内でファイル操作を行う直前に追加されています。

  1. file.Seek(0, 0):
    • fileは、/net/dnsまたは/net/csといった特殊なファイルを表す*os.File型の変数です。
    • Seek(0, 0)は、ファイルのオフセットを先頭(0バイト目)に設定する操作です。最初の0はオフセット値、2番目の0io.SeekStart(ファイルの先頭を基準とする)を意味します。
    • この行により、次に続くfile.WriteString(query)が常にファイルの先頭から開始されることが保証されます。
  2. if err != nil { return }:
    • Seek操作がエラーを返した場合(例えば、ファイルがシークをサポートしていない、または無効なファイルディスクリプタであるなど)、そのエラーを捕捉し、関数から早期にリターンします。これにより、不正な状態での後続のファイル操作を防ぎます。

この修正は、Plan 9の特殊なファイルシステムインターフェースの特性を考慮したもので、ネットワークルックアップの信頼性と正確性を確保するために不可欠です。

関連リンク

参考にした情報源リンク

  • Web検索結果: "plan9 /net/dns /net/cs nbd(8)"
  • Web検索結果: "Go plan9 network lookup lookup_plan9.go"
  • Go言語のos.File.Seekに関するドキュメント: https://pkg.go.dev/os#File.Seek
  • Plan 9のネットワークに関する資料 (例: ndbに関する情報): https://9p.io/magic/man2html/8/ndb (nbd(8)がndb(8)の誤記である可能性を考慮)