[インデックス 17758] ファイルの概要
このコミットは、Go言語のos/user
パッケージにおけるユーザー情報ルックアップの挙動を、DragonFly BSDオペレーティングシステム上で修正するものです。具体的には、getpwnam_r
やgetpwuid_r
といったPOSIX準拠の関数が内部的に使用するバッファサイズの決定方法に関する問題に対処しています。
コミット
commit fc1bea321de31243c2f68316941e0f99eeb86557
Author: Joel Sing <jsing@google.com>
Date: Mon Oct 7 09:21:33 2013 -0700
os/user: fix user lookups on dragonfly
Like FreeBSD, DragonFly does not provide a sysconf value for
_SC_GETPW_R_SIZE_MAX.
R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/14469043
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/fc1bea321de31243c2f68316941e0f99eeb86557
元コミット内容
このコミットは、src/pkg/os/user/lookup_unix.go
ファイルに対して行われた変更です。変更内容は以下の通りです。
--- a/src/pkg/os/user/lookup_unix.go
+++ b/src/pkg/os/user/lookup_unix.go
@@ -50,10 +50,10 @@ func lookupUnix(uid int, username string, lookupByName bool) (*User, error) {\
var result *C.struct_passwd
var bufSize C.long
- if runtime.GOOS == "freebsd" {
- // FreeBSD doesn't have _SC_GETPW_R_SIZE_MAX
- // and just returns -1. So just use the same
- // size that Linux returns
+ if runtime.GOOS == "dragonfly" || runtime.GOOS == "freebsd" {
+ // DragonFly and FreeBSD do not have _SC_GETPW_R_SIZE_MAX
+ // and just return -1. So just use the same
+ // size that Linux returns.
bufSize = 1024
} else {
bufSize = C.sysconf(C._SC_GETPW_R_SIZE_MAX)
変更の背景
Go言語のos/user
パッケージは、システム上のユーザー情報を取得するための機能を提供します。Unix系システムでは、ユーザー情報を取得するためにgetpwnam_r
(ユーザー名から)やgetpwuid_r
(UIDから)といった再入可能な(reentrant)関数が使用されます。これらの関数は、結果を格納するためのバッファを呼び出し元が提供する必要があります。
バッファの適切なサイズを決定するために、POSIX標準では_SC_GETPW_R_SIZE_MAX
というsysconf
値が定義されています。これは、getpwnam_r
やgetpwuid_r
が要求する可能性のある最大バッファサイズを示します。しかし、一部のUnix系オペレーティングシステム(特にFreeBSD)では、この_SC_GETPW_R_SIZE_MAX
が提供されておらず、sysconf
を呼び出しても-1
が返されることがあります。
このコミット以前は、Goのos/user
パッケージはFreeBSDに対してのみ、この_SC_GETPW_R_SIZE_MAX
の欠如を特別扱いし、固定のバッファサイズ(1024バイト)を使用していました。しかし、DragonFly BSDも同様に_SC_GETPW_R_SIZE_MAX
を提供しないことが判明しました。このため、DragonFly BSD上でユーザー情報のルックアップを行う際に、適切なバッファサイズが確保されず、問題が発生する可能性がありました。
この変更の背景には、Go言語がサポートするオペレーティングシステムの範囲を広げ、それぞれのOSの特性に合わせた堅牢な挙動を保証するという目的があります。
前提知識の解説
os/user
パッケージ
Go言語の標準ライブラリの一部で、現在のユーザーや指定されたユーザーの情報を取得するための機能を提供します。例えば、ユーザー名、UID、GID、ホームディレクトリなどの情報を取得できます。
getpwnam_r
とgetpwuid_r
これらはPOSIX標準で定義されているCライブラリ関数です。
getpwnam_r(const char *name, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result)
: ユーザー名name
に対応するユーザー情報を取得し、pwd
構造体とbuf
バッファに格納します。getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, size_t buflen, struct passwd **result)
: ユーザーIDuid
に対応するユーザー情報を取得し、pwd
構造体とbuf
バッファに格納します。
これらの関数は、スレッドセーフな再入可能バージョンであり、結果を格納するためのメモリを呼び出し元が提供する必要があります。buf
とbuflen
はそのバッファとそのサイズを指定します。
sysconf
と_SC_GETPW_R_SIZE_MAX
sysconf(int name)
: システム設定情報を取得するためのPOSIX関数です。様々なシステム制限やオプションの値を問い合わせるために使用されます。_SC_GETPW_R_SIZE_MAX
:sysconf
関数に渡すことができる定数の一つで、getpwnam_r
やgetpwuid_r
関数がユーザー情報を格納するために必要とする可能性のある最大バッファサイズを返します。この値はシステムによって異なります。
DragonFly BSDとFreeBSD
どちらもUnix系オペレーティングシステムであり、BSD系OSの派生です。FreeBSDは広く使われていますが、DragonFly BSDはFreeBSD 4.8からフォークして開発された、より実験的な側面を持つOSです。両者ともに、一部のPOSIX標準のsysconf
値(特に_SC_GETPW_R_SIZE_MAX
)の実装が他のUnix系OS(例: Linux)と異なる場合があります。
技術的詳細
このコミットの技術的な核心は、getpwnam_r
やgetpwuid_r
関数に渡すバッファサイズの決定ロジックにあります。
Goのos/user
パッケージは、内部的にC言語の関数を呼び出すためにcgoを使用しています。lookup_unix.go
ファイルは、Unix系システムにおけるユーザー情報のルックアップを担当しています。
元のコードでは、bufSize
を決定する際に、まずruntime.GOOS == "freebsd"
という条件でFreeBSDを特別扱いしていました。FreeBSDでは_SC_GETPW_R_SIZE_MAX
が-1
を返すため、固定値の1024
バイトをバッファサイズとして使用していました。これは、Linuxが通常返すサイズと同じ値です。
var bufSize C.long
if runtime.GOOS == "freebsd" {
// FreeBSD doesn't have _SC_GETPW_R_SIZE_MAX
// and just returns -1. So just use the same
// size that Linux returns
bufSize = 1024
} else {
bufSize = C.sysconf(C._SC_GETPW_R_SIZE_MAX)
}
このコミットでは、この条件にruntime.GOOS == "dragonfly"
を追加しました。これにより、DragonFly BSDもFreeBSDと同様に_SC_GETPW_R_SIZE_MAX
が利用できないシステムとして扱われ、固定の1024
バイトのバッファサイズが割り当てられるようになります。
if runtime.GOOS == "dragonfly" || runtime.GOOS == "freebsd" {
// DragonFly and FreeBSD do not have _SC_GETPW_R_SIZE_MAX
// and just return -1. So just use the same
// size that Linux returns.
bufSize = 1024
} else {
bufSize = C.sysconf(C._SC_GETPW_R_SIZE_MAX)
}
この変更により、DragonFly BSD上でもgetpwnam_r
やgetpwuid_r
が適切なサイズのバッファを受け取ることが保証され、ユーザー情報のルックアップが正しく機能するようになります。固定値の1024
バイトは、ほとんどのシステムでユーザー情報を格納するのに十分なサイズであり、互換性の問題を引き起こす可能性が低いと判断されたため採用されています。
コアとなるコードの変更箇所
変更はsrc/pkg/os/user/lookup_unix.go
ファイルの以下の部分です。
--- a/src/pkg/os/user/lookup_unix.go
+++ b/src/pkg/os/user/lookup_unix.go
@@ -50,10 +50,10 @@ func lookupUnix(uid int, username string, lookupByName bool) (*User, error) {\
var result *C.struct_passwd
var bufSize C.long
- if runtime.GOOS == "freebsd" {
- // FreeBSD doesn't have _SC_GETPW_R_SIZE_MAX
- // and just returns -1. So just use the same
- // size that Linux returns
+ if runtime.GOOS == "dragonfly" || runtime.GOOS == "freebsd" {
+ // DragonFly and FreeBSD do not have _SC_GETPW_R_SIZE_MAX
+ // and just return -1. So just use the same
+ // size that Linux returns.
bufSize = 1024
} else {
bufSize = C.sysconf(C._SC_GETPW_R_SIZE_MAX)
コアとなるコードの解説
このコードスニペットは、Unix系システムでユーザー情報をルックアップする際のバッファサイズを決定するロジックを含んでいます。
var bufSize C.long
: C言語のlong
型に対応するbufSize
変数を宣言しています。これは、getpwnam_r
やgetpwuid_r
に渡すバッファのサイズを保持します。if runtime.GOOS == "dragonfly" || runtime.GOOS == "freebsd"
: ここが変更された条件分岐です。runtime.GOOS
は、Goプログラムが実行されているオペレーティングシステムを示す文字列です。- この条件は、現在のOSがDragonFly BSDまたはFreeBSDである場合に真となります。
bufSize = 1024
: 上記の条件が真の場合、bufSize
は固定値の1024
に設定されます。これは、これらのOSが_SC_GETPW_R_SIZE_MAX
を提供しないため、既知の適切なデフォルトサイズを使用するためです。コメントにもあるように、これはLinuxが通常返すサイズと同じです。else { bufSize = C.sysconf(C._SC_GETPW_R_SIZE_MAX) }
: 上記の条件が偽の場合(つまり、DragonFly BSDでもFreeBSDでもないUnix系OSの場合)、sysconf
関数を呼び出して_SC_GETPW_R_SIZE_MAX
の値を取得し、それをbufSize
に設定します。これにより、システムが推奨する最大バッファサイズが動的に取得されます。
このロジックにより、Goのos/user
パッケージは、異なるUnix系OSのsysconf
実装の差異を吸収し、ユーザー情報のルックアップを堅牢に行うことができます。
関連リンク
- Go言語の
os/user
パッケージのドキュメント: https://pkg.go.dev/os/user getpwnam_r
(man page): 多くのUnix系システムで利用可能。例: https://man7.org/linux/man-pages/man3/getpwnam_r.3.htmlsysconf
(man page): 多くのUnix系システムで利用可能。例: https://man7.org/linux/man-pages/man3/sysconf.3.html
参考にした情報源リンク
- Go言語のコミット履歴: https://github.com/golang/go/commits/master
- Go言語のコードレビューシステム (Gerrit): https://go.dev/cl/14469043 (コミットメッセージに記載されているCLリンク)
- POSIX
sysconf
に関する情報: https://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html - FreeBSDの
sysconf
に関する情報 (例): https://www.freebsd.org/cgi/man.cgi?query=sysconf&sektion=3&apropos=0&manpath=FreeBSD+10.0-RELEASE - DragonFly BSDのドキュメント (一般的な情報): https://www.dragonflybsd.org/
getpwnam_r
のバッファサイズに関する議論 (例: Stack Overflowなど): https://stackoverflow.com/questions/1000000/how-to-determine-the-buffer-size-for-getpwnam_r (一般的な情報源として)- Go言語の
runtime.GOOS
に関する情報: https://pkg.go.dev/runtime#GOOS