規格違反にならないC言語でのファイルサイズ取得 |POSIX fstat 関数使用

シェアする

C言語には、標準ライブラリにてさまざまなファイル操作関数が提供されています。ですが、ファイルサイズを取得する標準関数はありません。そのため、ファイルサイズを取得するには自分でコードを実装する必要があります。

一般的に使われているfseek()関数を使った実装で事足りますが、これは厳密にはc言語規格に適合していません。そこで今回は、POSIX を利用してc言語規格に適合したファイルサイズ取得関数を紹介いたします。

fstat() 関数を使用した例を示します。Linux はもちろん、MSYS2@Windowsでも動作します

#include <stdio.h>
#include <stdlib.h>

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#define ERR_PRINTF_EXIT(...) do { fprintf(stderr, __VA_ARGS__); exit(EXIT_FAILURE); } while(0)

/**
 * @brief ファイルサイズ取得. Windows / Linux 両対応, のはず.
 * @param[in] in_fname ファイル名の文字列
 * @retval ファイルサイズ
 */
static long get_read_file_size(const char *in_fname)
{
    FILE *fp;
    long file_size;
    struct stat stbuf;
    int fd;

    fd = open(in_fname, O_RDONLY);
    if (fd == -1)
        ERR_PRINTF_EXIT("cant open file : %s.\n", in_fname);

    fp = fdopen(fd, "rb");
    if (fp == NULL)
        ERR_PRINTF_EXIT("cant open file : %s.\n", in_fname);

    if (fstat(fd, &stbuf) == -1)
        ERR_PRINTF_EXIT("cant get file state : %s.\n", in_fname);

    file_size = stbuf.st_size;

    if (fclose(fp) != 0)
        ERR_PRINTF_EXIT("cant close file : %s.\n", in_fname);

    return file_size;
}

fseek() 関数を使っても、まずちゃんと動くのですが、さらにコードの可搬性を求めるなら、今回紹介した実装の方が良いでしょう。
ぜひご活用ください!

上記の関数はJPCERT CCを参考にしました。