1

lseek()必要なサイズのファイルを作成しながら、の使用を真に理解しようとしています。そこで、input で指定されたサイズのファイルを作成することを唯一の目的とするこのコードを書きました。

たとえば、次のように実行します。

$ ./lseek_test myFile 5

myFile最後のバイトが数字の 5 で占められている 5 バイトという名前のファイルを作成することを期待しています。取得したファイルは、アクセスすることさえできません。どうしたの?lseek()使用法 をひどく解釈しましたか?

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>

#define abort_on_error(cond, msg) do {\
    if(cond) {\
        int _e = errno;\
        fprintf(stderr, "%s (%d)\n", msg, _e);\
        exit(EXIT_FAILURE);\
    }\
} while(0)

/* Write an integer with error control on the file */
void write_int(int fd, int v) {
    ssize_t c = write(fd, &v, sizeof(v));
    if (c == sizeof(v))
        return;
    abort_on_error(c == -1 && errno != EINTR, "Error writing the output file");
    abort_on_error(1, "Write operation interrupted, aborting");
}

int main(int argc, char *argv[]) {
    // Usage control
    abort_on_error(argc != 3, "Usage: ./lseek_test <FileName> <FileSize>");

    // Parsing of the input
    int size = strtol(argv[2], NULL, 0);
    // Open file
    int fd = open(argv[1], O_RDWR|O_CREAT, 0644);
    abort_on_error(fd == -1, "Error opening or creating file");

    // Use lseek() and write() to create the file of the needed size
    abort_on_error(lseek(fd, size, SEEK_SET) == -1, "Error in lseek");
    write_int(fd, size); // To truly extend the file 

    //Close file
    abort_on_error(close(fd) == -1, "Error closing file");
    return EXIT_SUCCESS;
}
4

2 に答える 2

6

あなたのプログラムは、その実装に基づいて、私が期待するとおりに機能します。

  • 指定されたファイルが最初に存在しないと仮定して、それを作成します
  • オフセット 5 から始まる、値 5 を持つint( )の 4 バイトをファイルに書き込みます。sizeof(int)
  • オフセット 0 ~ 4 には何も書き込みません。これらは null バイトで埋められます。

結果は、バイト値を含む 9 バイトのファイルです (印刷可能な数字ではありません)。

0 0 0 0 0 5 0 0 0

(私のシステムはリトルエンディアンです。)特に、このファイルは決してテキストファイルではないことに注意してください。テキスト ファイルを期待していた場合は、実際にはそうであるように、それに関して予期しない動作が発生し、アクセスできないと見なされる場合があります。

次に、いくつかの考慮事項:

  • ファイルの 5 番目のバイトは、先頭から 5 ではなく 4 のオフセットにあります。
  • 数字の '5'を書きたい場合は、それを a に格納して;charと書きます。その表現charを書かないでください。intまたは、ファイル記述子をストリームでラップし、 などのストリーム I/O 関数を使用しますfputc()
  • 他のスペースを null バイト以外で埋めたい場合は、手動で行う必要があります。
  • 私が判断できる限り、これはすべて POSIX で要求されているとおりです。特に、lseek について次のように述べています。

lseek() 関数を使用すると、ファイル オフセットをファイル内の既存のデータの末尾を超えて設定できます。この時点でデータが後で書き込まれる場合、ギャップ内のデータの後続の読み取りは、データが実際にギャップに書き込まれるまで、値 0 のバイトを返します。

( POSIX 1003.1-2008、2016 年版)

于 2017-01-05T17:35:32.703 に答える