Blob


1 /*
2 * Copyright (c) 2025 Tobias Heider <tobhe@openbsd.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
17 #include <err.h>
18 #include <fcntl.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <util.h>
25 #define DKTYPENAMES
26 #include <sys/disklabel.h>
27 #include <sys/dkio.h>
28 #include <sys/types.h>
29 #include <sys/sysctl.h>
30 #include <sys/mount.h>
31 #include <sys/ioctl.h>
32 #include <sys/param.h>
34 #define MEG(x) ((x) * 1024LL * (1024 / DEV_BSIZE))
35 #define GIG(x) (MEG(x) * 1024LL)
37 struct statfs *mntbuf;
38 int mntsize;
40 static void
41 usage(void)
42 {
43 fprintf(stderr,
44 "usage: disks [-h]\n"
45 " disks [-h] dev\n");
46 exit(1);
47 }
49 static char *
50 sysctl_disknames_get(void)
51 {
52 size_t len;
53 char *buf;
54 int mib[2] = { CTL_HW, HW_DISKNAMES } ;
55 int ret;
57 ret = sysctl(mib, 2, NULL, &len, NULL, 0);
58 if (ret == -1)
59 err(1, "%s: sysctl", __func__);
61 buf = malloc(len);
62 if (buf == NULL)
63 return NULL;
65 ret = sysctl(mib, 2, buf, &len, NULL, 0);
66 if (ret == -1)
67 err(1, "%s: sysctl", __func__);
69 return buf;
70 }
72 static void
73 print_partition(const char *devname, const struct disklabel *dl, int i, int last,
74 int human)
75 {
76 const struct partition *pp = &dl->d_partitions[i];
77 char sbuf[FMT_SCALED_STRSIZE];
78 int dplen;
79 char *dp;
80 int j;
82 if (DL_GETPSIZE(pp)) {
83 printf("\n%c-- %s%s%c\t", last ? '`' : '|',devname,
84 isduid(devname, OPENDEV_PART) ? "." : "",
85 DL_PARTNUM2NAME(i));
87 if (human) {
88 if(fmt_scaled(DL_GETPSIZE(pp) * dl->d_secsize, sbuf) == -1)
89 err(1, "%s: fmt_scaled()", __func__);
90 printf("%7s", sbuf);
91 } else {
92 printf("%16llu", DL_GETPSIZE(pp));
93 }
94 printf("\t%8s", fstypenames[pp->p_fstype]);
96 dplen = asprintf(&dp, "/dev/%s%c", devname, DL_PARTNUM2NAME(i));
98 for (j = 0; j < mntsize; j++)
99 if (strncmp(mntbuf[j].f_mntfromname, dp, dplen) == 0)
100 printf("\t%s", mntbuf[j].f_mntonname);
101 free(dp);
105 static void
106 print_device(char *devname, int human)
108 struct dk_inquiry di;
109 struct disklabel dl;
110 int dev;
111 int i, last_i;
113 /* Only root is allowed to do this */
114 dev = opendev(devname, O_RDONLY, OPENDEV_PART, NULL);
115 if (dev == -1)
116 err(1, "failed to open %s",devname);
118 if (ioctl(dev, DIOCINQ, &di) == -1)
119 err(1, "%s: ioctl(DIOCINQ)", __func__);
120 if (ioctl(dev, DIOCGDINFO, &dl) == -1)
121 err(1, "%s: ioctl(DIOCGDINFO)", __func__);
123 printf("%s", devname);
124 const uint8_t duid_zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0};
125 if (!isduid(devname, OPENDEV_PART) && (memcmp(dl.d_uid, duid_zero, sizeof(duid_zero)) != 0)) {
126 printf(":%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
127 dl.d_uid[0], dl.d_uid[1], dl.d_uid[2], dl.d_uid[3],
128 dl.d_uid[4], dl.d_uid[5], dl.d_uid[6], dl.d_uid[7]);
130 printf(" [%s %s]", di.vendor, di.product);
132 last_i = -1;
133 for (i = 0; i < dl.d_npartitions; i++)
134 if (DL_GETPSIZE(&dl.d_partitions[i]))
135 last_i = i;
137 for (i = 0; i < dl.d_npartitions; i++)
138 print_partition(devname, &dl, i, i == last_i, human);
139 printf("\n\n");
142 int
143 main(int argc, char *argv[])
145 char *disks = sysctl_disknames_get();
146 char *p;
147 int ch, human = 0;
149 while ((ch = getopt(argc, argv, "h")) != -1) {
150 switch (ch) {
151 case 'h':
152 human = 1;
153 break;
154 default:
155 usage();
158 argc -= optind;
159 argv += optind;
161 if ((mntsize = getmntinfo(&mntbuf, MNT_WAIT)) == 0)
162 err(1, "%s: getmntinfo", __func__);
164 if (human) {
165 printf("DISK \t TOTAL\t FSTYPE\tMOUNT\n");
166 } else {
167 printf("DISK \t TOTAL\t FSTYPE\tMOUNT\n");
170 if (argc == 1 && argv[0] != NULL) {
171 print_device(argv[0], human);
172 return 0;
175 /* Print all of those disks*/
176 while ((p = strsep(&disks, ",")) != NULL) {
178 p = strsep(&p, ":");
179 if (p == NULL)
180 errx(1, "%s: strsep", __func__);
182 print_device(p, human);
185 return 0;