summaryrefslogtreecommitdiffstats
path: root/toolbox
diff options
context:
space:
mode:
authorRom Lemarchand <romlem@google.com>2013-06-05 13:25:12 -0700
committerRom Lemarchand <romlem@google.com>2013-06-25 13:21:53 -0700
commit367297c3d764eaf6e60880964e1739df13f0b703 (patch)
tree1b23185e815e4c165c60acc8e3e17a505a4667e1 /toolbox
parent25383a5da2ce4ada76df46e1bc7ae56ac0e41fc4 (diff)
downloadsystem_core-367297c3d764eaf6e60880964e1739df13f0b703.zip
system_core-367297c3d764eaf6e60880964e1739df13f0b703.tar.gz
system_core-367297c3d764eaf6e60880964e1739df13f0b703.tar.bz2
toolbox: swap utils
Add swap utilities (mkswap, swapon, swapoff) to the toolbox Change-Id: If5ed6981670a1cdda6b528b587dbc1be7ccdf832 Signed-off-by: Rom Lemarchand <romlem@google.com>
Diffstat (limited to 'toolbox')
-rw-r--r--toolbox/Android.mk5
-rw-r--r--toolbox/mkswap.c94
-rw-r--r--toolbox/swapoff.c21
-rw-r--r--toolbox/swapon.c73
4 files changed, 192 insertions, 1 deletions
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 565ec2a..f60037d 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 0000000..1710ef6
--- /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 0000000..8f14158
--- /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 0000000..afa6868
--- /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;
+}