static int ask_number(struct fdisk_context *cxt, struct fdisk_ask *ask, char *buf, size_t bufsz) { char prompt[128] = { '\0' }; const char *q = fdisk_ask_get_query(ask); const char *range = fdisk_ask_number_get_range(ask); uint64_t dflt = fdisk_ask_number_get_default(ask), low = fdisk_ask_number_get_low(ask), high = fdisk_ask_number_get_high(ask); assert(q); DBG(ASK, dbgprint("asking for number ['%s', <%jd,%jd>, default=%jd, range: %s]", q, low, high, dflt, range)); if (range && dflt >= low && dflt <= high) snprintf(prompt, sizeof(prompt), _("%s (%s, default %jd): "), q, range, dflt); else if (dflt >= low && dflt <= high) snprintf(prompt, sizeof(prompt), _("%s (%jd-%jd, default %jd): "), q, low, high, dflt); else snprintf(prompt, sizeof(prompt), _("%s (%jd-%jd): "), q, low, high); do { int rc = get_user_reply(cxt, prompt, buf, bufsz); if (rc) return rc; if (!*buf && dflt >= low && dflt <= high) return fdisk_ask_number_set_result(ask, dflt); else if (isdigit_string(buf)) { char *end; uint64_t num; errno = 0; num = strtoumax(buf, &end, 10); if (errno || buf == end || (end && *end)) continue; if (num >= low && num <= high) return fdisk_ask_number_set_result(ask, num); printf(_("Value out of range.\n")); } } while (1); return -1; }
static int ask_offset(struct fdisk_context *cxt, struct fdisk_ask *ask, char *buf, size_t bufsz) { char prompt[128] = { '\0' }; const char *q = fdisk_ask_get_query(ask); const char *range = fdisk_ask_number_get_range(ask); uint64_t dflt = fdisk_ask_number_get_default(ask), low = fdisk_ask_number_get_low(ask), high = fdisk_ask_number_get_high(ask), base = fdisk_ask_number_get_base(ask); assert(q); DBG(ASK, ul_debug("asking for offset ['%s', <%ju,%ju>, base=%ju, default=%ju, range: %s]", q, low, high, base, dflt, range)); if (range && dflt >= low && dflt <= high) snprintf(prompt, sizeof(prompt), _("%s (%s, default %ju): "), q, range, dflt); else if (dflt >= low && dflt <= high) snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju, default %ju): "), q, low, high, dflt); else snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju): "), q, low, high); do { uint64_t num = 0; char sig = 0, *p; int pwr = 0; int rc = get_user_reply(cxt, prompt, buf, bufsz); if (rc) return rc; if (!*buf && dflt >= low && dflt <= high) return fdisk_ask_number_set_result(ask, dflt); p = buf; if (*p == '+' || *p == '-') { sig = *buf; p++; } rc = parse_size(p, &num, &pwr); if (rc) continue; DBG(ASK, ul_debug("parsed size: %ju", num)); if (sig && pwr) { /* +{size}{K,M,...} specified, the "num" is in bytes */ uint64_t unit = fdisk_ask_number_get_unit(ask); num += unit/2; /* round */ num /= unit; } if (sig == '+') num += base; else if (sig == '-') num = base - num; DBG(ASK, ul_debug("final offset: %ju [sig: %c, power: %d, %s]", num, sig, pwr, sig ? "relative" : "absolute")); if (num >= low && num <= high) { if (sig) fdisk_ask_number_set_relative(ask, 1); return fdisk_ask_number_set_result(ask, num); } fdisk_warnx(cxt, _("Value out of range.")); } while (1); return -1; }
static int ask_number(struct fdisk_context *cxt, struct fdisk_ask *ask, char *buf, size_t bufsz) { char prompt[128] = { '\0' }; const char *q = fdisk_ask_get_query(ask); const char *range = fdisk_ask_number_get_range(ask); uint64_t dflt = fdisk_ask_number_get_default(ask), low = fdisk_ask_number_get_low(ask), high = fdisk_ask_number_get_high(ask); int inchar = fdisk_ask_number_inchars(ask); assert(q); DBG(ASK, ul_debug("asking for number " "['%s', <%ju,%ju>, default=%ju, range: %s]", q, low, high, dflt, range)); if (range && dflt >= low && dflt <= high) { if (inchar) snprintf(prompt, sizeof(prompt), _("%s (%s, default %c): "), q, range, tochar(dflt)); else snprintf(prompt, sizeof(prompt), _("%s (%s, default %ju): "), q, range, dflt); } else if (dflt >= low && dflt <= high) { if (inchar) snprintf(prompt, sizeof(prompt), _("%s (%c-%c, default %c): "), q, tochar(low), tochar(high), tochar(dflt)); else snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju, default %ju): "), q, low, high, dflt); } else if (inchar) snprintf(prompt, sizeof(prompt), _("%s (%c-%c): "), q, tochar(low), tochar(high)); else snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju): "), q, low, high); do { int rc = get_user_reply(cxt, prompt, buf, bufsz); uint64_t num; if (rc) return rc; if (!*buf && dflt >= low && dflt <= high) return fdisk_ask_number_set_result(ask, dflt); if (isdigit_string(buf)) { char *end; errno = 0; num = strtoumax(buf, &end, 10); if (errno || buf == end || (end && *end)) continue; } else if (inchar && isalpha(*buf)) { num = tolower(*buf) - 'a' + 1; } else rc = -EINVAL; if (rc == 0 && num >= low && num <= high) return fdisk_ask_number_set_result(ask, num); fdisk_warnx(cxt, _("Value out of range.")); } while (1); return -1; }
/* returns: 1=0 on success, < 0 on error, 1 if no free/used partition */ int fdisk_ask_partnum(struct fdisk_context *cxt, size_t *partnum, int wantnew) { int rc = 0, inchar = 0; char range[BUFSIZ], *ptr = range; size_t i, len = sizeof(range), begin = 0, run = 0; struct fdisk_ask *ask = NULL; __typeof__(ask->data.num) *num; assert(cxt); assert(cxt->label); assert(partnum); if (cxt->label && cxt->label->flags & FDISK_LABEL_FL_INCHARS_PARTNO) inchar = 1; DBG(ASK, dbgprint("%s: asking for %s partition number " "(max: %zd, inchar: %s)", cxt->label->name, wantnew ? "new" : "used", cxt->label->nparts_max, inchar ? "yes" : "not")); ask = fdisk_new_ask(); if (!ask) return -ENOMEM; fdisk_ask_set_type(ask, FDISK_ASKTYPE_NUMBER); num = &ask->data.num; ask->data.num.inchars = inchar ? 1 : 0; for (i = 0; i < cxt->label->nparts_max; i++) { int status = 0; rc = fdisk_partition_get_status(cxt, i, &status); if (rc) break; if (wantnew && !(status & FDISK_PARTSTAT_USED)) { ptr = mk_string_list(ptr, &len, &begin, &run, i, inchar); if (!ptr) { rc = -EINVAL; break; } if (!num->low) num->dfl = num->low = i + 1; num->hig = i + 1; } else if (!wantnew && (status & FDISK_PARTSTAT_USED)) { ptr = mk_string_list(ptr, &len, &begin, &run, i, inchar); if (!num->low) num->low = i + 1; num->dfl = num->hig = i + 1; } } DBG(ASK, dbgprint("ask limits: low: %zd, high: %zd, default: %zd", num->low, num->hig, num->dfl)); if (!rc && !wantnew && num->low == num->hig) { if (num->low > 0) { /* only one existing partiton, don't ask, return the number */ fdisk_ask_number_set_result(ask, num->low); fdisk_info(cxt, _("Selected partition %d"), num->low); } else if (num->low == 0) { fdisk_warnx(cxt, _("No partition is defined yet!")); rc = 1; } goto dont_ask; } if (!rc && wantnew && num->low == num->hig) { if (num->low > 0) { /* only one free partition, don't ask, return the number */ fdisk_ask_number_set_result(ask, num->low); fdisk_info(cxt, _("Selected partition %d"), num->low); } if (num->low == 0) { fdisk_warnx(cxt, _("No free partition available!")); rc = 1; } goto dont_ask; } if (!rc) { mk_string_list(ptr, &len, &begin, &run, -1, inchar); /* terminate the list */ rc = fdisk_ask_number_set_range(ask, range); } if (!rc) rc = fdisk_ask_set_query(ask, _("Partition number")); if (!rc) rc = fdisk_do_ask(cxt, ask); dont_ask: if (!rc) { *partnum = fdisk_ask_number_get_result(ask); if (*partnum) *partnum -= 1; } DBG(ASK, dbgprint("result: %zd [rc=%d]\n", fdisk_ask_number_get_result(ask), rc)); fdisk_free_ask(ask); return rc; }