int get_user_reply(struct fdisk_context *cxt, const char *prompt, char *buf, size_t bufsz) { char *p; size_t sz; do { #ifdef HAVE_LIBREADLINE if (isatty(STDIN_FILENO)) { if (!rl_fgets(buf, bufsz, stdout, prompt)) { if (fdisk_label_is_changed(fdisk_get_label(cxt, NULL))) { if (rl_fgets(buf, bufsz, stderr, _("\nDo you really want to quit? ")) && !rpmatch(buf)) continue; } fdisk_unref_context(cxt); exit(EXIT_FAILURE); } else break; } else #endif { fputs(prompt, stdout); fflush(stdout); if (!fgets(buf, bufsz, stdin)) { if (fdisk_label_is_changed(fdisk_get_label(cxt, NULL))) { fprintf(stderr, _("\nDo you really want to quit? ")); if (fgets(buf, bufsz, stdin) && !rpmatch(buf)) continue; } fdisk_unref_context(cxt); exit(EXIT_FAILURE); } else break; } } while (1); for (p = buf; *p && !isgraph(*p); p++); /* get first non-blank */ if (p > buf) memmove(buf, p, p - buf); /* remove blank space */ sz = strlen(buf); if (sz && *(buf + sz - 1) == '\n') *(buf + sz - 1) = '\0'; DBG(ASK, ul_debug("user's reply: >>>%s<<<", buf)); return 0; }
/** * fdisk_unref_context: * @cxt: fdisk context * * Deallocates context struct. */ void fdisk_unref_context(struct fdisk_context *cxt) { int i; if (!cxt) return; cxt->refcount--; if (cxt->refcount <= 0) { DBG(CXT, ul_debugobj(cxt, "freeing context %p for %s", cxt, cxt->dev_path)); reset_context(cxt); /* this is sensitive to parent<->child relationship! */ /* deallocate label's private stuff */ for (i = 0; i < cxt->nlabels; i++) { if (!cxt->labels[i]) continue; if (cxt->labels[i]->op->free) cxt->labels[i]->op->free(cxt->labels[i]); else free(cxt->labels[i]); } fdisk_unref_context(cxt->parent); cxt->parent = NULL; free(cxt); } }
static int sfdisk_deinit(struct sfdisk *sf) { struct fdisk_context *parent; assert(sf); assert(sf->cxt); parent = fdisk_get_parent(sf->cxt); if (parent) { fdisk_unref_context(sf->cxt); sf->cxt = parent; } fdisk_unref_context(sf->cxt); memset(sf, 0, sizeof(*sf)); 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; }
static int test_listitems(struct fdisk_test *ts, int argc, char *argv[]) { const char *disk = argv[1]; struct fdisk_context *cxt; struct fdisk_labelitem *item; int i = 0, rc; cxt = fdisk_new_context(); item = fdisk_new_labelitem(); fdisk_assign_device(cxt, disk, 1); do { rc = fdisk_get_disklabel_item(cxt, i++, item); switch (rc) { case 0: /* success */ { const char *name = fdisk_labelitem_get_name(item); const char *str; uint64_t num; if (fdisk_labelitem_is_string(item) && fdisk_labelitem_get_data_string(item, &str) == 0) printf("%s: %s\n", name, str); else if (fdisk_labelitem_get_data_u64(item, &num) == 0) printf("%s: %ju\n", name, num); break; } case 1: /* item unsuported by label -- ignore */ rc = 0; break; case 2: /* end (out of range) */ break; default: /* error */ break; } } while (rc == 0); fdisk_unref_labelitem(item); fdisk_unref_context(cxt); return rc < 0 ? rc : 0; }
/* usable for example in usage() */ void list_available_columns(FILE *out) { size_t i; int termwidth; struct fdisk_label *lb = NULL; struct fdisk_context *cxt = fdisk_new_context(); if (!cxt) return; termwidth = get_terminal_width(); if (termwidth <= 0) termwidth = 80; fprintf(out, _("\nAvailable columns (for -o):\n")); while (fdisk_next_label(cxt, &lb) == 0) { size_t width = 6; /* label name and separators */ fprintf(out, " %s:", fdisk_label_get_name(lb)); for (i = 1; i < FDISK_NFIELDS; i++) { const struct fdisk_field *fl = fdisk_label_get_field(lb, i); const char *name = fl ? fdisk_field_get_name(fl) : NULL; size_t len; if (!name) continue; len = strlen(name) + 1; if (width + len > (size_t) termwidth) { fputs("\n ", out); width = 6; } fprintf(out, " %s", name); width += len; } fputc('\n', out); } fdisk_unref_context(cxt); }