diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2013-11-22 11:28:10 -0800 |
---|---|---|
committer | Conley Owens <cco3@android.com> | 2013-11-22 13:44:43 -0800 |
commit | 66ed50af6870210ce013a5588a688434a5d48ee9 (patch) | |
tree | a879f3ea31083496d0efe491bc187b6e0ebada39 /toolbox | |
parent | dd2ac3de625e6c0328a0f70530d8ade0d2151bfc (diff) | |
parent | 536dea9d61a032e64bbe584a97463c6638ead009 (diff) | |
download | system_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.mk | 7 | ||||
-rw-r--r-- | toolbox/log.c | 6 | ||||
-rw-r--r-- | toolbox/lsof.c | 18 | ||||
-rw-r--r-- | toolbox/mkswap.c | 94 | ||||
-rw-r--r-- | toolbox/mount.c | 22 | ||||
-rw-r--r-- | toolbox/readlink.c | 95 | ||||
-rw-r--r-- | toolbox/reboot.c | 58 | ||||
-rw-r--r-- | toolbox/rm.c | 19 | ||||
-rw-r--r-- | toolbox/swapoff.c | 21 | ||||
-rw-r--r-- | toolbox/swapon.c | 73 | ||||
-rw-r--r-- | toolbox/touch.c | 35 |
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; |