]> pd.if.org Git - zpackage/blob - src/verify.c
expand 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 foreach-path [-fncC] args ...\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         pkglist = jsw_anew(afind_strcmp, (dup_f)strdup, (rel_f)free);
155         struct config conf = { 0 };
156
157         conf.dbfile = "/var/lib/zpm/local.db";
158
159         if ((s = getenv("ZPMDB"))) {
160                 /* TODO does this need to be copied ? */
161                 conf.dbfile = s;
162         }
163
164         while ((opt = getopt(ac, av, "f:eF")) != -1) {
165                 switch (opt) {
166                         case 'f': conf.dbfile = optarg; break;
167                         case 'e': conf.skipuninstalled = 1; break;
168                         case 'F': conf.failed_only = 1; break;
169                         default:
170                                   usage();
171                                   exit(EXIT_FAILURE);
172                                   break;
173                 }
174         }
175
176         int argn = optind;
177
178         if (!zpm_open(&pkg, conf.dbfile)) {
179                 fprintf(stderr, "can't open zpm db %s\n", conf.dbfile);
180                 exit(EXIT_FAILURE);
181         }
182         char *errmsg = 0;
183
184         if (argn < ac) {
185         } else {
186                 fprintf(stderr, "must specify pkgid\n");
187                 usage();
188                 exit(EXIT_FAILURE);
189         }
190
191         for (i = argn; i < ac; i++) {
192                 pkgid = zpm_findpkg(&pkg, av[i], "status = 'installed'");
193                 if (!pkgid) {
194                         if (conf.skipuninstalled) {
195                                 continue;
196                         }
197                         fprintf(stderr, "no installed package: %s\n", av[i]);
198                         errors++;
199                         free(pkgid);
200                         pkgid = 0;
201                         continue;
202                 }
203
204                 if (!zpm_foreach_path(&pkg, pkgid, 0, count_plan, &conf, &errmsg)) {
205                         if (errmsg) {
206                                 fprintf(stderr, "database error: %s\n", errmsg);
207                                 exit(EXIT_FAILURE);
208                         }
209                         if (pkg.error == 1) {
210                                 fprintf(stderr, "unable to allocate memory\n");
211                         }
212                         fprintf(stderr, "unable to plan\n");
213                         exit(EXIT_FAILURE);
214                 }
215                 if (!jsw_ainsert(pkglist, pkgid)) {
216                         fprintf(stderr, "pkglist insert failed\n");
217                         exit(EXIT_FAILURE);
218                 }
219                 free(pkgid);
220         }
221         if (errors) {
222                 exit(EXIT_FAILURE);
223         }
224
225         plan(conf.plan);
226
227         list = jsw_atnew();
228
229         for (pkgid = jsw_atfirst(list, pkglist); pkgid; pkgid = jsw_atnext(list)) {
230                 conf.pkgid = pkgid;
231
232                 if (!zpm_foreach_path(&pkg, pkgid, 0, verify, &conf, &errmsg)) {
233                         if (errmsg) {
234                                 fprintf(stderr, "database error: %s\n", errmsg);
235                                 exit(EXIT_FAILURE);
236                         }
237                         if (pkg.error == 1) {
238                                 fprintf(stderr, "unable to allocate memory\n");
239                         }
240                         exit(EXIT_FAILURE);
241                 }
242         }
243
244         if (pkglist) jsw_adelete(pkglist);
245
246         zpm_close(&pkg);
247         return conf.failed ? 1 : 0;
248 }