Branch data Line data Source code
1 : : /*
2 : : * dpkg-deb - construction and deconstruction of *.deb archives
3 : : * info.c - providing information
4 : : *
5 : : * Copyright © 1994,1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 : : * Copyright © 2001 Wichert Akkerman
7 : : * Copyright © 2007-2015 Guillem Jover <guillem@debian.org>
8 : : *
9 : : * This is free software; you can redistribute it and/or modify
10 : : * it under the terms of the GNU General Public License as published by
11 : : * the Free Software Foundation; either version 2 of the License, or
12 : : * (at your option) any later version.
13 : : *
14 : : * This is distributed in the hope that it will be useful,
15 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : : * GNU General Public License for more details.
18 : : *
19 : : * You should have received a copy of the GNU General Public License
20 : : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : : */
22 : :
23 : : #include <config.h>
24 : : #include <compat.h>
25 : :
26 : : #include <sys/types.h>
27 : : #include <sys/stat.h>
28 : : #include <sys/wait.h>
29 : :
30 : : #include <errno.h>
31 : : #include <limits.h>
32 : : #include <string.h>
33 : : #include <fcntl.h>
34 : : #include <dirent.h>
35 : : #include <unistd.h>
36 : : #include <stdint.h>
37 : : #include <stdlib.h>
38 : : #include <stdio.h>
39 : :
40 : : #include <dpkg/i18n.h>
41 : : #include <dpkg/c-ctype.h>
42 : : #include <dpkg/dpkg.h>
43 : : #include <dpkg/dpkg-db.h>
44 : : #include <dpkg/parsedump.h>
45 : : #include <dpkg/pkg-format.h>
46 : : #include <dpkg/buffer.h>
47 : : #include <dpkg/path.h>
48 : : #include <dpkg/options.h>
49 : :
50 : : #include "dpkg-deb.h"
51 : :
52 : 21 : static void cu_info_prepare(int argc, void **argv) {
53 : : char *dir;
54 : :
55 : 21 : dir = argv[0];
56 : 21 : path_remove_tree(dir);
57 : 21 : free(dir);
58 : 21 : }
59 : :
60 : 21 : static void info_prepare(const char *const **argvp,
61 : : const char **debarp,
62 : : const char **dirp,
63 : : int admininfo) {
64 : : char *dbuf;
65 : :
66 : 21 : *debarp= *(*argvp)++;
67 [ - + ]: 21 : if (!*debarp) badusage(_("--%s needs a .deb filename argument"),cipaction->olong);
68 : :
69 : 21 : dbuf = mkdtemp(path_make_temp_template("dpkg-deb"));
70 [ - + ]: 21 : if (!dbuf)
71 : 0 : ohshite(_("unable to create temporary directory"));
72 : 21 : *dirp = dbuf;
73 : :
74 : 21 : push_cleanup(cu_info_prepare, -1, 1, (void *)dbuf);
75 : 21 : extracthalf(*debarp, dbuf, DPKG_TAR_EXTRACT | DPKG_TAR_NOMTIME, admininfo);
76 : 14 : }
77 : :
78 : 30 : static int ilist_select(const struct dirent *de) {
79 [ + + + + ]: 30 : return strcmp(de->d_name,".") && strcmp(de->d_name,"..");
80 : : }
81 : :
82 : : static void
83 : 1 : info_spew(const char *debar, const char *dir, const char *const *argv)
84 : : {
85 : : struct dpkg_error err;
86 : : const char *component;
87 : 1 : struct varbuf controlfile = VARBUF_INIT;
88 : 1 : int re= 0;
89 : :
90 [ + + ]: 2 : while ((component = *argv++) != NULL) {
91 : : int fd;
92 : :
93 : 1 : varbuf_reset(&controlfile);
94 : 1 : varbuf_printf(&controlfile, "%s/%s", dir, component);
95 : :
96 : 1 : fd = open(varbuf_str(&controlfile), O_RDONLY);
97 [ + - ]: 1 : if (fd >= 0) {
98 [ - + ]: 1 : if (fd_fd_copy(fd, 1, -1, &err) < 0)
99 : 0 : ohshit(_("cannot extract control file '%s' from '%s': %s"),
100 : : varbuf_str(&controlfile), debar, err.str);
101 : 1 : close(fd);
102 [ # # ]: 0 : } else if (errno == ENOENT) {
103 : 0 : notice(_("'%.255s' contains no control component '%.255s'"),
104 : : debar, component);
105 : 0 : re++;
106 : : } else {
107 : 0 : ohshite(_("open component '%.255s' (in %.255s) failed in an unexpected way"),
108 : : component, dir);
109 : : }
110 : : }
111 : 1 : varbuf_destroy(&controlfile);
112 : :
113 [ - + ]: 1 : if (re > 0)
114 : 0 : ohshit(P_("%d requested control component is missing",
115 : : "%d requested control components are missing", re), re);
116 : 1 : }
117 : :
118 : : static char *
119 : 10 : info_interpreter(FILE *cc, int *lines)
120 : : {
121 : : char interpreter[INTERPRETER_MAX + 1];
122 : : int c;
123 : :
124 : 10 : *lines = 0;
125 : 10 : interpreter[0] = '\0';
126 [ - + - - ]: 10 : if (getc(cc) == '#' && getc(cc) == '!') {
127 : : char *p;
128 : : int il;
129 : :
130 [ # # ]: 0 : while ((c = getc(cc)) == ' ')
131 : : ;
132 : 0 : p = interpreter;
133 : 0 : *p++ = '#';
134 : 0 : *p++ = '!';
135 : 0 : il = 2;
136 [ # # # # : 0 : while (il < INTERPRETER_MAX && !c_isspace(c) && c != EOF) {
# # ]
137 : 0 : *p++ = c;
138 : 0 : il++;
139 : 0 : c = getc(cc);
140 : : }
141 : 0 : *p = '\0';
142 [ # # ]: 0 : if (c == '\n')
143 : 0 : (*lines)++;
144 : : }
145 [ + + ]: 1972 : while ((c = getc(cc)) != EOF) {
146 [ + + ]: 1952 : if (c == '\n')
147 : 70 : (*lines)++;
148 : : }
149 : :
150 : 10 : return m_strdup(interpreter);
151 : : }
152 : :
153 : : static void
154 : 10 : info_list(const char *debar, const char *dir)
155 : : {
156 : 10 : struct varbuf controlfile = VARBUF_INIT;
157 : : struct dirent **cdlist;
158 : : int cdn, n;
159 : : FILE *cc;
160 : :
161 : 10 : cdn = scandir(dir, &cdlist, &ilist_select, alphasort);
162 [ - + ]: 10 : if (cdn < 0)
163 : 0 : ohshite(_("cannot scan directory '%.255s'"), dir);
164 : :
165 [ + + ]: 20 : for (n = 0; n < cdn; n++) {
166 : : struct dirent *cdep;
167 : : struct stat stab;
168 : :
169 : 10 : cdep = cdlist[n];
170 : :
171 : 10 : varbuf_reset(&controlfile);
172 : 10 : varbuf_printf(&controlfile, "%s/%s", dir, cdep->d_name);
173 : :
174 [ - + ]: 10 : if (stat(controlfile.buf, &stab))
175 : 0 : ohshite(_("cannot stat '%.255s' (in '%.255s')"), cdep->d_name, dir);
176 [ + - ]: 10 : if (S_ISREG(stab.st_mode)) {
177 [ - + ]: 10 : int exec_mark = (S_IXUSR & stab.st_mode) ? '*' : ' ';
178 : : char *interpreter;
179 : : int lines;
180 : :
181 : 10 : cc = fopen(controlfile.buf, "r");
182 [ - + ]: 10 : if (!cc)
183 : 0 : ohshite(_("cannot open '%.255s' (in '%.255s')"), cdep->d_name, dir);
184 : :
185 : 10 : interpreter = info_interpreter(cc, &lines);
186 : :
187 [ - + ]: 10 : if (ferror(cc))
188 : 0 : ohshite(_("failed to read '%.255s' (in '%.255s')"), cdep->d_name, dir);
189 : 10 : fclose(cc);
190 [ - + ]: 10 : if (str_is_set(interpreter))
191 : 0 : printf(_(" %7jd bytes, %5d lines %c %-20.127s %.127s\n"),
192 : 0 : (intmax_t)stab.st_size, lines, exec_mark, cdep->d_name,
193 : : interpreter);
194 : : else
195 : 10 : printf(_(" %7jd bytes, %5d lines %c %.127s\n"),
196 : 10 : (intmax_t)stab.st_size, lines, exec_mark, cdep->d_name);
197 : :
198 : 10 : free(interpreter);
199 : : } else {
200 : 0 : printf(_(" not a plain file %.255s\n"), cdep->d_name);
201 : : }
202 : 10 : free(cdep);
203 : : }
204 : 10 : free(cdlist);
205 : :
206 : 10 : varbuf_reset(&controlfile);
207 : 10 : varbuf_printf(&controlfile, "%s/%s", dir, CONTROLFILE);
208 : 10 : cc = fopen(controlfile.buf, "r");
209 [ - + ]: 10 : if (!cc) {
210 [ # # ]: 0 : if (errno != ENOENT)
211 : 0 : ohshite(_("failed to read '%.255s' (in '%.255s')"), CONTROLFILE, dir);
212 : 0 : warning(_("no 'control' file in control archive!"));
213 : : } else {
214 : : int lines, c;
215 : :
216 : 10 : lines= 1;
217 [ + + ]: 1972 : while ((c= getc(cc))!= EOF) {
218 [ + + ]: 1962 : if (lines)
219 : 70 : putc(' ', stdout);
220 : 1962 : putc(c, stdout);
221 : 1962 : lines= c=='\n';
222 : : }
223 [ - + ]: 10 : if (!lines)
224 : 0 : putc('\n', stdout);
225 : :
226 [ - + ]: 10 : if (ferror(cc))
227 : 0 : ohshite(_("failed to read '%.255s' (in '%.255s')"), CONTROLFILE, dir);
228 : 10 : fclose(cc);
229 : : }
230 : :
231 : 10 : m_output(stdout, _("<standard output>"));
232 : 10 : varbuf_destroy(&controlfile);
233 : 10 : }
234 : :
235 : : static void
236 : 3 : info_field(const char *debar, const char *dir, const char *const *fields,
237 : : enum fwriteflags fieldflags)
238 : : {
239 : : char *controlfile;
240 : 3 : struct varbuf str = VARBUF_INIT;
241 : : struct pkginfo *pkg;
242 : : int i;
243 : :
244 : 3 : controlfile = str_fmt("%s/%s", dir, CONTROLFILE);
245 : 3 : parsedb(controlfile, pdb_parse_binary | pdb_ignore_archives, &pkg);
246 : 3 : free(controlfile);
247 : :
248 [ + + ]: 9 : for (i = 0; fields[i]; i++) {
249 : : const struct fieldinfo *field;
250 : :
251 : 6 : varbuf_reset(&str);
252 : 6 : field = find_field_info(fieldinfos, fields[i]);
253 [ + + ]: 6 : if (field) {
254 : 4 : field->wcall(&str, pkg, &pkg->available, fieldflags, field);
255 : : } else {
256 : : const struct arbitraryfield *arbfield;
257 : :
258 : 2 : arbfield = find_arbfield_info(pkg->available.arbs, fields[i]);
259 [ + + ]: 2 : if (arbfield)
260 : 1 : varbuf_add_arbfield(&str, arbfield, fieldflags);
261 : : }
262 : :
263 [ + + ]: 6 : if (fieldflags & fw_printheader)
264 : 4 : printf("%s", varbuf_str(&str));
265 : : else
266 : 2 : printf("%s\n", varbuf_str(&str));
267 : : }
268 : :
269 : 3 : m_output(stdout, _("<standard output>"));
270 : :
271 : 3 : varbuf_destroy(&str);
272 : 3 : }
273 : :
274 : : int
275 : 0 : do_showinfo(const char *const *argv)
276 : : {
277 : : const char *debar, *dir;
278 : : char *controlfile;
279 : : struct dpkg_error err;
280 : : struct pkginfo *pkg;
281 : : struct pkg_format_node *fmt;
282 : :
283 : 0 : fmt = pkg_format_parse(opt_showformat, &err);
284 [ # # ]: 0 : if (!fmt)
285 : 0 : ohshit(_("error in show format: %s"), err.str);
286 : :
287 : 0 : info_prepare(&argv, &debar, &dir, 1);
288 : :
289 : 0 : controlfile = str_fmt("%s/%s", dir, CONTROLFILE);
290 : 0 : parsedb(controlfile, pdb_parse_binary | pdb_ignore_archives, &pkg);
291 : 0 : pkg_format_show(fmt, pkg, &pkg->available);
292 : 0 : pkg_format_free(fmt);
293 : 0 : free(controlfile);
294 : :
295 : 0 : return 0;
296 : : }
297 : :
298 : : int
299 : 18 : do_info(const char *const *argv)
300 : : {
301 : : const char *debar, *dir;
302 : :
303 [ + - + + ]: 18 : if (*argv && argv[1]) {
304 : 1 : info_prepare(&argv, &debar, &dir, 1);
305 : 1 : info_spew(debar, dir, argv);
306 : : } else {
307 : 17 : info_prepare(&argv, &debar, &dir, 2);
308 : 10 : info_list(debar, dir);
309 : : }
310 : :
311 : 11 : return 0;
312 : : }
313 : :
314 : : int
315 : 3 : do_field(const char *const *argv)
316 : : {
317 : : const char *debar, *dir;
318 : :
319 : 3 : info_prepare(&argv, &debar, &dir, 1);
320 [ + - ]: 3 : if (*argv) {
321 : 3 : info_field(debar, dir, argv, argv[1] != NULL ? fw_printheader : 0);
322 : : } else {
323 : : static const char *const controlonly[] = { CONTROLFILE, NULL };
324 : 0 : info_spew(debar, dir, controlonly);
325 : : }
326 : :
327 : 3 : return 0;
328 : : }
329 : :
330 : : int
331 : 17 : do_contents(const char *const *argv)
332 : : {
333 : 17 : const char *debar = *argv++;
334 : :
335 [ + - - + ]: 17 : if (debar == NULL || *argv)
336 : 0 : badusage(_("--%s takes exactly one argument"), cipaction->olong);
337 : 17 : extracthalf(debar, NULL, DPKG_TAR_LIST, 0);
338 : :
339 : 13 : return 0;
340 : : }
|