static int _error_device(const char *name, size_t size) { struct dm_task *dmt; int r = 0; if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) return 0; if (!dm_task_set_name(dmt, name)) goto error; if (!dm_task_add_target(dmt, UINT64_C(0), size, "error", "")) goto error; if (!dm_task_set_ro(dmt)) goto error; if (!dm_task_no_open_count(dmt)) goto error; if (!dm_task_run(dmt)) goto error; if (!_dm_simple(DM_DEVICE_RESUME, name, 1)) { _dm_simple(DM_DEVICE_CLEAR, name, 0); goto error; } r = 1; error: dm_task_destroy(dmt); return r; }
/* * Parse a mapping table and create the appropriate targets or * check that a target type is registered with the device-mapper core. */ static int handle_table(struct lib_context *lc, struct dm_task *dmt, char *table, struct dm_versions *targets) { int line = 0, n, ret = 0; uint64_t start, size; char *nl = table, *p, ttype[32]; do { p = nl; line++; /* * Not using sscanf string allocation * because it's not available in dietlibc. */ *ttype = 0; if (sscanf(p, "%" PRIu64 " %" PRIu64 " %31s %n", &start, &size, ttype, &n) < 3) LOG_ERR(lc, 0, "Invalid format in table line %d", line); if (!(ret = valid_ttype(lc, ttype, targets))) break; nl = remove_delimiter((p += n), '\n'); if (dmt) ret = dm_task_add_target(dmt, start, size, ttype, p); add_delimiter(&nl, '\n'); } while (nl && ret); return ret; }
int dm_mount_aspect(substrate_t *substrate, u64 header_offset, u8 *header_key, char *name) { char *params; struct dm_task *task; task = dm_task_create(DM_DEVICE_CREATE); if(!task) { die("dm_task_create"); } if(!dm_task_set_name(task, name)) { die("dm_task_set_name"); } if(!dm_task_set_uuid(task, name)) { die("dm_task_set_uuid"); } params = steg_malloc(strlen(substrate->filename) + 4096); sprintf(params, "%s %zu ", substrate->filename, header_offset); sprint_hex(params + strlen(params), header_key, KEY_BYTES); if(!dm_task_add_target(task, 0, substrate->bytes, "steg", params)) { die("dm_task_add_target"); } if(!dm_task_run(task)) { die("dm_task_run"); } dm_task_destroy(task); steg_free(params); return 0; }
int dm_addmap(int task, const char *name, const char *target, const char *params, uint64_t size, int ro, const char *uuid, int part, mode_t mode, uid_t uid, gid_t gid) { int r = 0; struct dm_task *dmt; char *prefixed_uuid = NULL; #ifdef LIBDM_API_COOKIE uint32_t cookie = 0; uint16_t udev_flags = 0; #endif if (!(dmt = dm_task_create (task))) return 0; if (!dm_task_set_name (dmt, name)) goto addout; if (!dm_task_add_target (dmt, 0, size, target, params)) goto addout; if (ro && !dm_task_set_ro (dmt)) goto addout; if (task == DM_DEVICE_CREATE && uuid) { prefixed_uuid = make_prefixed_uuid(part, uuid); if (prefixed_uuid == NULL) goto addout; if (!dm_task_set_uuid(dmt, prefixed_uuid)) goto addout; } if (!dm_task_set_mode(dmt, mode)) goto addout; if (!dm_task_set_uid(dmt, uid)) goto addout; if (!dm_task_set_gid(dmt, gid)) goto addout; dm_task_no_open_count(dmt); #ifdef LIBDM_API_COOKIE if (!udev_sync) udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK; if (task == DM_DEVICE_CREATE && !dm_task_set_cookie(dmt, &cookie, udev_flags)) goto addout; #endif r = dm_task_run (dmt); #ifdef LIBDM_API_COOKIE if (task == DM_DEVICE_CREATE) dm_udev_wait(cookie); #endif addout: dm_task_destroy (dmt); free(prefixed_uuid); return r; }
static int _dm_create(int task, int wait, const char *name, const char *uuid, uint64_t start, uint64_t length, const char *target, const char *table, struct era_dm_info *info) { struct dm_task *dmt; uint32_t cookie = 0; int rc; if (!(dmt = dm_task_create(task))) return -1; if (!dm_task_set_name(dmt, name)) goto out; if (uuid && !dm_task_set_uuid(dmt, uuid)) goto out; if (target && !dm_task_add_target(dmt, start, length, target, table)) goto out; if (wait && !dm_task_set_cookie(dmt, &cookie, 0)) goto out; rc = dm_task_run(dmt); if (wait) (void) dm_udev_wait(cookie); if (rc && info) { struct dm_info dmi; if (!dm_task_get_info(dmt, &dmi)) goto out; info->target_count = dmi.target_count; info->open_count = dmi.open_count; info->suspended = dmi.suspended; info->exists = dmi.exists; info->major = dmi.major; info->minor = dmi.minor; } dm_task_destroy(dmt); return rc ? 0 : -1; out: dm_task_destroy(dmt); return -1; }
/* * Create device via device mapper * return 0 when creation failed * return dev no for created device */ static uint64_t dm_device_create_mapped(const char *dev_name, struct bl_dm_table *p) { struct dm_task *dmt; struct dm_info dminfo; int ret = 0; dmt = dm_task_create(DM_DEVICE_CREATE); if (!dmt) { BL_LOG_ERR("Create dm_task for %s failed\n", dev_name); return 0; } ret = dm_task_set_name(dmt, dev_name); if (!ret) goto err_out; while (p) { ret = dm_task_add_target(dmt, p->offset, p->size, p->target_type, p->params); if (!ret) goto err_out; p = p->next; } ret = dm_task_run(dmt) && dm_task_get_info(dmt, &dminfo) && dminfo.exists; if (!ret) goto err_out; dm_task_update_nodes(); err_out: dm_task_destroy(dmt); if (!ret) { BL_LOG_ERR("Create device %s failed\n", dev_name); return 0; } return MKDEV(dminfo.major, dminfo.minor); }
/* Unmarshall the target info returned from a status call */ static int _unmarshal_status(struct dm_task *dmt, struct dm_ioctl *dmi) { char *outbuf = (char *) dmi + dmi->data_start; char *outptr = outbuf; uint32_t i; struct dm_target_spec *spec; for (i = 0; i < dmi->target_count; i++) { spec = (struct dm_target_spec *) outptr; if (!dm_task_add_target(dmt, spec->sector_start, spec->length, spec->target_type, outptr + sizeof(*spec))) { return 0; } outptr = outbuf + spec->next; } return 1; }
static int dm_addmap (int task, const char *target, struct multipath *mpp, char * params, int ro) { int r = 0; struct dm_task *dmt; char *prefixed_uuid = NULL; uint32_t cookie = 0; if (!(dmt = dm_task_create (task))) return 0; if (!dm_task_set_name (dmt, mpp->alias)) goto addout; if (!dm_task_add_target (dmt, 0, mpp->size, target, params)) goto addout; if (ro) dm_task_set_ro(dmt); if (task == DM_DEVICE_CREATE) { if (strlen(mpp->wwid) > 0) { prefixed_uuid = MALLOC(UUID_PREFIX_LEN + strlen(mpp->wwid) + 1); if (!prefixed_uuid) { condlog(0, "cannot create prefixed uuid : %s", strerror(errno)); goto addout; } sprintf(prefixed_uuid, UUID_PREFIX "%s", mpp->wwid); if (!dm_task_set_uuid(dmt, prefixed_uuid)) goto freeout; } dm_task_skip_lockfs(dmt); #ifdef LIBDM_API_FLUSH dm_task_no_flush(dmt); #endif } if (mpp->attribute_flags & (1 << ATTR_MODE) && !dm_task_set_mode(dmt, mpp->mode)) goto freeout; if (mpp->attribute_flags & (1 << ATTR_UID) && !dm_task_set_uid(dmt, mpp->uid)) goto freeout; if (mpp->attribute_flags & (1 << ATTR_GID) && !dm_task_set_gid(dmt, mpp->gid)) goto freeout; condlog(4, "%s: %s [0 %llu %s %s]", mpp->alias, task == DM_DEVICE_RELOAD ? "reload" : "addmap", mpp->size, target, params); dm_task_no_open_count(dmt); if (task == DM_DEVICE_CREATE && !dm_task_set_cookie(dmt, &cookie, DM_UDEV_DISABLE_LIBRARY_FALLBACK)) goto freeout; r = dm_task_run (dmt); if (task == DM_DEVICE_CREATE) dm_udev_wait(cookie); freeout: if (prefixed_uuid) FREE(prefixed_uuid); addout: dm_task_destroy (dmt); return r; }
int main(int argc, char *argv[]) try { State state; auto parsers = new_subparser({"device"}); argp argp = {options, init_parsers, nullptr, doc, parsers.get(), nullptr, nullptr}; argp_parse(&argp, argc, argv, 0, nullptr, &state); Params params; try { params.load(state.device); } catch(const std::exception& e) { std::cerr << "Error: Header corrupt." << std::endl; return 1; } std::uint64_t blocks = state.device.size()/params.block_size; Pinentry pinentry; pinentry.SETDESC("Enter passphrases for a partition on this volume."); pinentry.SETPROMPT("Passphrase:"); auto passphrase = pinentry.GETPIN(); Superblock superblock(params, passphrase, blocks); try { superblock.load(state.device); } catch(...) { std::cerr << "Error: No partition found for that passphrase." << std::endl; } Hash hash(params.hash); std::string key = PBKDF2::PBKDF2(hash, passphrase, params.salt, params.iters, params.key_size); if (state.name.empty()) { hash.reset(); hash.update(key); state.name = hex(hash.digest()).substr(8); } { std::unique_ptr<dm_task, void(*)(dm_task*)> dmt( dm_task_create(DM_DEVICE_CREATE), dm_task_destroy); if (!dmt.get()) throw std::runtime_error("dm_task_create failed"); if (!dm_task_set_name(dmt.get(), state.name.c_str())) throw std::runtime_error("dm_task_set_name failed"); std::uint64_t offset = 0; for (auto block = superblock.blocks.begin()+superblock.offset; block != superblock.blocks.end(); block++, offset += params.block_size) { if (*block != 0) { std::stringstream ss; ss << params.device_cipher << " " << hex(key) << " 0 "; ss << state.device.major() << ":" << state.device.minor() << " "; ss << (*block)*params.block_size/512; if (!dm_task_add_target(dmt.get(), offset/512, params.block_size/512, "crypt", ss.str().c_str())) throw std::runtime_error("dm_task_add_target(\"crypt\") failed"); } else { if (!dm_task_add_target(dmt.get(), offset/512, params.block_size/512, "error", "")) throw std::runtime_error("dm_task_add_target(\"error\") failed"); } } if (!dm_task_run(dmt.get())) throw std::runtime_error("dm_task_run failed"); } return 0; } catch(const std::exception& e) { std::cerr << "Error: " << e.what() << std::endl; return 1; }
int dm_create_device(const char *name, const char *device, const char *cipher, const char *type, const char *uuid, uint64_t size, uint64_t skip, uint64_t offset, size_t key_size, const char *key, int read_only, int reload) { struct dm_task *dmt = NULL; struct dm_info dmi; char *params = NULL; char *error = NULL; char dev_uuid[DM_UUID_LEN] = {0}; int r = -EINVAL; uint32_t read_ahead = 0; uint32_t cookie = 0; uint16_t udev_flags = 0; params = get_params(device, skip, offset, cipher, key_size, key); if (!params) goto out_no_removal; if (type && !strncmp(type, "TEMP", 4)) udev_flags = CRYPT_TEMP_UDEV_FLAGS; /* All devices must have DM_UUID, only resize on old device is exception */ if (reload) { if (!(dmt = dm_task_create(DM_DEVICE_RELOAD))) goto out_no_removal; if (!dm_task_set_name(dmt, name)) goto out_no_removal; } else { dm_prepare_uuid(name, type, uuid, dev_uuid, sizeof(dev_uuid)); if (!(dmt = dm_task_create(DM_DEVICE_CREATE))) goto out_no_removal; if (!dm_task_set_name(dmt, name)) goto out_no_removal; if (!dm_task_set_uuid(dmt, dev_uuid)) goto out_no_removal; if (_dm_use_udev() && !dm_task_set_cookie(dmt, &cookie, udev_flags)) goto out_no_removal; } if (read_only && !dm_task_set_ro(dmt)) goto out_no_removal; if (!dm_task_add_target(dmt, 0, size, DM_CRYPT_TARGET, params)) goto out_no_removal; #ifdef DM_READ_AHEAD_MINIMUM_FLAG if (_dev_read_ahead(device, &read_ahead) && !dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG)) goto out_no_removal; #endif if (!dm_task_run(dmt)) goto out_no_removal; if (reload) { dm_task_destroy(dmt); if (!(dmt = dm_task_create(DM_DEVICE_RESUME))) goto out; if (!dm_task_set_name(dmt, name)) goto out; if (uuid && !dm_task_set_uuid(dmt, dev_uuid)) goto out; if (_dm_use_udev() && !dm_task_set_cookie(dmt, &cookie, udev_flags)) goto out; if (!dm_task_run(dmt)) goto out; } if (!dm_task_get_info(dmt, &dmi)) goto out; r = 0; out: if (_dm_use_udev()) { (void)dm_udev_wait(cookie); cookie = 0; } if (r < 0 && !reload) { if (get_error()) error = strdup(get_error()); dm_remove_device(name, 0, 0); if (error) { set_error(error); free(error); } } out_no_removal: if (cookie && _dm_use_udev()) (void)dm_udev_wait(cookie); if (params) safe_free(params); if (dmt) dm_task_destroy(dmt); dm_task_update_nodes(); return r; }