> Date: Sat, 14 May 2016 17:07:45 +0200
> From: Theo Buehler <[email protected]>
>
> Here's a new version with lots of help and input from semarie, thanks!
> Besides lots of small tweaks, the main improvements are:
>
> * fork one pledged child per fs which reads the data.
> * pipe the data to the unpledged parent that dumps it to stdout.
> * parent waits for current child, then calls opendev(2) for next child.
> * make sure parent reports properly on child failure (e.g. pledge abort)
Must say the forking and piping seems to be a bit silly for a program
like this. Certainly adds alot of complexity. Why not simply call
opendev up front for each filesystem, creating a list of names and
filedescriptors before you pledge, and then iterate over that list
afterwards?
KISS
> Index: sbin/dumpfs/dumpfs.c
> ===================================================================
> RCS file: /var/cvs/src/sbin/dumpfs/dumpfs.c,v
> retrieving revision 1.33
> diff -u -p -r1.33 dumpfs.c
> --- sbin/dumpfs/dumpfs.c 23 Nov 2015 19:19:29 -0000 1.33
> +++ sbin/dumpfs/dumpfs.c 14 May 2016 15:02:24 -0000
> @@ -40,6 +40,7 @@
>
> #include <sys/param.h> /* DEV_BSIZE MAXBSIZE isset */
> #include <sys/time.h>
> +#include <sys/wait.h>
>
> #include <ufs/ufs/dinode.h>
> #include <ufs/ffs/fs.h>
> @@ -51,6 +52,7 @@
> #include <stdint.h>
> #include <stdio.h>
> #include <stdlib.h>
> +#include <string.h>
> #include <unistd.h>
> #include <util.h>
>
> @@ -73,6 +75,7 @@ int dumpcg(const char *, int, int);
> int marshal(const char *);
> int open_disk(const char *);
> void pbits(void *, int);
> +void writedata(int, int);
> __dead void usage(void);
>
> int
> @@ -80,7 +83,9 @@ main(int argc, char *argv[])
> {
> struct fstab *fs;
> const char *name;
> - int ch, domarshal, eval, fd;
> + pid_t pid, wpid;
> + int p[2];
> + int ch, domarshal, eval, fd, pstat;
>
> domarshal = eval = 0;
>
> @@ -100,25 +105,69 @@ main(int argc, char *argv[])
> if (argc < 1)
> usage();
>
> - if (pledge("stdio rpath disklabel", NULL) == -1)
> - err(1, "pledge");
> -
> for (; *argv != NULL; argv++) {
> if ((fs = getfsfile(*argv)) != NULL)
> name = fs->fs_spec;
> else
> name = *argv;
> +
> if ((fd = open_disk(name)) == -1) {
> eval |= 1;
> continue;
> }
> - if (domarshal)
> - eval |= marshal(name);
> - else
> - eval |= dumpfs(fd, name);
> - close(fd);
> +
> + if (pipe(p) < 0)
> + err(1, "pipe");
> +
> + switch(pid = fork()) {
> + case -1:
> + err(1, "fork");
> +
> + case 0:
> + if (pledge("stdio", NULL) == -1)
> + err(1, "pledge");
> +
> + close(p[0]);
> + dup2(p[1], STDOUT_FILENO);
> + close(p[1]);
> +
> + if (domarshal)
> + eval |= marshal(name);
> + else
> + eval |= dumpfs(fd, name);
> +
> + close(fd);
> +
> + if (fflush(stdout))
> + err(1, "fflush");
> +
> + _exit(eval);
> +
> + default:
> + close(p[1]);
> + writedata(p[0], STDOUT_FILENO);
> + close(p[0]);
> + close(fd);
> +
> + do {
> + wpid = waitpid(pid, &pstat, 0);
> + } while (wpid == -1 && errno == EINTR);
> +
> + if (wpid == -1) {
> + warn("waitpid");
> + eval |= 1;
> + } else if (WIFEXITED(pstat))
> + eval |= WEXITSTATUS(pstat);
> + else if (WIFSIGNALED(pstat)) {
> + warnx("child processing %s terminated: %s%s",
> + name, strsignal(WTERMSIG(pstat)),
> + WCOREDUMP(pstat) ? " (core dumped)" : "");
> + eval |= 1;
> + }
> + }
> }
> - exit(eval);
> +
> + return (eval);
> }
>
> int
> @@ -458,6 +507,23 @@ pbits(void *vp, int max)
> printf("-%d", i);
> }
> printf("\n");
> +}
> +
> +void
> +writedata(int ifd, int ofd)
> +{
> + int nr, nw, off;
> + char buf[1024];
> +
> + while ((nr = read(ifd, buf, sizeof(buf))) != -1 && nr != 0) {
> + for (off = 0; nr; nr -= nw, off += nw) {
> + if ((nw = write(ofd, buf + off, nr)) == 0 || nw == -1)
> + err(1, "write");
> + }
> + }
> +
> + if (nr < 0)
> + warn("read");
> }
>
> __dead void
>
>