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
This commit is contained in:
patacongo 2008-11-15 16:36:32 +00:00
parent 4a9e922943
commit d6aa80bbd0
6 changed files with 137 additions and 173 deletions

View File

@ -754,14 +754,50 @@ dd if=<infile> of=<outfile> [bs=<sectsize>] [count=<sectors
</pre></ul>
<p>
<b>Synopsis</b>.
Copy blocks from &lt;infile&gt; to &lt;outfile&gt;. As an example:
Copy blocks from &lt;infile&gt; to &lt;outfile&gt;.
&lt;infile&gt; or &lt;outfile&gt; may be the path to a standard file, a character device, or a block device.
Examples follow:
</p>
<ol>
<li>
Read from character device, write to regular file.
This will create a new file of the specified size filled with zero.
<ul><pre>
nsh&gt; ls -l /dev
/dev:
crw-rw-rw- 0 zero
nsh&gt; dd if=/dev/zero of=/tmp/zeros bs=64 count=16
nsh&gt; ls -l /tmp
/tmp:
-rw-rw-rw- 1024 ZEROS
</pre></ul>
</p>
</li>
<li>
Read from character device, write to block device.
This will fill the entire block device with zeros.
</li>
<ul><pre>
nsh&gt; ls -l /dev
/dev:
brw-rw-rw- 0 ram0
crw-rw-rw- 0 zero
nsh&gt; dd if=/dev/zero of=/dev/ram0
</pre></ul>
</li>
<li>
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.
</li>
<ul><pre>
nsh&gt; ls -l /dev
/dev:
crw-rw-rw- 0 null
brw-rw-rw- 0 ram0
nsh&gt; dd if=/dev/ram0 of=/dev/null
</pre></ul>
</li>
</ol>
<table width ="100%">
<tr bgcolor="#e4e4e4">

View File

@ -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;
}

View File

@ -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;

View File

@ -252,15 +252,38 @@ o cp <source-path> <dest-path>
o dd if=<infile> of=<outfile> [bs=<sectsize>] [count=<sectors>] [skip=<sectors>]
Copy blocks from <infile> to <outfile>.
Copy blocks from <infile> to <outfile>. <nfile> or <outfile> 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 [<string|$name> [<string|$name>...]]
Copy the sequence of strings and expanded environment variables to

View File

@ -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;
}

View File

@ -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);