0

標準の UNIX アーカイブ ar から抽出し、格納するファイルを作成する C プログラムをコーディングしています。

これは、vim で開いた場合の ar の例です。

!<arch>
yo              1382105439  501   20    100644  10        `
test1 lol
yo2             1382105444  501   20    100644  10        `
test2 lol

...ここで、"test1 lol" と "test2 lol" は各ファイルの内容、"yo" と "yo2" は 2 つの異なるファイル名、残りは標準の ar.h (詳しくはこちらをご覧ください: http://www.lehman.cuny.edu/cgi-bin/man-cgi?ar.h+3 )

とにかく、私はまだ関数を書いている途中ですが、これまでのところ私が持っているものは次のとおりです。

static void extract_files (int argc, char *argv[])
{

  int fd;
  int new_file_fd;
  int num_read = 0;
  int new_file_size;

  struct ar_hdr current_header;

  char name_buffer[16];
  char date_buffer[12];
  char uid_buffer[6];
  char gid_buffer[6];
  char mode_buffer[8];
  char size_buffer[10];
  char fmag_buffer[2];

  // grab the fd #
  fd = open(argv[2], O_RDWR | O_CREAT, 0666);

  // go to the first header
  lseek(fd, SARMAG, SEEK_CUR);

  // store the number of bits read in a struct current_header
  // until its size equal to the size of the entire
  // header, or in other words, until the entire
  // header is read
  while ((num_read = read(fd, (char*) &current_header, 
    sizeof(struct ar_hdr))) == sizeof(struct ar_hdr))
  {

    // scans the current string in header and stores
    // in nameStr array
    sscanf(current_header.ar_name, "%s", name_buffer);
    sscanf(current_header.ar_date, "%s", date_buffer);
    sscanf(current_header.ar_uid, "%s", uid_buffer);
    sscanf(current_header.ar_gid, "%s", gid_buffer);

    int mode;
    sscanf(current_header.ar_mode, "%o", &mode);
    sscanf(current_header.ar_size, "%s", size_buffer);
    int size = atoi(size_buffer);
    sscanf(current_header.ar_fmag, "%s", fmag_buffer);

    // Create a new file
    new_file_fd = creat(name_buffer, mode);
    // Grab new file size
    new_file_size = atoi(size_buffer);

    int io_size; // buffer size
    char buff[size];
    int read_cntr = 0;

    // from copy.c
    while ((io_size = read (fd, buff, new_file_size)) > 0)
    {
      read_cntr++;
      if (read_cntr > new_file_size)
        break;
      write (new_file_fd, buff, new_file_size);
    }

    close(new_file_fd);
    printf("%s\n", name_buffer);
    printf("%s\n", date_buffer);
    printf("%s\n", uid_buffer);
    printf("%s\n", gid_buffer);
    printf("%s\n", mode_buffer);
    printf("%s\n", size_buffer);
    printf("%s\n", fmag_buffer);

    /* Seek to next header. */
    lseek(fd, atoi(current_header.ar_size) + (atoi(current_header.ar_size)%2), SEEK_CUR);
  }

}

私が抱えている問題は、上記のコードの 2 番目の while ループにあります。

    // from copy.c
while ((io_size = read (fd, buff, new_file_size)) > 0)
{
  read_cntr++;
  if (read_cntr > new_file_size)
    break;
  write (new_file_fd, buff, new_file_size);
}

何らかの理由で、この while ループで書き込まれたファイルは、write で指定された長さまで実行されません。標準の read()/write() の 3 番目の引数は、書き込むバイト数です。ただし、何らかの理由で、私のコードでは、アーカイブ全体が読み込まれ、最初のファイルに書き込まれます。

結果の「yo」ファイルを開くと、アーカイブファイル全体が書き込まれていることがわかります

test1 lol
yo2             1382105444  501   20    100644  10        `
test2 lol

10バイトを読み取った後に終了し、期待される結果「test1 lol」を返す代わりに。

また、「new_file_size」の値が実際に 10 であることも確認できます。私の質問は、この while ループのどこが間違っているのでしょうか?

注:予想される入力は、次のようなコマンド ライン引数です。

この関数で処理する必要があると思われる唯一の関連情報は、extract_files の先頭で fd を取得するアーカイブ ファイルの名前です。

追加: Misc -- これを実行したときの出力:

yo
1382105439
501
20
X
10
`

ご覧のとおり、yo2 ファイルを認識したり、ヘッダーを出力したりすることはありません。これは、それが発生する前に「yo」に書き込まれるためです...この浮遊する while ループが原因です :(

4

2 に答える 2

1

ループの後にwhile()はおそらく中かっこ ( ) が必要です。それ以外の場合は、他に何もせず{ ... }にインクリメントするだけです。read_cntr

于 2013-10-18T19:25:22.327 に答える