Shiro Kawai
shiro****@lava*****
2004年 9月 1日 (水) 19:10:24 JST
From: Osamu NAKAMURA <naka****@hasak*****> Subject: [Gauche-devel-jp] directory 作成時の mode Date: Wed, 01 Sep 2004 18:14:38 +0900 > 1.sys-mkdir 、make-directory* ともに > mode は umask でマスクされると思いますが、 > 生成される directory の mode を直接(umask と関係なく) > 指定できる関数は用意されてませんか? > > (直接指定できるほうが使いやすそうな気がするけれど、 > 特にそうしてない理由があるなら知りたい、と。) > > sys-mkdir は、man 2 mkdir を見て、これに忠実に > 作ってあるんだなぁと思いましたが、make-directory* > も同様に動作するようなので、わけありなのかなぁ、と。 なるほど。いくつかレイヤがあるので順に説明します。 まず、Gaucheは基本的にUnixにべったりです。Unixのシステム プログラミングと同等のことがSchemeでできる、というのが Gauche作成の動機のひとつでした。そのため、Unixの セマンティクスに馴染んだ人が自然に使えるように、sys-* 系統は いくつかの例外を除いては、名前も動作もunixのコールに 合わせています。「余計な御世話」はしない方がわかりやすい、 というポリシーです。 で、make-directory* の方はシェルスクリプトでmkdir -p を 呼ぶ感覚で使える上位ライブラリ、という意図で作りました。 ただ、確かに mkdir -m XXX でモードを指定する場合はumaskは 反映されないので、そちらに合わせるという考え方もあります。 但し、後述するようにそれだとスレッド絡みで困るのです。 > (ついでに、make-directory* 等のアスタリスクはどういう > 関数の名前につけてあるものですか?) '*' は let* からの連想で、動作が再帰的にネストするような イメージがある場合に私は使います。これも参考にどうぞ↓ http://www.shiro.dreamhost.com/scheme/wiliki/wiliki.cgi?Scheme%3a!%a4%c8%3f > 2.そもそも、mode としてどういう数値を与えたらいいのか > 理解できてません。(情けなし) > shell の環境設定で umask コマンドに与える数値とは > 別物ですよね? (16877 で、rdxr_xr_x になりました。) > ”POSIXスタイルのパーミッションビットマスク”という > ものを与えるのでしょうか? はい。これはunixシステムプログラミングのドキュメントを 見てもらうしかないのですが、 stat(2), chmod(2), open(2) のmanpageで必要十分な情報が得られると思います。基本的にmodeに 渡す数値はそのままmkdir(2)に渡るので、システムのmkdir(2)の動作 そのものです。 > 3.umask を scope 毎に簡単に切替えられると嬉しいかも、 > と思っています。 > > gosh の環境内に gosh が参照する umask を収めた変数 > があるとしたら、それを local に変更するとその scope でだけ > local な umask が適用される、という使い方はできないでしょうか? umaskはGaucheの機能ではなく、OSが提供する機能で、 プロセスが持つ状態です。 従って、複数のスレッドが走っている場合に: > (define-syntax let-umask > (syntax-rules () > ((_ (umask) proc1 ...) > (let ((oldumask (sys-umask umask))) > proc1 > ... > (sys-umask oldumask))) > )) このようなマクロでumaskを変えた場合、そのumaskの変更は proc1... だけでなく、同時に走っているスレッド全てに 予測不可能な影響を与えてしまいます。 もちろん、使う側がその危険を承知で使うぶんには良いのですが、 そういう危険のある操作については、それにつりあうだけの 便利さが見えない限り、標準ライブラリへの取り込みの優先度は 低くなります。 なお、このように「あるコードの『実行期間中』はある状態になる」 というのは動的スコープといいます。Schemeではletなんとかは 静的スコープに使い、動的スコープを作るものはwithなんとか、 とすることが多いようです。エラーや継続によるフローの変更も 考慮に入れると、with-umaskはこんな感じになるでしょうか。 (define-syntax with-umask (syntax-rules () ((with-umask (mask) body ...) (let ((oldmask (sys-umask mask))) (dynamic-wind (lambda () (sys-umask mask)) (lambda () body ...) (lambda () (sys-umask oldmask))))) )) 実はこのコードは完全ではありません。最初のsys-umaskの呼び出し 直後からdynamic-windの開始までの間にシグナルが入って制御が 他に移ると、umaskの設定がおかしくなります。 実は、この手の処理をシグナルセーフに作るのは結構面倒です。 シグナルの使い方がわかっているのはアプリケーションの方なので、 アプリ任せにしておく方が使いやすい、ということはあります。 でも、実用性重視がGaucheの方針なので、まっとうなwith-umask があった方がよいという要望があれば標準ライブラリにバンドル するかもしれません。カレントディレクトリを一時的に変える with-cwdみたいのは欲しいと思ったこともありますし。 > ついでのついでなんですが、gosh のインタープリタで、行編集 > や履歴を使うようにはできないでしょうか。 > 通常は、emacs の shell mode で使ってますが、ふと、そこにある > terminal で立ち上げてしまって、悔しい思いをすることが時々。。 一応、goshはスクリプト実行に必要無いものは極力内部には抱えない、 という方針です。インタラクティブな実行時だけライブラリを読めば行編集が 使える、というふうに作れれば、つけるかもしれません。 --shiro