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:
parent
4a9e922943
commit
d6aa80bbd0
|
@ -754,14 +754,50 @@ dd if=<infile> of=<outfile> [bs=<sectsize>] [count=<sectors
|
|||
</pre></ul>
|
||||
<p>
|
||||
<b>Synopsis</b>.
|
||||
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:
|
||||
</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> 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
|
||||
</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> ls -l /dev
|
||||
/dev:
|
||||
brw-rw-rw- 0 ram0
|
||||
crw-rw-rw- 0 zero
|
||||
nsh> 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> ls -l /dev
|
||||
/dev:
|
||||
crw-rw-rw- 0 null
|
||||
brw-rw-rw- 0 ram0
|
||||
nsh> dd if=/dev/ram0 of=/dev/null
|
||||
</pre></ul>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<table width ="100%">
|
||||
<tr bgcolor="#e4e4e4">
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue