| /* swapon(8) without any sanity checks; simply calls swapon(2) directly. */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| #include <string.h> | |
| #include <sys/swap.h> | |
| #include <sys/types.h> | |
| #include <sys/stat.h> | |
| #include <sys/mman.h> | |
| #include <fcntl.h> | |
| #include <signal.h> | |
| static void usage(const char *prog) | |
| { | |
| fprintf(stderr, "usage: %s [-v verb] PATH\n", prog); | |
| exit(EXIT_FAILURE); | |
| } | |
| enum verbs { | |
| TEST_SWAPON = 0, | |
| TEST_WRITE, | |
| TEST_MWRITE_AFTER, | |
| TEST_MWRITE_BEFORE_AND_MWRITE_AFTER, | |
| TEST_MWRITE_BEFORE, | |
| MAX_TEST_VERBS, | |
| }; | |
| #define BUF_SIZE 262144 | |
| static char buf[BUF_SIZE]; | |
| static void handle_signal(int signal) | |
| { | |
| fprintf(stderr, "Caught signal %d, terminating...\n", signal); | |
| exit(EXIT_FAILURE); | |
| } | |
| int main(int argc, char **argv) | |
| { | |
| struct sigaction act = { | |
| .sa_handler = handle_signal, | |
| }; | |
| enum verbs verb = TEST_SWAPON; | |
| void *p = NULL; | |
| ssize_t sz; | |
| int fd = -1; | |
| int ret, c; | |
| memset(buf, 0x58, BUF_SIZE); | |
| while ((c = getopt(argc, argv, "v:")) != -1) { | |
| switch (c) { | |
| case 'v': | |
| verb = atoi(optarg); | |
| if (verb < TEST_SWAPON || verb >= MAX_TEST_VERBS) { | |
| fprintf(stderr, "Verbs must be 0-%d.\n", | |
| MAX_TEST_VERBS - 1); | |
| usage(argv[0]); | |
| } | |
| break; | |
| default: | |
| usage(argv[0]); | |
| break; | |
| } | |
| } | |
| ret = sigaction(SIGSEGV, &act, NULL); | |
| if (ret) { | |
| perror("sigsegv action"); | |
| return EXIT_FAILURE; | |
| } | |
| ret = sigaction(SIGBUS, &act, NULL); | |
| if (ret) { | |
| perror("sigbus action"); | |
| return EXIT_FAILURE; | |
| } | |
| switch (verb) { | |
| case TEST_WRITE: | |
| case TEST_MWRITE_AFTER: | |
| case TEST_MWRITE_BEFORE_AND_MWRITE_AFTER: | |
| case TEST_MWRITE_BEFORE: | |
| fd = open(argv[optind], O_RDWR); | |
| if (fd < 0) { | |
| perror(argv[optind]); | |
| return EXIT_FAILURE; | |
| } | |
| break; | |
| default: | |
| break; | |
| } | |
| switch (verb) { | |
| case TEST_MWRITE_BEFORE_AND_MWRITE_AFTER: | |
| case TEST_MWRITE_BEFORE: | |
| p = mmap(NULL, BUF_SIZE, PROT_WRITE | PROT_READ, MAP_SHARED, | |
| fd, 65536); | |
| if (p == MAP_FAILED) { | |
| perror("mmap"); | |
| return EXIT_FAILURE; | |
| } | |
| memcpy(p, buf, BUF_SIZE); | |
| break; | |
| default: | |
| break; | |
| } | |
| if (optind != argc - 1) | |
| usage(argv[0]); | |
| ret = swapon(argv[optind], 0); | |
| if (ret) { | |
| perror("swapon"); | |
| return EXIT_FAILURE; | |
| } | |
| switch (verb) { | |
| case TEST_WRITE: | |
| sz = pwrite(fd, buf, BUF_SIZE, 65536); | |
| if (sz < 0) { | |
| perror("pwrite"); | |
| return EXIT_FAILURE; | |
| } | |
| break; | |
| case TEST_MWRITE_AFTER: | |
| p = mmap(NULL, BUF_SIZE, PROT_WRITE | PROT_READ, MAP_SHARED, | |
| fd, 65536); | |
| if (p == MAP_FAILED) { | |
| perror("mmap"); | |
| return EXIT_FAILURE; | |
| } | |
| /* fall through */ | |
| case TEST_MWRITE_BEFORE_AND_MWRITE_AFTER: | |
| memcpy(p, buf, BUF_SIZE); | |
| break; | |
| default: | |
| break; | |
| } | |
| if (fd >= 0) { | |
| ret = fsync(fd); | |
| if (ret) | |
| perror("fsync"); | |
| ret = close(fd); | |
| if (ret) | |
| perror("close"); | |
| } | |
| return EXIT_SUCCESS; | |
| } |