commit - /dev/null
commit + 33bf1ca46df95a50bcf92dfa97e36620311e21ac
blob - /dev/null
blob + ccf77bad06d032847934382eb88a4ddc54e3fdd8 (mode 644)
--- /dev/null
+++ .gitignore
+/lsblk
blob - /dev/null
blob + d54c0cb5093a50eb504667e6181c5362270784aa (mode 644)
--- /dev/null
+++ Makefile
+.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
+# 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
+.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
+#define _XOPEN_SOURCE 700
+#define _BSD_SOURCE 1
+#define DKTYPENAMES
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/disklabel.h>
+#include <sys/sysctl.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <sys/dkio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+
+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;
+}