summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fdisks/Makemodule.am1
-rw-r--r--fdisks/fdisk-ask.c111
-rw-r--r--fdisks/fdisk.c10
-rw-r--r--fdisks/fdisk.h4
-rw-r--r--include/strutils.h2
-rw-r--r--lib/strutils.c10
6 files changed, 131 insertions, 7 deletions
diff --git a/fdisks/Makemodule.am b/fdisks/Makemodule.am
index dcb48e52f..f9488c221 100644
--- a/fdisks/Makemodule.am
+++ b/fdisks/Makemodule.am
@@ -7,6 +7,7 @@ fdisk_SOURCES = \
fdisks/dos_part_types.h \
fdisks/fdisk.c \
fdisks/fdisk.h \
+ fdisks/fdisk-ask.c \
fdisks/fdiskaixlabel.c \
fdisks/fdiskaixlabel.h \
fdisks/fdiskbsdlabel.c \
diff --git a/fdisks/fdisk-ask.c b/fdisks/fdisk-ask.c
new file mode 100644
index 000000000..ebfb404bb
--- /dev/null
+++ b/fdisks/fdisk-ask.c
@@ -0,0 +1,111 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include "c.h"
+#include "strutils.h"
+#include "rpmatch.h"
+
+#include "fdisk.h"
+
+static int get_user_reply(struct fdisk_context *cxt, char *prompt,
+ char *buf, size_t bufsz)
+{
+ char *p;
+ size_t sz;
+
+ do {
+ fputs(prompt, stdout);
+ fflush(stdout);
+
+ if (!fgets(buf, bufsz, stdin)) {
+ if (fdisk_label_is_changed(cxt->label)) {
+ fprintf(stderr, _("Do you really want to quit? "));
+
+ if (fgets(buf, bufsz, stdin) && !rpmatch(buf))
+ continue;
+ }
+ fdisk_free_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, dbgprint("user's reply: >>>%s<<<", buf));
+ return 0;
+}
+
+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_question(ask);
+ const char *range = fdisk_ask_number_get_range(ask);
+
+ uint64_t dfl = fdisk_ask_number_get_default(ask),
+ low = fdisk_ask_number_get_low(ask),
+ hig = fdisk_ask_number_get_high(ask);
+
+ assert(q);
+
+ DBG(ASK, dbgprint("asking for number ['%s', <%jd,%jd>, default: %jd, range: %s]",
+ q, low, hig, dfl, range));
+
+ if (range && dfl)
+ snprintf(prompt, sizeof(prompt), _("%s (%s, default %jd): "), q, range, dfl);
+ else if (dfl)
+ snprintf(prompt, sizeof(prompt), _("%s (%jd-%jd, default %jd): "), q, low, hig, dfl);
+ else
+ snprintf(prompt, sizeof(prompt), _("%s (%jd-%jd): "), q, low, hig);
+
+ do {
+ uint64_t num;
+ int rc = get_user_reply(cxt, prompt, buf, bufsz);
+ if (rc)
+ return rc;
+
+ if (!*buf && dfl)
+ return fdisk_ask_number_set_result(ask, dfl);
+ else if (isdigit_string(buf)) {
+ char *end;
+ errno = 0;
+ num = strtoumax(buf, &end, 10);
+ if (errno || buf == end || (end && *end))
+ continue;
+ if (num >= low && num <= hig)
+ return fdisk_ask_number_set_result(ask, num);
+ printf(_("Value out of range.\n"));
+ }
+ } while (1);
+
+ return -1;
+}
+
+int ask_callback(struct fdisk_context *cxt, struct fdisk_ask *ask,
+ void *data __attribute__((__unused__)))
+{
+ char buf[BUFSIZ];
+
+ assert(cxt);
+ assert(ask);
+
+ switch(fdisk_ask_get_type(ask)) {
+ case FDISK_ASKTYPE_NUMBER:
+ return ask_number(cxt, ask, buf, sizeof(buf));
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
diff --git a/fdisks/fdisk.c b/fdisks/fdisk.c
index 094b7e0f6..453583ee1 100644
--- a/fdisks/fdisk.c
+++ b/fdisks/fdisk.c
@@ -752,19 +752,13 @@ void print_partition_size(struct fdisk_context *cxt,
static void new_partition(struct fdisk_context *cxt)
{
- int partnum = 0;
-
assert(cxt);
assert(cxt->label);
if (warn_geometry(cxt))
return;
- if (!(cxt->label->flags & FDISK_LABEL_FL_ADDPART_NOPARTNO))
- partnum = get_partition_dflt(cxt, 0, cxt->label->nparts_max,
- cxt->label->nparts_cur + 1);
-
- fdisk_add_partition(cxt, partnum, NULL);
+ fdisk_add_partition(cxt, NULL);
}
static void write_table(struct fdisk_context *cxt)
@@ -1197,6 +1191,8 @@ int main(int argc, char **argv)
if (!cxt)
err(EXIT_FAILURE, _("failed to allocate libfdisk context"));
+ fdisk_context_set_ask(cxt, ask_callback, NULL);
+
while ((c = getopt(argc, argv, "b:c::C:hH:lsS:u::vV")) != -1) {
switch (c) {
case 'b':
diff --git a/fdisks/fdisk.h b/fdisks/fdisk.h
index e337aefd2..627b0d91f 100644
--- a/fdisks/fdisk.h
+++ b/fdisks/fdisk.h
@@ -60,6 +60,10 @@ enum failure {
unable_to_write
};
+
+extern int ask_callback(struct fdisk_context *cxt, struct fdisk_ask *ask,
+ void *data __attribute__((__unused__)));
+
/* prototypes for fdisk.c */
extern char *line_ptr;
extern unsigned int display_in_cyl_units, units_per_sector;
diff --git a/include/strutils.h b/include/strutils.h
index 00598cf62..38eb1ce6a 100644
--- a/include/strutils.h
+++ b/include/strutils.h
@@ -28,6 +28,8 @@ extern double strtod_or_err(const char *str, const char *errmesg);
extern long strtol_or_err(const char *str, const char *errmesg);
extern unsigned long strtoul_or_err(const char *str, const char *errmesg);
+extern int isdigit_string(const char *str);
+
#ifndef HAVE_MEMPCPY
extern void *mempcpy(void *restrict dest, const void *restrict src, size_t n);
#endif
diff --git a/lib/strutils.c b/lib/strutils.c
index 2337b07b9..8e8ab2f37 100644
--- a/lib/strutils.c
+++ b/lib/strutils.c
@@ -132,6 +132,16 @@ err:
return -1;
}
+int isdigit_string(const char *str)
+{
+ const char *p;
+
+ for (p = str; p && *p && isdigit((unsigned char) *p); p++);
+
+ return p && p > str && !*p;
+}
+
+
#ifndef HAVE_MEMPCPY
void *mempcpy(void *restrict dest, const void *restrict src, size_t n)
{