From b968f8ed826b9cc662c1a484040c55b0e0ad18c4 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sun, 22 Sep 2024 00:17:14 +0200 Subject: Expose device information in confirmation prompt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- ask.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 156 insertions(+), 2 deletions(-) (limited to 'ask.c') diff --git a/ask.c b/ask.c index bb8fa50..5917a12 100644 --- a/ask.c +++ b/ask.c @@ -5,6 +5,146 @@ #endif +struct devinfo { + char *part; + char *dev; + char *part_start; + char *part_size; + char *dev_size; + char *dev_wwid; + char *dev_model; + char *dev_serial; + char *dev_transport; +}; + + +static void +destroy_devinfo(struct devinfo *info) +{ + free(info->part); + free(info->dev); + free(info->part_start); + free(info->part_size); + free(info->dev_size); + free(info->dev_wwid); + free(info->dev_model); + free(info->dev_serial); + free(info->dev_transport); +} + + +static char * +strip(char *s) +{ + char *ret = s; + if (s) { + char *p = s; + while (*s) { + while (*s && !isspace(*s)) + s++; + p = s; + while (*s && isspace(*s)) + s++; + } + *p = '\0'; + } + return ret; +} + + +static char * +fmtsize(char *s) +{ + uintmax_t val; + char *end, *ret; + char buf[256]; + + if (!s) + return NULL; + + errno = 0; + val = strtoumax(s, &end, 10); + if (!isdigit(*s) || *end || errno || val > (uintmax_t)(OFF_MAX / 512)) { + free(s); + return NULL; + } + + ret = estrdup(exact_and_human_size((off_t)val * 512, buf, 1)); + free(s); + return ret; +} + + +static int +get_devinfo(struct devinfo *info, const char *name) +{ + struct stat st; + char *path, *p; + int dfd; + + info->part = NULL; + info->dev = NULL; + info->part_start = NULL; + info->part_size = NULL; + info->dev_size = NULL; + info->dev_wwid = NULL; + info->dev_model = NULL; + info->dev_serial = NULL; + info->dev_transport = NULL; + + path = emalloc(sizeof("/sys/class/block/") + strlen(name)); + p = stpcpy(stpcpy(path, "/sys/class/block/"), name); + + dfd = open(path, O_PATH); + if (dfd < 0) + return 0; + + info->part = strip(readtextfileat(dfd, "partition")); + if (info->part) { + info->part_start = fmtsize(strip(readtextfileat(dfd, "start"))); + info->part_size = fmtsize(strip(readtextfileat(dfd, "size"))); + + close(dfd); + + if (!isdigit(p[-1])) + return 1; + while (isdigit(p[-1])) + *--p = '\0'; + + dfd = open(path, O_PATH); + if (dfd < 0) { + if (isalpha(p[-1])) { + *--p = '\0'; + dfd = open(path, O_PATH); + } + if (dfd < 0) + return 1; + } + + if (fstatat(dfd, name, &st, 0) || !S_ISDIR(st.st_mode)) { + close(dfd); + return 1; + } + + while (p[-1] != '/') + p--; + info->dev = estrdup(p); + } + + info->dev_size = fmtsize(strip(readtextfileat(dfd, "size"))); + info->dev_wwid = strip(readtextfileat(dfd, "wwid")); + if (!info->dev_wwid) + info->dev_wwid = strip(readtextfileat(dfd, "device/wwid")); + info->dev_model = strip(readtextfileat(dfd, "device/model")); + info->dev_serial = strip(readtextfileat(dfd, "device/serial")); + info->dev_transport = strip(readtextfileat(dfd, "device/transport")); + + close(dfd); + + return info->part || info->dev_size || info->dev_wwid || info->dev_model || info->dev_serial || info->dev_transport; +} + + int confirm(const char *device, off_t off, off_t len, off_t end) { @@ -66,8 +206,22 @@ confirm(const char *device, off_t off, off_t len, off_t end) #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//) */ + struct devinfo info; + if (devname && get_devinfo(&info, devname)) { + if ((dprintf(ttyfd, "\nFile is identified as block device %s. Details below:\n", devname) < 0) || + (info.part && info.dev && dprintf(ttyfd, "\tPartition %s of %s\n", info.part, info.dev) < 0) || + (info.part_size && dprintf(ttyfd, "\tSize of the partition: %s\n", info.part_size) < 0) || + (info.part_start && dprintf(ttyfd, "\tOffset of the partition: %s\n", info.part_start) < 0) || + (info.dev_size && dprintf(ttyfd, "\tSize of the device: %s\n", info.dev_size) < 0) || + (info.dev_model && dprintf(ttyfd, "\tModel of the device: %s\n", info.dev_model) < 0) || + (info.dev_serial && dprintf(ttyfd, "\tSerial number of the device: %s\n", info.dev_serial) < 0) || + (info.dev_transport && dprintf(ttyfd, "\tTransport type of the device: %s\n", info.dev_transport) < 0) || + (info.dev_wwid && dprintf(ttyfd, "\tWWID of the device: %s\n", info.dev_wwid) < 0)) + goto printerror; + destroy_devinfo(&info); + } else if (devname) { + if (dprintf(ttyfd, "\nFile is identified as block device %s. No details available.\n", devname) < 0) + goto printerror; } #endif } -- cgit v1.2.3-70-g09d2