/** * fdisk_deassign_device: * @cxt: context * @nosync: disable fsync() * * Close device and call fsync(). If the @cxt is nested context than the * request is redirected to the parent. * * Returns: 0 on success, < 0 on error. */ int fdisk_deassign_device(struct fdisk_context *cxt, int nosync) { assert(cxt); assert(cxt->dev_fd >= 0); if (cxt->parent) { int rc = fdisk_deassign_device(cxt->parent, nosync); if (!rc) rc = init_nested_from_parent(cxt, 0); return rc; } if (cxt->readonly) close(cxt->dev_fd); else { if (fsync(cxt->dev_fd) || close(cxt->dev_fd)) { fdisk_warn(cxt, _("%s: close device failed"), cxt->dev_path); return -errno; } if (!nosync) { fdisk_info(cxt, _("Syncing disks.")); sync(); } } free(cxt->dev_path); cxt->dev_path = NULL; cxt->dev_fd = -1; return 0; }
/** * fdisk_new_nested_context: * @parent: parental context * @name: optional label name (e.g. "bsd") * * Create a new nested fdisk context for nested disk labels (e.g. BSD or PMBR). * The function also probes for the nested label on the device if device is * already assigned to parent. * * The new context is initialized according to @parent and both context shares * some settings and file descriptor to the device. The child propagate some * changes (like fdisk_assign_device()) to parent, but it does not work * vice-versa. The behavior is undefined if you assign another device to * parent. * * Returns: new context for nested partition table. */ struct fdisk_context *fdisk_new_nested_context(struct fdisk_context *parent, const char *name) { struct fdisk_context *cxt; struct fdisk_label *lb = NULL; assert(parent); cxt = calloc(1, sizeof(*cxt)); if (!cxt) return NULL; DBG(CXT, ul_debugobj(parent, "alloc nested [%p] [name=%s]", cxt, name)); cxt->refcount = 1; fdisk_ref_context(parent); cxt->parent = parent; if (init_nested_from_parent(cxt, 1) != 0) { cxt->parent = NULL; fdisk_unref_context(cxt); return NULL; } if (name) { if (strcasecmp(name, "bsd") == 0) lb = cxt->labels[ cxt->nlabels++ ] = fdisk_new_bsd_label(cxt); else if (strcasecmp(name, "dos") == 0 || strcasecmp(name, "mbr") == 0) lb = cxt->labels[ cxt->nlabels++ ] = fdisk_new_dos_label(cxt); } if (lb && parent->dev_fd >= 0) { DBG(CXT, ul_debugobj(cxt, "probing for nested %s", lb->name)); cxt->label = lb; if (lb->op->probe(cxt) == 1) __fdisk_switch_label(cxt, lb); else { DBG(CXT, ul_debugobj(cxt, "not found %s label", lb->name)); if (lb->op->deinit) lb->op->deinit(lb); cxt->label = NULL; } } return cxt; }
/** * fdisk_assign_device: * @cxt: context * @fname: path to the device to be handled * @readonly: how to open the device * * Open the device, discovery topology, geometry, detect disklabel and switch * the current label driver to reflect the probing result. * * Note that this function resets all generic setting in context. If the @cxt * is nested context then the device is assigned to the parental context and * necessary properties are copied to the @cxt. The change is propagated in * child->parent direction only. It's impossible to use a different device for * primary and nested contexts. * * Returns: 0 on success, < 0 on error. */ int fdisk_assign_device(struct fdisk_context *cxt, const char *fname, int readonly) { int fd; DBG(CXT, ul_debugobj(cxt, "assigning device %s", fname)); assert(cxt); /* redirect request to parent */ if (cxt->parent) { int rc, org = fdisk_is_listonly(cxt->parent); /* assign_device() is sensitive to "listonly" mode, so let's * follow the current context setting for the parent to avoid * unwanted extra warnings. */ fdisk_enable_listonly(cxt->parent, fdisk_is_listonly(cxt)); rc = fdisk_assign_device(cxt->parent, fname, readonly); fdisk_enable_listonly(cxt->parent, org); if (!rc) rc = init_nested_from_parent(cxt, 0); if (!rc) fdisk_probe_labels(cxt); return rc; } reset_context(cxt); fd = open(fname, (readonly ? O_RDONLY : O_RDWR ) | O_CLOEXEC); if (fd < 0) return -errno; cxt->readonly = readonly; cxt->dev_fd = fd; cxt->dev_path = strdup(fname); if (!cxt->dev_path) goto fail; fdisk_discover_topology(cxt); fdisk_discover_geometry(cxt); if (fdisk_read_firstsector(cxt) < 0) goto fail; /* detect labels and apply labes specific stuff (e.g geomery) * to the context */ fdisk_probe_labels(cxt); /* let's apply user geometry *after* label prober * to make it possible to override in-label setting */ fdisk_apply_user_device_properties(cxt); /* warn about obsolete stuff on the device if we aren't in * list-only mode and there is not PT yet */ if (!fdisk_is_listonly(cxt) && !fdisk_has_label(cxt)) warn_wipe(cxt); DBG(CXT, ul_debugobj(cxt, "initialized for %s [%s]", fname, readonly ? "READ-ONLY" : "READ-WRITE")); return 0; fail: DBG(CXT, ul_debugobj(cxt, "failed to assign device")); return -errno; }