Imported Upstream version 2.8.4
[platform/upstream/man-db.git] / lib / decompress.c
1 /*
2  * decompress.c: decompression abstraction layer
3  *
4  * Copyright (C) 2007, 2008 Colin Watson.
5  *
6  * This file is part of man-db.
7  *
8  * man-db is free software; you can redistribute it and/or modify it
9  * 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  * man-db 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
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with man-db; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #  include "config.h"
25 #endif /* HAVE_CONFIG_H */
26
27 #include <string.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34
35 #ifdef HAVE_LIBZ
36 #  include "zlib.h"
37 #endif /* HAVE_LIBZ */
38
39 #include "xvasprintf.h"
40
41 #include "manconfig.h"
42 #include "comp_src.h"
43 #include "pipeline.h"
44 #include "decompress.h"
45 #include "sandbox.h"
46
47 #ifdef HAVE_LIBZ
48
49 static void decompress_zlib (void *data ATTRIBUTE_UNUSED)
50 {
51         gzFile zlibfile;
52
53         zlibfile = gzdopen (dup (STDIN_FILENO), "r");
54         if (!zlibfile)
55                 return;
56
57         for (;;) {
58                 char buffer[4096];
59                 int r = gzread (zlibfile, buffer, 4096);
60                 if (r <= 0)
61                         break;
62                 if (fwrite (buffer, 1, (size_t) r, stdout) < (size_t) r)
63                         break;
64         }
65
66         gzclose (zlibfile);
67         return;
68 }
69
70 #endif /* HAVE_LIBZ */
71
72 extern man_sandbox *sandbox;
73
74 pipeline *decompress_open (const char *filename)
75 {
76         pipecmd *cmd;
77         pipeline *p;
78         struct stat st;
79 #ifdef HAVE_LIBZ
80         size_t filename_len;
81 #endif /* HAVE_LIBZ */
82         char *ext;
83         struct compression *comp;
84
85         if (stat (filename, &st) < 0 || S_ISDIR (st.st_mode))
86                 return NULL;
87
88 #ifdef HAVE_LIBZ
89         filename_len = strlen (filename);
90         if (filename_len > 3 && STREQ (filename + filename_len - 3, ".gz")) {
91                 cmd = pipecmd_new_function ("zcat", &decompress_zlib, NULL,
92                                             NULL);
93                 pipecmd_pre_exec (cmd, sandbox_load, sandbox_free, sandbox);
94                 p = pipeline_new_commands (cmd, NULL);
95                 goto got_pipeline;
96         }
97 #endif /* HAVE_LIBZ */
98
99         ext = strrchr (filename, '.');
100         if (ext) {
101                 ++ext;
102
103                 for (comp = comp_list; comp->ext; ++comp) {
104                         if (!STREQ (comp->ext, ext))
105                                 continue;
106
107                         cmd = pipecmd_new_argstr (comp->prog);
108                         pipecmd_pre_exec (cmd, sandbox_load, sandbox_free,
109                                           sandbox);
110                         p = pipeline_new_commands (cmd, NULL);
111                         goto got_pipeline;
112                 }
113         }
114
115 #ifdef HAVE_GZIP
116         /* HP-UX */
117         ext = strstr (filename, ".Z/");
118         if (ext) {
119                 cmd = pipecmd_new_argstr (GUNZIP);
120                 pipecmd_pre_exec (cmd, sandbox_load, sandbox_free, sandbox);
121                 p = pipeline_new_commands (cmd, NULL);
122                 goto got_pipeline;
123         }
124 #endif
125
126         p = pipeline_new ();
127
128 got_pipeline:
129         pipeline_want_infile (p, filename);
130         pipeline_want_out (p, -1);
131         return p;
132 }
133
134 pipeline *decompress_fdopen (int fd)
135 {
136         pipeline *p;
137 #ifdef HAVE_LIBZ
138         pipecmd *cmd;
139 #endif /* HAVE_LIBZ */
140
141 #ifdef HAVE_LIBZ
142         cmd = pipecmd_new_function ("zcat", &decompress_zlib, NULL, NULL);
143         pipecmd_pre_exec (cmd, sandbox_load, sandbox_free, sandbox);
144         p = pipeline_new_commands (cmd, NULL);
145 #else /* HAVE_LIBZ */
146         p = pipeline_new ();
147 #endif /* HAVE_LIBZ */
148
149         pipeline_want_in (p, fd);
150         pipeline_want_out (p, -1);
151         return p;
152 }