aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--ask.c158
-rw-r--r--common.h1
-rw-r--r--deadshred.c6
-rw-r--r--io.c39
4 files changed, 200 insertions, 4 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
}
diff --git a/common.h b/common.h
index ad4b8a8..891f1c6 100644
--- a/common.h
+++ b/common.h
@@ -51,6 +51,7 @@ struct status {
/* io.c */
+char *readtextfileat(int dfd, const char *path);
void writeall(int fd, const void *data, size_t n, const char *fname);
void filecpy(int fd, off_t src, off_t len, const char *fname);
off_t filesize(int fd, const char *fname);
diff --git a/deadshred.c b/deadshred.c
index 8b8a74c..baa7bf6 100644
--- a/deadshred.c
+++ b/deadshred.c
@@ -57,8 +57,8 @@ print_status(int done, struct status *s)
libsimple_difftimespec(&time_spent, &s->now, &start_time);
sprintf(bufi == 0 ? buf1 : buf2,
- "%ji bytes (%s, %s, %.2lf %%) of %s (%s) shredded\033[K\n"
- "failed writes: %ju; bad sections: %ju (%ji bytes, %s, %s)\033[K\n"
+ "%ji byte%s (%s, %s, %.2lf %%) of %s (%s) shredded\033[K\n"
+ "failed writes: %ju; bad sections: %ju (%ji byte%s, %s, %s)\033[K\n"
"time spent shredding: %s; performance: %s\033[K\n"
"time since last successful write: %s\033[K\n"
"maximum time until a successful write: %s\033[K\n"
@@ -66,6 +66,7 @@ print_status(int done, struct status *s)
"%s",
/* line 1 { */
(intmax_t)s->shredded,
+ s->shredded == 1 ? "" : "s",
humansize1000(s->shredded, subbuf1),
humansize1024(s->shredded, subbuf2),
100 * (double)s->shredded / (double)total_size,
@@ -75,6 +76,7 @@ print_status(int done, struct status *s)
s->bad_writes,
s->bad_sections,
(intmax_t)s->bad_bytes,
+ s->bad_bytes == 1 ? "" : "s",
humansize1000(s->bad_bytes, subbuf3),
humansize1024(s->bad_bytes, subbuf4),
/* } line 3 { */
diff --git a/io.c b/io.c
index 98afe53..063265b 100644
--- a/io.c
+++ b/io.c
@@ -2,6 +2,45 @@
#include "common.h"
+char *
+readtextfileat(int dfd, const char *path)
+{
+ int fd;
+ char *text = NULL;
+ size_t size = 0;
+ size_t len = 0;
+ ssize_t r;
+
+ fd = openat(dfd, path, O_RDONLY);
+ if (fd < 0)
+ return NULL;
+
+ for (;;) {
+ if (len == size) {
+ size = size ? size * 2U : 64U;
+ text = erealloc(text, size);
+ }
+ r = read(fd, &text[len], size - len);
+ if (r <= 0) {
+ if (!r)
+ break;
+ if (errno == EINTR)
+ continue;
+ close(fd);
+ return NULL;
+ }
+ len += (size_t)r;
+ }
+
+ close(fd);
+
+ if (len == size)
+ text = erealloc(text, len + 1U);
+ text[len] = '\0';
+ return text;
+}
+
+
void
writeall(int fd, const void *data, size_t n, const char *fname)
{