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