blob: fe8949a3dd32381052cfb2427efd059bc92626bf [file] [log] [blame]
/* 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;
}