db22523900a77151c265dccf7e9fc0bf23e3dd95
2 * Copyright (C) 2016 Jo-Philipp Wich <jo@mein.io>
3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
5 * Zlib decrompression utility routines.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Library General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33 static void to_devnull(int fd
)
35 int devnull
= open("/dev/null", fd
? O_WRONLY
: O_RDONLY
);
40 if (devnull
> STDERR_FILENO
)
44 void *gzip_thread(void *ptr
)
46 struct gzip_handle
*zh
= ptr
;
52 len
= fread(buf
, 1, sizeof(buf
), zh
->file
);
54 len
= gzip_read(zh
->gzip
, buf
, sizeof(buf
));
60 ret
= write(zh
->wfd
, buf
, len
);
61 } while (ret
== -1 && errno
== EINTR
);
68 int gzip_exec(struct gzip_handle
*zh
, const char *filename
)
70 int rpipe
[2] = { -1, -1 }, wpipe
[2] = {
72 struct sigaction pipe_sa
= {.sa_handler
= SIG_IGN
};
77 if (sigaction(SIGPIPE
, &pipe_sa
, &zh
->pipe_sa
) < 0)
83 if (!filename
&& pipe(wpipe
) < 0) {
96 to_devnull(STDERR_FILENO
);
99 to_devnull(STDIN_FILENO
);
101 dup2(wpipe
[0], STDIN_FILENO
);
106 dup2(rpipe
[1], STDOUT_FILENO
);
110 execlp("gzip", "gzip", "-d", "-c", filename
, NULL
);
117 fcntl(zh
->rfd
, F_SETFD
, fcntl(zh
->rfd
, F_GETFD
) | FD_CLOEXEC
);
121 fcntl(zh
->wfd
, F_SETFD
,
122 fcntl(zh
->wfd
, F_GETFD
) | FD_CLOEXEC
);
124 pthread_create(&zh
->thread
, NULL
, gzip_thread
, zh
);
131 ssize_t
gzip_read(struct gzip_handle
* zh
, char *buf
, ssize_t len
)
136 ret
= read(zh
->rfd
, buf
, len
);
137 } while (ret
== -1 && errno
!= EINTR
);
142 ssize_t
gzip_copy(struct gzip_handle
* zh
, FILE * out
, ssize_t len
)
145 ssize_t rlen
, total
= 0;
148 rlen
= gzip_read(zh
, buf
,
149 (len
> sizeof(buf
)) ? sizeof(buf
) : len
);
155 if (fwrite(buf
, 1, rlen
, out
) != rlen
)
166 FILE *gzip_fdopen(struct gzip_handle
* zh
, const char *filename
)
168 memset(zh
, 0, sizeof(*zh
));
170 if (!filename
|| gzip_exec(zh
, filename
) < 0)
173 fcntl(zh
->rfd
, F_SETFL
, fcntl(zh
->rfd
, F_GETFL
) & ~O_NONBLOCK
);
175 return fdopen(zh
->rfd
, "r");
178 int gzip_close(struct gzip_handle
*zh
)
189 kill(zh
->pid
, SIGKILL
);
190 waitpid(zh
->pid
, &code
, 0);
197 pthread_join(zh
->thread
, NULL
);
199 sigaction(SIGPIPE
, &zh
->pipe_sa
, NULL
);
201 return WIFEXITED(code
) ? WEXITSTATUS(code
) : -1;