]> pd.if.org Git - zpackage/blob - src/verify.c
rework verify
[zpackage] / src / verify.c
1 #define _POSIX_C_SOURCE 200112L
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <errno.h>
7 #include <ctype.h>
8 #include <limits.h>
9 #include <unistd.h>
10 #include <sys/types.h>
11 #include <sys/wait.h>
12
13 #include <string.h>
14
15 #include "zpm.h"
16 #include "t/ctap/ctap.h"
17 #include "lib/jsw/jsw_atree.h"
18
19 struct config {
20         char *dbfile;
21         char *pkgid;
22         int plan;
23         int ran;
24         int failed;
25         int quiet;
26         int skipuninstalled;
27         int failed_only;
28         int tap;
29         int check_owner;
30         int check_group;
31         int check_perms;
32         int check_content; /* ignored for config files */
33         int check_mtime;
34 };
35
36 static void usage() {
37         printf("usage: zpm verify [-f file] -eF [pkgid ...]\n");
38 }
39
40 static char *column(char *col, int ncols, char **vals, char **cols) {
41         int i = 0;
42         char *val = NULL;
43
44         for (i=0; i < ncols; i++) {
45                 if (!strcmp(col, cols[i])) {
46                         val = vals[i];
47                         break;
48                 }
49         }
50         return val;
51 }
52
53 static int count_plan(void *f, int ncols, char **vals, char **cols) {
54         struct config *conf = f;
55
56         int ftype, configfile = 0;
57         char *v;
58
59         v = column("filetype", ncols, vals, cols);
60         ftype = *v;
61         v = column("configuration", ncols, vals, cols);
62         if (*v == '1') {
63                 configfile = 1;
64         }
65
66         if (ftype == 'r' && !configfile) {
67                 conf->plan++;
68         }
69
70         conf->plan++;
71
72         return 0;
73 }
74
75 static int verify(void *f, int ncols, char **vals, char **cols) {
76         struct config *conf = f;
77         char *path;
78         struct stat st;
79         int rv;
80         int ftype, configfile = 0;
81         char *v, *hash, ehash[ZPM_HASH_STRLEN+1];
82
83         path = column("path", ncols, vals, cols);
84         hash = column("hash", ncols, vals, cols);
85         v = column("filetype", ncols, vals, cols);
86         ftype = *v;
87         v = column("configuration", ncols, vals, cols);
88         if (*v == '1') {
89                 configfile = 1;
90         }
91
92         conf->ran++;
93
94         rv = lstat(path, &st);
95         if (rv == -1) {
96                 switch (errno) {
97                         case ENOENT: ok(0, "%s does not exist", path);
98                                      conf->failed++;
99                                      break;
100                         default: ok(0, "%s%scannot stat %s: %s",
101                                         conf->pkgid ? conf->pkgid : "",
102                                         conf->pkgid ? " " : "",
103                                                  path, strerror(errno));
104                                 conf->failed++;
105                                  break;
106                 }
107                 if (ftype == 'r' && !configfile) {
108                         skip("no hash");
109                 }
110                 return 0;
111         }
112
113         if (!conf->failed_only) {
114                 ok(1, "%s%s%s exists",
115                                 conf->pkgid ? conf->pkgid : "",
116                                 conf->pkgid ? " " : "",
117                                 path);
118         }
119
120         if (ftype != 'r') {
121                 return 0;
122         }
123
124         if (ftype == 'r' && !configfile) {
125                 zpm_hash(path, ehash, 0);
126                 rv = strcmp(ehash, hash);
127                 if (rv != 0) {
128                         conf->failed++;
129                 }
130                 if (rv != 0 || !conf->failed_only) {
131                         is_string(ehash, hash, "%s%shash %s",
132                                         conf->pkgid ? conf->pkgid : "",
133                                         conf->pkgid ? " " : "",
134                                         path);
135                 }
136         }
137
138         return 0;
139 }
140
141 static int afind_strcmp(const void *a, const void *b) {
142         return strcmp(a, b);
143 }
144
145 int main(int ac, char **av) {
146         struct zpm pkg;
147         char *s;
148         int opt;
149         char *pkgid;
150         jsw_atree_t *pkglist;
151         jsw_atrav_t *list;
152         int i, errors = 0;
153         
154         struct config conf = { 0 };
155
156         /* TODO could do nothing for the dup */
157         pkglist = jsw_anew(afind_strcmp, (dup_f)strdup, (rel_f)free);
158
159         conf.dbfile = "/var/lib/zpm/local.db";
160
161         if ((s = getenv("ZPMDB"))) {
162                 /* TODO does this need to be copied ? */
163                 conf.dbfile = s;
164         }
165
166         while ((opt = getopt(ac, av, "f:eF")) != -1) {
167                 switch (opt) {
168                         case 'f': conf.dbfile = optarg; break;
169                         case 'e': conf.skipuninstalled = 1; break;
170                         case 'F': conf.failed_only = 1; break;
171                         default:
172                                   usage();
173                                   exit(EXIT_FAILURE);
174                                   break;
175                 }
176         }
177
178         int argn = optind;
179
180         if (!zpm_open(&pkg, conf.dbfile)) {
181                 fprintf(stderr, "can't open zpm db %s\n", conf.dbfile);
182                 exit(EXIT_FAILURE);
183         }
184         char *errmsg = 0;
185
186         if (argn < ac) {
187                 for (i = argn; i < ac; i++) {
188                         pkgid = zpm_findpkg(&pkg, av[i], "status = 'installed'");
189                         if (!pkgid) {
190                                 if (conf.skipuninstalled) {
191                                         continue;
192                                 }
193                                 fprintf(stderr, "no installed package: %s\n", av[i]);
194                                 errors++;
195                                 free(pkgid);
196                                 pkgid = 0;
197                                 continue;
198                         }
199                         if (!jsw_ainsert(pkglist, pkgid)) {
200                                 fprintf(stderr, "pkglist insert failed\n");
201                                 exit(EXIT_FAILURE);
202                         }
203                         free(pkgid);
204                 }
205         } else {
206                 fprintf(stderr, "must specify pkgid\n");
207                 usage();
208                 exit(EXIT_FAILURE);
209         }
210
211         list = jsw_atnew();
212
213         for (pkgid = jsw_atfirst(list, pkglist); pkgid; pkgid = jsw_atnext(list)) {
214                 conf.pkgid = pkgid;
215
216                 if (!zpm_foreach_path(&pkg, pkgid, 0, count_plan, &conf, &errmsg)) {
217                         if (errmsg) {
218                                 fprintf(stderr, "database error: %s\n", errmsg);
219                                 exit(EXIT_FAILURE);
220                         }
221                         if (pkg.error == 1) {
222                                 fprintf(stderr, "unable to allocate memory\n");
223                         }
224                         exit(EXIT_FAILURE);
225                 }
226         }
227
228         if (errors) {
229                 exit(EXIT_FAILURE);
230         }
231
232         plan(conf.plan);
233
234         list = jsw_atnew();
235
236         for (pkgid = jsw_atfirst(list, pkglist); pkgid; pkgid = jsw_atnext(list)) {
237                 conf.pkgid = pkgid;
238
239                 if (!zpm_foreach_path(&pkg, pkgid, 0, verify, &conf, &errmsg)) {
240                         if (errmsg) {
241                                 fprintf(stderr, "database error: %s\n", errmsg);
242                                 exit(EXIT_FAILURE);
243                         }
244                         if (pkg.error == 1) {
245                                 fprintf(stderr, "unable to allocate memory\n");
246                         }
247                         exit(EXIT_FAILURE);
248                 }
249         }
250
251         if (pkglist) jsw_adelete(pkglist);
252
253         zpm_close(&pkg);
254         return conf.failed ? 1 : 0;
255 }