教訓

アーカイブファイルを読み出す際、アーカイブファイルサイズ分のメモリを確保するのは馬鹿げている。何も考えずに open(2) -> fstat(2) -> malloc(3) -> read(2) しちゃいけませんって事で…。いきなり 4GB 位のファイルを食わせると泣けます…。
fread(3) や fgetc(3) を使うのはエラー処理とか面倒なので、こういう時には mmap(2)。
修正前:

#include 

#include 
#include 
#include 
#include 

int
kma(void)
{
    struct stat sb;
    char *top = NULL, *p;
    int fd = -1;
    int rv = 1;

    fd = open("kma.arc", O_RDONLY);
    if (fd < 0) {
        perror("open");
        goto failure;
    }
    if (fstat(fd, &sb) < 0) {
        perror("fstat");
        goto file_close;
    }
    top = malloc(sb.st_size);
    if (top == NULL) {
        fprintf(stderr, "malloc failure (size = %d)\n", sb.st_size);
        goto file_close;
    }
    if (read(fd, p, sb.st_size) != sb.st_size) {
        perror("read");
        goto memory_free;
    }

    p = top;
...
    rv = 0;

memory_free:
    if (top != NULL)
        free(top);
file_close:
    if (fd >= 0)
        close(fd);
failure:
    return rv;
}

修正後:

#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 

int
kma(void)
{
    struct stat sb;
    char *top = MAP_FAILURE, *p;
    int fd = -1;
    int rv = 1;

    fd = open("kma.arc", O_RDONLY);
    if (fd < 0) {
        perror("open");
        goto failure;
    }
    if (fstat(fd, &sb) < 0) {
        perror("fstat");
        goto file_close;
    }
    top = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (top == MAP_FAILURE) {
        perror("mmap");
        goto file_close;
    }

    p = top;
...
    rv = 0;

memory_free:
    if (top != MAP_FAILURE)
        munmap(top, sb.st_size);
file_close:
    if (fd >= 0)
        close(fd);
failure:
    return rv;
}