[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[FDclone-users:01010] Re: カレントディレクトリを失ったときの動作
- Subject: [FDclone-users:01010] Re: カレントディレクトリを失ったときの動作
- From: Takashi SHIRAI <shirai@unixusers.net>
- Date: Sun, 28 Apr 2013 21:32:54 +0900
しらいです。
In Message-Id <CA+=WMa+DEyX=_dsnYYwfBQB0fd3vWt_eM8cc5OktBwie8L9VGQ@mail.gmail.com>
Hironao Komatsu <hirkmt@gmail.com>さんwrites:
> 小松です。
> 1. 起点となるディレクトリ…例えば$HOMEから、ディレクトリ hoge/fuga を作成
> 2. fdでそのディレクトリへ移動
> 3. 別のシェルなどから rm -r hoge
> 4. fdで再描画(^L)などすると「ファイルがありません」となる
> 5. Backspaceで「カレントディレクトリを失ったので〜」で$HOMEに戻る
> 6. ファイル一覧は「ファイルがありません」のままとなる
このとおりの挙動になるのは環境依存だと思います。実際、私の
持っている環境では問題なく $HOME のファイル一覧が表示されま
す。
一般的な UNIX file system では、3. で fuga が削除された実
行中の fd は「.」に access 出来なくなるので、4. の時点で 5.
のエラーになります。
一般的な UNIX でも再現させるためには、4. を飛ばして 3. の
直後に 5. を行なうことで、ここに書かれたような挙動を示すこと
になります。
内部的には、「..」への移動に失敗したので元 directory に移
動しようとしたらそちらも失われていたのでエラーを生じさせてい
ます。
本来なら「.. がない」「CWD がない」という順番でエラー表示
すべきなんですが、UI 制御は処理の最後に生じるので、画面への
表示はこの逆順になっていると思います。
> 過去に遡ると、3.00kから発生しているようです。再度再描画すれば直ることで、
> さほど深刻ではないのですが……次回リリースにでも反映していただけたら、と。
3.00j までは、割と上位層の関数内で chdir() していたので、
chdir() に失敗した場合の制御を割と柔軟にこなせていましたが、
その分遅い phase での error 判定になっていました。
3.00k からは、もう少し深い階層の関数内で chdir() している
ので、上位関数では chdir() の失敗を画一的に処理するしか出来
ていませんでした。
chdir() の失敗だけなら何も効果は無いので無視すれば良いので
すが、実際は CWD の移動という副作用をもたらしているので、副
作用に対する処理が必要になります。
かと言って、chdir() に失敗した際に必ず副作用があるかと言う
とそうではなくて、普通は CWD に無事戻れて何事も無かったよう
に処理続行が可能なのです。
関数の返り値に、「失敗」と「CWD まで失った失敗」とを持たせ
ると話がややこしくなりそうなので、「CWD を失った」ことは大域
変数に持たせることにしました。
構造型言語としては美しくないので、ちゃんと実装するなら関数
の返り値は構造体にして様々な要素を埋め込ませるべきなんですが、
それに拘るとコードの流れが複雑怪奇化するのでやめました。
という訳で ad-hoc な実装ですが patch です。
---- Cut Here ----
diff -u ../old/FD-3.01/browse.c ./browse.c
--- ../old/FD-3.01/browse.c Fri Aug 3 00:00:00 2012
+++ ./browse.c Sun Apr 28 20:49:34 2013
@@ -41,6 +41,7 @@
extern int writefs;
#endif
extern char *curfilename;
+extern int lostcount;
extern char *origpath;
#ifndef _NOARCHIVE
extern char archivedir[];
@@ -1788,6 +1789,7 @@
curfilename = filelist[filepos].name;
setlastfile(NULL);
+ lostcount = 0;
no = dointernal(getfuncno(ch),
filelist[filepos].name, ICM_BINDKEY, &funcstat);
@@ -1804,6 +1806,7 @@
if (sorton) haste = 0;
#endif
if (no < FNC_NONE || no >= FNC_EFFECT) break;
+ if (no == FNC_CANCEL && lostcount > 0) break;
if (no == FNC_CANCEL || no == FNC_HELPSPOT) helpbar();
if (no < FNC_UPDATE) {
funcstat = 0;
diff -u ../old/FD-3.01/libc.c ./libc.c
--- ../old/FD-3.01/libc.c Fri Aug 3 00:00:00 2012
+++ ./libc.c Sun Apr 28 20:45:30 2013
@@ -51,6 +51,7 @@
#ifdef DEP_PSEUDOPATH
char *unixpath = NULL;
#endif
+int lostcount = 0;
static char *lastpath = NULL;
static int wasttyflags = 0;
@@ -129,7 +130,10 @@
}
# endif /* CYGWIN */
duperrno = errno;
- if (Xchdir(cwd) < 0) lostcwd(cwd);
+ if (Xchdir(cwd) < 0) {
+ lostcwd(cwd);
+ lostcount++;
+ }
errno = duperrno;
return(-1);
}
@@ -162,7 +166,10 @@
if (_chdir2(fullpath) < 0) {
duperrno = errno;
- if (_chdir2(cwd) < 0) lostcwd(fullpath);
+ if (_chdir2(cwd) < 0) {
+ lostcwd(fullpath);
+ lostcount++;
+ }
else Xstrcpy(fullpath, cwd);
errno = duperrno;
return(-1);
---- Cut Here ----
しらい たかし