Index: bin/dd/args.c =================================================================== --- bin/dd/args.c +++ bin/dd/args.c @@ -317,6 +317,7 @@ u_int set, noset; const u_char *ctab; } clist[] = { + /* ACHTUNG! keep this sorted in alphabetical order by conv.name */ { "ascii", C_ASCII, C_EBCDIC, e2a_POSIX }, { "block", C_BLOCK, C_UNBLOCK, NULL }, { "ebcdic", C_EBCDIC, C_ASCII, a2e_POSIX }, @@ -335,6 +336,7 @@ { "sparse", C_SPARSE, 0, NULL }, { "swab", C_SWAB, 0, NULL }, { "sync", C_SYNC, 0, NULL }, + { "trim", C_TRIM, 0, NULL }, { "ucase", C_UCASE, C_LCASE, NULL }, { "unblock", C_UNBLOCK, C_BLOCK, NULL }, }; Index: bin/dd/dd.h =================================================================== --- bin/dd/dd.h +++ bin/dd/dd.h @@ -101,6 +101,7 @@ #define C_NOXFER 0x10000000 #define C_NOINFO 0x20000000 #define C_PROGRESS 0x40000000 +#define C_TRIM 0x80000000 #define C_PARITY (C_PAREVEN | C_PARODD | C_PARNONE | C_PARSET) Index: bin/dd/dd.1 =================================================================== --- bin/dd/dd.1 +++ bin/dd/dd.1 @@ -308,6 +308,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 @@ -507,6 +507,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) { @@ -543,11 +562,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 { @@ -565,8 +584,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; }