-// DecompressFile - wrapper for decompressing gzip/bzip2/xz compressed files /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool DecompressFile(string Filename, int *fd, off_t *FileSize)
-{
- string CompressProg;
- string CompressProgFind;
- FileFd From;
- struct stat Buf;
- *fd = -1;
-
- if (stat((Filename + ".gz").c_str(), &Buf) == 0)
- {
- CompressProg = "gzip";
- CompressProgFind = "Dir::bin::gzip";
- From.Open(Filename + ".gz",FileFd::ReadOnly);
- }
- else if (stat((Filename + ".bz2").c_str(), &Buf) == 0)
- {
- CompressProg = "bzip2";
- CompressProgFind = "Dir::bin::bzip2";
- From.Open(Filename + ".bz2",FileFd::ReadOnly);
- }
- else if (stat((Filename + ".xz").c_str(), &Buf) == 0)
- {
- CompressProg = "xz";
- CompressProgFind = "Dir::bin::xz";
- From.Open(Filename + ".xz",FileFd::ReadOnly);
- }
- else
- {
- return _error->Errno("decompressor", "Unable to parse file");
- }
-
- if (_error->PendingError() == true)
- return -1;
-
- *FileSize = Buf.st_size;
-
- // Get a temp file
- FILE *tmp = tmpfile();
- if (tmp == 0)
- return _error->Errno("tmpfile","Unable to create a tmp file");
- *fd = dup(fileno(tmp));
- fclose(tmp);
-
- // Fork decompressor
- pid_t Process = fork();
- if (Process < 0)
- return _error->Errno("fork","Couldn't fork to run decompressor");
-
- // The child
- if (Process == 0)
- {
- dup2(From.Fd(),STDIN_FILENO);
- dup2(*fd,STDOUT_FILENO);
- SetCloseExec(STDIN_FILENO,false);
- SetCloseExec(STDOUT_FILENO,false);
-
- const char *Args[3];
- string Tmp = _config->Find(CompressProgFind, CompressProg);
- Args[0] = Tmp.c_str();
- Args[1] = "-d";
- Args[2] = 0;
- if(execvp(Args[0],(char **)Args))
- return(_error->Errno("decompressor","decompress failed"));
- /* Should never get here */
- exit(100);
- }
-
- // Wait for decompress to finish
- if (ExecWait(Process,CompressProg.c_str(),false) == false)
- return false;
-
- return true;
-}
- /*}}}*/