Pull up following revision(s) (requested by manu in ticket #640):

bin/dd/extern.h: revision 1.23
	bin/dd/dd.1: revision 1.26
	bin/dd/dd.1: revision 1.27
	bin/dd/dd.h: revision 1.16
	bin/dd/dd.c: revision 1.50
	bin/dd/Makefile: revision 1.18
	bin/dd/args.c: revision 1.39
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

New sentence, new line. Fix typos. Bump date for previous.
This commit is contained in:
martin 2015-03-26 11:08:43 +00:00
parent 176e45f806
commit 88e41e77d5
6 changed files with 196 additions and 13 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.17 2012/08/08 14:09:14 christos Exp $
# $NetBSD: Makefile,v 1.17.12.1 2015/03/26 11:08:43 martin Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
.include <bsd.own.mk>
@ -10,8 +10,9 @@ DPADD+= ${LIBUTIL}
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

View File

@ -1,4 +1,4 @@
/* $NetBSD: args.c,v 1.38 2013/07/17 12:55:48 christos Exp $ */
/* $NetBSD: args.c,v 1.38.6.1 2015/03/26 11:08:43 martin 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.38.6.1 2015/03/26 11:08:43 martin 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 void f_conv(char *);
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 @@ static const struct arg {
{ "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 @@ c_conv(const void *a, const void *b)
}
#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 */

View File

@ -1,4 +1,4 @@
.\" $NetBSD: dd.1,v 1.25 2012/06/20 17:54:16 wiz Exp $
.\" $NetBSD: dd.1,v 1.25.12.1 2015/03/26 11:08:43 martin Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -32,7 +32,7 @@
.\"
.\" @(#)dd.1 8.2 (Berkeley) 1/13/94
.\"
.Dd November 6, 2011
.Dd March 18, 2015
.Dt DD 1
.Os
.Sh NAME
@ -91,6 +91,21 @@ bytes instead of the default 512.
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,32 @@ If an initial portion of the output file is skipped (see the
.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 explicitly added in
.Cm oflag
in order to output to a nonexistent 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

View File

@ -1,4 +1,4 @@
/* $NetBSD: dd.c,v 1.49 2012/02/21 01:49:01 matt Exp $ */
/* $NetBSD: dd.c,v 1.49.12.1 2015/03/26 11:08:43 martin Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1991, 1993, 1994\
#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.49.12.1 2015/03/26 11:08:43 martin Exp $");
#endif
#endif /* not lint */
@ -81,6 +81,13 @@ void (*cfunc)(void); /* conversion function */
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 @@ setup(void)
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 @@ setup(void)
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 */
#define OFLAGS \
(O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC))
(oflag | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC))
out.fd = ddop_open(out, out.name, O_RDWR | OFLAGS, DEFFILEMODE);
/*
* May not have read access, so try again with write only.

View File

@ -1,4 +1,4 @@
/* $NetBSD: dd.h,v 1.15 2011/02/04 19:42:12 pooka Exp $ */
/* $NetBSD: dd.h,v 1.15.24.1 2015/03/26 11:08:43 martin Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -98,7 +98,8 @@ typedef struct {
struct timeval start; /* start time of dd */
} STAT;
/* Flags (in ddflags). */
/* Flags (in ddflags, iflag and oflag). */
#define C_NONE 0x00000
#define C_ASCII 0x00001
#define C_BLOCK 0x00002
#define C_BS 0x00004
@ -121,3 +122,5 @@ typedef struct {
#define C_UNBLOCK 0x80000
#define C_OSYNC 0x100000
#define C_SPARSE 0x200000
#define C_IFLAG 0x400000
#define C_OFLAG 0x800000

View File

@ -1,4 +1,4 @@
/* $NetBSD: extern.h,v 1.22 2011/11/07 22:24:23 jym Exp $ */
/* $NetBSD: extern.h,v 1.22.20.1 2015/03/26 11:08:43 martin Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -72,6 +72,10 @@ extern void (*cfunc)(void);
extern uint64_t cpy_cnt;
extern uint64_t cbsz;
extern u_int ddflags;
#ifndef NO_IOFLAG
extern u_int iflag;
extern u_int oflag;
#endif /* NO_IOFLAG */
extern u_int files_cnt;
extern uint64_t progress;
extern const u_char *ctab;