From 2e55bedc45e836899a18ea7f4a488f50597afad5 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 21 Sep 2024 19:31:16 +0200 Subject: misc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- ask.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 ask.c (limited to 'ask.c') diff --git a/ask.c b/ask.c new file mode 100644 index 0000000..bb8fa50 --- /dev/null +++ b/ask.c @@ -0,0 +1,115 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#if defined(__linux__) +# include +#endif + + +int +confirm(const char *device, off_t off, off_t len, off_t end) +{ + char buf[1024]; + int ttyfd = -1; + int need_close; + int ret = 1; + int custom_section = (off >= 0 || len >= 0 || end >= 0); + const char *type; + ssize_t i, r; + int confirm_state = 0; + struct stat st; + + if (isatty(STDIN_FILENO)) { + ttyfd = STDIN_FILENO; + need_close = 0; + } else { + ttyfd = open("/dev/tty", O_RDWR); + if (ttyfd < 0) + return 1; + need_close = 1; + } + + if (getpgrp() != tcgetpgrp(ttyfd)) + goto out; + + if (custom_section) { + if (off < 0) + off = 0; + if (end >= 0) + len = end - off; + else if (len >= 0) + end = off + len; + else if (off == 0) + custom_section = 0; + if (end >= 0 && end < off) + eprintf("the value of -e option is lower than value of -o option"); + } + + if (stat(device, &st)) + eprintf("stat %s:", device); + switch (st.st_mode & S_IFMT) { + case S_IFREG: + type = "file"; + break; + case S_IFBLK: + type = "device"; + break; + default: + eprintf("%s: not a regular file or block device", device); + } + + if (dprintf(ttyfd, "Are you sure you want to erase the contents of %s?\n", device) < 0) + goto printerror; + + if (S_ISREG(st.st_mode)) { + if (dprintf(ttyfd, "\nThe file is %s large.\n", exact_and_human_size(st.st_size, buf, 1)) < 0) + goto printerror; +#if defined(__linux__) + } else if (S_ISBLK(st.st_mode)) { + char *devname = get_device_name(major(st.st_rdev), minor(st.st_rdev)); + if (devname) { + /* TODO display device identity and size (look in /sys/class/block//) */ + } +#endif + } + + if (custom_section) { + if (dprintf(ttyfd, "\nYou have requested to only erase part of the %s:\n", type) < 0 || + (off >= 0 && dprintf(ttyfd, "\tFirst byte: %s\n", exact_and_human_size(off, buf, 0)) < 0) || + (len >= 0 && dprintf(ttyfd, "\tNumber of bytes: %s\n", exact_and_human_size(len, buf, 0)) < 0) || + (end >= 0 && dprintf(ttyfd, "\tEnd of overwrite: %s\n", exact_and_human_size(end, buf, 1)) < 0)) + goto printerror; + } + + if (dprintf(ttyfd, "\nAffirm by entering 'yes' in majuscule without quotes.\n") < 0) + goto printerror; + + ret = 0; + for (;;) { + r = read(ttyfd, buf, sizeof(buf)); + if (!r) { + goto out; + } else if (r < 0) { + if (errno == EINTR) + continue; + eprintf("read %s:", need_close ? "/dev/tty" : ""); + } + for (i = 0; i < r; i++) { + if (buf[i] != "YES\n"[confirm_state++]) + goto out; + if (buf[i] == '\n') { + ret = 1; + goto out; + } + } + } + +out: + if (need_close) + close(ttyfd); + if (dprintf(ttyfd, "%s\n", ret ? "" : "User did not affirm action. Aborting...") < 0) + goto printerror; + return ret; + +printerror: + eprintf("dprintf %s:", need_close ? "/dev/tty" : ""); +} -- cgit v1.2.3-70-g09d2