Commit | Line | Data |
---|---|---|
1479465f GJ |
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 | } |