Is this any slower on very large compressions or decompressions?

> Ted Unangst wrote:
> > This splits gzip into two processes, such that the heavy lifting is done in 
> > a
> > process with even fewer privileges. The idea is the child decompresses the
> > data and feeds it to the parent over a pipe. There's also a control pipe 
> > used
> > for some metadata that needs to be passed up.
> > 
> > early version, i'm not sure it's entirely reliable. it does seem to 
> > decompress
> > some test files, however.
> 
> Does anybody really know what time it is?
> Does anybody really care?
> 
> > 
> > 
> > Index: gzopen.c
> > ===================================================================
> > RCS file: /cvs/src/usr.bin/compress/gzopen.c,v
> > retrieving revision 1.34
> > diff -u -p -r1.34 gzopen.c
> > --- gzopen.c        3 Sep 2016 12:29:30 -0000       1.34
> > +++ gzopen.c        3 Sep 2016 15:04:26 -0000
> > @@ -92,6 +92,8 @@ struct gz_stream {
> >     u_int32_t z_hlen;       /* length of the gz header */
> >     u_int64_t z_total_in;   /* # bytes in */
> >     u_int64_t z_total_out;  /* # bytes out */
> > +   int     z_pipe[2];
> > +   int     z_ctlpipe[2];
> >  } gz_stream;
> >  
> >  static const u_char gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
> > @@ -100,10 +102,13 @@ static u_int32_t get_int32(gz_stream *);
> >  static int get_header(gz_stream *, char *, int);
> >  static int get_byte(gz_stream *);
> >  
> > +static void childcopier(gz_stream *, char *, int);
> > +
> >  void *
> >  gz_ropen(int fd, char *name, int gotmagic)
> >  {
> >     gz_stream *s;
> > +   int ok;
> >  
> >     if (fd < 0)
> >             return NULL;
> > @@ -126,20 +131,31 @@ gz_ropen(int fd, char *name, int gotmagi
> >     s->z_crc = crc32(0L, Z_NULL, 0);
> >     s->z_mode = 'r';
> >  
> > -   if (inflateInit2(&(s->z_stream), -MAX_WBITS) != Z_OK) {
> > -           free (s);
> > +   if (pipe(s->z_pipe) || pipe(s->z_ctlpipe))
> >             return NULL;
> > -   }
> > -   s->z_stream.next_in = s->z_buf;
> > -   s->z_stream.avail_out = Z_BUFSIZE;
> >  
> >     errno = 0;
> >     s->z_fd = fd;
> >  
> > -   /* read the .gz header */
> > -   if (get_header(s, name, gotmagic) != 0) {
> > -           gz_close(s, NULL, NULL, NULL);
> > -           s = NULL;
> > +   switch(fork()) {
> > +   case -1:
> > +           free(s);
> > +           return NULL;
> > +   case 0:
> > +           close(s->z_pipe[1]);
> > +           close(s->z_ctlpipe[1]);
> > +           childcopier(s, name, gotmagic);
> > +           break;
> > +   default:
> > +           close(s->z_pipe[0]);
> > +           close(s->z_ctlpipe[0]);
> > +           break;
> > +   }
> > +
> > +   if (read(s->z_ctlpipe[1], &ok, sizeof(ok)) != sizeof(ok) ||
> > +       ok != 0) {
> > +           free(s);
> > +           return NULL;
> >     }
> >  
> >     return s;
> > @@ -260,6 +276,26 @@ int
> >  gz_read(void *cookie, char *buf, int len)
> >  {
> >     gz_stream *s = (gz_stream*)cookie;
> > +   int amt;
> > +   int ok;
> > +
> > +   amt = read(s->z_pipe[1], buf, len);
> > +   if (amt == -1)
> > +           return -1;
> > +   
> > +   if (amt > 0)
> > +           return amt;
> > +   
> > +   if (read(s->z_ctlpipe[1], &ok, sizeof(ok)) != sizeof(ok) ||
> > +       ok != 0) {
> > +           return -1;
> > +   }
> > +}
> > +
> > +int
> > +do_gz_read(void *cookie, char *buf, int len)
> > +{
> > +   gz_stream *s = (gz_stream*)cookie;
> >     u_char *start = buf; /* starting point for crc computation */
> >     int error = Z_OK;
> >  
> > @@ -330,6 +366,62 @@ bad:
> >     return (-1);
> >  }
> >  
> > +static void
> > +childcopier(gz_stream *s, char *name, int gotmagic)
> > +{
> > +   struct z_info info;
> > +   char tmpbuffer[Z_BUFSIZE];
> > +   int one = 1;
> > +   int zero = 0;
> > +   int amt;
> > +
> > +   if (pledge("stdio", NULL) == -1)
> > +           goto die;
> > +
> > +   if (inflateInit2(&(s->z_stream), -MAX_WBITS) != Z_OK) {
> > +           goto die;
> > +   }
> > +   s->z_stream.next_in = s->z_buf;
> > +   s->z_stream.avail_out = Z_BUFSIZE;
> > +
> > +   /* read the .gz header */
> > +   if (get_header(s, name, gotmagic) != 0) {
> > +           goto die;
> > +   }
> > +
> > +   write(s->z_ctlpipe[0], &zero, sizeof(zero));
> > +
> > +   while (1) {
> > +           amt = do_gz_read(s, tmpbuffer, sizeof(tmpbuffer));
> > +           if (amt == -1)
> > +                   goto die;
> > +           if (amt == 0)
> > +                   break;
> > +           while (amt > 0) {
> > +                   int x = write(s->z_pipe[0], tmpbuffer, amt);
> > +                   if (x < 1)
> > +                           goto die;
> > +                   amt -= x;
> > +           }
> > +   }
> > +   close(s->z_pipe[0]);
> > +   write(s->z_ctlpipe[0], &zero, sizeof(zero));
> > +
> > +   info.mtime = s->z_time;
> > +   info.crc = s->z_crc;
> > +   info.hlen = s->z_hlen;
> > +   info.total_in = s->z_total_in;
> > +   info.total_out = s->z_total_out;
> > +
> > +   write(s->z_ctlpipe[0], &info, sizeof(info));
> > +
> > +   _exit(0);
> > +
> > +die:
> > +   write(s->z_ctlpipe[0], &one, sizeof(one));
> > +   _exit(1);
> > +}
> > +
> >  #ifndef SMALL
> >  static int
> >  put_int32(gz_stream *s, u_int32_t x)
> > @@ -493,37 +585,35 @@ gz_close(void *cookie, struct z_info *in
> >             return -1;
> >  
> >  #ifndef SMALL
> > -   if (s->z_mode == 'w' && (err = gz_flush (s, Z_FINISH)) == Z_OK) {
> > -           if ((err = put_int32 (s, s->z_crc)) == Z_OK) {
> > -                   s->z_hlen += sizeof(int32_t);
> > -                   if ((err = put_int32 (s, s->z_stream.total_in)) == Z_OK)
> > +   if (s->z_mode == 'w') {
> > +           if ((err = gz_flush (s, Z_FINISH)) == Z_OK) {
> > +                   if ((err = put_int32 (s, s->z_crc)) == Z_OK) {
> >                             s->z_hlen += sizeof(int32_t);
> > +                           if ((err = put_int32 (s, s->z_stream.total_in)) 
> > == Z_OK)
> > +                                   s->z_hlen += sizeof(int32_t);
> > +                   }
> >             }
> > -   }
> > -#endif
> > -   if (!err && s->z_stream.state != NULL) {
> > -           if (s->z_mode == 'w')
> > -#ifndef SMALL
> > +           if (!err && s->z_stream.state != NULL)
> >                     err = deflateEnd(&s->z_stream);
> > -#else
> > -                   err = -1;
> > -#endif
> > -           else if (s->z_mode == 'r')
> > -                   err = inflateEnd(&s->z_stream);
> > -   }
> > +           if (info != NULL) {
> > +                   info->mtime = s->z_time;
> > +                   info->crc = s->z_crc;
> > +                   info->hlen = s->z_hlen;
> > +                   if (s->z_mode == 'r') {
> > +                           info->total_in = s->z_total_in;
> > +                           info->total_out = s->z_total_out;
> > +                   } else {
> > +                           info->total_in = s->z_stream.total_in;
> > +                           info->total_out = s->z_stream.total_out;
> > +                   }
> >  
> > -   if (info != NULL) {
> > -           info->mtime = s->z_time;
> > -           info->crc = s->z_crc;
> > -           info->hlen = s->z_hlen;
> > -           if (s->z_mode == 'r') {
> > -                   info->total_in = s->z_total_in;
> > -                   info->total_out = s->z_total_out;
> > -           } else {
> > -                   info->total_in = s->z_stream.total_in;
> > -                   info->total_out = s->z_stream.total_out;
> >             }
> > -
> > +   } else
> > +#endif
> > +   if (s->z_mode == 'r') {
> > +           if (info != NULL)
> > +                   if (read(s->z_ctlpipe[1], info, sizeof(*info)) != 
> > sizeof(*info))
> > +                           err = -1;
> >     }
> >  
> >     setfile(name, s->z_fd, sb);
> > @@ -536,4 +626,3 @@ gz_close(void *cookie, struct z_info *in
> >  
> >     return err;
> >  }
> > -
> > Index: main.c
> > ===================================================================
> > RCS file: /cvs/src/usr.bin/compress/main.c,v
> > retrieving revision 1.94
> > diff -u -p -r1.94 main.c
> > --- main.c  3 Sep 2016 13:26:50 -0000       1.94
> > +++ main.c  3 Sep 2016 15:04:26 -0000
> > @@ -166,7 +166,7 @@ main(int argc, char *argv[])
> >     char outfile[PATH_MAX], _infile[PATH_MAX], suffix[16];
> >     int bits, ch, error, rc, cflag, oflag;
> >  
> > -   if (pledge("stdio rpath wpath cpath fattr chown", NULL) == -1)
> > +   if (pledge("stdio rpath wpath cpath fattr chown proc", NULL) == -1)
> >             err(1, "pledge");
> >  
> >     bits = cflag = oflag = 0;
> > @@ -332,7 +332,7 @@ main(int argc, char *argv[])
> >     argv += optind;
> >  
> >     if (cflag || testmode || (!oflag && argc == 0))
> > -           if (pledge("stdio rpath", NULL) == -1)
> > +           if (pledge("stdio rpath proc", NULL) == -1)
> >                     err(1, "pledge");
> >  
> >     if (argc == 0) {
> 

Reply via email to