diff options
-rw-r--r-- | toolbox/Android.mk | 5 | ||||
-rw-r--r-- | toolbox/mkswap.c | 94 | ||||
-rw-r--r-- | toolbox/swapoff.c | 21 | ||||
-rw-r--r-- | toolbox/swapon.c | 73 |
4 files changed, 192 insertions, 1 deletions
diff --git a/toolbox/Android.mk b/toolbox/Android.mk index 565ec2aa5..f60037dae 100644 --- a/toolbox/Android.mk +++ b/toolbox/Android.mk @@ -65,7 +65,10 @@ TOOLS := \ runcon \ getsebool \ setsebool \ - load_policy + load_policy \ + swapon \ + swapoff \ + mkswap ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT))) TOOLS += r diff --git a/toolbox/mkswap.c b/toolbox/mkswap.c new file mode 100644 index 000000000..1710ef6f8 --- /dev/null +++ b/toolbox/mkswap.c @@ -0,0 +1,94 @@ +#include <stdio.h> +#include <unistd.h> +#include <asm/page.h> +#include <sys/swap.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +/* XXX This needs to be obtained from kernel headers. See b/9336527 */ +struct linux_swap_header { + char bootbits[1024]; /* Space for disklabel etc. */ + uint32_t version; + uint32_t last_page; + uint32_t nr_badpages; + unsigned char sws_uuid[16]; + unsigned char sws_volume[16]; + uint32_t padding[117]; + uint32_t badpages[1]; +}; + +#define MAGIC_SWAP_HEADER "SWAPSPACE2" +#define MAGIC_SWAP_HEADER_LEN 10 +#define MIN_PAGES 10 + +int mkswap_main(int argc, char **argv) +{ + int err = 0; + int fd; + ssize_t len; + off_t swap_size; + int pagesize; + struct linux_swap_header sw_hdr; + + if (argc != 2) { + fprintf(stderr, "Usage: %s <filename>\n", argv[0]); + return -EINVAL; + } + + fd = open(argv[1], O_WRONLY); + if (fd < 0) { + err = errno; + fprintf(stderr, "Cannot open %s\n", argv[1]); + return err; + } + + pagesize = getpagesize(); + /* Determine the length of the swap file */ + swap_size = lseek(fd, 0, SEEK_END); + if (swap_size < MIN_PAGES * pagesize) { + fprintf(stderr, "Swap file needs to be at least %dkB\n", + (MIN_PAGES * pagesize) >> 10); + err = -ENOSPC; + goto err; + } + if (lseek(fd, 0, SEEK_SET)) { + err = errno; + fprintf(stderr, "Can't seek to the beginning of the file\n"); + goto err; + } + + memset(&sw_hdr, 0, sizeof(sw_hdr)); + sw_hdr.version = 1; + sw_hdr.last_page = (swap_size / pagesize) - 1; + + len = write(fd, &sw_hdr, sizeof(sw_hdr)); + if (len != sizeof(sw_hdr)) { + err = errno; + fprintf(stderr, "Failed to write swap header into %s\n", argv[1]); + goto err; + } + + /* Write the magic header */ + if (lseek(fd, pagesize - MAGIC_SWAP_HEADER_LEN, SEEK_SET) < 0) { + err = errno; + fprintf(stderr, "Failed to seek into %s\n", argv[1]); + goto err; + } + + len = write(fd, MAGIC_SWAP_HEADER, MAGIC_SWAP_HEADER_LEN); + if (len != MAGIC_SWAP_HEADER_LEN) { + err = errno; + fprintf(stderr, "Failed to write magic swap header into %s\n", argv[1]); + goto err; + } + + if (fsync(fd) < 0) { + err = errno; + fprintf(stderr, "Failed to sync %s\n", argv[1]); + goto err; + } +err: + close(fd); + return err; +} diff --git a/toolbox/swapoff.c b/toolbox/swapoff.c new file mode 100644 index 000000000..8f1415850 --- /dev/null +++ b/toolbox/swapoff.c @@ -0,0 +1,21 @@ +#include <stdio.h> +#include <unistd.h> +#include <asm/page.h> +#include <sys/swap.h> + +int swapoff_main(int argc, char **argv) +{ + int err = 0; + + if (argc != 2) { + fprintf(stderr, "Usage: %s <filename>\n", argv[0]); + return -EINVAL; + } + + err = swapoff(argv[1]); + if (err) { + fprintf(stderr, "swapoff failed for %s\n", argv[1]); + } + + return err; +} diff --git a/toolbox/swapon.c b/toolbox/swapon.c new file mode 100644 index 000000000..afa686852 --- /dev/null +++ b/toolbox/swapon.c @@ -0,0 +1,73 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <getopt.h> +#include <asm/page.h> +#include <sys/swap.h> + +/* XXX These need to be obtained from kernel headers. See b/9336527 */ +#define SWAP_FLAG_PREFER 0x8000 +#define SWAP_FLAG_PRIO_MASK 0x7fff +#define SWAP_FLAG_PRIO_SHIFT 0 +#define SWAP_FLAG_DISCARD 0x10000 + +void usage(char *name) +{ + fprintf(stderr, "Usage: %s [-p prio] <filename>\n" + " prio must be between 0 and %d\n", name, SWAP_FLAG_PRIO_MASK); +} + +int parse_prio(char *prio_str) +{ + unsigned long p = strtoul(prio_str, NULL, 10); + + return (p > SWAP_FLAG_PRIO_MASK)? -1 : (int)p; +} + +int swapon_main(int argc, char **argv) +{ + int err = 0; + int flags = 0; + int prio; + + opterr = 0; + do { + int c = getopt(argc, argv, "hp:"); + if (c == -1) + break; + + switch (c) { + case 'p': + if (optarg != NULL) + prio = parse_prio(optarg); + else + prio = -1; + + if (prio < 0) { + usage(argv[0]); + return -EINVAL; + } + flags |= SWAP_FLAG_PREFER; + flags |= (prio << SWAP_FLAG_PRIO_SHIFT) & SWAP_FLAG_PRIO_MASK; + break; + case 'h': + usage(argv[0]); + return 0; + case '?': + fprintf(stderr, "unknown option: %c\n", optopt); + return -EINVAL; + } + } while (1); + + if (optind != argc - 1) { + usage(argv[0]); + return -EINVAL; + } + + err = swapon(argv[argc - 1], flags); + if (err) { + fprintf(stderr, "swapon failed for %s\n", argv[argc - 1]); + } + + return err; +} |