diff options
Diffstat (limited to '')
| -rw-r--r-- | ask.c | 158 | ||||
| -rw-r--r-- | common.h | 1 | ||||
| -rw-r--r-- | deadshred.c | 6 | ||||
| -rw-r--r-- | io.c | 39 | 
4 files changed, 200 insertions, 4 deletions
| @@ -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  	} @@ -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 { */ @@ -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)  { | 
