diff options
Diffstat (limited to 'libbb/gz_open.c')
-rw-r--r-- | libbb/gz_open.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/libbb/gz_open.c b/libbb/gz_open.c index dbaf3bb..ba4d6a5 100644 --- a/libbb/gz_open.c +++ b/libbb/gz_open.c @@ -56,3 +56,78 @@ extern FILE *gz_open(FILE *compressed_file, int *pid) } return(fdopen(unzip_pipe[0], "r")); } + +/* gz_open implementation using gunzip and a vfork/exec -- dodges OOM killer */ +extern FILE *gzvopen(FILE *compressed_file, int *pid) +{ + int unzip_pipe[2]; + off_t floc; + int cfile; + + /* create a new file descriptor for the input stream + * (it *must* be associated with a file) + * and seek to the same position in that fd as the stream. + */ + cfile = dup(fileno(compressed_file)); + floc = ftello(compressed_file); + lseek(cfile, floc, SEEK_SET); + + /* create the pipe */ + if (pipe(unzip_pipe)!=0) { + error_msg("gzvopen(): pipe error"); + return(NULL); + } + + *pid = vfork(); + + if (*pid < 0) { + error_msg("gzvopen(): fork failed"); + return(NULL); + } + + if (*pid==0) { + /* child process - reads STDIN, writes to pipe */ + + /* close unused read end of pipe */ + close(unzip_pipe[0]); + + /* connect child's stdout to the pipe write end */ + dup2(unzip_pipe[1], 1); + + /* connect child's stdin to the fd passed in to us */ + dup2(cfile, 0); + + /* execute the gunzip utility */ + execlp("gunzip","gunzip",NULL); + + /* if we get here, we had a failure - since we are + * using vfork(), we cannot call exit(), must call _exit(). + */ + _exit(-1); + } + + /* Parent process is executing here */ + + /* we have no more need of the duplicate fd */ + close(cfile); + + /* close the write end of the pipe */ + close(unzip_pipe[1]); + + /* return the read end of the pipe as a FILE */ + return(fdopen(unzip_pipe[0], "r")); +} + +extern void gzvclose(int gunzip_pid) +{ + if (kill(gunzip_pid, SIGTERM) == -1) { + perror("gzvclose()"); + fprintf(stderr,"%s: unable to kill gunzip pid.\n", + __FUNCTION__); + } + + if (waitpid(gunzip_pid, NULL, 0) == -1) { + fprintf(stderr,"%s: unable to wait on gunzip pid.\n", + __FUNCTION__); + } +} |