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