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