• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:C言語で自作したcpコマンドが上手く動作しません)

C言語で自作したcpコマンドが上手く動作しない

このQ&Aのポイント
  • C言語で自作したcpコマンドが上手く動作しない問題について解説します。
  • ファイルのパーミッションが「----------」となっているため、読み書き実行ができない状態です。
  • ソースコードの一部を修正することで、ファイルのコピーが正常に行われるようになります。

質問者が選んだベストアンサー

  • ベストアンサー
  • entree
  • ベストアンサー率55% (405/735)
回答No.4

> そのファイルのパーミッションを確認してみたところ > 「----------」となっており、読み書き実行すべて不可となっていました。 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; }

nun00nun
質問者

お礼

お礼が遅くなってしまい失礼しました。 訂正したコードまで付けてくださるとは(泣) 勉強させていただきます。 ありがとうございました!

すると、全ての回答が全文表示されます。

その他の回答 (3)

  • trapezium
  • ベストアンサー率62% (276/442)
回答No.3

細いことだけど。 > fd1 = open(argv[1], O_RDONLY); > fd2 = open(argv[2], O_WRONLY | O_CREAT); > if (fd1 < 0 || fd2 < 0) { fd1 が失敗しても、fd2 が成功した段階で errno がクリアされるので、その下のエラーメッセージが正しくないときがある。 > write(2, strerror(errno), strlen(strerror(errno))); その都度処理するか、errno を保存しておく。 まあ、err(1, なんたらでいいじゃないかと思わないこともないが、stdio 使わないことに意味があるんだろうと write(2, に関しては…

nun00nun
質問者

お礼

お礼が遅くなってしまい失礼しました。 回答ありがとうございます。勉強になりました!

すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

ついでにいうと, read の返り値を捨てちゃうのもまずかったような.

nun00nun
質問者

お礼

おっしゃるとおりですね。プログラムを修正させていただきました。 回答ありがとうございました!

すると、全ての回答が全文表示されます。
  • f272
  • ベストアンサー率46% (8419/18026)
回答No.1

fd2 = open(argv[2], O_WRONLY | O_CREAT); の第3引数にパーミッションを指定してみたらどうかな? それよりも whileの中で if (read(fd1, buf, SIZE) == 0) { でfd1から読んで,また } else if (read(fd1, buf, SIZE) > 0) { でfd1から読むのは意図と違う気がする。

nun00nun
質問者

お礼

回答ありがとうございます。 ご指摘の通り、プログラム自体もよろしくありませんでした(^^:) 参考にさせていただきます!

すると、全ての回答が全文表示されます。
このQ&Aのポイント
  • MFC-J739DNのPresto! PageManagerのインストール方法を教えてください。
  • Windows11でMFC-J739DNをUSBケーブルで接続し、Presto! PageManagerをインストールする方法について教えてください。
  • J:COM回線を利用しているMFC-J739DNのためのPresto! PageManagerのインストール手順を教えてください。
回答を見る

専門家に質問してみよう