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 
cu_info_prepare(int argc,void ** argv)52 static void cu_info_prepare(int argc, void **argv) {
53   char *dir;
54 
55   dir = argv[0];
56   path_remove_tree(dir);
57   free(dir);
58 }
59 
info_prepare(const char * const ** argvp,const char ** debarp,const char ** dirp,int admininfo)60 static void info_prepare(const char *const **argvp,
61                          const char **debarp,
62                          const char **dirp,
63                          int admininfo) {
64   char *dbuf;
65 
66   *debarp= *(*argvp)++;
67   if (!*debarp) badusage(_("--%s needs a .deb filename argument"),cipaction->olong);
68 
69   dbuf = mkdtemp(path_make_temp_template("dpkg-deb"));
70   if (!dbuf)
71     ohshite(_("unable to create temporary directory"));
72   *dirp = dbuf;
73 
74   push_cleanup(cu_info_prepare, -1, 1, (void *)dbuf);
75   extracthalf(*debarp, dbuf, DPKG_TAR_EXTRACT | DPKG_TAR_NOMTIME, admininfo);
76 }
77 
ilist_select(const struct dirent * de)78 static int ilist_select(const struct dirent *de) {
79   return strcmp(de->d_name,".") && strcmp(de->d_name,"..");
80 }
81 
82 static void
info_spew(const char * debar,const char * dir,const char * const * argv)83 info_spew(const char *debar, const char *dir, const char *const *argv)
84 {
85   struct dpkg_error err;
86   const char *component;
87   struct varbuf controlfile = VARBUF_INIT;
88   int fd;
89   int re= 0;
90 
91   while ((component = *argv++) != NULL) {
92     varbuf_reset(&controlfile);
93     varbuf_printf(&controlfile, "%s/%s", dir, component);
94 
95     fd = open(controlfile.buf, O_RDONLY);
96     if (fd >= 0) {
97       if (fd_fd_copy(fd, 1, -1, &err) < 0)
98         ohshit(_("cannot extract control file '%s' from '%s': %s"),
99                controlfile.buf, debar, err.str);
100       close(fd);
101     } else if (errno == ENOENT) {
102       notice(_("'%.255s' contains no control component '%.255s'"),
103              debar, component);
104       re++;
105     } else {
106       ohshite(_("open component '%.255s' (in %.255s) failed in an unexpected way"),
107               component, dir);
108     }
109   }
110   varbuf_destroy(&controlfile);
111 
112   if (re > 0)
113     ohshit(P_("%d requested control component is missing",
114               "%d requested control components are missing", re), re);
115 }
116 
117 static void
info_list(const char * debar,const char * dir)118 info_list(const char *debar, const char *dir)
119 {
120   char interpreter[INTERPRETER_MAX+1], *p;
121   int il, lines;
122   struct varbuf controlfile = VARBUF_INIT;
123   struct dirent **cdlist, *cdep;
124   int cdn, n;
125   FILE *cc;
126   struct stat stab;
127   int c;
128 
129   cdn = scandir(dir, &cdlist, &ilist_select, alphasort);
130   if (cdn == -1)
131     ohshite(_("cannot scan directory '%.255s'"), dir);
132 
133   for (n = 0; n < cdn; n++) {
134     cdep = cdlist[n];
135 
136     varbuf_reset(&controlfile);
137     varbuf_printf(&controlfile, "%s/%s", dir, cdep->d_name);
138 
139     if (stat(controlfile.buf, &stab))
140       ohshite(_("cannot stat '%.255s' (in '%.255s')"), cdep->d_name, dir);
141     if (S_ISREG(stab.st_mode)) {
142       cc = fopen(controlfile.buf, "r");
143       if (!cc)
144         ohshite(_("cannot open '%.255s' (in '%.255s')"), cdep->d_name, dir);
145       lines = 0;
146       interpreter[0] = '\0';
147       if (getc(cc) == '#') {
148         if (getc(cc) == '!') {
149           while ((c= getc(cc))== ' ');
150           p=interpreter; *p++='#'; *p++='!'; il=2;
151           while (il < INTERPRETER_MAX && !c_isspace(c) && c != EOF) {
152             *p++= c; il++; c= getc(cc);
153           }
154           *p = '\0';
155           if (c=='\n') lines++;
156         }
157       }
158       while ((c= getc(cc))!= EOF) { if (c == '\n') lines++; }
159       if (ferror(cc))
160         ohshite(_("failed to read '%.255s' (in '%.255s')"), cdep->d_name, dir);
161       fclose(cc);
162       printf(_(" %7jd bytes, %5d lines   %c  %-20.127s %.127s\n"),
163              (intmax_t)stab.st_size, lines,
164              (S_IXUSR & stab.st_mode) ? '*' : ' ',
165              cdep->d_name, interpreter);
166     } else {
167       printf(_("     not a plain file          %.255s\n"), cdep->d_name);
168     }
169     free(cdep);
170   }
171   free(cdlist);
172 
173   varbuf_reset(&controlfile);
174   varbuf_printf(&controlfile, "%s/%s", dir, CONTROLFILE);
175   cc = fopen(controlfile.buf, "r");
176   if (!cc) {
177     if (errno != ENOENT)
178       ohshite(_("failed to read '%.255s' (in '%.255s')"), CONTROLFILE, dir);
179     warning(_("no 'control' file in control archive!"));
180   } else {
181     lines= 1;
182     while ((c= getc(cc))!= EOF) {
183       if (lines)
184         putc(' ', stdout);
185       putc(c, stdout);
186       lines= c=='\n';
187     }
188     if (!lines)
189       putc('\n', stdout);
190 
191     if (ferror(cc))
192       ohshite(_("failed to read '%.255s' (in '%.255s')"), CONTROLFILE, dir);
193     fclose(cc);
194   }
195 
196   m_output(stdout, _("<standard output>"));
197   varbuf_destroy(&controlfile);
198 }
199 
200 static void
info_field(const char * debar,const char * dir,const char * const * fields,enum fwriteflags fieldflags)201 info_field(const char *debar, const char *dir, const char *const *fields,
202            enum fwriteflags fieldflags)
203 {
204   char *controlfile;
205   struct varbuf str = VARBUF_INIT;
206   struct pkginfo *pkg;
207   int i;
208 
209   controlfile = str_fmt("%s/%s", dir, CONTROLFILE);
210   parsedb(controlfile, pdb_parse_binary | pdb_ignore_archives, &pkg);
211   free(controlfile);
212 
213   for (i = 0; fields[i]; i++) {
214     const struct fieldinfo *field;
215     const struct arbitraryfield *arbfield;
216 
217     varbuf_reset(&str);
218     field = find_field_info(fieldinfos, fields[i]);
219     if (field) {
220       field->wcall(&str, pkg, &pkg->available, fieldflags, field);
221     } else {
222       arbfield = find_arbfield_info(pkg->available.arbs, fields[i]);
223       if (arbfield)
224         varbuf_add_arbfield(&str, arbfield, fieldflags);
225     }
226     varbuf_end_str(&str);
227 
228     if (fieldflags & fw_printheader)
229       printf("%s", str.buf);
230     else
231       printf("%s\n", str.buf);
232   }
233 
234   m_output(stdout, _("<standard output>"));
235 
236   varbuf_destroy(&str);
237 }
238 
239 int
do_showinfo(const char * const * argv)240 do_showinfo(const char *const *argv)
241 {
242   const char *debar, *dir;
243   char *controlfile;
244   struct dpkg_error err;
245   struct pkginfo *pkg;
246   struct pkg_format_node *fmt;
247 
248   fmt = pkg_format_parse(showformat, &err);
249   if (!fmt)
250     ohshit(_("error in show format: %s"), err.str);
251 
252   info_prepare(&argv, &debar, &dir, 1);
253 
254   controlfile  = str_fmt("%s/%s", dir, CONTROLFILE);
255   parsedb(controlfile, pdb_parse_binary | pdb_ignore_archives, &pkg);
256   pkg_format_show(fmt, pkg, &pkg->available);
257   pkg_format_free(fmt);
258   free(controlfile);
259 
260   return 0;
261 }
262 
263 int
do_info(const char * const * argv)264 do_info(const char *const *argv)
265 {
266   const char *debar, *dir;
267 
268   if (*argv && argv[1]) {
269     info_prepare(&argv, &debar, &dir, 1);
270     info_spew(debar, dir, argv);
271   } else {
272     info_prepare(&argv, &debar, &dir, 2);
273     info_list(debar, dir);
274   }
275 
276   return 0;
277 }
278 
279 int
do_field(const char * const * argv)280 do_field(const char *const *argv)
281 {
282   const char *debar, *dir;
283 
284   info_prepare(&argv, &debar, &dir, 1);
285   if (*argv) {
286     info_field(debar, dir, argv, argv[1] != NULL ? fw_printheader : 0);
287   } else {
288     static const char *const controlonly[] = { CONTROLFILE, NULL };
289     info_spew(debar, dir, controlonly);
290   }
291 
292   return 0;
293 }
294 
295 int
do_contents(const char * const * argv)296 do_contents(const char *const *argv)
297 {
298   const char *debar = *argv++;
299 
300   if (debar == NULL || *argv)
301     badusage(_("--%s takes exactly one argument"), cipaction->olong);
302   extracthalf(debar, NULL, DPKG_TAR_LIST, 0);
303 
304   return 0;
305 }
306