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