UNIX システムでは、アプリケーションがファイルを読み込む際、ディスク上にあるファイルの内容をきっちり正確に読み取り、書き込む際もそれと同様に動作します。 DOS/Windows の世界ではこの状況は異なり、ファイルはバイナリ又はテキストという二つのモードのどちらかで読み込まれます。 バイナリモードでは、システムは UNIX と同様にきっちり正確に動作します。 しかしテキストモードにおける書き込みでは、NL(\n、^J)は CR (\r, ^M) NL の連続へと変換されます。
アプリケーションから見たバイト数が実際のものとは異なってくるため、seek/fseek を呼び出したときには大混乱が発生することでしょう。
以下のプログラミングの章に記述されているように、このモードは明示的に指定することが出来ます。
理想的な DOS/Windows の世界では、行をレコードとみなして動作するプログラム
(bash、make、
sed ... など)はファイルをテキストモードでオープンします
(そして標準入出力を使用するときはモードを変更します)。それ以外の全てのプログラム
(cat、cmp、tr
... など)はバイナリモードを使用します。Cygwin の習慣では、
明示的にオブジェクトファイルを扱うプログラムではバイナリモードを指定します(CR 問題を診断する際に有用である
od コマンドがこれに該当します)。
その他の多くのプログラム(cat、cmp、
trなど)はデフォルトのモードを使用します。
Cygwin システムには、明示的にモードを指定しなかった場合、どのようにファイルをオープンするかを決定するための柔軟性が備わっています。 このルールは発展中であり、本章ではデザインゴールを示します。
ファイルがマウントされたファイルシステム中に存在するのであれば(パス名が mount
によって表示されるディレクトリから始まっていれば)、デフォルトはマウントフラグによって指定されます。
もしファイルがシンボリックリンクであるなら、ターゲットファイルシステムのモードが適用されます。
ファイルがマウントされていないファイルシステム中に存在するのであれば(パスがドライブ文字を含んでいるような場合)、デフォルトはバイナリモードとなります。
CYGWIN 環境変数が nobinmode を含んでいる場合を除き、パイプと非ファイルデバイスはバイナリモードでオープンされます。
1998 年 12 月 の b20.1 では、ファイルは以下の状況下ではバイナリモードでオープンされます。
open 呼び出しでバイナリモードが指定されていた場合
CYGWIN が binmode
を含んでいる場合
バイナリマウントされたパーティション中のファイル
ディスクファイル以外のファイル
Cygwin プログラムがシェルから起動された場合、パイプされるかリダイレクトされる場合を除き、
標準入力、標準出力、標準エラー出力は
CYGWIN 環境変数が tty
を含んでいればバイナリモードとなり、そうでなければテキストモードとなります。
リダイレクト時、Cygwin シェルはルール(a-c)を使用します。
これらのシェルが使用する CYGWIN
の値はシェルが起動した時点での値であり、プログラムが実行された時点の値ではありません。
非 Cygwin シェルは常にパイプとリダイレクトをバイナリモードで行います。
非 Cygwin シェルでは、テキストマウントされたパーティションに存在する
filename に対しては、コマンド
cat filename | program と
program < filename は、異なるものとなります。
様々なルールを説明するために、標準出力にのみ出力出来る tr
プログラムを使った、ファイルから CR を削除するスクリプトを準備します。このスクリプト
#!/bin/sh # 引数として与えられたファイルから \r を取り除く tr -d '\r' < "$1" > "$1".nocr
はテキストマウントされたシステムでは正しく動作しません。 なぜなら、書込み時に \r が再度付与されるからです。しかし、以下のスクリプト
#!/bin/sh # 引数として与えられたファイルから \r を取り除く tr -d '\r' | gzip | gunzip > "$1".nocr
そしてこのバッチファイル
REM 引数として与えられたファイルから \r を取り除く @echo off tr -d \r < %1 > %1.nocr
は正しく動作します。最初の事例では(パイプはバイナリモードであると仮定します)、gunzip
がバイナリモードで出力することを期待しており、シェルによって使用されるモードを上書きすることが出来ます。
次の事例では、DOS シェルがバイナリモードでリダイレクトすることを期待しています。
最大限の移植性を考慮して書かれた UNIX プログラムはテキストとバイナリのファイルの違いを知っており、Cygwin の元でも適切に動作します。 これらのプログラムにおいては、デフォルトがテキストモードであるのは有用な選択です。公式な Cygwin の配布物中に含まれるプログラムはデフォルトのモードで正しく動作します。
Windows プログラムは通常 CRLF フォーマットを使用するので、テキストモードは Cygwin と Windows プログラムの間でのファイルの混在をより簡単なものにします。 あいにく、テキストモードにはまだ幾つかの問題があります。 まず、Cygwin に含まれる幾つかのユーティリティは、必要なときにもまだバイナリモードを指定しません。 次に、作成するテキストファイルに CR を持ち込むと、それらを UNIX システムに持ち帰った時点で問題が発生することになるでしょう。
UNIX マシンのリモートファイルシステムをマウントするなら、又はファイルを UNIX マシンへ持ち帰るか、持ってくるのであれば、ファイルへのアクセスをバイナリモードで行いたいと考えるでしょう。 テキストファイルは UNIX の NL フォーマットとして通常通り作成され、Cygwin プログラムは UNIX 上で理解可能なフォーマットで全てのファイルを保存することを期待するでしょう。 Makefile とシェルスクリプトからは必ず CR を取り除き、ファイルを編集する場合は NL で終了する行を正しく編集 / 保存することが可能な DOS/Windows のエディタだけを使わなければなりません。
モードはディスク単位で決定することが出来ます(例えば、ローカルディスクはテキストモードでマウントし、ネットワークディスクはバイナリモードでマウントすることが出来ます)。
ディスクのパーティションについても同様です。
例えば、c: をテキストモードで、c:\home をバイナリモードでマウント出来ます。
open() 関数呼び出しでは、フラグ O_BINARY
によってバイナリモードを指定し、O_TEXT によってテキストモードを指定できます。
これらのシンボルは fcntl.h 中で定義されています。
fopen() 関数呼出しにおいては、モード文字列に b
を追加することによってバイナリモードを指定できます。テキストモードを指定する直接的な方法はありません。
ファイルのモードは setmode(fd,mode) を呼び出すことで変更出来ます。
ここで fd はファイル記述子(整数)であり、mode は
O_BINARY 又は O_TEXT です。
この関数は呼び出しに応じて O_BINARY 又は O_TEXT を返し、エラー時には
EOF を返します。