chiark / gitweb /
lib/dpkg/tarfn.c: Kludge `tar_header_decode' to handle spurious `errno'.
[dpkg] / src / verify.c
1 /*
2  * dpkg - main program for package management
3  * verify.c - verify package integrity
4  *
5  * Copyright © 2012-2015 Guillem Jover <guillem@debian.org>
6  *
7  * This is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <compat.h>
23
24 #include <string.h>
25 #include <stdbool.h>
26 #include <stdio.h>
27
28 #include <dpkg/i18n.h>
29 #include <dpkg/dpkg.h>
30 #include <dpkg/dpkg-db.h>
31 #include <dpkg/options.h>
32
33 #include "filesdb.h"
34 #include "infodb.h"
35 #include "main.h"
36
37
38 enum verify_result {
39         VERIFY_NONE,
40         VERIFY_PASS,
41         VERIFY_FAIL,
42 };
43
44 struct verify_checks {
45         enum verify_result md5sum;
46 };
47
48 typedef void verify_output_func(struct filenamenode *, struct verify_checks *);
49
50 static int
51 verify_result_rpm(enum verify_result result, int check)
52 {
53         switch (result) {
54         case VERIFY_FAIL:
55                 return check;
56         case VERIFY_PASS:
57                 return '.';
58         case VERIFY_NONE:
59         default:
60                 return '?';
61         }
62 }
63
64 static void
65 verify_output_rpm(struct filenamenode *namenode, struct verify_checks *checks)
66 {
67         char result[9];
68         int attr;
69
70         memset(result, '?', sizeof(result));
71
72         result[2] = verify_result_rpm(checks->md5sum, '5');
73
74         if (namenode->flags & fnnf_old_conff)
75                 attr = 'c';
76         else
77                 attr = ' ';
78
79         printf("%.9s %c %s\n", result, attr, namenode->name);
80 }
81
82 static verify_output_func *verify_output = verify_output_rpm;
83
84 bool
85 verify_set_output(const char *name)
86 {
87         if (strcmp(name, "rpm") == 0)
88                 verify_output = verify_output_rpm;
89         else
90                 return false;
91
92         return true;
93 }
94
95 static void
96 verify_package(struct pkginfo *pkg)
97 {
98         struct fileinlist *file;
99         struct varbuf filename = VARBUF_INIT;
100
101         ensure_packagefiles_available(pkg);
102         parse_filehash(pkg, &pkg->installed);
103         pkg_conffiles_mark_old(pkg);
104
105         for (file = pkg->clientdata->files; file; file = file->next) {
106                 struct verify_checks checks;
107                 struct filenamenode *fnn;
108                 char hash[MD5HASHLEN + 1];
109                 int failures = 0;
110
111                 fnn = namenodetouse(file->namenode, pkg, &pkg->installed);
112
113                 if (strcmp(fnn->newhash, EMPTYHASHFLAG) == 0) {
114                         if (fnn->oldhash == NULL)
115                                 continue;
116                         else
117                                 fnn->newhash = fnn->oldhash;
118                 }
119
120                 varbuf_reset(&filename);
121                 varbuf_add_str(&filename, instdir);
122                 varbuf_add_str(&filename, fnn->name);
123                 varbuf_end_str(&filename);
124
125                 memset(&checks, 0, sizeof(checks));
126
127                 md5hash(pkg, hash, filename.buf);
128                 if (strcmp(hash, fnn->newhash) != 0) {
129                         checks.md5sum = VERIFY_FAIL;
130                         failures++;
131                 }
132
133                 if (failures)
134                         verify_output(fnn, &checks);
135         }
136
137         varbuf_destroy(&filename);
138 }
139
140 int
141 verify(const char *const *argv)
142 {
143         struct pkginfo *pkg;
144         int rc = 0;
145
146         modstatdb_open(msdbrw_readonly);
147         ensure_diversions();
148
149         if (!*argv) {
150                 struct pkgiterator *iter;
151
152                 iter = pkg_db_iter_new();
153                 while ((pkg = pkg_db_iter_next_pkg(iter)))
154                         verify_package(pkg);
155                 pkg_db_iter_free(iter);
156         } else {
157                 const char *thisarg;
158
159                 while ((thisarg = *argv++)) {
160                         pkg = dpkg_options_parse_pkgname(cipaction, thisarg);
161                         if (pkg->status == PKG_STAT_NOTINSTALLED) {
162                                 notice(_("package '%s' is not installed"),
163                                        pkg_name(pkg, pnaw_nonambig));
164                                 rc = 1;
165                                 continue;
166                         }
167
168                         verify_package(pkg);
169                 }
170         }
171
172         modstatdb_shutdown();
173
174         m_output(stdout, _("<standard output>"));
175
176         return rc;
177 }