Index: bin/dd/args.c =================================================================== --- bin/dd/args.c +++ bin/dd/args.c @@ -315,6 +315,7 @@ { "ascii", C_ASCII, C_EBCDIC, e2a_POSIX }, { "block", C_BLOCK, C_UNBLOCK, NULL }, { "ebcdic", C_EBCDIC, C_ASCII, a2e_POSIX }, + { "trim", C_TRIM, 0, NULL }, { "ibm", C_EBCDIC, C_ASCII, a2ibm_POSIX }, { "lcase", C_LCASE, C_UCASE, NULL }, { "noerror", C_NOERROR, 0, NULL }, Index: bin/dd/dd.h =================================================================== --- bin/dd/dd.h +++ bin/dd/dd.h @@ -99,6 +99,7 @@ #define C_STATUS 0x08000000 #define C_NOXFER 0x10000000 #define C_NOINFO 0x20000000 +#define C_TRIM 0x40000000 #define C_PARITY (C_PAREVEN | C_PARODD | C_PARNONE | C_PARSET) Index: bin/dd/dd.1 =================================================================== --- bin/dd/dd.1 +++ bin/dd/dd.1 @@ -306,6 +306,14 @@ filling them with .Dv NUL Ns s , resulting in a sparse file. +.It Cm trim +If one or more output blocks would consist solely of +.Dv NUL +bytes, trim (delete) corresponding block(s) of the output media by issuing +appropriate +.Xr ioctl 2 +instead of filling them with +.Dv NUL Ns s . .It Cm swab Swap every pair of input bytes. If an input buffer has an odd number of bytes, the last byte will be Index: bin/dd/dd.c =================================================================== --- bin/dd/dd.c +++ bin/dd/dd.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -461,6 +462,25 @@ } } +static ssize_t +dsk_trim(int d_fd, size_t size) +{ + off_t ioarg[2], npos; + int eval; + + ioarg[0] = lseek(d_fd, (off_t)0, SEEK_CUR); + if (ioarg[0] < 0) + return (ioarg[0]); + ioarg[1] = size; + eval = ioctl(d_fd, DIOCGDELETE, ioarg); + if (eval != 0) + return (-1); + npos = lseek(d_fd, size, SEEK_CUR); + if (npos < 0) + return (npos); + return (npos - ioarg[0]); +} + void dd_out(int force) { @@ -497,11 +517,11 @@ cnt = n; do { sparse = 0; - if (ddflags & C_SPARSE) { + if (ddflags & (C_SPARSE | C_TRIM)) { /* Is buffer sparse? */ sparse = BISZERO(outp, cnt); } - if (sparse && !force) { + if (sparse && !force && !(ddflags & C_TRIM)) { pending += cnt; nw = cnt; } else { @@ -519,8 +539,11 @@ pending = 0; } if (cnt) { - nw = write(out.fd, outp, cnt); - out.seek_offset = 0; + if (!sparse || !(ddflags & C_TRIM)) { + nw = write(out.fd, outp, cnt); + } else { + nw = dsk_trim(out.fd, cnt); + } } else { return; }