web-dev-qa-db-ja.com

ファイル記述子が有効かどうかのテスト(入力用)

ファイル記述子が有効かどうかのテスト 」という質問では、ファイル記述子が開かれているかどうかをテストするためのテストが求められます。

すべての答えは、ファイル記述子がoutputに対して開かれているかどうかのテストに焦点を当てていますが、ファイル記述子がinput

これは、別の質問への回答を求めるコメントスレッドで出てきました。

if [ -n "$1" ]; then
    # read input from file "$1" (we're assuming it exists)
Elif [ ! -t 0 ]; then
    # read input from standard input (from pipe or redirection)
else
    # no input given (we don't want to read from the terminal)
fi

[ ! -t 0 ]の問題は、ファイル記述子が開いているおよび端末に関連付けられている場合、-tテストが真であることです。テストがfalseの場合、記述子はどちらか閉じているか、ターミナルに関連付けられていません(つまり、パイプまたはリダイレクトから読み取っています)。したがって、[ ! -t 0 ]を使用したテストは、ファイル記述子が有効であることを保証するものではありません。

それが有効であるか(readが文句を言わないように)、または閉じているかを判断する方法は?

5
Kusalananda

チェックはCでread(fd, 0, 0)または_(fcntl(fd, F_GETFL) & O_WRONLY) == 0_を使用して簡単に実行できます。標準のユーティリティをだましてそれを実行することはできなかったので、考えられる回避策をいくつか紹介します。

Linuxでは、_/proc/PID/fdinfo/FD_を使用できます。

_if [ ! -d "/proc/$$/fd/$fd" ] && grep -sq '^flags.*[02]$' "/proc/$$/fdinfo/$fd"; then
    echo "$fd" is valid for input
fi
_

OpenBSDおよびNetBSDでは、_/dev/fd/FD_およびddをゼロカウントで使用できます。

_if dd if=/dev/fd/3 count=0 3<&"$fd" 2>/dev/null; then
    echo "$fd" is valid for input
fi
_

FreeBSDでは、最初の3つのfdsだけがデフォルトで_/dev/fd_で提供されます。 _/dev/fd_にfdescfs(5)をマウントするか、または:

_if (dd if=/dev/fd/0 count=0 <&"$fd") 2>/dev/null; then
    echo "$fd" is valid for input
fi
_

ノート:

一部のシステムでは、bashが_/dev/fd/FD_のエミュレーションを行うため、_cat </dev/fd/7_は_cat /dev/fd/7_とは完全に異なる動作をする場合があります。同じ警告がgawkにも適用されます。

長さが0のread(2)(またはフラグに_O_TRUNC_がないopen(2))はしないアクセス時間またはその他のタイムスタンプを更新します。

Linuxでは、たとえread(2)が開かれていても、ディレクトリで常に失敗しますwithout _O_DIRECTORY_フラグ。他のUnixシステムでは、ディレクトリは別のファイルと同じように読み取られる場合があります。

standard は、_dd count=0_がブロックをコピーしないか、ファイルからallブロックをコピーするかどうかを指定しません。前者はGNU ddの動作ですgdd)および* BSDのddの。

5
mosvy