> そのファイルのパーミッションを確認してみたところ
> 「----------」となっており、読み書き実行すべて不可となっていました。
openは第三引数にパーミッションを指定できます。0666を設定すると期待した動作になるのではないでしょうか。(umaskが022なら、作成されるファイルのパーミッションは644になります)
その他の点について。
1.fd1, fd2をopenしてからエラーチェックしていますが、fd1のオープンに失敗してfd2のオープンが成功すると、O_CREATがあるために空ファイルができてしまう。
==> 面倒でもエラーチェックは2つに分けるべきでしょう。
2.fd2のopen時にO_TRUNCがないと、ファイルがあった場合の動作がおかしいことになる。
==> fd1のファイルサイズ < fd2のファイルサイズのファイルが存在する状況を作って、やってみるとわかると思います。read側の内容がabc、write側の内容がhijklmnなら、実行後のwrite側の内容はabcklmnになってしまいますよね? 期待される動作はabcのはずです。
3.read, writeのエラーチェックでEINTR(割り込み)に対する考慮がされていない。
==> EINTRの場合はエラーとはみなさずリトライする処理が必要です。
4.read成功時の読み取りバイト数がSIZEであるという仮定が置かれている。
==> 実際にはそれよりも少ないこともあり得ます。
5.nun00nunさんのコードでは、write成功時の書き込みバイト数がSIZEであるという仮定が置かれている。
==> 実際にはそれよりも少ないこともあり得ます。その場合は残りの部分の書き出し処理が必要です。
以下、私の方で修正したコードです。
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#define SIZE 8192
int
main (int argc, char *argv[])
{
int fd1, fd2;
char buf[SIZE], *bufp;
int rsize, wsize;
if (argc != 3)
{
char err_message[] = "ファイル名を指定して下さい。\n";
write (2, err_message, strlen (err_message));
return 1;
}
argv[0] = "mycopy";
fd1 = open (argv[1], O_RDONLY);
if (fd1 < 0)
{
char err_message[] = "ファイルをオープンできません。";
write (2, err_message, strlen (err_message));
write (2, strerror (errno), strlen (strerror (errno)));
write (2, "\n", 1);
return 1;
}
fd2 = open (argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd2 < 0)
{
char err_message[] = "ファイルをオープンできません。";
write (2, err_message, strlen (err_message));
write (2, strerror (errno), strlen (strerror (errno)));
write (2, "\n", 1);
return 1;
}
while (1)
{
bufp = buf;
rsize = read (fd1, bufp, SIZE);
if (rsize == -1)
{
if (errno == EINTR)
{
continue;
}
char err_message[] = "読み込みエラーが発生しました。";
write (2, err_message, strlen (err_message));
write (2, strerror (errno), strlen (strerror (errno)));
write (2, "\n", 1);
return 1;
}
if (rsize == 0)
{
break;
}
while (1)
{
wsize = write (fd2, bufp, rsize);
if (wsize == -1)
{
if (errno == EINTR)
{
continue;
}
char err_message[] = "書き込みエラーが発生しました。";
write (2, err_message, strlen (err_message));
write (2, strerror (errno), strlen (strerror (errno)));
write (2, "\n", 1);
return 1;
}
bufp += wsize;
rsize -= wsize;
if (rsize == 0)
{
break;
}
}
}
close (fd1);
close (fd2);
return 0;
}
お礼
お礼が遅くなってしまい失礼しました。 訂正したコードまで付けてくださるとは(泣) 勉強させていただきます。 ありがとうございました!