summaryrefslogtreecommitdiffstats
path: root/toolbox
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2013-11-22 11:28:10 -0800
committerConley Owens <cco3@android.com>2013-11-22 13:44:43 -0800
commit66ed50af6870210ce013a5588a688434a5d48ee9 (patch)
treea879f3ea31083496d0efe491bc187b6e0ebada39 /toolbox
parentdd2ac3de625e6c0328a0f70530d8ade0d2151bfc (diff)
parent536dea9d61a032e64bbe584a97463c6638ead009 (diff)
downloadsystem_core-66ed50af6870210ce013a5588a688434a5d48ee9.tar.gz
system_core-66ed50af6870210ce013a5588a688434a5d48ee9.tar.bz2
system_core-66ed50af6870210ce013a5588a688434a5d48ee9.zip
Merge commit '536dea9d61a032e64bbe584a97463c6638ead009' into HEAD
Change-Id: I5c469a4b738629d99d721cad7ded02d6c35f56d5
Diffstat (limited to 'toolbox')
-rw-r--r--toolbox/Android.mk7
-rw-r--r--toolbox/log.c6
-rw-r--r--toolbox/lsof.c18
-rw-r--r--toolbox/mkswap.c94
-rw-r--r--toolbox/mount.c22
-rw-r--r--toolbox/readlink.c95
-rw-r--r--toolbox/reboot.c58
-rw-r--r--toolbox/rm.c19
-rw-r--r--toolbox/swapoff.c21
-rw-r--r--toolbox/swapon.c73
-rw-r--r--toolbox/touch.c35
11 files changed, 366 insertions, 82 deletions
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index c7646902c..75ce53f0a 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -16,7 +16,6 @@ TOOLS := \
rm \
mkdir \
rmdir \
- reboot \
getevent \
sendevent \
date \
@@ -66,7 +65,11 @@ TOOLS := \
runcon \
getsebool \
setsebool \
- load_policy
+ load_policy \
+ swapon \
+ swapoff \
+ mkswap \
+ readlink
ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
TOOLS += r
diff --git a/toolbox/log.c b/toolbox/log.c
index f30e6a782..2f020a8a4 100644
--- a/toolbox/log.c
+++ b/toolbox/log.c
@@ -30,7 +30,7 @@
*/
#include <stdio.h>
-#include <cutils/logd.h>
+#include <log/logd.h>
#include <ctype.h>
#include <sys/socket.h>
#include <sys/types.h>
@@ -130,8 +130,8 @@ int log_main(int argc, char *argv[])
buffer[0] = '\0';
for (i = optind ; i < argc ; i++) {
- strncat(buffer, argv[i], sizeof(buffer)-1);
- strncat(buffer, " ", sizeof(buffer)-1);
+ strlcat(buffer, argv[i], sizeof(buffer)-1);
+ strlcat(buffer, " ", sizeof(buffer)-1);
}
if(buffer[0] == 0) {
diff --git a/toolbox/lsof.c b/toolbox/lsof.c
index 376a642e7..113c120fc 100644
--- a/toolbox/lsof.c
+++ b/toolbox/lsof.c
@@ -54,7 +54,7 @@ struct pid_info_t {
ssize_t parent_length;
};
-void print_header()
+static void print_header()
{
printf("%-9s %5s %10s %4s %9s %18s %9s %10s %s\n",
"COMMAND",
@@ -68,12 +68,12 @@ void print_header()
"NAME");
}
-void print_type(char *type, struct pid_info_t* info)
+static void print_type(char *type, struct pid_info_t* info)
{
static ssize_t link_dest_size;
static char link_dest[PATH_MAX];
- strncat(info->path, type, sizeof(info->path));
+ strlcat(info->path, type, sizeof(info->path));
if ((link_dest_size = readlink(info->path, link_dest, sizeof(link_dest)-1)) < 0) {
if (errno == ENOENT)
goto out;
@@ -96,7 +96,7 @@ out:
}
// Prints out all file that have been memory mapped
-void print_maps(struct pid_info_t* info)
+static void print_maps(struct pid_info_t* info)
{
FILE *maps;
char buffer[PATH_MAX + 100];
@@ -107,7 +107,7 @@ void print_maps(struct pid_info_t* info)
long int inode;
char file[PATH_MAX];
- strncat(info->path, "maps", sizeof(info->path));
+ strlcat(info->path, "maps", sizeof(info->path));
maps = fopen(info->path, "r");
if (!maps)
@@ -131,10 +131,10 @@ out:
}
// Prints out all open file descriptors
-void print_fds(struct pid_info_t* info)
+static void print_fds(struct pid_info_t* info)
{
static char* fd_path = "fd/";
- strncat(info->path, fd_path, sizeof(info->path));
+ strlcat(info->path, fd_path, sizeof(info->path));
int previous_length = info->parent_length;
info->parent_length += strlen(fd_path);
@@ -163,7 +163,7 @@ out:
info->path[info->parent_length] = '\0';
}
-void lsof_dumpinfo(pid_t pid)
+static void lsof_dumpinfo(pid_t pid)
{
int fd;
struct pid_info_t info;
@@ -187,7 +187,7 @@ void lsof_dumpinfo(pid_t pid)
}
// Read the command line information; each argument is terminated with NULL.
- strncat(info.path, "cmdline", sizeof(info.path));
+ strlcat(info.path, "cmdline", sizeof(info.path));
fd = open(info.path, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Couldn't read %s\n", info.path);
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/mount.c b/toolbox/mount.c
index bcda2a284..66ae8b115 100644
--- a/toolbox/mount.c
+++ b/toolbox/mount.c
@@ -138,6 +138,24 @@ parse_mount_options(char *arg, unsigned long rwflag, struct extra_opts *extra, i
return rwflag;
}
+/*
+ * Mark the given block device as read-write, using the BLKROSET ioctl.
+ */
+static void fs_set_blk_rw(const char *blockdev)
+{
+ int fd;
+ int OFF = 0;
+
+ fd = open(blockdev, O_RDONLY);
+ if (fd < 0) {
+ // should never happen
+ return;
+ }
+
+ ioctl(fd, BLKROSET, &OFF);
+ close(fd);
+}
+
static char *progname;
static struct extra_opts extra;
@@ -179,6 +197,10 @@ do_mount(char *dev, char *dir, char *type, unsigned long rwflag, void *data, int
dev = loopdev;
}
+ if ((rwflag & MS_RDONLY) == 0) {
+ fs_set_blk_rw(dev);
+ }
+
while ((s = strsep(&type, ",")) != NULL) {
retry:
if (mount(dev, dir, s, rwflag, data) == -1) {
diff --git a/toolbox/readlink.c b/toolbox/readlink.c
new file mode 100644
index 000000000..d114e2098
--- /dev/null
+++ b/toolbox/readlink.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013, The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google, Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static int skip_newline, quiet_errors, canonicalize;
+
+static void usage(char* name) {
+ fprintf(stderr, "Usage: %s [OPTION]... FILE\n", name);
+}
+
+int readlink_main(int argc, char* argv[]) {
+ int c;
+ while ((c = getopt(argc, argv, "nfqs")) != -1) {
+ switch (c) {
+ case 'n':
+ skip_newline = 1;
+ break;
+ case 'f':
+ canonicalize = 1;
+ break;
+ case 'q':
+ case 's':
+ quiet_errors = 1;
+ break;
+ case '?':
+ default:
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+ }
+ int index = optind;
+ if (argc - index != 1) {
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ char name[PATH_MAX+1];
+ if (canonicalize) {
+ if(!realpath(argv[optind], name)) {
+ if (!quiet_errors) {
+ perror("readlink");
+ }
+ return EXIT_FAILURE;
+ }
+ } else {
+ ssize_t len = readlink(argv[1], name, PATH_MAX);
+
+ if (len < 0) {
+ if (!quiet_errors) {
+ perror("readlink");
+ }
+ return EXIT_FAILURE;
+ }
+ name[len] = '\0';
+ }
+
+ fputs(name, stdout);
+ if (!skip_newline) {
+ fputs("\n", stdout);
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/toolbox/reboot.c b/toolbox/reboot.c
deleted file mode 100644
index f8546de2d..000000000
--- a/toolbox/reboot.c
+++ /dev/null
@@ -1,58 +0,0 @@
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <cutils/android_reboot.h>
-#include <unistd.h>
-
-int reboot_main(int argc, char *argv[])
-{
- int ret;
- int nosync = 0;
- int poweroff = 0;
- int flags = 0;
-
- opterr = 0;
- do {
- int c;
-
- c = getopt(argc, argv, "np");
-
- if (c == EOF) {
- break;
- }
-
- switch (c) {
- case 'n':
- nosync = 1;
- break;
- case 'p':
- poweroff = 1;
- break;
- case '?':
- fprintf(stderr, "usage: %s [-n] [-p] [rebootcommand]\n", argv[0]);
- exit(EXIT_FAILURE);
- }
- } while (1);
-
- if(argc > optind + 1) {
- fprintf(stderr, "%s: too many arguments\n", argv[0]);
- exit(EXIT_FAILURE);
- }
-
- if(nosync)
- /* also set NO_REMOUNT_RO as remount ro includes an implicit sync */
- flags = ANDROID_RB_FLAG_NO_SYNC | ANDROID_RB_FLAG_NO_REMOUNT_RO;
-
- if(poweroff)
- ret = android_reboot(ANDROID_RB_POWEROFF, flags, 0);
- else if(argc > optind)
- ret = android_reboot(ANDROID_RB_RESTART2, flags, argv[optind]);
- else
- ret = android_reboot(ANDROID_RB_RESTART, flags, 0);
- if(ret < 0) {
- perror("reboot");
- exit(EXIT_FAILURE);
- }
- fprintf(stderr, "reboot returned\n");
- return 0;
-}
diff --git a/toolbox/rm.c b/toolbox/rm.c
index 3a24becb6..957b5867f 100644
--- a/toolbox/rm.c
+++ b/toolbox/rm.c
@@ -45,8 +45,10 @@ static int unlink_recursive(const char* name, int flags)
continue;
sprintf(dn, "%s/%s", name, de->d_name);
if (unlink_recursive(dn, flags) < 0) {
- fail = 1;
- break;
+ if (!(flags & OPT_FORCE)) {
+ fail = 1;
+ break;
+ }
}
errno = 0;
}
@@ -71,6 +73,7 @@ int rm_main(int argc, char *argv[])
int ret;
int i, c;
int flags = 0;
+ int something_failed = 0;
if (argc < 2)
return usage();
@@ -103,17 +106,21 @@ int rm_main(int argc, char *argv[])
ret = unlink_recursive(argv[i], flags);
} else {
ret = unlink(argv[i]);
- if (errno == ENOENT && (flags & OPT_FORCE)) {
- return 0;
+ if (ret < 0 && errno == ENOENT && (flags & OPT_FORCE)) {
+ continue;
}
}
if (ret < 0) {
fprintf(stderr, "rm failed for %s, %s\n", argv[i], strerror(errno));
- return -1;
+ if (!(flags & OPT_FORCE)) {
+ return -1;
+ } else {
+ something_failed = 1;
+ }
}
}
- return 0;
+ return something_failed;
}
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;
+}
diff --git a/toolbox/touch.c b/toolbox/touch.c
index b8ab310d0..52ddf2a55 100644
--- a/toolbox/touch.c
+++ b/toolbox/touch.c
@@ -5,13 +5,40 @@
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>
+#include <time.h>
static void usage(void)
{
- fprintf(stderr, "touch: usage: touch [-alm] [-t time_t] <file>\n");
+ fprintf(stderr, "touch: usage: touch [-alm] [-t YYYYMMDD[.hhmmss]] <file>\n");
exit(1);
}
+static time_t parse_time(char *s)
+{
+ struct tm tm;
+ int day = atoi(s);
+ int hour = 0;
+
+ while (*s && *s != '.') {
+ s++;
+ }
+
+ if (*s) {
+ s++;
+ hour = atoi(s);
+ }
+
+ tm.tm_year = day / 10000 - 1900;
+ tm.tm_mon = (day % 10000) / 100 - 1;
+ tm.tm_mday = day % 100;
+ tm.tm_hour = hour / 10000;
+ tm.tm_min = (hour % 10000) / 100;
+ tm.tm_sec = hour % 100;
+ tm.tm_isdst = -1;
+
+ return mktime(&tm);
+}
+
int touch_main(int argc, char *argv[])
{
int i, fd, aflag = 0, mflag = 0, debug = 0, flags = 0;
@@ -31,9 +58,9 @@ int touch_main(int argc, char *argv[])
case 't':
if ((i+1) >= argc)
usage();
- specified_time.tv_sec = atol(argv[++i]);
- if (specified_time.tv_sec == 0) {
- fprintf(stderr, "touch: invalid time_t\n");
+ specified_time.tv_sec = parse_time(argv[++i]);
+ if (specified_time.tv_sec == -1) {
+ fprintf(stderr, "touch: invalid timestamp specified\n");
exit(1);
}
specified_time.tv_nsec = 0;