Add two new operands: "rif" and "rof". They operate exactly like

"if" and "of" with the exception that the communicate with a rump
kernel instead of the host kernel.

For example, to write stdout to /tmp/file.txt in a rump kernel namespace:
	dd rof=/tmp/file.txt

copy /file1 to /file2 inside a rump kernel:
	dd rif=/file1 rof=/file2

copy a snippet from /dev/rmd0d on the rump kernel to the host fs:
	dd rif=/dev/rmd0d of=save seek=1000 count=3

Eat that, usermode OS.

(I'll document the operands one I have some manpage to refer to
for rump client use).
This commit is contained in:
pooka 2010-11-22 21:04:27 +00:00
parent 9be034428c
commit 6b03da8b7e
6 changed files with 158 additions and 46 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.12 2007/10/05 07:23:09 lukem Exp $
# $NetBSD: Makefile,v 1.13 2010/11/22 21:04:27 pooka Exp $
# @(#)Makefile 8.1 (Berkeley) 5/31/93
PROG= dd
@ -8,9 +8,11 @@ DPADD+= ${LIBUTIL}
LDADD+= -lutil
.ifdef SMALLPROG
CPPFLAGS+= -DNO_CONV
CPPFLAGS+= -DNO_CONV -DSMALL
.else
SRCS+= conv_tab.c
DPADD+= ${LIBRUMPCLIENT}
LDADD+= -lrumpclient
.endif
.include <bsd.prog.mk>

View File

@ -1,4 +1,4 @@
/* $NetBSD: args.c,v 1.26 2006/01/09 10:17:05 apb Exp $ */
/* $NetBSD: args.c,v 1.27 2010/11/22 21:04:27 pooka Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "@(#)args.c 8.3 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: args.c,v 1.26 2006/01/09 10:17:05 apb Exp $");
__RCSID("$NetBSD: args.c,v 1.27 2010/11/22 21:04:27 pooka Exp $");
#endif
#endif /* not lint */
@ -55,6 +55,10 @@ __RCSID("$NetBSD: args.c,v 1.26 2006/01/09 10:17:05 apb Exp $");
#include "dd.h"
#include "extern.h"
#ifndef SMALL
#include <rump/rumpclient.h>
#endif
static int c_arg(const void *, const void *);
#ifndef NO_CONV
static int c_conv(const void *, const void *);
@ -72,6 +76,11 @@ static void f_seek(char *);
static void f_skip(char *);
static void f_progress(char *);
#ifndef SMALL
static void f_rif(char *);
static void f_rof(char *);
#endif
static const struct arg {
const char *name;
void (*f)(char *);
@ -85,10 +94,14 @@ static const struct arg {
{ "count", f_count, C_COUNT, C_COUNT },
{ "files", f_files, C_FILES, C_FILES },
{ "ibs", f_ibs, C_IBS, C_BS|C_IBS },
{ "if", f_if, C_IF, C_IF },
{ "if", f_if, C_IF, C_IF|C_RIF },
{ "obs", f_obs, C_OBS, C_BS|C_OBS },
{ "of", f_of, C_OF, C_OF },
{ "of", f_of, C_OF, C_OF|C_ROF },
{ "progress", f_progress, 0, 0 },
#ifndef SMALL
{ "rif", f_rif, C_RIF|C_RUMP, C_RIF|C_IF },
{ "rof", f_rof, C_ROF|C_RUMP, C_ROF|C_ROF },
#endif
{ "seek", f_seek, C_SEEK, C_SEEK },
{ "skip", f_skip, C_SKIP, C_SKIP },
};
@ -185,6 +198,12 @@ jcl(char **argv)
* if (in.offset > INT_MAX/in.dbsz || out.offset > INT_MAX/out.dbsz)
* errx(1, "seek offsets cannot be larger than %d", INT_MAX);
*/
#ifndef SMALL
if (ddflags & C_RUMP)
if (rumpclient_init() == -1)
err(1, "rumpclient init failed");
#endif
}
static int
@ -257,6 +276,40 @@ f_of(char *arg)
out.name = arg;
}
#ifndef SMALL
#include <rump/rump.h>
#include <rump/rump_syscalls.h>
static const struct ddfops ddfops_rump = {
.op_open = rump_sys_open,
.op_close = rump_sys_close,
.op_fcntl = rump_sys_fcntl,
.op_ioctl = rump_sys_ioctl,
.op_fstat = rump_sys_fstat,
.op_fsync = rump_sys_fsync,
.op_ftruncate = rump_sys_ftruncate,
.op_lseek = rump_sys_lseek,
.op_read = rump_sys_read,
.op_write = rump_sys_write,
};
static void
f_rif(char *arg)
{
in.name = arg;
in.ops = &ddfops_rump;
}
static void
f_rof(char *arg)
{
out.name = arg;
out.ops = &ddfops_rump;
}
#endif
static void
f_seek(char *arg)
{

View File

@ -1,4 +1,4 @@
/* $NetBSD: dd.c,v 1.43 2009/02/14 07:13:40 lukem Exp $ */
/* $NetBSD: dd.c,v 1.44 2010/11/22 21:04:27 pooka 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.43 2009/02/14 07:13:40 lukem Exp $");
__RCSID("$NetBSD: dd.c,v 1.44 2010/11/22 21:04:27 pooka Exp $");
#endif
#endif /* not lint */
@ -70,7 +70,7 @@ __RCSID("$NetBSD: dd.c,v 1.43 2009/02/14 07:13:40 lukem Exp $");
static void dd_close(void);
static void dd_in(void);
static void getfdtype(IO *);
static int redup_clean_fd(int);
static void redup_clean_fd(IO *);
static void setup(void);
int main(int, char *[]);
@ -87,6 +87,21 @@ uint64_t progress = 0; /* display sign of life */
const u_char *ctab; /* conversion table */
sigset_t infoset; /* a set blocking SIGINFO */
static const struct ddfops ddfops_host = {
.op_open = open,
.op_close = close,
.op_fcntl = fcntl,
.op_ioctl = ioctl,
.op_fstat = fstat,
.op_fsync = fsync,
.op_ftruncate = ftruncate,
.op_lseek = lseek,
.op_read = read,
.op_write = write,
};
#include <rump/rumpclient.h>
int
main(int argc, char *argv[])
{
@ -127,17 +142,21 @@ static void
setup(void)
{
if (in.ops == NULL)
in.ops = &ddfops_host;
if (out.ops == NULL)
out.ops = &ddfops_host;
if (in.name == NULL) {
in.name = "stdin";
in.fd = STDIN_FILENO;
} else {
in.fd = open(in.name, O_RDONLY, 0);
in.fd = ddop_open(in, in.name, O_RDONLY, 0);
if (in.fd < 0)
err(EXIT_FAILURE, "%s", in.name);
/* NOTREACHED */
/* Ensure in.fd is outside the stdio descriptor range */
in.fd = redup_clean_fd(in.fd);
redup_clean_fd(&in);
}
getfdtype(&in);
@ -154,14 +173,15 @@ setup(void)
} else {
#define OFLAGS \
(O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC))
out.fd = open(out.name, O_RDWR | OFLAGS, DEFFILEMODE);
out.fd = ddop_open(out, out.name, O_RDWR | OFLAGS, DEFFILEMODE);
/*
* May not have read access, so try again with write only.
* Without read we may have a problem if output also does
* not support seeks.
*/
if (out.fd < 0) {
out.fd = open(out.name, O_WRONLY | OFLAGS, DEFFILEMODE);
out.fd = ddop_open(out, out.name, O_WRONLY | OFLAGS,
DEFFILEMODE);
out.flags |= NOREAD;
}
if (out.fd < 0) {
@ -170,7 +190,7 @@ setup(void)
}
/* Ensure out.fd is outside the stdio descriptor range */
out.fd = redup_clean_fd(out.fd);
redup_clean_fd(&out);
}
getfdtype(&out);
@ -205,7 +225,7 @@ setup(void)
* kinds of output files, tapes, for example.
*/
if ((ddflags & (C_OF | C_SEEK | C_NOTRUNC)) == (C_OF | C_SEEK))
(void)ftruncate(out.fd, (off_t)out.offset * out.dbsz);
(void)ddop_ftruncate(out, out.fd, (off_t)out.offset * out.dbsz);
/*
* If converting case at the same time as another conversion, build a
@ -251,13 +271,15 @@ getfdtype(IO *io)
struct mtget mt;
struct stat sb;
if (fstat(io->fd, &sb)) {
if (io->ops->op_fstat(io->fd, &sb)) {
err(EXIT_FAILURE, "%s", io->name);
/* NOTREACHED */
}
if (S_ISCHR(sb.st_mode))
io->flags |= ioctl(io->fd, MTIOCGET, &mt) ? ISCHR : ISTAPE;
else if (lseek(io->fd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE)
io->flags |= io->ops->op_ioctl(io->fd, MTIOCGET, &mt)
? ISCHR : ISTAPE;
else if (io->ops->op_lseek(io->fd, (off_t)0, SEEK_CUR) == -1
&& errno == ESPIPE)
io->flags |= ISPIPE; /* XXX fixed in 4.4BSD */
}
@ -267,29 +289,29 @@ getfdtype(IO *io)
* accidentally outputting completion or error messages into the
* output file that were intended for the tty.
*/
static int
redup_clean_fd(int fd)
static void
redup_clean_fd(IO *io)
{
int fd = io->fd;
int newfd;
if (fd != STDIN_FILENO && fd != STDOUT_FILENO &&
fd != STDERR_FILENO)
/* File descriptor is ok, return immediately. */
return fd;
return;
/*
* 3 is the first descriptor greater than STD*_FILENO. Any
* free descriptor valued 3 or above is acceptable...
*/
newfd = fcntl(fd, F_DUPFD, 3);
newfd = io->ops->op_fcntl(fd, F_DUPFD, 3);
if (newfd < 0) {
err(EXIT_FAILURE, "dupfd IO");
/* NOTREACHED */
}
close(fd);
return newfd;
io->ops->op_close(fd);
io->fd = newfd;
}
static void
@ -316,7 +338,7 @@ dd_in(void)
(void)memset(in.dbp, 0, in.dbsz);
}
n = read(in.fd, in.dbp, in.dbsz);
n = ddop_read(in, in.fd, in.dbp, in.dbsz);
if (n == 0) {
in.dbrcnt = 0;
return;
@ -343,7 +365,7 @@ dd_in(void)
* in sector size chunks.
*/
if (!(in.flags & (ISPIPE|ISTAPE)) &&
lseek(in.fd, (off_t)in.dbsz, SEEK_CUR))
ddop_lseek(in, in.fd, (off_t)in.dbsz, SEEK_CUR))
warn("%s", in.name);
/* If sync not specified, omit block and continue. */
@ -431,11 +453,12 @@ dd_close(void)
* may be shared among with other processes and close(2) just
* decreases the reference count.
*/
if (out.fd == STDOUT_FILENO && fsync(out.fd) == -1 && errno != EINVAL) {
if (out.fd == STDOUT_FILENO && ddop_fsync(out, out.fd) == -1
&& errno != EINVAL) {
err(EXIT_FAILURE, "fsync stdout");
/* NOTREACHED */
}
if (close(out.fd) == -1) {
if (ddop_close(out, out.fd) == -1) {
err(EXIT_FAILURE, "close");
/* NOTREACHED */
}
@ -484,12 +507,12 @@ dd_out(int force)
}
}
if (pending != 0) {
if (lseek(out.fd, pending, SEEK_CUR) ==
-1)
if (ddop_lseek(out,
out.fd, pending, SEEK_CUR) == -1)
err(EXIT_FAILURE, "%s: seek error creating sparse file",
out.name);
}
nw = bwrite(out.fd, outp, cnt);
nw = bwrite(&out, outp, cnt);
if (nw <= 0) {
if (nw == 0)
errx(EXIT_FAILURE,
@ -545,14 +568,14 @@ dd_out(int force)
* A protected against SIGINFO write
*/
ssize_t
bwrite(int fd, const void *buf, size_t len)
bwrite(IO *io, const void *buf, size_t len)
{
sigset_t oset;
ssize_t rv;
int oerrno;
(void)sigprocmask(SIG_BLOCK, &infoset, &oset);
rv = write(fd, buf, len);
rv = io->ops->op_write(io->fd, buf, len);
oerrno = errno;
(void)sigprocmask(SIG_SETMASK, &oset, NULL);
errno = oerrno;

View File

@ -1,4 +1,4 @@
/* $NetBSD: dd.h,v 1.12 2004/01/17 20:48:57 dbj Exp $ */
/* $NetBSD: dd.h,v 1.13 2010/11/22 21:04:27 pooka Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -35,6 +35,35 @@
* @(#)dd.h 8.3 (Berkeley) 4/2/94
*/
#include <sys/stat.h>
struct ddfops {
int (*op_open)(const char *, int, ...);
int (*op_close)(int);
int (*op_fcntl)(int, int, ...);
int (*op_ioctl)(int, unsigned long, ...);
int (*op_fstat)(int, struct stat *);
int (*op_fsync)(int);
int (*op_ftruncate)(int, off_t);
off_t (*op_lseek)(int, off_t, int);
ssize_t (*op_read)(int, void *, size_t);
ssize_t (*op_write)(int, const void *, size_t);
};
#define ddop_open(dir, a1, a2, ...) dir.ops->op_open(a1, a2, __VA_ARGS__)
#define ddop_close(dir, a1) dir.ops->op_close(a1)
#define ddop_fcntl(dir, a1, a2, ...) dir.ops->op_fcntl(a1, a2, __VA_ARGS__)
#define ddop_ioctl(dir, a1, a2, ...) dir.ops->op_ioctl(a1, a2, __VA_ARGS__)
#define ddop_fsync(dir, a1) dir.ops->op_fsync(a1)
#define ddop_ftruncate(dir, a1, a2) dir.ops->op_ftruncate(a1, 2)
#define ddop_lseek(dir, a1, a2, a3) dir.ops->op_lseek(a1, a2, a3)
#define ddop_read(dir, a1, a2, a3) dir.ops->op_read(a1, a2, a3)
#define ddop_write(dir, a1, a2, a3) dir.ops->op_write(a1, a2, a3)
/* Input/output stream state. */
typedef struct {
u_char *db; /* buffer address */
@ -52,6 +81,7 @@ typedef struct {
const char *name; /* name */
int fd; /* file descriptor */
uint64_t offset; /* # of blocks to skip */
struct ddfops const *ops; /* ops to use with fd */
} IO;
typedef struct {
@ -89,3 +119,6 @@ typedef struct {
#define C_UNBLOCK 0x80000
#define C_OSYNC 0x100000
#define C_SPARSE 0x200000
#define C_RIF 0x400000
#define C_ROF 0x800000
#define C_RUMP 0x1000000

View File

@ -1,4 +1,4 @@
/* $NetBSD: extern.h,v 1.17 2006/01/09 10:17:05 apb Exp $ */
/* $NetBSD: extern.h,v 1.18 2010/11/22 21:04:28 pooka Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -50,7 +50,7 @@ void summaryx(int);
void terminate(int);
void unblock(void);
void unblock_close(void);
ssize_t bwrite(int, const void *, size_t);
ssize_t bwrite(IO *, const void *, size_t);
extern IO in, out;
extern STAT st;

View File

@ -1,4 +1,4 @@
/* $NetBSD: position.c,v 1.17 2009/02/14 07:13:40 lukem Exp $ */
/* $NetBSD: position.c,v 1.18 2010/11/22 21:04:28 pooka Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "@(#)position.c 8.3 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: position.c,v 1.17 2009/02/14 07:13:40 lukem Exp $");
__RCSID("$NetBSD: position.c,v 1.18 2010/11/22 21:04:28 pooka Exp $");
#endif
#endif /* not lint */
@ -70,7 +70,7 @@ pos_in(void)
/* If not a pipe or tape device, try to seek on it. */
if (!(in.flags & (ISPIPE|ISTAPE))) {
if (lseek(in.fd,
if (ddop_lseek(in, in.fd,
(off_t)in.offset * (off_t)in.dbsz, SEEK_CUR) == -1) {
err(EXIT_FAILURE, "%s", in.name);
/* NOTREACHED */
@ -85,7 +85,7 @@ pos_in(void)
* blocks for other devices.
*/
for (bcnt = in.dbsz, cnt = in.offset, warned = 0; cnt;) {
if ((nr = read(in.fd, in.db, bcnt)) > 0) {
if ((nr = ddop_read(in, in.fd, in.db, bcnt)) > 0) {
if (in.flags & ISPIPE) {
if (!(bcnt -= nr)) {
bcnt = in.dbsz;
@ -137,7 +137,7 @@ pos_out(void)
* have specified the seek operand.
*/
if (!(out.flags & ISTAPE)) {
if (lseek(out.fd,
if (ddop_lseek(out, out.fd,
(off_t)out.offset * (off_t)out.dbsz, SEEK_SET) == -1)
err(EXIT_FAILURE, "%s", out.name);
/* NOTREACHED */
@ -149,7 +149,7 @@ pos_out(void)
t_op.mt_op = MTFSR;
t_op.mt_count = out.offset;
if (ioctl(out.fd, MTIOCTOP, &t_op) < 0)
if (ddop_ioctl(out, out.fd, MTIOCTOP, &t_op) < 0)
err(EXIT_FAILURE, "%s", out.name);
/* NOTREACHED */
return;
@ -157,7 +157,7 @@ pos_out(void)
/* Read it. */
for (cnt = 0; cnt < out.offset; ++cnt) {
if ((n = read(out.fd, out.db, out.dbsz)) > 0)
if ((n = ddop_read(out, out.fd, out.db, out.dbsz)) > 0)
continue;
if (n < 0)
@ -171,12 +171,13 @@ pos_out(void)
*/
t_op.mt_op = MTBSR;
t_op.mt_count = 1;
if (ioctl(out.fd, MTIOCTOP, &t_op) == -1)
if (ddop_ioctl(out, out.fd, MTIOCTOP, &t_op) == -1)
err(EXIT_FAILURE, "%s", out.name);
/* NOTREACHED */
while (cnt++ < out.offset)
if ((uint64_t)(n = bwrite(out.fd, out.db, out.dbsz)) != out.dbsz)
if ((uint64_t)(n = bwrite(&out,
out.db, out.dbsz)) != out.dbsz)
err(EXIT_FAILURE, "%s", out.name);
/* NOTREACHED */
break;