1 /* vi: set sw=4 ts=4: */ 2 /* 3 * Utility routines. 4 * 5 * Copyright (C) many different people. If you wrote this, please 6 * acknowledge your work. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 21 * USA 22 */ 23 24 #include <sys/types.h> 25 #include <sys/wait.h> 26 #include <signal.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <unistd.h> 30 #include "libbb.h" 31 32 static int gz_use_vfork; 33 34 FILE *gz_open(FILE * compressed_file, int *pid) 35 { 36 int unzip_pipe[2]; 37 off_t floc; 38 int cfile = -1; 39 40 gz_use_vfork = (getenv("OPKG_USE_VFORK") != NULL); 41 42 if (gz_use_vfork) { 43 /* Create a new file descriptor for the input stream 44 * (it *must* be associated with a file), and lseek() 45 * to the same position in that fd as the stream. 46 */ 47 cfile = dup(fileno(compressed_file)); 48 floc = ftello(compressed_file); 49 lseek(cfile, floc, SEEK_SET); 50 setenv("GZIP", "--quiet", 0); 51 } 52 53 if (pipe(unzip_pipe) != 0) { 54 perror_msg("pipe"); 55 return (NULL); 56 } 57 58 /* If we don't flush, we end up with two copies of anything pending, 59 one from the parent, one from the child */ 60 fflush(stdout); 61 fflush(stderr); 62 63 if (gz_use_vfork) { 64 *pid = vfork(); 65 } else { 66 *pid = fork(); 67 } 68 69 if (*pid < 0) { 70 perror_msg("fork"); 71 return (NULL); 72 } 73 74 if (*pid == 0) { 75 /* child process */ 76 close(unzip_pipe[0]); 77 if (gz_use_vfork) { 78 dup2(unzip_pipe[1], 1); 79 dup2(cfile, 0); 80 execlp("gunzip", "gunzip", NULL); 81 /* If we get here, we had a failure */ 82 _exit(EXIT_FAILURE); 83 } else { 84 unzip(compressed_file, fdopen(unzip_pipe[1], "w")); 85 fflush(NULL); 86 fclose(compressed_file); 87 close(unzip_pipe[1]); 88 _exit(EXIT_SUCCESS); 89 } 90 } 91 /* Parent process is executing here */ 92 if (gz_use_vfork) { 93 close(cfile); 94 } 95 close(unzip_pipe[1]); 96 return (fdopen(unzip_pipe[0], "r")); 97 } 98 99 int gz_close(int gunzip_pid) 100 { 101 int status; 102 int ret; 103 104 if (gz_use_vfork) { 105 /* The gunzip process remains running in the background if we 106 * used the vfork()/exec() technique - so we have to kill it 107 * forcibly. There might be a better way to do this, but that 108 * affect a lot of other parts of opkg, and this works fine. 109 */ 110 if (kill(gunzip_pid, SIGTERM) == -1) { 111 perror_msg("gz_close(): unable to kill gunzip pid."); 112 return -1; 113 } 114 } 115 116 if (waitpid(gunzip_pid, &status, 0) == -1) { 117 perror_msg("waitpid"); 118 return -1; 119 } 120 121 if (gz_use_vfork) { 122 /* Bail out here if we used the vfork()/exec() technique. */ 123 return 0; 124 } 125 126 if (WIFSIGNALED(status)) { 127 error_msg("Unzip process killed by signal %d.\n", 128 WTERMSIG(status)); 129 return -1; 130 } 131 132 if (!WIFEXITED(status)) { 133 /* shouldn't happen */ 134 error_msg 135 ("Your system is broken: got status %d from waitpid.\n", 136 status); 137 return -1; 138 } 139 140 if ((ret = WEXITSTATUS(status))) { 141 error_msg("Unzip process failed with return code %d.\n", ret); 142 return -1; 143 } 144 145 return 0; 146 } 147
This page was automatically generated by LXR 0.3.1. • OpenWrt