Logo address

u9fs

2005/05/10 改訂
2008/02/18 追加
2016/02/17 補足
2017/06/13 改訂

u9fs とは

Plan9 端末から UNIX のファイルシステムを参照するには u9fs が一番使いやすい。rlogin と異なり、u9fs は UNIX のファイルシステムを Plan9 端末にマウントしてくれる。また Plan9 の ftpfs と異なり、ファイルに対してシーク(seek)命令が働くので tail などのコマンドでファイルの全てがコピーされることはない。

以下に簡単な使用例を挙げる。
nx を UNIX システムとすると、

term% 9fs nx
post ...		# message
term%
この結果 nx のファイルシステムは /n/nx の下に見える。
term% ls /n/nx
term% ls /n/nx
...
/n/nx/bin
/n/nx/dev
/n/nx/etc
/n/nx/home
...
/n/nx/tmp
/n/nx/usr
term%
従ってリモートの UNIX システムが端末に組み込まれたのと同等の効果が得られる。
すなわち、cp や grep などのツールが使え、マウスベースのエディタで編集できる。

u9fs のインストール

方針

u9fs は認証方式として次の3種類をサポートしている。

以下では認証方式を説明する。

また Linux や FreeBSD では (inetd ではなく) xinetd の下で動かす。Mac は全く方法が異なるので、独立して解説する。

u9fs のインストール

u9fs は /sys/src/cmd/unix/u9fs に置かれている。
これを UNIX 側にコピーして(ftpfs を使うがよい)、
unix$ make
unix$ su
root# cp u9fs /usr/local/sbin
root# touch /var/log/u9fs.log

Mac にインストールするなら筆者のをダウンロードするのが良いだろう。
理由は

である。

筆者のは
http:/netlib/u9fs/
に置かれている。

認証キーの設定

/etc/u9fs.key に利用者のキーを設定する。(この場所は u9fs の -A オプションで変更できる。

xxxxxxxx
arisawa
dddddd
ここに xxxxxxxx はパスワードで dddddddom の名称である。dom の名称は適当に付けてよいが、パスワードが異なる他のシステムの名称と同じであってはならない。筆者の場合には u9fs をインストールしている Mac は家庭に設置されており、記憶力に乏しい筆者は mac にしている。

/etc/service

さらに /etc/services

u9fs    564/tcp u9fs
を追加する。(最近の xinetd は /etc/xinetd.d/u9fs の中でも可能になったようです)

xinetd による設定

2017/06/05 更新

まず

ps -axg|grep inetd
を実行し、 xinetd が使われていることを確認する。

次に /etc/xinetd.d/ に以下の内容のファイル u9fs を追加する

service u9fs
{
        disable         = no
        socket_type     = stream
        protocol        = tcp
        wait            = no
        user            = root
        server          = /usr/local/sbin/u9fs
        server_args     = -a p9any -l /var/log/u9fs.log
        groups          = yes
        flags           = REUSE
}

xinetd の設定を変更した場合には root 権限で

-bash$ sudo /etc/init.d/xinetd restart
を実行しておく。

OSX Leopard の plist による設定

2008/02/18

OSX Leopard になって xinetd が無くなって launchd による plist に一本化された。設定例は次の通りである。

/Library/LaunchDaemons/com.bell-labs.plan9.u9fs.plist の内容

plist のロード

/Library/LaunchDaemons/com.bell-labs.plan9.u9fs.plist の設定を変更した後、それを Launchd に反映させるには

-bash$ sudo launchctl unload /Library/LaunchDaemons/
-bash$ sudo launchctl load /Library/LaunchDaemons/
-bash$
を実行すればよい。

設定上の注意

/etc/services で既に 9pfs が定義されているので、"SockServiceName" の値を 9pfs にしたい所であるが、認識しない。次のエラーが出る。

sh-3.2# launchctl load /Library/LaunchDaemons/com.bell-labs.plan9.u9fs.plist
getaddrinfo(): nodename nor servname provided, or not known

僕はこれまで plist を設定した事がなかった。このために今回は大変手間取った。
C プログラミングの世界に住んでいる者にとって、plist における、実行されるプログラムとその引数の指定の方法は "???" になりやすい。つまり "ProgramArguments" を次のように書きやすいのである。

0	/usr/local/sbin/u9fs
1	u9fs
2	-l
3	/var/log/u9fs.log
4	-a
5	p9any
なぜ "/usr/local/sbin/u9fs" を "Program" に指定しないで "ProgramArguments" なんだ! と違和感を覚えつつ上記のように設定して、その為に 2 日程無駄な時間を費やした。僕は接続を検証するためにシンプルなプログラム "connect" を持っているが、それを使って 564 ポートにアクセスして、ようやくこの誤りに気付いた次第である。Plan 9 の "con" でも、あるいは OSX から
telnet loaclhost 564
でも同様に誤りに気付いたはずである。

initgroups (xinetd の groups) の値は YES でなくてはならない。Leopard でのデフォールトは YES であるが Tiger では NO なので、ここに上げた plist はそのまま Tiger では使えない。

参考になる文献

マニュアルによると plist の置き場所は次の 5 カ所である。

~/Library/LaunchAgents         Per-user agents provided by the user.
/Library/LaunchAgents          Per-user agents provided by the administrator.
/Library/LaunchDaemons         System wide daemons provided by the administrator.
/System/Library/LaunchAgents   Mac OS X Per-user agents.
/System/Library/LaunchDaemons  Mac OS X System wide daemons.
最後の 2 つには多数の plist が置かれており、設定サンプルとして役に立つ。

マニュアルは次の 3 つが基本的である。

またネット上には次の優れた解説がある。

Launchd のデバッグ

僕は NeXT 時代にから NetInfo を使っているが、Launchd の plist にせよ、このような複雑なものは苦手だ。
Plan9 であれば netstat -n によってサービスが行われているポートが直ちに分かる。これに相当する UNIX のコマンドは netstat -na である1。次に示すのはその出力例で

-bash$ netstat -na
Active Internet connections (including servers)
Proto Recv-Q Send-Q  Local Address          Foreign Address        (state)
tcp4       0      0  *.564                  *.*                    LISTEN
tcp6       0      0  *.564                  *.*                    LISTEN
tcp4       0      0  127.0.0.1.631          *.*                    LISTEN
tcp6       0      0  ::1.631                *.*                    LISTEN
564ポート(9pfs) が開いている事が分かる。ポート名を名前で表示させたい場合には
netstat -a
とすればよい。この情報は「ネットワークユーティリティ」の「Netstat」からも得られる。

ラベル(例えば com.bell-labs.plan9.u9fs)を指定して、launchd が実際に実行する plist の内容がダンプされるとありがたいのだが、launchctl にはその機能が見当たらない。

launchd のアクセスログは /var/log/system.log に記録される。この内容はデバッグに役に立つ。

注1: Linux では現在は
netstat -an64
となっている。このオプションで 6 と 4 は各々 IPv6 と IPv4 を意味する。(2010/04/02)

ソースコード

コンパイル

なお u9fs のソースコードをコンパイルすると 2 つのファイルで warning が出る1。この warning は無視しても構わないが、いずれも include の追加で解決する。(以下の /* OSX,Linux */ の行)
oldfcall.c:

#include <plan9.h>
#include <stdlib.h> /* OSX,Linux */
#include <fcall.h>
#include <oldfcall.h>

safecpy.c:

#include <stdio.h>
#include <string.h> /* OSX,Linux */

注1: 現在はもっと多くの警告がでるが、コンパイルは可能である。(2017/06/06)

さらに次のエラーメッセージは(OSX の場合には) XCode がインストールされていない場合に発生する。

/usr/libexec/gcc/i686-apple-darwin8/4.0.1/ld: /usr/lib/gcc/i686-apple-darwin8/4.0.1/../../../libSystem.dylib unknown flags (type) of section 6 (__TEXT,__literal16) in load command 0
collect2: ld returned 1 exit status
make: *** [u9fs] Error 1

u9fs の仕様の不十分な点

不思議な事に /etc/u9fs.key は一人分のキーしかサポートしていない1。この点は改善されるべきで、好ましい仕様はキーはユーザの責任で管理することとし
$HOME/keys/u9fs
にでも置けるようにしたらよい。なお unix はあいも変わらずプログラムの初期化ファイルを $HOME/.* に置いており、いっこうに改善されない。


注1: この問題は u9fs のプログラム構造と関係しているらしい。fork が使われていない。(thread さえも使われていない) それでいて複数のクライアントからの同時接続が可能である。しかし結局はせいぜい1人分である。大規模なクライアントをサポートするには認証システムの他に、プログラム構造にメスを入れる必要がある。しかし、難しいという程ではないだろう。若い子の手ごろな課題である。それに、unix の分散ファイルシステムを置き換えるポテンシャルを持っているのでやり甲斐があるだろう。(2016/02/17)

不可思議な unix の kill の仕様

今回気がついた事であるがユーザモードで
-bash$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
 5) SIGTRAP      6) SIGABRT      7) SIGEMT       8) SIGFPE
 9) SIGKILL     10) SIGBUS      11) SIGSEGV     12) SIGSYS
13) SIGPIPE     14) SIGALRM     15) SIGTERM     16) SIGURG
17) SIGSTOP     18) SIGTSTP     19) SIGCONT     20) SIGCHLD
21) SIGTTIN     22) SIGTTOU     23) SIGIO       24) SIGXCPU
25) SIGXFSZ     26) SIGVTALRM   27) SIGPROF     28) SIGWINCH
29) SIGINFO     30) SIGUSR1     31) SIGUSR2
-bash$
スーパーバイザモードで
root# kill -l
HUP INT QUIT ILL TRAP ABRT EMT FPE KILL BUS SEGV SYS PIPE ALRM TERM URG STOP
TSTP CONT CHLD TTIN TTOU IO XCPU XFSZ VTALRM PROF WINCH INFO USR1 USR2
root#
そしてどちらのモードでも
-bash$ /bin/kill -l
hup int quit ill trap abrt emt fpe kill bus segv sys pipe alrm term urg
stop tstp cont chld ttin ttou io xcpu xfsz vtalrm prof winch info usr1 usr2
-bash$
異なるプログラムが動いているのではないことは which コマンドで確認できる。
筆者はこのように動作するプログラムを作る事はできるけれども、このような仕様を考えるプログラマーの気持ちが分からない。

ssh からの u9fs の起動

2005/05/10
2016/02/17 改定

UNIX ホストが ssh によるログインを許していれば1もっとエレガントな方法で Plan 9 から UNIX ホストのファイルをマウントできる。この方法の利点は、UNIX ホストの管理者権限を必要とせず、完全にユーザレベルの設定でやって行ける事、さらに UNIX 側の設定が要らない事にある。

注1: 最近の Linux では SSH-2.0 になっている。しかし Plan9 の方は(正式配布版では) 2.0 には対応していないので接続できなかったが、現在では ssh2 が 9atom の配布の中に含まれている。(2016/02/17)

以下に筆者の Mac OSX を例に解説する。なお以下において mac は筆者の Mac のホスト名はである。

1. Plan 9 端末から ssh でログインできる事を確認する。

ssh -r mac
を実行すると
term% ssh -r mac
Last login: Tue May 10 13:06:26 2005 from 192.168.1.2
Welcome to Darwin!
-bash$
となれば OK である。
最初の1回目は暗号キーの確認を求められる。

2. u9fs へのパスが通っている事を確認する

Plan 9 端末から

ssh mac echo '$PATH'
を実行してみる。
u9fs へのパスが通っていない時には
$HOME/.bashrc
にパスを追加する。

3. u9fs の実行

Plan 9 端末から

term% mntgen
term% srvssh mac
post...
そして(この window はそのままにして)他のウィンドウから
term% mount /srv/mac /n/mac
term% ls /n/mac
/n/temp/.DS_Store
/n/temp/.Trashes
...

srvssh はポート564(9fs ポート)を使わずに、ssh ポートを使った u9fs だと考えて良い。
この利点は、

ことにある。先に「u9fs の仕様の不十分な点」で指摘した部分が u9fs に手を加えなくてもやっていけるのである。(しかし将来 u9fs が本格的に利用されるなら、本格的なサーバーとして実装した方が良いだろう)

ssh ポートの入出力は、古い(RS232C)時代の通信と相手が人間であると想定しており、そのために Byte 通過性が担保しずらい。通信路を Byte 透過にする方法は相手(unix)に依存する。旨く働くには多少の試行錯誤が要求されるかもしれない。その場合、やるべきことは

/rc/bin/srvssh
の中にコメントとして書かれている。

さて、「この window はそのままにして」と書いたが、srvssh の仕組みを考えると重要である。この window の中での I/O は srvssh でも使われており、干渉するリスクがある。

文字コード

u9fs は utf-8 に対応している。従って Mac OS X の日本語のフォルダはちゃんと表示される。もっとも OSX の日本語ファイル名/フォルダ名の扱いは少し変なのだ。OSX はファイル名やフォルダ名に UNICODE を使用している。不思議にも OSX は「ダ」や「パ」あるいは「だ」や「ぱ」などのように濁点や半濁点が名前に含まれる場合に、本来1文字として扱うべき文字を2文字として扱っているのである。まるで半角片仮名時代への逆行である!

さて、このような嫌らしい Mac のファイル名が Plan9 に流れ込むのは嫌なので、パッチを当てることにしていた。今回、文字コードの対応を日本語文字だけではなく、全てのラテン系の文字、およびギリシャ文字に拡張した(2017/06/23)。

注釈: この点に関しては、他のページに詳しい。→ http:/p9p/index.html

終わりに

u9fs に相当するプログラムが Windows にもあれば便利なのであるが、残念ながら存在しない。