> 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
> 
> 

Reply via email to