commit - 0c422a5b7d0b4f4ddf3f70089c95d9ae2d2baf06
commit + b0a1b4203e231ca2b6ec3ab5a88efda868349631
blob - faadd5ac7957d4c3cc3487fa9e3610d40587a282
blob + 4eb647aabbd55b501e8ff215a50ac233388b669c
--- ChangeLog.md
+++ ChangeLog.md
## [1.2] - TBD
### Added
- Accept "disk" arguments.
+- Show RAID disks
- Options:
- `-a` print all fields
- `-i` don't print fancy unicode characters
blob - 4141794cedcce65dbb0f62e3ccbddd8735e1e870
blob + 9c892b22b21731c19c377f1438944009c056a939
--- lsblk.c
+++ lsblk.c
#define _BSD_SOURCE 1
#define DKTYPENAMES
#include <stddef.h>
+#include <dev/biovar.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/disklabel.h>
OPT_NOUNICODE = 0x02,
};
+struct my_diskinfo;
+
struct my_partinfo {
char letter;
uint64_t size;
uint64_t free;
const char *fstype;
const char *mount;
+ const struct my_diskinfo *sub;
};
struct my_diskinfo {
char name[4];
uint64_t size;
uint64_t used;
- uint8_t num_parts;
u_char duid[8];
+ uint8_t num_parts;
struct my_partinfo parts[MAXPARTITIONS];
};
static void print_header (int fields)
{
if (fields & FIELD_NAME)
- printf ("%-6s ", "NAME");
+ printf ("%-7s ", "NAME");
if (fields & FIELD_DUID)
printf ("%-18s ", "DUID");
}
}
+static void print_disk (const struct my_diskinfo *disk, int fields, int options, bool sub);
static void print_part (
const struct my_diskinfo *disk,
const struct my_partinfo *part,
) {
if (fields & FIELD_NAME) {
const char *prefix = (options & OPT_NOUNICODE) ? " " : (last ? "└─" : "├─");
- printf ("%s%s%c ", prefix, disk->name, part->letter);
+ printf ("%s%s%c ", prefix, disk->name, part->letter);
}
if (fields & FIELD_DUID) {
printf ("%s ", part->mount);
putchar ('\n');
+
+ if (part->sub) {
+ printf ("│ └─");
+ print_disk (part->sub, fields, options, true);
+ }
}
-static void print_disk (const struct my_diskinfo *disk, int fields, int options)
+static void print_disk (const struct my_diskinfo *disk, int fields, int options, bool sub)
{
- if (fields & FIELD_NAME)
- printf ("%s ", disk->name);
+ if (fields & FIELD_NAME) {
+ printf ("%s ", disk->name);
+ if (!sub)
+ printf (" ");
+ }
if (fields & FIELD_DUID) {
print_duid (disk->duid);
putchar ('\n');
- for (uint8_t i = 0; i < disk->num_parts; ++i)
- print_part (disk, &disk->parts[i], fields, options, i == (disk->num_parts - 1));
+ if (!sub) {
+ for (uint8_t i = 0; i < disk->num_parts; ++i)
+ print_part (disk, &disk->parts[i], fields, options, i == (disk->num_parts - 1));
+ }
}
static const struct statfs *find_mount (const char *dev)
return disk;
}
+static void read_raid (
+ const struct my_diskinfo *disk,
+ struct my_diskinfo *disks,
+ size_t num_disks
+) {
+ struct bioc_inq bi;
+ int fd;
+
+ fd = opendev (disk->name, O_RDONLY, OPENDEV_PART | OPENDEV_BLCK, NULL);
+ if (fd < 0) {
+ warn ("read_raid(): opendev(%s)", disk->name);
+ return;
+ }
+
+ bzero (&bi, sizeof bi);
+
+ if (ioctl (fd, BIOCINQ, &bi) == -1)
+ goto ret;
+
+ for (int i = 0; i < bi.bi_nodisk; ++i) {
+ struct bioc_disk bd;
+ const char *vendor;
+ size_t len_vendor;
+ char letter;
+
+ bzero (&bd, sizeof bd);
+ memcpy (&bd.bd_bio, &bi.bi_bio, sizeof bi.bi_bio);
+ bd.bd_volid = 0;
+ bd.bd_diskid = i;
+
+ if (ioctl (fd, BIOCDISK, &bd) == -1) {
+ warn ("read_raid(%s): BIOCDISK(%d)", disk->name, i);
+ continue;
+ }
+
+ vendor = bd.bd_vendor;
+ len_vendor = strlen (vendor);
+ if (len_vendor != 4) {
+ warnx ("read_raid(%s): unexpected vendor string: '%.32s'", disk->name, vendor);
+ continue;
+ }
+ letter = vendor[len_vendor - 1];
+
+ for (size_t j = 0; j < num_disks; ++j) {
+ if (!memcmp (vendor, disks[j].name, 3)) {
+ for (size_t k = 0; k < disks[j].num_parts; ++k) {
+ if (letter == disks[j].parts[k].letter) {
+ disks[j].parts[k].sub = disk;
+ goto found;
+ }
+ }
+ }
+ }
+ found:;
+ }
+
+ret:
+ close (fd);
+}
+
static int usage (void)
{
fputs ("Usage: lsblk [-ainUuV] [disk...]\n", stderr);
free (names);
+ for (size_t i = 0; i < num_disks; ++i) {
+ read_raid (&disks[i], disks, num_disks);
+ }
+
if (!(options & OPT_NOHEADER))
print_header (fields);
for (size_t i = 0; i < num_disks; ++i) {
- print_disk (&disks[i], fields, options);
+ print_disk (&disks[i], fields, options, false);
}
return 0;