| /* 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; |
| } |