Hello,
Some time ago, I wrote a conv=sparse option for dd, attached is the
patch. The goal is to recreate a sparse file from a file with 0s.
Typically, I use it to do this:
# mount /dev/hda6 /mnt/mnt
# dd bs=1M < /dev/zero > /mnt/mnt/foo
# rm -f /mnt/mnt/foo
# umount /mnt/mnt
# dd bs=1M conv=sparse < /dev/hda6 > /mnt/savhda6
Which creates a sparse file out of my not-so-filled partition. Of
course, there may be other uses: re-sparsing a qemu image before tarring
it for public download, etc.
Maybe it could be useful to apply it mainstream?
Samuel
--- coreutils-5.2.1/src/dd.c 2005-06-26 22:31:51.000000000 +0200
+++ ../coreutils-mine/build-tree/coreutils-5.2.1/src/dd.c 2005-06-23
22:49:33.000000000 +0200
@@ -80,6 +80,7 @@
#define C_SYNC 02000
/* Use separate input and output buffers, and combine partial input blocks. */
#define C_TWOBUFS 04000
+#define C_SPARSE 010000
/* The name this program was run with. */
char *program_name;
@@ -168,9 +169,12 @@
{"noerror", C_NOERROR}, /* Ignore i/o errors. */
{"notrunc", C_NOTRUNC}, /* Do not truncate output file. */
{"sync", C_SYNC}, /* Pad input records to ibs with NULs. */
+ {"sparse", C_SPARSE}, /* Generate sparse file */
{NULL, 0}
};
+size_t sparseblocksize;
+const char *zeroblock;
/* Translation table formed by applying successive transformations. */
static unsigned char trans_table[256];
@@ -1079,7 +1083,41 @@
if (ibuf == obuf) /* If not C_TWOBUFS. */
{
- size_t nwritten = full_write (STDOUT_FILENO, obuf, n_bytes_read);
+ size_t nwritten;
+
+ if (conversions_mask & C_SPARSE && (n_bytes_read % sparseblocksize)
== 0)
+ {
+ size_t towrite = 0;
+ nwritten = 0;
+ if (memcmp(obuf, zeroblock, sparseblocksize))
+ goto firstnotzero;
+ while (nwritten < n_bytes_read) {
+ do {
+ towrite += sparseblocksize;
+ } while (nwritten + towrite < n_bytes_read &&
+ !memcmp (obuf + nwritten + towrite, zeroblock,
sparseblocksize));
+ if (lseek (STDOUT_FILENO, towrite, SEEK_CUR) == -1)
+ {
+ error (0, errno, _("seeking %s"), quote (output_file));
+ quit (EXIT_FAILURE);
+ }
+ nwritten += towrite;
+ if (nwritten == n_bytes_read)
+ break;
+ towrite = 0;
+firstnotzero:
+ do {
+ towrite += sparseblocksize;
+ } while (nwritten + towrite < n_bytes_read &&
+ memcmp (obuf + nwritten + towrite, zeroblock,
sparseblocksize));
+ if (full_write (STDOUT_FILENO, obuf + nwritten, towrite) !=
towrite)
+ break;
+ nwritten += towrite;
+ towrite = 0;
+ }
+ }
+ else
+ nwritten = full_write (STDOUT_FILENO, obuf, n_bytes_read);
st.bytes += nwritten;
@@ -1261,6 +1299,18 @@
output_file = _("standard output");
}
+ if (conversions_mask & C_SPARSE)
+ {
+ struct stat stdout_stat;
+
+ if (fstat (STDOUT_FILENO, &stdout_stat) != 0)
+ error (EXIT_FAILURE, errno, _("cannot fstat %s"),
+ quote (output_file));
+
+ sparseblocksize = stdout_stat.st_blksize;
+ zeroblock = calloc(1,sparseblocksize);
+ }
+
install_handler (SIGINT, interrupt_handler);
install_handler (SIGQUIT, interrupt_handler);
install_handler (SIGPIPE, interrupt_handler);
_______________________________________________
Bug-coreutils mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-coreutils