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

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

このコミットは、Go言語の標準ライブラリであるmimeパッケージに、Plan 9オペレーティングシステムにおけるMIMEタイプ(Multipurpose Internet Mail Extensions)のサポートを追加するものです。これにより、GoアプリケーションがPlan 9環境で実行される際に、システムに定義されたMIMEタイプ設定を適切に読み込み、ファイル拡張子からMIMEタイプを判別できるようになります。

コミット

commit 5567592c07b5ef2c9563a511851c7792868f0312
Author: Anthony Martin <ality@pbrane.org>
Date:   Tue Jun 4 17:30:45 2013 -0700

    mime: add support for Plan 9
    
    R=golang-dev, bradfitz
    CC=golang-dev
    https://golang.org/cl/10028043

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

https://github.com/golang/go/commit/5567592c07b5ef2c9563a511851c7792868f0312

元コミット内容

このコミットの目的は、Go言語のmimeパッケージにPlan 9オペレーティングシステム向けのMIMEタイプサポートを追加することです。具体的には、Plan 9のMIMEタイプ定義ファイルを読み込むための新しいコードが導入され、既存のUnix系システム向けのMIMEタイプ処理からPlan 9が除外されています。

変更の背景

Go言語はクロスプラットフォーム対応を重視しており、様々なオペレーティングシステムで動作するように設計されています。MIMEタイプは、インターネット上でファイルの形式を識別するために広く使用される標準です。多くのUnix系システムでは、/etc/mime.typesのようなファイルにMIMEタイプとファイル拡張子のマッピングが定義されています。しかし、Plan 9は独自の設計思想を持つオペレーティングシステムであり、MIMEタイプの定義方法も他のUnix系システムとは異なります。

このコミット以前のGoのmimeパッケージは、主にUnix系システム(Linux, macOS, FreeBSDなど)のMIMEタイプ定義を想定していました。Plan 9環境でGoアプリケーションがMIMEタイプを正確に判別するためには、Plan 9独自のMIMEタイプ定義ファイル(通常/sys/lib/mimetypes)を読み込むメカニズムが必要でした。この変更は、GoのmimeパッケージがPlan 9環境でも適切に機能し、より広範なOSサポートを提供するためのものです。

前提知識の解説

MIMEタイプ (Multipurpose Internet Mail Extensions)

MIMEタイプは、インターネット上で交換されるファイルやデータの種類を識別するための標準的な方法です。例えば、ウェブサーバーがクライアントにファイルを送信する際、そのファイルがHTMLドキュメントなのか、画像なのか、PDFなのかをMIMEタイプで伝えます。MIMEタイプは通常、「タイプ/サブタイプ」の形式で表現されます(例: text/html, image/jpeg, application/pdf)。Go言語のmimeパッケージは、ファイル拡張子からMIMEタイプを推測したり、MIMEタイプからファイル拡張子を推測したりする機能を提供します。

Plan 9 from Bell Labs

Plan 9は、ベル研究所で開発された分散オペレーティングシステムです。Unixの設計思想をさらに推し進め、すべてのリソース(ファイル、デバイス、ネットワーク接続など)をファイルシステムとして表現するという特徴を持っています。Plan 9は、そのシンプルで一貫性のある設計、強力なネットワーク機能、そして独自のプロトコルやツールで知られています。MIMEタイプの定義に関しても、他のUnix系システムとは異なる独自のアプローチを採用しています。Plan 9では、MIMEタイプ定義は通常/sys/lib/mimetypesファイルに格納されており、そのフォーマットも異なります。

Go言語のビルドタグ (Build Tags)

Go言語には「ビルドタグ」という機能があります。これは、ソースコードファイルの先頭に特定のコメント行(// +build tagname)を記述することで、そのファイルが特定の環境(OS、アーキテクチャなど)でのみコンパイルされるように制御するメカニズムです。例えば、// +build linuxと書かれたファイルはLinux環境でのみコンパイルされ、他のOSでは無視されます。このコミットでは、type_unix.goからplan9ビルドタグを削除し、type_plan9.goにPlan 9固有のMIMEタイプ処理を分離するために利用されています。

技術的詳細

このコミットの主要な変更点は、GoのmimeパッケージがPlan 9環境でMIMEタイプを処理する方法を分離し、Plan 9固有のMIMEタイプ定義ファイルを読み込むロジックを導入したことです。

  1. type_plan9.goの新規追加:

    • このファイルは、Plan 9環境でのみコンパイルされるように設計されています(ただし、明示的なビルドタグは付与されていませんが、type_unix.goからplan9が削除されたことで、Plan 9環境ではこのファイルが選択されるようになります)。
    • typeFilesというグローバル変数が定義されており、Plan 9のMIMEタイプ定義ファイルである/sys/lib/mimetypesのパスが格納されています。
    • loadMimeFile関数は、指定されたMIMEタイプ定義ファイルを読み込み、その内容を解析してGoのmimeパッケージ内部のMIMEタイプマップに登録します。Plan 9のMIMEタイプファイルは、拡張子、タイプ、サブタイプなどがスペース区切りで記述される独自のフォーマットを持っています。この関数は、そのフォーマットを解析し、setExtensionType関数(mimeパッケージの内部関数)を呼び出してマッピングを登録します。
    • initMime関数は、typeFilesに定義されたすべてのMIMEタイプファイルを読み込むためのエントリポイントです。
    • initMimeForTests関数は、テスト目的でMIMEタイプを初期化するための関数です。これは、実際のシステムファイルではなく、testdata/test.types.plan9というテスト用のMIMEタイプ定義ファイルを読み込むようにtypeFilesを上書きします。
  2. type_unix.goの変更:

    • 既存のtype_unix.goファイルは、Unix系システム(darwin, freebsd, linux, netbsd, openbsd)向けのMIMEタイプ処理を担っていました。
    • このコミットでは、ファイルの先頭にあるビルドタグからplan9が削除されました。これにより、Plan 9環境ではtype_unix.goはコンパイルされなくなり、代わりに新しく追加されたtype_plan9.goが使用されるようになります。
  3. testdata/test.types.plan9の新規追加:

    • これは、type_plan9.goloadMimeFile関数がPlan 9のMIMEタイプ定義ファイルを正しく解析できることを検証するためのテストデータファイルです。
    • .t1.t2という架空の拡張子に対するMIMEタイプ定義が含まれています。

これらの変更により、Goのmimeパッケージは、コンパイルされるオペレーティングシステムに応じて適切なMIMEタイプ定義ファイルを読み込むようになり、Plan 9環境でも正確なMIMEタイプ判別が可能になります。

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

src/pkg/mime/testdata/test.types.plan9 (新規ファイル)

# Copyright 2013 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.


 # mime package test
.t1		application	test		-		y # Simple test	
.t2		text		test		-		y # Text test	

src/pkg/mime/type_plan9.go (新規ファイル)

// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package mime

import (
	"bufio"
	"os"
	"strings"
)

var typeFiles = []string{
	"/sys/lib/mimetypes",
}

func loadMimeFile(filename string) {
	f, err := os.Open(filename)
	if err != nil {
		return
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		fields := strings.Fields(scanner.Text())
		if len(fields) <= 2 || fields[0][0] != '.' {
			continue
		}
		if fields[1] == "-" || fields[2] == "-" {
			continue
		}
		setExtensionType(fields[0], fields[1]+"/"+fields[2])
	}
	if err := scanner.Err(); err != nil {
		panic(err)
	}
}

func initMime() {
	for _, filename := range typeFiles {
		loadMimeFile(filename)
	}
}

func initMimeForTests() map[string]string {
	typeFiles = []string{"testdata/test.types.plan9"}
	return map[string]string{
		".t1":  "application/test",
		".t2":  "text/test; charset=utf-8",
		".png": "image/png",
	}
}

src/pkg/mime/type_unix.go (変更箇所)

--- a/src/pkg/mime/type_unix.go
+++ b/src/pkg/mime/type_unix.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build darwin freebsd linux netbsd openbsd plan9
+// +build darwin freebsd linux netbsd openbsd
 
 package mime
 

コアとなるコードの解説

src/pkg/mime/type_plan9.go

  • typeFiles変数:

    • var typeFiles = []string{"/sys/lib/mimetypes"}: Plan 9システムにおけるMIMEタイプ定義ファイルの標準パスを定義しています。GoのmimeパッケージがMIMEタイプを初期化する際に、このパスのファイルを読み込もうとします。
  • loadMimeFile関数:

    • この関数は、指定されたfilename(MIMEタイプ定義ファイル)を開き、行ごとに読み込みます。
    • bufio.NewScannerを使用してファイルを効率的にスキャンします。
    • 各行をstrings.Fieldsでスペース区切りに分割し、フィールドの数が2以下の場合や、最初のフィールドがピリオド(.)で始まらない場合はスキップします。これは、Plan 9のMIMEタイプ定義ファイルのフォーマット(.拡張子 タイプ サブタイプ ...)に合致しない行を無視するためです。
    • タイプまたはサブタイプがハイフン(-)の場合もスキップします。これは、MIMEタイプが未定義であることを示す慣習的な表現である可能性があります。
    • setExtensionType(fields[0], fields[1]+"/"+fields[2]):解析された拡張子(fields[0])と、タイプとサブタイプを結合したMIMEタイプ文字列(例: application/test)を、mimeパッケージ内部のマップに登録します。setExtensionTypeはパッケージ内部の関数であり、外部からは直接呼び出されません。
  • initMime関数:

    • for _, filename := range typeFiles { loadMimeFile(filename) }: typeFilesに定義されているすべてのMIMEタイプファイルをループで処理し、それぞれloadMimeFileを呼び出してMIMEタイプをロードします。この関数は、Goのmimeパッケージが初期化される際に、Plan 9環境で自動的に呼び出されることが期待されます。
  • initMimeForTests関数:

    • typeFiles = []string{"testdata/test.types.plan9"}: テスト実行時に、実際のシステムファイルではなく、テストデータファイルtestdata/test.types.plan9を読み込むようにtypeFilesを上書きします。これにより、テストがシステム環境に依存せず、再現性のあるMIMEタイプ初期化を行うことができます。
    • この関数は、テストで期待されるMIMEタイプマッピングのサンプルを返します。

src/pkg/mime/type_unix.go

  • ビルドタグの変更:
    • - // +build darwin freebsd linux netbsd openbsd plan9
    • + // +build darwin freebsd linux netbsd openbsd
    • この変更により、type_unix.goはPlan 9環境ではコンパイルされなくなります。これにより、Plan 9固有のMIMEタイプ処理がtype_plan9.goに完全に分離され、各OSのMIMEタイプ処理が適切にモジュール化されます。

これらの変更により、Goのmimeパッケージは、Plan 9環境においてもそのMIMEタイプ定義を適切に読み込み、ファイル拡張子からMIMEタイプを正確に判別できるようになりました。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード (特にsrc/mimeディレクトリ)
  • Plan 9のMIMEタイプ定義に関する一般的な情報 (Web検索)
  • Go言語のビルドタグに関するドキュメント (Web検索)
  • コミットメッセージに記載されているGoのコードレビューリンク: https://golang.org/cl/10028043