aboutsummaryrefslogtreecommitdiffstats
path: root/ask.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2024-09-22 00:17:14 +0200
committerMattias Andrée <maandree@kth.se>2024-09-22 00:17:14 +0200
commitb968f8ed826b9cc662c1a484040c55b0e0ad18c4 (patch)
tree9b69a95fb5154d14837991bef604fd25585f7087 /ask.c
parentPeriodically save progress (diff)
downloaddeadshred-b968f8ed826b9cc662c1a484040c55b0e0ad18c4.tar.gz
deadshred-b968f8ed826b9cc662c1a484040c55b0e0ad18c4.tar.bz2
deadshred-b968f8ed826b9cc662c1a484040c55b0e0ad18c4.tar.xz
Expose device information in confirmation prompt
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to '')
-rw-r--r--ask.c158
1 files changed, 156 insertions, 2 deletions
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/<devname>/) */
+ 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
}