+#endif
+
+static int config_handler(void *f, int ncols, char **vals, char **cols) {
+ struct config *conf = f;
+ struct nitem nitem;
+ struct stat existing;
+ char *save = 0;
+ char *note = 0;
+ char *notehash = 0;
+ int update = 0;
+
+ if (!read_item(conf, ncols, vals, cols, &nitem)) {
+ fprintf(stderr, "can't read item\n");
+ conf->errors++;
+ return conf->errabort;
+ }
+
+ unsigned int diffs = file_compare(&nitem, &existing);
+ if (diffs >= D_ERROR) {
+ return seterror(conf, "can't check %s", nitem.dest);
+ }
+
+ int exist = (!(diffs & D_NOEXIST));
+ int sametype = (!(diffs & D_TYPE));
+ //int mdsame = (!(diffs & D_MD));
+ int hashsame = (!(diffs & D_HASH));
+ int oldhashsame = (!(diffs & D_OHASH));
+ int isdir = (diffs & D_ISDIR);
+ int eisdir = (diffs & D_EISDIR);
+ update = (nitem.op == OP_UPDATE);
+
+ notehash = nitem.hash;
+
+ /* if the file doesn't exist in the system, nothing to do */
+ /* could possibly note if we expected it, but the regular handling
+ * should do that
+ */
+ if (!exist) {
+ return 0;
+ }
+
+ if (nitem.op == OP_UPDATE && !nitem.oldwasconf) {
+ /* possibly save anyway */
+ return 0;
+ }
+
+ /* so, old was conf, and something exists in the filesystem */
+
+ if (!sametype) {
+ warn("won't %s %s%s, %s exists",
+ nitem.op == OP_NEW ? "install" : nitem.opstr,
+ nitem.path,
+ isdir ? "/" : "",
+ eisdir ? "directory" : "file"
+ );
+ conf->errors++;
+ return conf->errabort;
+ }
+
+ /* all below are same type of file */
+ /* what about sametype, but old was different type */
+
+ if (isdir) {
+ return 0;
+ }
+
+ /* save or note cases */
+
+ if (nitem.op == OP_REMOVE) {
+ save ="saved removed config file %.8s";
+ } else
+
+ if (nitem.op == OP_UPDATE) {
+ if (!nitem.configuration) {
+ /* replacing config with non-config */
+ save = "replacing configuration file %.8s with non-configuration file";
+ } else if (oldhashsame) {
+ /* config file hasn't changed from old default,
+ * so go ahead and install the new one
+ */
+ save = "replaced old default config (%.8s) with new one.";
+ notehash = nitem.ohash;
+ } else {
+ note = "kept existing config file. new default version is %.8s";
+ save = 0;
+ }
+ } else
+
+ if (nitem.op == OP_NEW && !hashsame) {
+ note = "config file already existed. would have installed %.8s";
+ save = 0;
+ }
+
+ /*
+ * save files, add notes
+ */
+ if (!conf->dryrun) {
+ if (save) {
+ warn("saving config file: %s (root %s)", nitem.path, conf->rootdir ? conf->rootdir : "/");
+ save_config_file(conf, &nitem, save);
+ }
+ if (note) {
+ zpm_note_add(conf->log, nitem.pkglist, nitem.path, nitem.hash,
+ note, nitem.hash);
+ }
+ } else {
+ if (save) {
+ fprintf(stderr, "dry run: %s %s: ", nitem.pkglist,
+ nitem.path);
+ warn(save, notehash);
+ }
+ if (note) {
+ fprintf(stderr, "dry run: %s %s: ", nitem.pkglist,
+ nitem.path);
+ warn(note, notehash);
+ }
+
+ }
+
+ return 0;
+}
+
+static void handle_config_files(struct config *conf) {
+ int rv;
+ char *errmsg;
+ sqlite3_str *s;
+ char *sql;
+
+ s = sqlite3_str_new(conf->log->db);
+ sqlite3_str_appendall(s, "select *, ");
+ if (conf->rootdir) {
+ sqlite3_str_appendf(s, "printf('%%s/%%s',rtrim(%Q,'/'),ltrim(path,'/'))", conf->rootdir);
+ } else {
+ sqlite3_str_appendf(s, "printf('/%%s', trim(path, '/'))");
+ }
+ sqlite3_str_appendall(s, " as dest from syncinfo");
+
+ sqlite3_str_appendall(s," where configuration > 0 and op in ('new','update','remove')");
+
+ if (conf->reverse) {
+ sqlite3_str_appendall(s," order by length(path) desc, path desc");
+ }
+
+ sql = sqlite3_str_value(s);
+
+ rv = zpm_exec(conf->log, sql, config_handler, conf, &errmsg);
+
+ sqlite3_str_finish(s);
+
+ if (rv) {
+ fprintf(stderr, "exec fail: %s\n", sqlite3_errstr(rv));
+ if (errmsg) {
+ fprintf(stderr, "database error: %s\n", errmsg);
+ conf->errors++;
+ }
+ if (conf->log->error == 1) {
+ fprintf(stderr, "unable to allocate memory\n");
+ }
+ fprintf(stderr, "zpm_exec failure: %s\n",
+ conf->log->errmsg ? conf->log->errmsg : "unknown");
+ conf->errors++;
+ }
+
+ if (conf->errors && conf->exitonerror) {
+ zpm_close(conf->log);
+ zpm_close(conf->src);
+ exit(EXIT_FAILURE);
+ }
+}