int keydiv_dtable::create(int dfd, const char * name, const params & config, dtype::ctype key_type){ int r, kdd_dfd, meta; divider_list dividers; const dtable_factory * base; params base_config; kddtable_header header; header.magic = KDDTABLE_MAGIC; header.version = KDDTABLE_VERSION; switch(key_type) { case dtype::UINT32: header.key_type = 1; r = load_dividers<int, uint32_t>(config, 0, ÷rs); break; case dtype::DOUBLE: header.key_type = 2; r = load_dividers<float, double>(config, 0, ÷rs); break; case dtype::STRING: header.key_type = 3; r = load_dividers<istr, istr>(config, 0, ÷rs); break; case dtype::BLOB: header.key_type = 4; r = load_dividers<blob, blob>(config, 0, ÷rs, true); break; default: return -EINVAL; } header.dt_count = dividers.size() + 1; /* make sure we don't overflow the header field */ if(header.dt_count != dividers.size() + 1) return -EINVAL; base = dtable_factory::lookup(config, "base"); if(!base) return -EINVAL; if(!config.get("base_config", &base_config, params())) return -EINVAL; r = mkdirat(dfd, name, 0755); if(r < 0) return r; kdd_dfd = openat(dfd, name, O_RDONLY); if(kdd_dfd < 0) { unlinkat(dfd, name, AT_REMOVEDIR); return kdd_dfd; } for(uint32_t i = 0; i < header.dt_count; i++) { char name[32]; sprintf(name, "kdd_data.%u", i); r = base->create(kdd_dfd, name, base_config, key_type); if(r < 0) goto fail; } meta = openat(kdd_dfd, "kdd_meta", O_WRONLY | O_CREAT, 0644); if(meta < 0) { r = meta; goto fail; } r = pwrite(meta, &header, sizeof(header), 0); close(meta); if(r != sizeof(header)) goto fail; close(kdd_dfd); return 0; fail: close(kdd_dfd); util::rm_r(dfd, name); return (r < 0) ? r : -1;}