From d6aa80bbd02d970b7d2c179c153e195d42cf51cc Mon Sep 17 00:00:00 2001 From: patacongo Date: Sat, 15 Nov 2008 16:36:32 +0000 Subject: [PATCH] NSH dd command test with block devices git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1242 42af7a65-404d-4744-a932-0658087f49c3 --- Documentation/NuttShell.html | 40 ++++++++++- drivers/bch/bchlib_read.c | 134 +---------------------------------- drivers/bch/bchlib_write.c | 2 +- examples/nsh/README.txt | 27 ++++++- examples/nsh/nsh_ddcmd.c | 95 ++++++++++++++++--------- include/nuttx/fs.h | 12 +++- 6 files changed, 137 insertions(+), 173 deletions(-) diff --git a/Documentation/NuttShell.html b/Documentation/NuttShell.html index a2a4a7c5b3..9418056eb9 100644 --- a/Documentation/NuttShell.html +++ b/Documentation/NuttShell.html @@ -754,14 +754,50 @@ dd if=<infile> of=<outfile> [bs=<sectsize>] [count=<sectors

Synopsis. - Copy blocks from <infile> to <outfile>. As an example: + Copy blocks from <infile> to <outfile>. + <infile> or <outfile> may be the path to a standard file, a character device, or a block device. + Examples follow: +

+
    +
  1. + Read from character device, write to regular file. + This will create a new file of the specified size filled with zero.
      +nsh> ls -l /dev
      +/dev:
      + crw-rw-rw-       0 zero
       nsh> dd if=/dev/zero of=/tmp/zeros bs=64 count=16
       nsh> ls -l /tmp
       /tmp:
        -rw-rw-rw-    1024 ZEROS
       
    -

    +
  2. +
  3. + Read from character device, write to block device. + This will fill the entire block device with zeros. +
  4. + + +
  5. + Read from a block devic, write to a character device. This + will read the entire block device and dump the contents in + the bit bucket. +
  6. + + +
diff --git a/drivers/bch/bchlib_read.c b/drivers/bch/bchlib_read.c index 7af72ce8ad..d2301d4392 100644 --- a/drivers/bch/bchlib_read.c +++ b/drivers/bch/bchlib_read.c @@ -85,7 +85,7 @@ ssize_t bchlib_read(FAR void *handle, FAR char *buffer, size_t offset, size_t len) { - FAR struct bchlib_s *bch; + FAR struct bchlib_s *bch = (FAR struct bchlib_s *)handle; size_t nsectors; size_t sector; uint16 sectoffset; @@ -202,135 +202,3 @@ ssize_t bchlib_read(FAR void *handle, FAR char *buffer, size_t offset, size_t le return bytesread; } - -/**************************************************************************** - * Name: bchlib_write - * - * Description: - * Write to the block device set-up by bchlib_setup as if it were a character - * device. - * - ****************************************************************************/ - -ssize_t bchlib_write(FAR void *handle, FAR const char *buffer, size_t offset, size_t len) -{ - FAR struct bchlib_s *bch; - size_t nsectors; - size_t sector; - uint16 sectoffset; - size_t nbytes; - size_t byteswritten; - int ret; - - /* Get rid of this special case right away */ - - if (len < 1) - { - return 0; - } - - /* Convert the file position into a sector number an offset. */ - - sector = offset / bch->sectsize; - sectoffset = offset - sector * bch->sectsize; - - if (sector >= bch->nsectors) - { - return -EFBIG; - } - - /* Write the initial partial sector */ - - byteswritten = 0; - if (sectoffset > 0) - { - /* Read the full sector into the sector buffer */ - - bchlib_readsector(bch, sector); - - /* Copy the tail end of the sector from the user buffer */ - - if (sectoffset + len > bch->sectsize) - { - nbytes = bch->sectsize - sectoffset; - } - else - { - nbytes = len; - } - - memcpy(&bch->buffer[sectoffset], buffer, nbytes); - bch->dirty = TRUE; - - /* Adjust pointers and counts */ - - sectoffset = 0; - sector++; - - if (sector >= bch->nsectors) - { - return nbytes; - } - - byteswritten = nbytes; - buffer += nbytes; - len -= nbytes; - } - - /* Then write all of the full sectors following the partial sector */ - - if (len >= bch->sectsize ) - { - nsectors = len / bch->sectsize; - if (sector + nsectors > bch->nsectors) - { - nsectors = bch->nsectors - sector; - } - - /* Write the contiguous sectors */ - - ret = bch->inode->u.i_bops->write(bch->inode, bch->buffer, sector, nsectors); - if (ret < 0) - { - fdbg("Write failed: %d\n"); - return ret; - } - - /* Adjust pointers and counts */ - - sectoffset = 0; - sector += nsectors; - - nbytes = nsectors * bch->sectsize; - byteswritten += nbytes; - - if (sector >= bch->nsectors) - { - return byteswritten; - } - - buffer += nbytes; - len -= nbytes; - } - - /* Then write any partial final sector */ - - if (len > 0) - { - /* Read the sector into the sector buffer */ - - bchlib_readsector(bch, sector); - - /* Copy the head end of the sector from the user buffer */ - - memcpy(bch->buffer, buffer, len); - bch->dirty = TRUE; - - /* Adjust counts */ - - byteswritten += len; - } - - return byteswritten; -} - diff --git a/drivers/bch/bchlib_write.c b/drivers/bch/bchlib_write.c index a897215ea4..ad0737faf3 100644 --- a/drivers/bch/bchlib_write.c +++ b/drivers/bch/bchlib_write.c @@ -85,7 +85,7 @@ ssize_t bchlib_write(FAR void *handle, FAR const char *buffer, size_t offset, size_t len) { - FAR struct bchlib_s *bch; + FAR struct bchlib_s *bch = (FAR struct bchlib_s *)handle; size_t nsectors; size_t sector; uint16 sectoffset; diff --git a/examples/nsh/README.txt b/examples/nsh/README.txt index 4b822e02e9..9ea0464099 100644 --- a/examples/nsh/README.txt +++ b/examples/nsh/README.txt @@ -252,15 +252,38 @@ o cp o dd if= of= [bs=] [count=] [skip=] - Copy blocks from to . + Copy blocks from to . or may + be the path to a standard file, a character device, or a block device. - Example: + Examples: + + 1. Read from character device, write to regular file. This will + create a new file of the specified size filled with zero. nsh> dd if=/dev/zero of=/tmp/zeros bs=64 count=16 nsh> ls -l /tmp /tmp: -rw-rw-rw- 1024 ZEROS + 2. Read from character device, write to block device. This will + fill the entire block device with zeros. + + nsh> ls -l /dev + /dev: + brw-rw-rw- 0 ram0 + crw-rw-rw- 0 zero + nsh> dd if=/dev/zero of=/dev/ram0 + + 3. Read from a block devic, write to a character device. This + will read the entire block device and dump the contents in + the bit bucket. + + nsh> ls -l /dev + /dev: + crw-rw-rw- 0 null + brw-rw-rw- 0 ram0 + nsh> dd if=/dev/ram0 of=/dev/null + o echo [ [...]] Copy the sequence of strings and expanded environment variables to diff --git a/examples/nsh/nsh_ddcmd.c b/examples/nsh/nsh_ddcmd.c index 86f829f2be..48cc822f10 100644 --- a/examples/nsh/nsh_ddcmd.c +++ b/examples/nsh/nsh_ddcmd.c @@ -209,11 +209,24 @@ static int dd_writeblk(struct dd_s *dd) ssize_t nbytes; off_t offset = (dd->sector - dd->skip) * dd->sectsize; + /* Write the sector at the specified offset */ + nbytes = bchlib_write(DD_OUTHANDLE, (char*)dd->buffer, offset, dd->sectsize); if (nbytes < 0) { - nsh_output(dd->vtbl, g_fmtcmdfailed, g_dd, "bshlib_write", NSH_ERRNO); - return ERROR; + /* bchlib_write return -EFBIG on attempts to write past the end of + * the device. + */ + + if (nbytes == -EFBIG) + { + dd->eof = TRUE; /* Set end-of-file */ + } + else + { + nsh_output(dd->vtbl, g_fmtcmdfailed, g_dd, "bshlib_write", NSH_ERRNO_OF(-nbytes)); + return ERROR; + } } return OK; @@ -238,7 +251,7 @@ static int dd_writech(struct dd_s *dd) nbytes = write(DD_OUTFD, buffer, dd->sectsize - written); if (nbytes < 0) { - nsh_output(dd->vtbl, g_fmtcmdfailed, g_dd, "write", NSH_ERRNO); + nsh_output(dd->vtbl, g_fmtcmdfailed, g_dd, "write", NSH_ERRNO_OF(-nbytes)); return ERROR; } @@ -263,11 +276,14 @@ static int dd_readblk(struct dd_s *dd) nbytes = bchlib_read(DD_INHANDLE, (char*)dd->buffer, offset, dd->sectsize); if (nbytes < 0) { - nsh_output(dd->vtbl, g_fmtcmdfailed, g_dd, "bshlib_read", NSH_ERRNO); + nsh_output(dd->vtbl, g_fmtcmdfailed, g_dd, "bshlib_read", NSH_ERRNO_OF(-nbytes)); return ERROR; } + /* bchlib_read return 0 on attempts to write past the end of the device. */ + dd->nbytes = nbytes; + dd->eof = (nbytes == 0); return OK; } #endif @@ -287,7 +303,7 @@ static int dd_readch(struct dd_s *dd) nbytes = read(DD_INFD, buffer, dd->sectsize - dd->nbytes); if (nbytes < 0) { - nsh_output(dd->vtbl, g_fmtcmdfailed, g_dd, "read", NSH_ERRNO); + nsh_output(dd->vtbl, g_fmtcmdfailed, g_dd, "read", NSH_ERRNO_OF(-nbytes)); return ERROR; } @@ -337,7 +353,7 @@ static inline int dd_infopen(const char *name, struct dd_s *dd) type = dd_filetype(name); if (type < 0) { - nsh_output(dd->vtbl, g_fmtcmdfailed, g_dd, "stat", NSH_ERRNO); + nsh_output(dd->vtbl, g_fmtcmdfailed, g_dd, "stat", NSH_ERRNO_OF(-type)); return type; } @@ -449,9 +465,9 @@ static inline int dd_outfopen(const char *name, struct dd_s *dd) int cmd_dd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { struct dd_s dd; - const char *infile = NULL; - const char *outfile = NULL; - int ret; + char *infile = NULL; + char *outfile = NULL; + int ret = ERROR; int i; /* Initialize the dd structure */ @@ -490,11 +506,11 @@ int cmd_dd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) { if (strncmp(argv[i], "if=", 3) == 0) { - infile = &argv[i][3]; + infile = nsh_getfullpath(vtbl, &argv[i][3]); } else if (strncmp(argv[i], "of=", 3) == 0) { - outfile = &argv[i][3]; + outfile = nsh_getfullpath(vtbl, &argv[i][3]); } else if (strncmp(argv[i], "bs=", 3) == 0) { @@ -514,14 +530,14 @@ int cmd_dd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) if (!infile || !outfile) { nsh_output(vtbl, g_fmtargrequired, g_dd); - return ERROR; + goto errout_with_paths; } #endif if (dd.skip < 0 || dd.skip > dd.nsectors) { nsh_output(vtbl, g_fmtarginvalid, g_dd); - return ERROR; + goto errout_with_paths; } /* Allocate the I/O buffer */ @@ -530,7 +546,7 @@ int cmd_dd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) if (!dd.buffer) { nsh_output(vtbl, g_fmtcmdoutofmemory, g_dd); - return ERROR; + goto errout_with_paths; } /* Open the input file */ @@ -538,7 +554,7 @@ int cmd_dd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) ret = dd_infopen(infile, &dd); if (ret < 0) { - return ret; + goto errout_with_paths; } /* Open the output file */ @@ -562,38 +578,53 @@ int cmd_dd(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv) goto errout_with_outf; } - /* Pad with zero if necessary (at the end of file only) */ + /* Has the incoming data stream ended? */ - for (i = dd.nbytes; i < dd.sectsize; i++) + if (!dd.eof) { - dd.buffer[i] = 0; - } + /* Pad with zero if necessary (at the end of file only) */ - /* Write one sector to the output file */ - - if (dd.sector >= dd.skip) - { - ret = DD_WRITE(&dd); - if (ret < 0) + for (i = dd.nbytes; i < dd.sectsize; i++) { - goto errout_with_outf; + dd.buffer[i] = 0; } - /* Decrement to show that a sector was written */ + /* Write one sector to the output file */ - dd.nsectors--; + if (dd.sector >= dd.skip) + { + ret = DD_WRITE(&dd); + if (ret < 0) + { + goto errout_with_outf; + } + + /* Decrement to show that a sector was written */ + + dd.nsectors--; + } + + /* Increment the sector number */ + + dd.sector++; } - - /* Increment the sector number */ - - dd.sector++; } + ret = OK; errout_with_outf: DD_INCLOSE(&dd); errout_with_inf: DD_OUTCLOSE(&dd); free(dd.buffer); +errout_with_paths: + if (infile) + { + free(infile); + } + if (outfile) + { + free(outfile); + } return ret; } diff --git a/include/nuttx/fs.h b/include/nuttx/fs.h index 8a174b0117..ad979c5849 100644 --- a/include/nuttx/fs.h +++ b/include/nuttx/fs.h @@ -370,9 +370,10 @@ EXTERN int lib_flushall(FAR struct streamlist *list); * subdirectory */ -/* Register /dev/null */ +/* Register /dev/null and /dev/zero */ EXTERN void devnull_register(void); +EXTERN void devzero_register(void); /* Setup the loop device so that it exports the file referenced by 'filename' * as a block device. @@ -382,12 +383,17 @@ EXTERN int losetup(const char *devname, const char *filename, uint16 sectsize, off_t offset, boolean readonly); EXTERN int loteardown(const char *devname); -/* Setup so that the block driver referenced by 'blkdev' can be accessed - * similar to a character device. +/* Setup so that the block driver referenced by 'blkdev' can be accessed + * similar to a character device. + * + * Access via a character device: */ EXTERN int bchdev_register(const char *blkdev, const char *chardev, boolean readonly); EXTERN int bchdev_unregister(const char *chardev); + +/* Low level, direct access: */ + EXTERN int bchlib_setup(const char *blkdev, boolean readonly, FAR void **handle); EXTERN int bchlib_teardown(FAR void *handle); EXTERN ssize_t bchlib_read(FAR void *handle, FAR char *buffer, size_t offset, size_t len);