[Gauche-devel-jp] Re: directory 作成時の mode

Back to archive index

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




Gauche-devel-jp メーリングリストの案内
Back to archive index