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.
36 int devnull = open("/dev/null", fd ? O_WRONLY : O_RDONLY);
41 if (devnull > STDERR_FILENO)
46 gzip_thread(void *ptr)
48 struct gzip_handle *zh = ptr;
54 len = fread(buf, 1, sizeof(buf), zh->file);
56 len = gzip_read(zh->gzip, buf, sizeof(buf));
62 ret = write(zh->wfd, buf, len);
63 } while (ret == -1 && errno == EINTR);
71 gzip_exec(struct gzip_handle *zh, const char *filename)
73 int rpipe[2] = { -1, -1 }, wpipe[2] = { -1, -1 };
74 struct sigaction pipe_sa = { .sa_handler = SIG_IGN };
79 if (sigaction(SIGPIPE, &pipe_sa, &zh->pipe_sa) < 0)
85 if (!filename && pipe(wpipe) < 0) {
98 to_devnull(STDERR_FILENO);
101 to_devnull(STDIN_FILENO);
104 dup2(wpipe[0], STDIN_FILENO);
109 dup2(rpipe[1], STDOUT_FILENO);
113 execlp("gzip", "gzip", "-d", "-c", filename, NULL);
120 fcntl(zh->rfd, F_SETFD, fcntl(zh->rfd, F_GETFD) | FD_CLOEXEC);
124 fcntl(zh->wfd, F_SETFD, fcntl(zh->wfd, F_GETFD) | FD_CLOEXEC);
126 pthread_create(&zh->thread, NULL, gzip_thread, zh);
134 gzip_read(struct gzip_handle *zh, char *buf, ssize_t len)
139 ret = read(zh->rfd, buf, len);
140 } while (ret == -1 && errno != EINTR);
146 gzip_copy(struct gzip_handle *zh, FILE *out, ssize_t len)
149 ssize_t rlen, total = 0;
152 rlen = gzip_read(zh, buf,
153 (len > sizeof(buf)) ? sizeof(buf) : len);
159 if (fwrite(buf, 1, rlen, out) != rlen)
171 gzip_fdopen(struct gzip_handle *zh, const char *filename)
173 memset(zh, 0, sizeof(*zh));
175 if (!filename || gzip_exec(zh, filename) < 0)
178 fcntl(zh->rfd, F_SETFL, fcntl(zh->rfd, F_GETFL) & ~O_NONBLOCK);
180 return fdopen(zh->rfd, "r");
184 gzip_close(struct gzip_handle *zh)
195 kill(zh->pid, SIGKILL);
196 waitpid(zh->pid, &code, 0);
203 pthread_join(zh->thread, NULL);
205 sigaction(SIGPIPE, &zh->pipe_sa, NULL);
207 return WIFEXITED(code) ? WEXITSTATUS(code) : -1;