int exception_dtable::init(int dfd, const char * file, const params & config, sys_journal * sysj) { const dtable_factory * base_factory; const dtable_factory * alt_factory; params base_config, alt_config; int excp_dfd; if(base || alt) deinit(); base_factory = dtable_factory::lookup(config, "base"); alt_factory = dtable_factory::lookup(config, "alt"); if(!base_factory || !alt_factory) return -EINVAL; if(!config.get("base_config", &base_config, params())) return -EINVAL; if(!config.get("alt_config", &alt_config, params())) return -EINVAL; if(!config.get_blob_or_string("reject_value", &reject_value)) return -EINVAL; /* the reject value must exist, because nonexistent values * can get pruned out if the shadow does not require them */ if(!reject_value.exists()) return -EINVAL; excp_dfd = openat(dfd, file, O_RDONLY); if(excp_dfd < 0) return excp_dfd; base = base_factory->open(excp_dfd, "base", base_config, sysj); if(!base) goto fail_base; alt = alt_factory->open(excp_dfd, "alt", alt_config, sysj); if(!alt) goto fail_alt; ktype = base->key_type(); if(ktype != alt->key_type()) goto fail_ktype; cmp_name = base->get_cmp_name(); close(excp_dfd); return 0; fail_ktype: alt->destroy(); alt = NULL; fail_alt: base->destroy(); base = NULL; fail_base: close(excp_dfd); return -1; }
int exception_dtable::create(int dfd, const char * file, const params & config, dtable::iter * source, const ktable * shadow) { int excp_dfd, r; memory_dtable alt_mdt; reject_iter * handler; params base_config, alt_config; blob reject_value; const dtable_factory * base = dtable_factory::lookup(config, "base"); const dtable_factory * alt = dtable_factory::lookup(config, "alt"); if(!base || !alt) return -EINVAL; if(!config.get("base_config", &base_config, params())) return -EINVAL; if(!config.get("alt_config", &alt_config, params())) return -EINVAL; if(!config.get_blob_or_string("reject_value", &reject_value)) return -EINVAL; /* the reject value must exist, because nonexistent values * can get pruned out if the shadow does not require them */ if(!reject_value.exists()) return -EINVAL; if(!source_shadow_ok(source, shadow)) return -EINVAL; r = mkdirat(dfd, file, 0755); if(r < 0) return r; excp_dfd = openat(dfd, file, O_RDONLY); if(excp_dfd < 0) goto fail_open; /* we should really save the reject_value in a meta file here */ /* we'll always be appending, but it's faster if we say false here */ r = alt_mdt.init(source->key_type(), false, true); if(r < 0) goto fail_mdt; if(source->get_blob_cmp()) alt_mdt.set_blob_cmp(source->get_blob_cmp()); handler = new reject_iter(source, &alt_mdt, reject_value); if(!handler) goto fail_mdt; r = base->create(excp_dfd, "base", base_config, handler, shadow); if(r < 0) goto fail_base; /* no shadow - this only has exceptions */ r = alt->create(excp_dfd, "alt", alt_config, &alt_mdt, NULL); if(r < 0) goto fail_alt; delete handler; close(excp_dfd); return 0; fail_alt: util::rm_r(excp_dfd, "base"); fail_base: delete handler; fail_mdt: close(excp_dfd); fail_open: unlinkat(dfd, file, AT_REMOVEDIR); return -1; }