LCOV - code coverage report
Current view: top level - src/deb - info.c (source / functions) Coverage Total Hit
Test: dpkg 1.22.7-3-g89f48 C code coverage Lines: 71.6 % 155 111
Test Date: 2024-07-17 02:53:43 Functions: 90.9 % 11 10
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 54.8 % 84 46

             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                 :             : }
        

Generated by: LCOV version 2.0-1