test: Fix varbuf memory leak in t-pkg-format test
[dpkg.git] / src / deb / info.c
blob659866323d47b9fea2b0574063ec6b2daab87249
1 /*
2 * dpkg-deb - construction and deconstruction of *.deb archives
3 * info.c - providing information
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>
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.
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.
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/>.
23 #include <config.h>
24 #include <compat.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/wait.h>
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>
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>
50 #include "dpkg-deb.h"
52 static void cu_info_prepare(int argc, void **argv) {
53 char *dir;
55 dir = argv[0];
56 path_remove_tree(dir);
57 free(dir);
60 static void info_prepare(const char *const **argvp,
61 const char **debarp,
62 const char **dirp,
63 int admininfo) {
64 char *dbuf;
66 *debarp= *(*argvp)++;
67 if (!*debarp) badusage(_("--%s needs a .deb filename argument"),cipaction->olong);
69 dbuf = mkdtemp(path_make_temp_template("dpkg-deb"));
70 if (!dbuf)
71 ohshite(_("unable to create temporary directory"));
72 *dirp = dbuf;
74 push_cleanup(cu_info_prepare, -1, 1, (void *)dbuf);
75 extracthalf(*debarp, dbuf, DPKG_TAR_EXTRACT | DPKG_TAR_NOMTIME, admininfo);
78 static int ilist_select(const struct dirent *de) {
79 return strcmp(de->d_name,".") && strcmp(de->d_name,"..");
82 static void
83 info_spew(const char *debar, const char *dir, const char *const *argv)
85 struct dpkg_error err;
86 const char *component;
87 struct varbuf controlfile = VARBUF_INIT;
88 int re= 0;
90 while ((component = *argv++) != NULL) {
91 int fd;
93 varbuf_reset(&controlfile);
94 varbuf_printf(&controlfile, "%s/%s", dir, component);
96 fd = open(controlfile.buf, O_RDONLY);
97 if (fd >= 0) {
98 if (fd_fd_copy(fd, 1, -1, &err) < 0)
99 ohshit(_("cannot extract control file '%s' from '%s': %s"),
100 controlfile.buf, debar, err.str);
101 close(fd);
102 } else if (errno == ENOENT) {
103 notice(_("'%.255s' contains no control component '%.255s'"),
104 debar, component);
105 re++;
106 } else {
107 ohshite(_("open component '%.255s' (in %.255s) failed in an unexpected way"),
108 component, dir);
111 varbuf_destroy(&controlfile);
113 if (re > 0)
114 ohshit(P_("%d requested control component is missing",
115 "%d requested control components are missing", re), re);
118 static char *
119 info_interpreter(FILE *cc, int *lines)
121 char interpreter[INTERPRETER_MAX + 1];
122 int c;
124 *lines = 0;
125 interpreter[0] = '\0';
126 if (getc(cc) == '#' && getc(cc) == '!') {
127 char *p;
128 int il;
130 while ((c = getc(cc)) == ' ')
132 p = interpreter;
133 *p++ = '#';
134 *p++ = '!';
135 il = 2;
136 while (il < INTERPRETER_MAX && !c_isspace(c) && c != EOF) {
137 *p++ = c;
138 il++;
139 c = getc(cc);
141 *p = '\0';
142 if (c == '\n')
143 (*lines)++;
145 while ((c = getc(cc)) != EOF) {
146 if (c == '\n')
147 (*lines)++;
150 return m_strdup(interpreter);
153 static void
154 info_list(const char *debar, const char *dir)
156 struct varbuf controlfile = VARBUF_INIT;
157 struct dirent **cdlist;
158 int cdn, n;
159 FILE *cc;
161 cdn = scandir(dir, &cdlist, &ilist_select, alphasort);
162 if (cdn == -1)
163 ohshite(_("cannot scan directory '%.255s'"), dir);
165 for (n = 0; n < cdn; n++) {
166 struct dirent *cdep;
167 struct stat stab;
169 cdep = cdlist[n];
171 varbuf_reset(&controlfile);
172 varbuf_printf(&controlfile, "%s/%s", dir, cdep->d_name);
174 if (stat(controlfile.buf, &stab))
175 ohshite(_("cannot stat '%.255s' (in '%.255s')"), cdep->d_name, dir);
176 if (S_ISREG(stab.st_mode)) {
177 int exec_mark = (S_IXUSR & stab.st_mode) ? '*' : ' ';
178 char *interpreter;
179 int lines;
181 cc = fopen(controlfile.buf, "r");
182 if (!cc)
183 ohshite(_("cannot open '%.255s' (in '%.255s')"), cdep->d_name, dir);
185 interpreter = info_interpreter(cc, &lines);
187 if (ferror(cc))
188 ohshite(_("failed to read '%.255s' (in '%.255s')"), cdep->d_name, dir);
189 fclose(cc);
190 if (str_is_set(interpreter))
191 printf(_(" %7jd bytes, %5d lines %c %-20.127s %.127s\n"),
192 (intmax_t)stab.st_size, lines, exec_mark, cdep->d_name,
193 interpreter);
194 else
195 printf(_(" %7jd bytes, %5d lines %c %.127s\n"),
196 (intmax_t)stab.st_size, lines, exec_mark, cdep->d_name);
198 free(interpreter);
199 } else {
200 printf(_(" not a plain file %.255s\n"), cdep->d_name);
202 free(cdep);
204 free(cdlist);
206 varbuf_reset(&controlfile);
207 varbuf_printf(&controlfile, "%s/%s", dir, CONTROLFILE);
208 cc = fopen(controlfile.buf, "r");
209 if (!cc) {
210 if (errno != ENOENT)
211 ohshite(_("failed to read '%.255s' (in '%.255s')"), CONTROLFILE, dir);
212 warning(_("no 'control' file in control archive!"));
213 } else {
214 int lines, c;
216 lines= 1;
217 while ((c= getc(cc))!= EOF) {
218 if (lines)
219 putc(' ', stdout);
220 putc(c, stdout);
221 lines= c=='\n';
223 if (!lines)
224 putc('\n', stdout);
226 if (ferror(cc))
227 ohshite(_("failed to read '%.255s' (in '%.255s')"), CONTROLFILE, dir);
228 fclose(cc);
231 m_output(stdout, _("<standard output>"));
232 varbuf_destroy(&controlfile);
235 static void
236 info_field(const char *debar, const char *dir, const char *const *fields,
237 enum fwriteflags fieldflags)
239 char *controlfile;
240 struct varbuf str = VARBUF_INIT;
241 struct pkginfo *pkg;
242 int i;
244 controlfile = str_fmt("%s/%s", dir, CONTROLFILE);
245 parsedb(controlfile, pdb_parse_binary | pdb_ignore_archives, &pkg);
246 free(controlfile);
248 for (i = 0; fields[i]; i++) {
249 const struct fieldinfo *field;
251 varbuf_reset(&str);
252 field = find_field_info(fieldinfos, fields[i]);
253 if (field) {
254 field->wcall(&str, pkg, &pkg->available, fieldflags, field);
255 } else {
256 const struct arbitraryfield *arbfield;
258 arbfield = find_arbfield_info(pkg->available.arbs, fields[i]);
259 if (arbfield)
260 varbuf_add_arbfield(&str, arbfield, fieldflags);
262 varbuf_end_str(&str);
264 if (fieldflags & fw_printheader)
265 printf("%s", str.buf);
266 else
267 printf("%s\n", str.buf);
270 m_output(stdout, _("<standard output>"));
272 varbuf_destroy(&str);
276 do_showinfo(const char *const *argv)
278 const char *debar, *dir;
279 char *controlfile;
280 struct dpkg_error err;
281 struct pkginfo *pkg;
282 struct pkg_format_node *fmt;
284 fmt = pkg_format_parse(opt_showformat, &err);
285 if (!fmt)
286 ohshit(_("error in show format: %s"), err.str);
288 info_prepare(&argv, &debar, &dir, 1);
290 controlfile = str_fmt("%s/%s", dir, CONTROLFILE);
291 parsedb(controlfile, pdb_parse_binary | pdb_ignore_archives, &pkg);
292 pkg_format_show(fmt, pkg, &pkg->available);
293 pkg_format_free(fmt);
294 free(controlfile);
296 return 0;
300 do_info(const char *const *argv)
302 const char *debar, *dir;
304 if (*argv && argv[1]) {
305 info_prepare(&argv, &debar, &dir, 1);
306 info_spew(debar, dir, argv);
307 } else {
308 info_prepare(&argv, &debar, &dir, 2);
309 info_list(debar, dir);
312 return 0;
316 do_field(const char *const *argv)
318 const char *debar, *dir;
320 info_prepare(&argv, &debar, &dir, 1);
321 if (*argv) {
322 info_field(debar, dir, argv, argv[1] != NULL ? fw_printheader : 0);
323 } else {
324 static const char *const controlonly[] = { CONTROLFILE, NULL };
325 info_spew(debar, dir, controlonly);
328 return 0;
332 do_contents(const char *const *argv)
334 const char *debar = *argv++;
336 if (debar == NULL || *argv)
337 badusage(_("--%s takes exactly one argument"), cipaction->olong);
338 extracthalf(debar, NULL, DPKG_TAR_LIST, 0);
340 return 0;