Subject: `dd` seek/skip which way is up?
From: Bela Lubkin <[email-masked]>
To: [email-masked]
Date: Sun, 3 Jan 2021 19:03:17 -0800
List-Id: <debbugs-submit.debbugs.gnu.org>

Hello --

I constantly confuse 'seek=N' and 'skip=N'.  The two words have no natural
affinity to one I/O direction or the other.

I previously encountered a `dd` implementation which also accepted
'oseek=N' and 'iseek=N', which I found far more natural and easy to
remember.

Here is a small patch implementing the same for coreutils `dd`.  Patch is
against just-gotten git tree; `dd --version` reports 'dd (coreutils)
8.32.101-ebf2c-dirty'.  (I probably got the .texi formatting wrong; please
repair as needed.)

While in the area, I slightly improved some of the help (and therefore man
page).

>Bela<

========================================================================

diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index e9dd21c4e..417857c5e 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -9100,6 +9100,15 @@ Skip @var{n} @samp{obs}-byte blocks in the output
file before copying.
 if @samp{oflag=seek_bytes} is specified, @var{n} is interpreted
 as a byte count rather than a block count.

+@item oseek
+@item iseek
+@opindex oseek
+@opindex iseek
+As the distinction between @samp{seek} and @samp{skip}
+is easily confused, @samp{oseek} is accepted as an alias
+for @samp{seek}; @samp{iseek} for @samp{skip}.
+Do not use these in scripts, as this reduces compatibility.
+
 @item count=@var{n}
 @opindex count
 Copy @var{n} @samp{ibs}-byte blocks from the input file, instead
@@ -9457,6 +9466,15 @@ rather than a block count, which allows specifying
 an offset that is not a multiple of the I/O block size.
 This flag can be used only with @code{oflag}.

+@item oseek_bytes
+@item iseek_bytes
+@opindex oseek_bytes
+@opindex iseek_bytes
+As the distinction between @samp{seek_bytes} and @samp{skip_bytes}
+is easily confused, @samp{oseek_bytes} is accepted as an alias
+for @samp{seek_bytes}; @samp{iseek_bytes} for @samp{skip_bytes}.
+Do not use these in scripts, as this reduces compatibility.
+
 @end table

 These flags are not supported on all systems, and @samp{dd} rejects
diff --git a/src/dd.c b/src/dd.c
index 9152a2550..a187522c2 100644
--- a/src/dd.c
+++ b/src/dd.c
@@ -381,7 +381,9 @@ static struct symbol_value const flags[] =
   {"fullblock",   O_FULLBLOCK}, /* Accumulate full blocks from input.  */
   {"count_bytes", O_COUNT_BYTES},
   {"skip_bytes",  O_SKIP_BYTES},
+  {"iseek_bytes", O_SKIP_BYTES},
   {"seek_bytes",  O_SEEK_BYTES},
+  {"oseek_bytes", O_SEEK_BYTES},
   {"", 0}
 };

@@ -571,7 +573,7 @@ Copy a file, converting and formatting according to the
operands.\n\
                   overrides ibs and obs\n\
   cbs=BYTES       convert BYTES bytes at a time\n\
   conv=CONVS      convert the file as per the comma separated symbol
list\n\
-  count=N         copy only N input blocks\n\
+  count=N         copy only N input blocks (bytes if iflag=count_bytes)\n\
   ibs=BYTES       read up to BYTES bytes at a time (default: 512)\n\
 "), stdout);
       fputs (_("\
@@ -580,8 +582,8 @@ Copy a file, converting and formatting according to the
operands.\n\
   obs=BYTES       write BYTES bytes at a time (default: 512)\n\
   of=FILE         write to FILE instead of stdout\n\
   oflag=FLAGS     write as per the comma separated symbol list\n\
-  seek=N          skip N obs-sized blocks at start of output\n\
-  skip=N          skip N ibs-sized blocks at start of input\n\
+  seek=N (or oseek=N)  skip N obs-sized blocks at start of output (bytes
if oflag=seek_bytes)\n\
+  skip=N (or iseek=N)  skip N ibs-sized blocks at start of input (bytes if
iflag=skip_bytes)\n\
   status=LEVEL    The LEVEL of information to print to stderr;\n\
                   'none' suppresses everything but error messages,\n\
                   'noxfer' suppresses the final transfer statistics,\n\
@@ -660,10 +662,10 @@ Each FLAG symbol may be:\n\
         fputs (_("  count_bytes  treat 'count=N' as a byte count (iflag
only)\n\
 "), stdout);
       if (O_SKIP_BYTES)
-        fputs (_("  skip_bytes  treat 'skip=N' as a byte count (iflag
only)\n\
+        fputs (_("  skip_bytes (or iseek_bytes)  treat 'skip=N' as a byte
count (iflag only)\n\
 "), stdout);
       if (O_SEEK_BYTES)
-        fputs (_("  seek_bytes  treat 'seek=N' as a byte count (oflag
only)\n\
+        fputs (_("  seek_bytes (or oseek_bytes)  treat 'seek=N' as a byte
count (oflag only)\n\
 "), stdout);

       {
@@ -1554,9 +1556,11 @@ scanargs (int argc, char *const *argv)
               n_max = SIZE_MAX;
               conversion_blocksize = n;
             }
-          else if (operand_is (name, "skip"))
+          else if (operand_is (name, "skip") ||
+                    operand_is (name, "iseek"))
             skip = n;
-          else if (operand_is (name, "seek"))
+          else if (operand_is (name, "seek") ||
+                   operand_is (name, "oseek"))
             seek = n;
           else if (operand_is (name, "count"))
             count = n;