summaryrefslogtreecommitdiffstats
path: root/toolbox
diff options
context:
space:
mode:
Diffstat (limited to 'toolbox')
-rw-r--r--toolbox/Android.mk4
-rw-r--r--toolbox/chown.c27
-rw-r--r--toolbox/ionice.c57
-rw-r--r--toolbox/ls.c47
-rw-r--r--toolbox/nandread.c286
-rw-r--r--toolbox/newfs_msdos.c59
6 files changed, 430 insertions, 50 deletions
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index bf7cfde..05b2a34 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -51,7 +51,9 @@ TOOLS := \
iftop \
id \
uptime \
- vmstat
+ vmstat \
+ nandread \
+ ionice
LOCAL_SRC_FILES:= \
toolbox.c \
diff --git a/toolbox/chown.c b/toolbox/chown.c
index 13617db..e9d108b 100644
--- a/toolbox/chown.c
+++ b/toolbox/chown.c
@@ -35,19 +35,29 @@ int chown_main(int argc, char **argv)
gid_t gid = -1; // passing -1 to chown preserves current group
pw = getpwnam(user);
- if (pw == NULL) {
- fprintf(stderr, "No such user '%s'\n", user);
- return 10;
+ if (pw != NULL) {
+ uid = pw->pw_uid;
+ } else {
+ char* endptr;
+ uid = (int) strtoul(user, &endptr, 0);
+ if (endptr == user) { // no conversion
+ fprintf(stderr, "No such user '%s'\n", user);
+ return 10;
+ }
}
- uid = pw->pw_uid;
if (group != NULL) {
grp = getgrnam(group);
- if (grp == NULL) {
- fprintf(stderr, "No such group '%s'\n", group);
- return 10;
+ if (grp != NULL) {
+ gid = grp->gr_gid;
+ } else {
+ char* endptr;
+ gid = (int) strtoul(group, &endptr, 0);
+ if (endptr == group) { // no conversion
+ fprintf(stderr, "No such group '%s'\n", group);
+ return 10;
+ }
}
- gid = grp->gr_gid;
}
for (i = 2; i < argc; i++) {
@@ -59,4 +69,3 @@ int chown_main(int argc, char **argv)
return 0;
}
-
diff --git a/toolbox/ionice.c b/toolbox/ionice.c
new file mode 100644
index 0000000..4a182f2
--- /dev/null
+++ b/toolbox/ionice.c
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <cutils/iosched_policy.h>
+
+static char *classes[] = {"none", "rt", "be", "idle", NULL};
+
+int ionice_main(int argc, char *argv[])
+{
+ IoSchedClass clazz = IoSchedClass_NONE;
+ int ioprio = 0;
+ int pid;
+
+ if(argc != 2 && argc != 4) {
+ fprintf(stderr, "usage: ionice <pid> [none|rt|be|idle] [prio]\n");
+ return 1;
+ }
+
+ if (!(pid = atoi(argv[1]))) {
+ fprintf(stderr, "Invalid pid specified\n");
+ return 1;
+ }
+
+ if (argc == 2) {
+ if (android_get_ioprio(pid, &clazz, &ioprio)) {
+ fprintf(stderr, "Failed to read priority (%s)\n", strerror(errno));
+ return 1;
+ }
+ fprintf(stdout, "Pid %d, class %s (%d), prio %d\n", pid, classes[clazz], clazz, ioprio);
+ return 0;
+ }
+
+ if (!strcmp(argv[2], "none")) {
+ clazz = IoSchedClass_NONE;
+ } else if (!strcmp(argv[2], "rt")) {
+ clazz = IoSchedClass_RT;
+ } else if (!strcmp(argv[2], "be")) {
+ clazz = IoSchedClass_BE;
+ } else if (!strcmp(argv[2], "idle")) {
+ clazz = IoSchedClass_IDLE;
+ } else {
+ fprintf(stderr, "Unsupported class '%s'\n", argv[2]);
+ return 1;
+ }
+
+ ioprio = atoi(argv[3]);
+
+ printf("Setting pid %d i/o class to %d, prio %d\n", pid, clazz, ioprio);
+ if (android_set_ioprio(pid, clazz, ioprio)) {
+ fprintf(stderr, "Failed to set priority (%s)\n", strerror(errno));
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/toolbox/ls.c b/toolbox/ls.c
index aa0113b..6c8de7a 100644
--- a/toolbox/ls.c
+++ b/toolbox/ls.c
@@ -210,15 +210,50 @@ static void group2str(unsigned gid, char *out)
}
}
-static int listfile_size(const char *path, int flags)
+static int show_total_size(const char *dirname, DIR *d, int flags)
{
+ struct dirent *de;
+ char tmp[1024];
struct stat s;
+ int sum = 0;
+
+ /* run through the directory and sum up the file block sizes */
+ while ((de = readdir(d)) != 0) {
+ if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
+ continue;
+ if (de->d_name[0] == '.' && (flags & LIST_ALL) == 0)
+ continue;
+
+ if (strcmp(dirname, "/") == 0)
+ snprintf(tmp, sizeof(tmp), "/%s", de->d_name);
+ else
+ snprintf(tmp, sizeof(tmp), "%s/%s", dirname, de->d_name);
+
+ if (lstat(tmp, &s) < 0) {
+ fprintf(stderr, "stat failed on %s: %s\n", tmp, strerror(errno));
+ rewinddir(d);
+ return -1;
+ }
+
+ sum += s.st_blocks / 2;
+ }
+
+ printf("total %d\n", sum);
+ rewinddir(d);
+ return 0;
+}
- if (lstat(path, &s) < 0)
+static int listfile_size(const char *path, const char *filename, int flags)
+{
+ struct stat s;
+
+ if (lstat(path, &s) < 0) {
+ fprintf(stderr, "lstat '%s' failed: %s\n", path, strerror(errno));
return -1;
+ }
/* blocks are 512 bytes, we want output to be KB */
- printf("%lld %s\n", s.st_blocks / 2, path);
+ printf("%lld %s\n", s.st_blocks / 2, filename);
return 0;
}
@@ -313,7 +348,7 @@ static int listfile(const char *dirname, const char *filename, int flags)
if ((flags & LIST_LONG) != 0) {
return listfile_long(pathname, flags);
} else /*((flags & LIST_SIZE) != 0)*/ {
- return listfile_size(pathname, flags);
+ return listfile_size(pathname, filename, flags);
}
}
@@ -330,6 +365,10 @@ static int listdir(const char *name, int flags)
return -1;
}
+ if ((flags & LIST_SIZE) != 0) {
+ show_total_size(name, d, flags);
+ }
+
while((de = readdir(d)) != 0){
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue;
if(de->d_name[0] == '.' && (flags & LIST_ALL) == 0) continue;
diff --git a/toolbox/nandread.c b/toolbox/nandread.c
new file mode 100644
index 0000000..9644973
--- /dev/null
+++ b/toolbox/nandread.c
@@ -0,0 +1,286 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <mtd/mtd-user.h>
+#include <sys/ioctl.h>
+
+static int test_empty(const char *buf, size_t size)
+{
+ while(size--) {
+ if (*buf++ != 0xff)
+ return 0;
+ }
+ return 1;
+}
+
+int nandread_main(int argc, char **argv)
+{
+ char *devname = NULL;
+ char *filename = NULL;
+ char *statusfilename = NULL;
+ char *statusext = ".stat";
+ int fd;
+ int outfd = -1;
+ FILE *statusfile = NULL;
+ int ret;
+ int verbose = 0;
+ void *buffer;
+ loff_t pos, opos, end, bpos;
+ loff_t start = 0, len = 0;
+ int c;
+ int i;
+ int empty_pages = 0;
+ int page_count = 0;
+ int bad_block;
+ int rawmode = 0;
+ uint32_t *oob_data;
+ uint8_t *oob_fixed;
+ size_t spare_size = 64;
+ struct mtd_info_user mtdinfo;
+ struct mtd_ecc_stats initial_ecc, last_ecc, ecc;
+ struct mtd_oob_buf oobbuf;
+ struct nand_ecclayout ecclayout;
+
+ do {
+ c = getopt(argc, argv, "d:f:s:S:L:Rhv");
+ if (c == EOF)
+ break;
+ switch (c) {
+ case 'd':
+ devname = optarg;
+ break;
+ case 'f':
+ filename = optarg;
+ break;
+ case 's':
+ spare_size = atoi(optarg);
+ break;
+ case 'S':
+ start = strtoll(optarg, NULL, 0);
+ break;
+ case 'L':
+ len = strtoll(optarg, NULL, 0);
+ break;
+ case 'R':
+ rawmode = 1;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'h':
+ fprintf(stderr, "%s [-d <dev>] [-f file] [-s sparesize] [-vh]\n"
+ " -d <dev> Read from <dev>\n"
+ " -f <file> Write to <file>\n"
+ " -s <size> Number of spare bytes in file (default 64)\n"
+ " -R Raw mode\n"
+ " -S <start> Start offset (default 0)\n"
+ " -L <len> Length (default 0)\n"
+ " -v Print info\n"
+ " -h Print help\n", argv[0]);
+ return -1;
+ case '?':
+ fprintf(stderr, "%s: invalid option -%c\n",
+ argv[0], optopt);
+ exit(1);
+ }
+ } while (1);
+
+ if (optind < argc) {
+ fprintf(stderr, "%s: extra arguments\n", argv[0]);
+ return 1;
+ }
+ if (!devname) {
+ fprintf(stderr, "%s: specify device name\n", argv[0]);
+ return 1;
+ }
+
+ fd = open(devname, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "cannot open %s, %s\n", devname, strerror(errno));
+ return 1;
+ }
+
+ if (filename) {
+ outfd = creat(filename, 0666);
+ if (outfd < 0) {
+ fprintf(stderr, "cannot open %s, %s\n", filename, strerror(errno));
+ return 1;
+ }
+ statusfilename = malloc(strlen(filename) + strlen(statusext) + 1);
+ strcpy(statusfilename, filename);
+ strcat(statusfilename, statusext);
+ statusfile = fopen(statusfilename, "w+");
+ if (!statusfile) {
+ fprintf(stderr, "cannot open %s, %s\n", statusfilename, strerror(errno));
+ return 1;
+ }
+ }
+
+ ret = ioctl(fd, MEMGETINFO, &mtdinfo);
+ if (ret) {
+ fprintf(stderr, "failed get mtd info for %s, %s\n",
+ devname, strerror(errno));
+ return 1;
+ }
+
+ if (verbose) {
+ printf("size: %u\n", mtdinfo.size);
+ printf("erase size: %u\n", mtdinfo.erasesize);
+ printf("write size: %u\n", mtdinfo.writesize);
+ printf("oob size: %u\n", mtdinfo.oobsize);
+ }
+
+ buffer = malloc(mtdinfo.writesize + mtdinfo.oobsize + spare_size);
+ if (!buffer) {
+ fprintf(stderr, "failed allocate readbuffer size %u\n",
+ mtdinfo.writesize + mtdinfo.oobsize);
+ return 1;
+ }
+
+ oobbuf.length = mtdinfo.oobsize;
+ oob_data = (uint32_t *)((uint8_t *)buffer + mtdinfo.writesize);
+ memset(oob_data, 0xff, mtdinfo.oobsize + spare_size);
+ oobbuf.ptr = (uint8_t *)oob_data + spare_size;
+
+ ret = ioctl(fd, ECCGETLAYOUT, &ecclayout);
+ if (ret) {
+ fprintf(stderr, "failed get ecc layout for %s, %s\n",
+ devname, strerror(errno));
+ return 1;
+ }
+ if (verbose) {
+ printf("ecc bytes: %u\n", ecclayout.eccbytes);
+ printf("oobavail: %u\n", ecclayout.oobavail);
+ }
+ if (ecclayout.oobavail > spare_size)
+ printf("oobavail, %d > image spare size, %d\n", ecclayout.oobavail, spare_size);
+
+ ret = ioctl(fd, ECCGETSTATS, &initial_ecc);
+ if (ret) {
+ fprintf(stderr, "failed get ecc stats for %s, %s\n",
+ devname, strerror(errno));
+ return 1;
+ }
+ last_ecc = initial_ecc;
+
+ if (verbose) {
+ printf("initial ecc corrected: %u\n", initial_ecc.corrected);
+ printf("initial ecc failed: %u\n", initial_ecc.failed);
+ printf("initial ecc badblocks: %u\n", initial_ecc.badblocks);
+ printf("initial ecc bbtblocks: %u\n", initial_ecc.bbtblocks);
+ }
+
+ if (rawmode) {
+ rawmode = mtdinfo.oobsize;
+ ret = ioctl(fd, MTDFILEMODE, MTD_MODE_RAW);
+ if (ret) {
+ fprintf(stderr, "failed set raw mode for %s, %s\n",
+ devname, strerror(errno));
+ return 1;
+ }
+ }
+
+ end = len ? (start + len) : mtdinfo.size;
+ for (pos = start, opos = 0; pos < end; pos += mtdinfo.writesize) {
+ bad_block = 0;
+ if (verbose > 3)
+ printf("reading at %llx\n", pos);
+ lseek64(fd, pos, SEEK_SET);
+ ret = read(fd, buffer, mtdinfo.writesize + rawmode);
+ if (ret < (int)mtdinfo.writesize) {
+ fprintf(stderr, "short read at %llx, %d\n", pos, ret);
+ bad_block = 2;
+ }
+ if (!rawmode) {
+ oobbuf.start = pos;
+ ret = ioctl(fd, MEMREADOOB, &oobbuf);
+ if (ret) {
+ fprintf(stderr, "failed to read oob data at %llx, %d\n", pos, ret);
+ bad_block = 2;
+ }
+ }
+ ret = ioctl(fd, ECCGETSTATS, &ecc);
+ if (ret) {
+ fprintf(stderr, "failed get ecc stats for %s, %s\n",
+ devname, strerror(errno));
+ return 1;
+ }
+ bpos = pos / mtdinfo.erasesize * mtdinfo.erasesize;
+ ret = ioctl(fd, MEMGETBADBLOCK, &bpos);
+ if (ret && errno != EOPNOTSUPP) {
+ printf("badblock at %llx\n", pos);
+ bad_block = 1;
+ }
+ if (ecc.corrected != last_ecc.corrected)
+ printf("ecc corrected, %u, at %llx\n", ecc.corrected - last_ecc.corrected, pos);
+ if (ecc.failed != last_ecc.failed)
+ printf("ecc failed, %u, at %llx\n", ecc.failed - last_ecc.failed, pos);
+ if (ecc.badblocks != last_ecc.badblocks)
+ printf("ecc badblocks, %u, at %llx\n", ecc.badblocks - last_ecc.badblocks, pos);
+ if (ecc.bbtblocks != last_ecc.bbtblocks)
+ printf("ecc bbtblocks, %u, at %llx\n", ecc.bbtblocks - last_ecc.bbtblocks, pos);
+
+ if (!rawmode) {
+ oob_fixed = (uint8_t *)oob_data;
+ for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) {
+ int len = ecclayout.oobfree[i].length;
+ if (oob_fixed + len > oobbuf.ptr)
+ len = oobbuf.ptr - oob_fixed;
+ if (len) {
+ memcpy(oob_fixed, oobbuf.ptr + ecclayout.oobfree[i].offset, len);
+ oob_fixed += len;
+ }
+ }
+ }
+
+ if (outfd >= 0) {
+ ret = write(outfd, buffer, mtdinfo.writesize + spare_size);
+ if (ret < (int)(mtdinfo.writesize + spare_size)) {
+ fprintf(stderr, "short write at %llx, %d\n", pos, ret);
+ close(outfd);
+ outfd = -1;
+ }
+ if (ecc.corrected != last_ecc.corrected)
+ fprintf(statusfile, "%08llx: ecc corrected\n", opos);
+ if (ecc.failed != last_ecc.failed)
+ fprintf(statusfile, "%08llx: ecc failed\n", opos);
+ if (bad_block == 1)
+ fprintf(statusfile, "%08llx: badblock\n", opos);
+ if (bad_block == 2)
+ fprintf(statusfile, "%08llx: read error\n", opos);
+ opos += mtdinfo.writesize + spare_size;
+ }
+
+ last_ecc = ecc;
+ page_count++;
+ if (test_empty(buffer, mtdinfo.writesize + mtdinfo.oobsize + spare_size))
+ empty_pages++;
+ else if (verbose > 2 || (verbose > 1 && !(pos & (mtdinfo.erasesize - 1))))
+ printf("page at %llx (%d oobbytes): %08x %08x %08x %08x "
+ "%08x %08x %08x %08x\n", pos, oobbuf.start,
+ oob_data[0], oob_data[1], oob_data[2], oob_data[3],
+ oob_data[4], oob_data[5], oob_data[6], oob_data[7]);
+ }
+
+ if (outfd >= 0) {
+ fprintf(statusfile, "read %d pages, %d empty\n", page_count, empty_pages);
+ fprintf(statusfile, "total ecc corrected, %u\n", ecc.corrected - initial_ecc.corrected);
+ fprintf(statusfile, "total ecc failed, %u\n", ecc.failed - initial_ecc.failed);
+ fprintf(statusfile, "total ecc badblocks, %u\n", ecc.badblocks - initial_ecc.badblocks);
+ fprintf(statusfile, "total ecc bbtblocks, %u\n", ecc.bbtblocks - initial_ecc.bbtblocks);
+ }
+ if (verbose) {
+ printf("total ecc corrected, %u\n", ecc.corrected - initial_ecc.corrected);
+ printf("total ecc failed, %u\n", ecc.failed - initial_ecc.failed);
+ printf("total ecc badblocks, %u\n", ecc.badblocks - initial_ecc.badblocks);
+ printf("total ecc bbtblocks, %u\n", ecc.bbtblocks - initial_ecc.bbtblocks);
+ }
+ printf("read %d pages, %d empty\n", page_count, empty_pages);
+
+ return 0;
+}
+
diff --git a/toolbox/newfs_msdos.c b/toolbox/newfs_msdos.c
index 4483cc0..ff9e844 100644
--- a/toolbox/newfs_msdos.c
+++ b/toolbox/newfs_msdos.c
@@ -235,35 +235,6 @@ static void setstr(u_int8_t *, const char *, size_t);
static void usage(void);
#ifdef ANDROID
-static void err(int val, const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- char *fmt2;
- asprintf(&fmt2, "%s\n", fmt);
- vfprintf(stderr, fmt2, ap);
- free(fmt2);
- va_end(ap);
-}
-
-static void errx(int val, const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- char *fmt2;
- asprintf(&fmt2, "%s\n", fmt);
- vfprintf(stderr, fmt2, ap);
- free(fmt2);
- va_end(ap);
-}
-
-static void warnx(const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- char *fmt2;
- asprintf(&fmt2, "%s\n", fmt);
- vfprintf(stderr, fmt2, ap);
- free(fmt2);
- va_end(ap);
-}
#define powerof2(x) ((((x) - 1) & (x)) == 0)
#define howmany(x, y) (((x) + ((y) - 1)) / (y))
#define MAX(x,y) ((x) > (y) ? (x) : (y))
@@ -443,11 +414,14 @@ newfs_msdos_main(int argc, char *argv[])
if (!(opt_f || (opt_h && opt_u && opt_S && opt_s && oflag))) {
off_t delta;
getdiskinfo(fd, fname, dtype, oflag, &bpb);
+ if (opt_s) {
+ bpb.bsec = opt_s;
+ }
bpb.bsec -= (opt_ofs / bpb.bps);
delta = bpb.bsec % bpb.spt;
if (delta != 0) {
- warnx("trim %d sectors to adjust to a multiple of %d",
- (int)delta, bpb.spt);
+ warnx("trim %d sectors from %d to adjust to a multiple of %d",
+ (int)delta, bpb.bsec, bpb.spt);
bpb.bsec -= delta;
}
if (bpb.spc == 0) { /* set defaults */
@@ -745,8 +719,10 @@ newfs_msdos_main(int argc, char *argv[])
}
if ((n = write(fd, img, bpb.bps)) == -1)
err(1, "%s", fname);
- if ((unsigned)n != bpb.bps)
+ if ((unsigned)n != bpb.bps) {
errx(1, "%s: can't write sector %u", fname, lsn);
+ exit(1);
+ }
}
}
return 0;
@@ -811,20 +787,31 @@ getdiskinfo(int fd, const char *fname, const char *dtype, __unused int oflag,
struct hd_geometry geom;
if (ioctl(fd, BLKSSZGET, &bpb->bps)) {
- fprintf(stderr, "Error getting bytes / sector (%s)", strerror(errno));
+ fprintf(stderr, "Error getting bytes / sector (%s)\n", strerror(errno));
exit(1);
}
ckgeom(fname, bpb->bps, "bytes/sector");
if (ioctl(fd, BLKGETSIZE, &bpb->bsec)) {
- fprintf(stderr, "Error getting blocksize (%s)", strerror(errno));
+ fprintf(stderr, "Error getting blocksize (%s)\n", strerror(errno));
exit(1);
}
if (ioctl(fd, HDIO_GETGEO, &geom)) {
- fprintf(stderr, "Error getting gemoetry (%s)", strerror(errno));
- exit(1);
+ fprintf(stderr, "Error getting gemoetry (%s) - trying sane values\n", strerror(errno));
+ geom.heads = 64;
+ geom.sectors = 63;
+ }
+
+ if (!geom.heads) {
+ printf("Bogus heads from kernel - setting sane value\n");
+ geom.heads = 64;
+ }
+
+ if (!geom.sectors) {
+ printf("Bogus sectors from kernel - setting sane value\n");
+ geom.sectors = 63;
}
bpb->spt = geom.sectors;