#include #include #include #include #include #include #include #include #include #include #define PATH "c-mmap-testfile" #define PAGESIZE 4096 static void sighdl(int); static void sighdl(int signo) { const char errmsg[] = "\nSignal occurred, cleaning up\n"; (void)signo; (void)signal(SIGSEGV, SIG_DFL); (void)signal(SIGBUS, SIG_DFL); write(2, errmsg, sizeof(errmsg)-1); (void)unlink(PATH); return; } int main(void) { int fd, estat = 0; void *addr; auto struct stat s; /* *Final* sizes (string written after lseek(2): "abcd") */ const size_t *ct, tests[] = { /* Tested good */ //0x100000000 - PAGESIZE - 5, //0x100000000 - 4, //0x100000000 - 3, //0x100000000 - 1, 0x100000000 + PAGESIZE + 4, //0x100000000 + PAGESIZE + 5, /* Tested bad */ //0x100000000, //0x100000000 + PAGESIZE, //0x100000000 + PAGESIZE + 1, //0x100000000 + PAGESIZE + 3, 0 }; if (signal(SIGSEGV, &sighdl) == SIG_ERR) goto jerror; if (signal(SIGBUS, &sighdl) == SIG_ERR) goto jerror; for (ct = tests; *ct != 0; ++ct) { fprintf(stderr, "Size %lu/0x%lX: open", *ct, *ct); fd = open(PATH, O_RDWR|O_TRUNC|O_CREAT, 0666); if (fd < 0) goto jerror; fprintf(stderr, ". "); fprintf(stderr, "lseek"); if (lseek(fd, *ct-4, SEEK_END) < 0) goto jerror; fprintf(stderr, ". "); fprintf(stderr, "write"); if (write(fd, "abcd", 4) != 4) goto jerror; fprintf(stderr, ". "); fprintf(stderr, "fsync"); if (fsync(fd) != 0) goto jerror; fprintf(stderr, ". "); fprintf(stderr, "fstat"); if (fstat(fd, &s) != 0) goto jerror; fprintf(stderr, ". "); if (*ct != (size_t)s.st_size) { fprintf(stderr, "fstat size mismatch: %lu is not %lu\n", (size_t)s.st_size, *ct); continue; } fprintf(stderr, "mmap"); addr = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (addr == NULL) goto jerror; fprintf(stderr, ". "); (void)close(fd); fprintf(stderr, "[0]"); if (((char*)addr)[0] != '\0') goto jerror; fprintf(stderr, ". "); fprintf(stderr, "[s.st_size-4]"); if (((char*)addr)[s.st_size-4] != 'a') goto jerror; fprintf(stderr, ". "); fprintf(stderr, "munmap"); if (munmap(addr, s.st_size) != 0) goto jerror; fprintf(stderr, "."); fprintf(stderr, "\n"); } jleave: (void)unlink(PATH); return estat; jerror: fprintf(stderr, "\n%s\n", strerror(errno)); estat = 1; goto jleave; }