commit 33bf1ca46df95a50bcf92dfa97e36620311e21ac from: Benjamin Stürz date: Sat Apr 08 21:14:55 2023 UTC Initial commit commit - /dev/null commit + 33bf1ca46df95a50bcf92dfa97e36620311e21ac blob - /dev/null blob + ccf77bad06d032847934382eb88a4ddc54e3fdd8 (mode 644) --- /dev/null +++ .gitignore @@ -0,0 +1 @@ +/lsblk blob - /dev/null blob + d54c0cb5093a50eb504667e6181c5362270784aa (mode 644) --- /dev/null +++ Makefile @@ -0,0 +1,23 @@ +.POSIX: + +VERSION = 0.1 +PREFIX = /usr/local +MANPREFIX = ${PREFIX}/man +CFLAGS = -pipe -O2 -Wall -Werror + +all: lsblk + +lsblk: lsblk.c + ${CC} -o $@ $< ${CFLAGS} -DVERSION=\"${VERSION}\" + +clean: + rm -f lsblk + +install: lsblk + mkdir -p ${DESTDIR}${PREFIX}/bin ${DESTDIR}${MANPREFIX} + cp -f lsblk ${DESTDIR}${PREFIX}/bin + chmod 755 ${DESTDIR}${PREFIX}/bin/lsblk + cp -f lsblk.8 ${DESTDIR}${MANPREFIX} + +uninstall: + rm -f $(DESTDIR)$(PREFIX)/bin/lsblk blob - /dev/null blob + 59ddb42ff6b0e6953d2fec72ba514b0870f5a383 (mode 644) --- /dev/null +++ README.md @@ -0,0 +1,9 @@ +# lsblk for OpenBSD +This project aims to implement a clone of lsblk for OpenBSD. + +## Quirks +- It requires root privileges + +## TODO +- Header +- Padding/Spacing blob - /dev/null blob + ed0f461bdabb97eed90436858d7766557bca988b (mode 644) --- /dev/null +++ lsblk.8 @@ -0,0 +1,11 @@ +.TH LSBLK 8 lsblk-0.1 2023-04-08 +.SH NAME +lsblk \- list block devices +.SH SYNOPSIS +.B lsblk +.SH DESCRIPTION +The +.B lsblk +utilit can be used to examine the attached block devices on the system. +.SH SEE ALSO +.BR disklabel (8) blob - /dev/null blob + 78a36646696a653ace47134ea73902f38067ba6e (mode 644) --- /dev/null +++ lsblk.c @@ -0,0 +1,186 @@ +#define _XOPEN_SOURCE 700 +#define _BSD_SOURCE 1 +#define DKTYPENAMES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void die (const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + fputs ("Error: ", stderr); + vfprintf (stderr, fmt, ap); + + if (errno != 0) { + fprintf (stderr, ": %s\n", strerror (errno)); + } else { + fputc ('\n', stderr); + } + + exit (1); +} + +static int diskcount (void) +{ + const int mib[2] = { CTL_HW, HW_DISKCOUNT }; + int diskcount; + size_t len = sizeof diskcount; + + if (sysctl (mib, 2, &diskcount, &len, NULL, 0) == -1) + die ("sysctl(hw.diskcount)"); + + return diskcount; +} + +static char *disknames (void) +{ + const int num = diskcount (); + const int mib[2] = { CTL_HW, HW_DISKNAMES }; + size_t len = 32 * num; + char *buffer = malloc (len); + + if (sysctl (mib, 2, buffer, &len, NULL, 0) == -1) + die ("sysctl(hw.disknames)"); + + return buffer; +} + +static void printsize (uint64_t sz) +{ + struct unit { + char sym; + uint64_t factor; + }; + + const struct unit units[] = { + { 'P', 1ull << 50 }, + { 'T', 1ull << 40 }, + { 'G', 1ull << 30 }, + { 'M', 1ull << 20 }, + { 'K', 1ull << 10 }, + { '0', 0 }, + }; + + char sym = 'B'; + uint64_t factor = 1; + + for (const struct unit *u = &units[0]; u->factor; ++u) { + if (sz >= (u->factor * 9 / 10)) { + sym = u->sym; + factor = u->factor; + break; + } + } + + const unsigned scaled10 = sz * 10 / factor; + const unsigned scaled = sz / factor; + if (scaled10 >= 1000) { + printf (" %u", scaled); + } else if (scaled10 >= 100) { + printf ("%u.%u", scaled, scaled10 % 10); + } else { + printf (" %u.%u", scaled, scaled10 % 10); + } + + putchar (sym); +} + +static int usage (void) +{ + fputs ("Usage: lsblk [-V]\n", stderr); + return 1; +} + +int main (int argc, char *argv[]) +{ + int option; + while ((option = getopt (argc, argv, ":V")) != -1) { + switch (option) { + case 'V': + puts ("lsblk-" VERSION); + return 0; + default: + return usage (); + } + } + + if (argc != optind) + return usage (); + + struct statfs *mounts; + char *names = disknames (); + + if (pledge ("stdio rpath disklabel", NULL) == -1) + die ("pledge()"); + + const int n_mounts = getmntinfo (&mounts, MNT_NOWAIT); + if (n_mounts == 0) + die ("getmntinfo()"); + + for (char *disk; (disk = strsep (&names, ",")) != NULL;) { + struct disklabel label; + char *colon, *name = NULL; + int fd; + + colon = strchr (disk, ':'); + if (colon) + *colon = '\0'; + + asprintf (&name, "/dev/%sc", disk); + + fd = open (name, O_RDONLY); + if (fd < 0) + die ("open(%s)", name); + + if (ioctl (fd, DIOCGDINFO, &label) < 0) + die ("ioctl(%s, IOCGDINFO)", name); + + close (fd); + + const uint32_t ss = label.d_secsize; + + char *letter = name + strlen (name) - 1; + + printf ("%s ", disk); + printsize ((uint64_t)label.d_nsectors * ss); + printf (" %s\n", label.d_typename); + for (uint16_t i = 0; i < label.d_npartitions; ++i) { + const struct partition *p = &label.d_partitions[i]; + const uint64_t size = (((uint64_t)p->p_sizeh << 32) | p->p_size) * ss; + if (size == 0) + continue; + + *letter = i + 'a'; + const char *mp = ""; + for (int i = 0; i < n_mounts; ++i) { + const struct statfs *m = &mounts[i]; + if (!strcmp (name, m->f_mntfromname)) { + mp = m->f_mntonname; + break; + } + } + + printf (" %s%c ", disk, *letter); + printsize (size); + printf (" %s %s\n", fstypenames[p->p_fstype], mp); + } + } + + free (names); + return 0; +}