LCOV - code coverage report
Current view: top level - src/deb - info.c (source / functions) Hit Total Coverage
Test: dpkg 1.21.11 C code coverage Lines: 106 143 74.1 %
Date: 2022-12-03 00:40:01 Functions: 9 10 90.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 45 82 54.9 %

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

Generated by: LCOV version 1.16