Patch / RFC: add "flashcp" applet
Tito
farmatito at tiscali.it
Sat Nov 14 21:15:14 UTC 2009
Hi,
just some ideas I had while looking at your patch,
hope they can help you to improve/optimize it.
Ciao,
Tito
PS.: progress() is used only in two sites, is it worth the hassle, couldn't it be inlined?
On Saturday 14 November 2009 20:00:44 Stefan Seyfried wrote:
> Hi,
>
> the attached patch implements a "flashcp" similar the one form
> mtd-utils.
>
> I have read the style-guide and I think that I did everything right.
> If so, please "git am", if not, please comment ;)
>
> Have fun,
>
> Stefan
>
> int flashcp_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
> +int flashcp_main(int argc, char *argv[])
> +{
> + int fd_f, fd_d; /* input file and mtd device file descriptors */
> + int i, count;
> + int filesize_kb;
> + unsigned opts;
> + size_t todo, done;
> + ssize_t ret;
> + struct mtd_info_user mtd;
> + struct erase_info_user e;
> + struct stat f;
> + uint8_t buf[BUFSIZE], buf2[BUFSIZE];
> +
> + opts = getopt32(argv, "rvh");
> +
> + if (optind + 2 != argc || opts & FCP_OPT_h) {
> + bb_show_usage();
> + }
> + argv += optind;
> +
> + /* open input file and mtd device and do sanity checks */
> + fd_d = xopen(argv[1], O_SYNC | O_RDWR);
Use xioctl here?
> + if (ioctl(fd_d, MEMGETINFO, &mtd) < 0) {
> + bb_error_msg_and_die("%s is no valid MTD flash device", argv[1]);
> + }
> +
> + fd_f = xopen(argv[0], O_RDONLY);
Use xstat here?
xstat(argv[0], &f);
> + if (fstat (fd_f, &f) < 0) {
> + bb_error_msg_and_die("fstat");
> + }
> + if (f.st_size > mtd.size) {
> + bb_error_msg_and_die("%s bigger than %s", argv[0], argv[1]);
> + }
> +
I know this is a gccism, still couldn't resist.... ;-)
filesize_kb = ( f.st_size / 1024 ) ? : 1;
> + filesize_kb = f.st_size / 1024;
> + if (filesize_kb == 0) { /* wrong output if size is < 1k, but avoids division by zero */
> + filesize_kb++; /* in addition, this reduces the size ?!? (at least on i386) */ + }
> +
> + /* always erase a complete block */
> + e.start = 0;
> + e.length = mtd.erasesize;
> + count = (f.st_size + mtd.erasesize - 1) / mtd.erasesize;
> +
Maybe keep it simple here and skip this optimization to save size?
> + /* optimization: if not verbose, erase in one go */
> + if (!(opts & FCP_OPT_v)) {
> + e.length = mtd.erasesize * count;
> + count = 1;
> + }
> +
> + /* erase 1 block at a time to be able to give verbose output */
> + e.length = mtd.erasesize;
> + for (i = 1; i <= count; i++) {
> + if (opts & FCP_OPT_v) {
> + progress(0, i, count);
> + }
Use xioctl here ?
> + if (ioctl(fd_d, MEMERASE, &e) < 0) {
> + bb_perror_msg_and_die("MEMERASE blocks 0x%.8x-0x%.8x on %s",
> + (unsigned)e.start, (unsigned)(e.start + e.length), argv[1]);
> + }
> + e.start += mtd.erasesize;
> + }
> + if (opts & FCP_OPT_v) {
is puts("") smaller ?
> + printf("\n");
> + }
> +
> + /* doing this outer loop gives significantly smaller code
> + than doing two separate loops for writing and verifying */
> + for (i = 1; i <= 2; i++) {
> + /* not using xlseek here. Failure of the lseek will only hurt during
> + verification stage and xlseek is signifikantly bigger */
> + lseek(fd_f, 0, SEEK_SET);
> + lseek(fd_d, 0, SEEK_SET);
> + todo = f.st_size;
> + done = 0;
> + count = BUFSIZE;
> + while (todo) {
> + if (todo < BUFSIZE) {
> + count = todo;
> + }
> + if (opts & FCP_OPT_v) {
> + progress(i, (done + count) / 1024, filesize_kb);
> + }
Use xread(int fd, void *buf, size_t count) here?
> + ret = full_read(fd_f, buf, count);
> + if (ret != count) {
> + bb_perror_msg_and_die("short read of %s", argv[0]);
> + }
> + if (i == 1) {
Use xwrite(int fd, const void *buf, size_t count) here ?
> + ret = write(fd_d, buf, count);
> + if (ret != count) {
> + bb_perror_msg_and_die("while writing to x%.8x-0x%.8x on %s: "
> + "%d/%lu bytes written to flash. returncode: %ld\n",
> + done, done + count, argv[1], done + ret,
> + (unsigned long)f.st_size, (long)ret);
> + }
> + } else { /* i == 2 */
> + full_read(fd_d, buf2, count);
No error checking on this full_read ? Use xread instead?
> + if (memcmp(buf, buf2, count)) {
Maybe shorten error message?
> + bb_error_msg_and_die("file does not match flash data, "
> + "first mismatch at 0x%.8x-0x%.8x\n",
> + done, done + count);
> + }
> + }
> +
> + done += count;
> + todo -= count;
> + }
> +
> + if (opts & FCP_OPT_v) {
is puts("") smaller ?
> + printf("\n");
> + }
> + }
> +
> + /* we won't come here if there was an error */
> + if (opts & FCP_OPT_r) {
is puts("rebooting...") smaller ?
> + printf("rebooting...\n");
> + sleep(1);
> + reboot(RB_AUTOBOOT);
> + }
> +
> + return EXIT_SUCCESS;
More information about the busybox
mailing list