diff options
Diffstat (limited to 'toolbox')
| -rw-r--r-- | toolbox/Android.mk | 4 | ||||
| -rw-r--r-- | toolbox/chown.c | 27 | ||||
| -rw-r--r-- | toolbox/ionice.c | 57 | ||||
| -rw-r--r-- | toolbox/ls.c | 47 | ||||
| -rw-r--r-- | toolbox/nandread.c | 286 | ||||
| -rw-r--r-- | toolbox/newfs_msdos.c | 59 |
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; |
