Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/bin/dd Add iflag and oflag operands to dd(1)



details:   https://anonhg.NetBSD.org/src/rev/c09f020fd8fd
branches:  trunk
changeset: 336769:c09f020fd8fd
user:      manu <manu%NetBSD.org@localhost>
date:      Wed Mar 18 13:23:49 2015 +0000

description:
Add iflag and oflag operands to dd(1)

Like GNU dd(1) similar operands, iflag and oflag allow specifying the
O_* flags given to open(2) for the input and the output file. The values
are comma-sepratated, lower-case, O_ prefix-stripped constants documented
in open(2).

Since iflag and oflag override default values, specifying oflag means
O_CREATE is not set by default and must be specified explicitely.

Some values do not make sense (e.g.: iflag=directory) but are still used
and will raise a warning. For oflag, values rdonly, rdwr and wronly are
filtered out with a warning (dd(1) attempts open(2) with O_RDWR and
then O_WRONLY on failure).

Specifying oflag=trunc along with (seek, oseek or conv=notrunc) is
contradictory and will raise an error.

iflag and oflag are disabled if building with -DMALLPROG

diffstat:

 bin/dd/Makefile |    5 +-
 bin/dd/args.c   |  118 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 bin/dd/dd.1     |   41 ++++++++++++++++++-
 bin/dd/dd.c     |   28 +++++++++++-
 bin/dd/dd.h     |    7 ++-
 bin/dd/extern.h |    6 ++-
 6 files changed, 193 insertions(+), 12 deletions(-)

diffs (truncated from 351 to 300 lines):

diff -r 725ba719d596 -r c09f020fd8fd bin/dd/Makefile
--- a/bin/dd/Makefile   Wed Mar 18 13:20:20 2015 +0000
+++ b/bin/dd/Makefile   Wed Mar 18 13:23:49 2015 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: Makefile,v 1.17 2012/08/08 14:09:14 christos Exp $
+#      $NetBSD: Makefile,v 1.18 2015/03/18 13:23:49 manu Exp $
 #      @(#)Makefile    8.1 (Berkeley) 5/31/93
 
 .include <bsd.own.mk>
@@ -10,8 +10,9 @@
 LDADD+=        -lutil
 
 .ifdef SMALLPROG
-CPPFLAGS+=     -DNO_CONV -DNO_MSGFMT -DSMALL
+CPPFLAGS+=     -DNO_CONV -DNO_MSGFMT -DNO_IOFLAG -DSMALL
 .else
+CPPFLAGS+=     -D_NETBSD_SOURCE -D_INCOMPLETE_XOPEN_C063
 SRCS+=         conv_tab.c
 .ifdef CRUNCHEDPROG
 CPPFLAGS+=     -DSMALL
diff -r 725ba719d596 -r c09f020fd8fd bin/dd/args.c
--- a/bin/dd/args.c     Wed Mar 18 13:20:20 2015 +0000
+++ b/bin/dd/args.c     Wed Mar 18 13:23:49 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: args.c,v 1.38 2013/07/17 12:55:48 christos Exp $       */
+/*     $NetBSD: args.c,v 1.39 2015/03/18 13:23:49 manu Exp $   */
 
 /*-
  * Copyright (c) 1991, 1993, 1994
@@ -38,13 +38,16 @@
 #if 0
 static char sccsid[] = "@(#)args.c     8.3 (Berkeley) 4/2/94";
 #else
-__RCSID("$NetBSD: args.c,v 1.38 2013/07/17 12:55:48 christos Exp $");
+__RCSID("$NetBSD: args.c,v 1.39 2015/03/18 13:23:49 manu Exp $");
 #endif
 #endif /* not lint */
 
 #include <sys/types.h>
 #include <sys/time.h>
 
+#ifndef NO_IOFLAG
+#include <fcntl.h>
+#endif /* NO_IOFLAG */
 #include <err.h>
 #include <errno.h>
 #include <limits.h>
@@ -70,6 +73,16 @@
 static int     c_conv(const void *, const void *);
 #endif /* NO_CONV */
 
+#ifdef NO_IOFLAG
+static void    f_iflag(char *) __dead;
+static void    f_oflag(char *) __dead;
+#else
+static void    f_iflag(char *);
+static void    f_oflag(char *);
+static u_int   f_ioflag(char *, u_int);
+static int     c_ioflag(const void *, const void *);
+#endif /* NO_IOFLAG */
+
 static void    f_bs(char *);
 static void    f_cbs(char *);
 static void    f_count(char *);
@@ -96,10 +109,12 @@
        { "files",      f_files,        C_FILES, C_FILES },
        { "ibs",        f_ibs,          C_IBS,   C_BS|C_IBS },
        { "if",         f_if,           C_IF,    C_IF },
+       { "iflag",      f_iflag,        C_IFLAG, C_IFLAG },
        { "iseek",      f_skip,         C_SKIP,  C_SKIP },
        { "msgfmt",     f_msgfmt,       0,       0 },
        { "obs",        f_obs,          C_OBS,   C_BS|C_OBS },
        { "of",         f_of,           C_OF,    C_OF },
+       { "oflag",      f_oflag,        C_OFLAG, C_OFLAG },
        { "oseek",      f_seek,         C_SEEK,  C_SEEK },
        { "progress",   f_progress,     0,       0 },
        { "seek",       f_seek,         C_SEEK,  C_SEEK },
@@ -389,3 +404,102 @@
 }
 
 #endif /* NO_CONV */
+
+static void
+f_iflag(char *arg)
+{
+/* Build a small version (i.e. for a ramdisk root) */
+#ifdef NO_IOFLAG
+       errx(EXIT_FAILURE, "iflag option disabled");
+       /* NOTREACHED */
+#else
+       iflag = f_ioflag(arg, C_IFLAG);
+       return;
+#endif
+}
+
+static void
+f_oflag(char *arg)
+{
+/* Build a small version (i.e. for a ramdisk root) */
+#ifdef NO_IOFLAG
+       errx(EXIT_FAILURE, "oflag option disabled");
+       /* NOTREACHED */
+#else
+       oflag = f_ioflag(arg, C_OFLAG);
+       return;
+#endif
+}
+
+#ifndef        NO_IOFLAG
+static const struct ioflag {
+       const char *name;
+       u_int set;
+       u_int allowed;
+} olist[] = {
+     /* the array needs to be sorted by the first column so
+       bsearch() can be used to find commands quickly */
+       { "alt_io",     O_ALT_IO,       C_IFLAG|C_OFLAG },
+       { "append",     O_APPEND,       C_OFLAG         },
+       { "async",      O_ASYNC,        C_IFLAG|C_OFLAG },
+       { "cloexec",    O_CLOEXEC,      C_IFLAG|C_OFLAG },
+       { "creat",      O_CREAT,        C_OFLAG         },
+       { "direct",     O_DIRECT,       C_IFLAG|C_OFLAG },
+       { "directory",  O_DIRECTORY,    C_NONE          },
+       { "dsync",      O_DSYNC,        C_OFLAG         },
+       { "excl",       O_EXCL,         C_IFLAG|C_OFLAG },
+       { "exlock",     O_EXLOCK,       C_IFLAG|C_OFLAG },
+       { "noctty",     O_NOCTTY,       C_IFLAG|C_OFLAG },
+       { "nofollow",   O_NOFOLLOW,     C_IFLAG|C_OFLAG },
+       { "nonblock",   O_NONBLOCK,     C_IFLAG|C_OFLAG },
+       { "nosigpipe",  O_NOSIGPIPE,    C_IFLAG|C_OFLAG },
+       { "rdonly",     O_RDONLY,       C_IFLAG         },
+       { "rdwr",       O_RDWR,         C_IFLAG         },
+       { "rsync",      O_RSYNC,        C_IFLAG         },
+       { "search",     O_SEARCH,       C_IFLAG|C_OFLAG },
+       { "shlock",     O_SHLOCK,       C_IFLAG|C_OFLAG },
+       { "sync",       O_SYNC,         C_IFLAG|C_OFLAG },
+       { "trunc",      O_TRUNC,        C_IFLAG|C_OFLAG },
+       { "wronly",     O_WRONLY,       C_NONE          },
+};
+
+static u_int
+f_ioflag(char *arg, u_int flagtype)
+{
+       u_int ioflag = 0;
+       struct ioflag *cp, tmp;
+       const char *flagstr = (flagtype == C_IFLAG) ? "iflag" : "oflag";
+
+       while (arg != NULL) {
+               tmp.name = strsep(&arg, ",");
+               if (!(cp = bsearch(&tmp, olist,
+                   __arraycount(olist), sizeof(*olist), c_ioflag))) {
+                       errx(EXIT_FAILURE, "unknown %s %s", flagstr, tmp.name);
+                       /* NOTREACHED */
+               }
+
+               if ((cp->set & O_ACCMODE) && (flagtype == C_OFLAG)) {
+                       warnx("rdonly, rdwr and wronly are ignored for oflag");
+                       continue;
+               }
+
+               if ((cp->allowed & flagtype) == 0) {
+                       warnx("%s set for %s but makes no sense",
+                             cp->name, flagstr);
+               }
+               
+               ioflag |= cp->set;
+       }
+
+
+       return ioflag;
+}
+
+static int
+c_ioflag(const void *a, const void *b)
+{
+
+       return (strcmp(((const struct ioflag *)a)->name,
+           ((const struct ioflag *)b)->name));
+}
+#endif /* NO_IOFLAG */
diff -r 725ba719d596 -r c09f020fd8fd bin/dd/dd.1
--- a/bin/dd/dd.1       Wed Mar 18 13:20:20 2015 +0000
+++ b/bin/dd/dd.1       Wed Mar 18 13:23:49 2015 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: dd.1,v 1.25 2012/06/20 17:54:16 wiz Exp $
+.\"    $NetBSD: dd.1,v 1.26 2015/03/18 13:23:49 manu Exp $
 .\"
 .\" Copyright (c) 1990, 1993
 .\"    The Regents of the University of California.  All rights reserved.
@@ -91,6 +91,21 @@
 Read input from
 .Ar file
 instead of the standard input.
+.It Cm iflag= Ns Ar flags
+Use comma-separated
+.Ar flags
+when calling
+.Xr open 2
+for the input file.
+The possible values are
+.Va O_
+flags documented in
+.Xr open 2 ,
+specified as lowercase and with the leading
+.Va O_
+removed.
+Default value is
+.Va rdonly .
 .It Cm iseek= Ns Ar n
 Seek on the input file
 .Ar n
@@ -180,6 +195,30 @@
 .Cm seek
 operand)
 the output file is truncated at that point.
+.It Cm oflag= Ns Ar flags
+Same as
+.Cm iflag
+but for the call to
+.Xr open 2
+on the output file. The default value is
+.Va creat ,
+which should be explictely added in
+.Cm oflag
+in order to output to a nonexistant file.
+The default or specified value is or'ed with
+.Va rdwr
+for a first
+.Xt open 2
+attempt, then on failure with
+.Va wronly
+on a second attempt. In both cases,
+.Va trunc
+is automatically added if none of
+.Cm oseek ,
+.Cm seek ,
+or
+.Cm conv=notrunc
+operands are used,
 .It Cm oseek= Ns Ar n
 Seek on the output file
 .Ar n
diff -r 725ba719d596 -r c09f020fd8fd bin/dd/dd.c
--- a/bin/dd/dd.c       Wed Mar 18 13:20:20 2015 +0000
+++ b/bin/dd/dd.c       Wed Mar 18 13:23:49 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: dd.c,v 1.49 2012/02/21 01:49:01 matt Exp $     */
+/*     $NetBSD: dd.c,v 1.50 2015/03/18 13:23:49 manu Exp $     */
 
 /*-
  * Copyright (c) 1991, 1993, 1994
@@ -43,7 +43,7 @@
 #if 0
 static char sccsid[] = "@(#)dd.c       8.5 (Berkeley) 4/2/94";
 #else
-__RCSID("$NetBSD: dd.c,v 1.49 2012/02/21 01:49:01 matt Exp $");
+__RCSID("$NetBSD: dd.c,v 1.50 2015/03/18 13:23:49 manu Exp $");
 #endif
 #endif /* not lint */
 
@@ -81,6 +81,13 @@
 uint64_t       cpy_cnt;                /* # of blocks to copy */
 static off_t   pending = 0;            /* pending seek if sparse */
 u_int          ddflags;                /* conversion options */
+#ifdef NO_IOFLAG
+#define                iflag   O_RDONLY
+#define                oflag   O_CREAT
+#else
+u_int          iflag = O_RDONLY;       /* open(2) flags for input file */
+u_int          oflag = O_CREAT;        /* open(2) flags for output file */
+#endif /* NO_IOFLAG */
 uint64_t       cbsz;                   /* conversion block size */
 u_int          files_cnt = 1;          /* # of files to copy */
 uint64_t       progress = 0;           /* display sign of life */
@@ -160,7 +167,7 @@
                in.ops = &ddfops_stdfd;
        } else {
                in.ops = prog_ops;
-               in.fd = ddop_open(in, in.name, O_RDONLY, 0);
+               in.fd = ddop_open(in, in.name, iflag, 0);
                if (in.fd < 0)
                        err(EXIT_FAILURE, "%s", in.name);
                        /* NOTREACHED */
@@ -183,8 +190,21 @@
                out.ops = &ddfops_stdfd;
        } else {
                out.ops = prog_ops;
+
+#ifndef NO_IOFLAG
+               if ((oflag & O_TRUNC) && (ddflags & C_SEEK)) {
+                       errx(EXIT_FAILURE, "oflag=trunc is incompatible "
+                            "with seek or oseek operands, giving up.");
+                       /* NOTREACHED */
+               }
+               if ((oflag & O_TRUNC) && (ddflags & C_NOTRUNC)) {
+                       errx(EXIT_FAILURE, "oflag=trunc is incompatible "
+                            "with conv=notrunc operand, giving up.");
+                       /* NOTREACHED */
+               }
+#endif /* NO_IOFLAG */



Home | Main Index | Thread Index | Old Index