Blame


1 9ddaf4ab 2023-04-08 benni /*
2 9ddaf4ab 2023-04-08 benni * Copyright (c) 2023 Benjamin Stürz <benni@stuerz.xyz>
3 9ddaf4ab 2023-04-08 benni *
4 9ddaf4ab 2023-04-08 benni * Permission to use, copy, modify, and distribute this software for any
5 9ddaf4ab 2023-04-08 benni * purpose with or without fee is hereby granted, provided that the above
6 9ddaf4ab 2023-04-08 benni * copyright notice and this permission notice appear in all copies.
7 9ddaf4ab 2023-04-08 benni *
8 9ddaf4ab 2023-04-08 benni * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 9ddaf4ab 2023-04-08 benni * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 9ddaf4ab 2023-04-08 benni * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 9ddaf4ab 2023-04-08 benni * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 9ddaf4ab 2023-04-08 benni * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 9ddaf4ab 2023-04-08 benni * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 9ddaf4ab 2023-04-08 benni * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 9ddaf4ab 2023-04-08 benni */
16 33bf1ca4 2023-04-08 benni #define _XOPEN_SOURCE 700
17 33bf1ca4 2023-04-08 benni #define _BSD_SOURCE 1
18 33bf1ca4 2023-04-08 benni #define DKTYPENAMES
19 33bf1ca4 2023-04-08 benni #include <stddef.h>
20 9c5d8ecc 2023-05-02 benni #include <sys/cdefs.h>
21 33bf1ca4 2023-04-08 benni #include <sys/types.h>
22 33bf1ca4 2023-04-08 benni #include <sys/disklabel.h>
23 33bf1ca4 2023-04-08 benni #include <sys/sysctl.h>
24 33bf1ca4 2023-04-08 benni #include <sys/ioctl.h>
25 33bf1ca4 2023-04-08 benni #include <sys/mount.h>
26 33bf1ca4 2023-04-08 benni #include <sys/dkio.h>
27 33bf1ca4 2023-04-08 benni #include <inttypes.h>
28 8380cc51 2023-05-01 benni #include <stdbool.h>
29 33bf1ca4 2023-04-08 benni #include <string.h>
30 33bf1ca4 2023-04-08 benni #include <stdarg.h>
31 33bf1ca4 2023-04-08 benni #include <stdint.h>
32 33bf1ca4 2023-04-08 benni #include <stdlib.h>
33 33bf1ca4 2023-04-08 benni #include <unistd.h>
34 33bf1ca4 2023-04-08 benni #include <stdio.h>
35 33bf1ca4 2023-04-08 benni #include <fcntl.h>
36 33bf1ca4 2023-04-08 benni #include <errno.h>
37 33bf1ca4 2023-04-08 benni
38 9c5d8ecc 2023-05-02 benni static __dead void die (const char *fmt, ...)
39 33bf1ca4 2023-04-08 benni {
40 33bf1ca4 2023-04-08 benni va_list ap;
41 33bf1ca4 2023-04-08 benni
42 33bf1ca4 2023-04-08 benni va_start (ap, fmt);
43 33bf1ca4 2023-04-08 benni fputs ("Error: ", stderr);
44 33bf1ca4 2023-04-08 benni vfprintf (stderr, fmt, ap);
45 33bf1ca4 2023-04-08 benni
46 33bf1ca4 2023-04-08 benni if (errno != 0) {
47 33bf1ca4 2023-04-08 benni fprintf (stderr, ": %s\n", strerror (errno));
48 33bf1ca4 2023-04-08 benni } else {
49 33bf1ca4 2023-04-08 benni fputc ('\n', stderr);
50 33bf1ca4 2023-04-08 benni }
51 33bf1ca4 2023-04-08 benni
52 33bf1ca4 2023-04-08 benni exit (1);
53 33bf1ca4 2023-04-08 benni }
54 33bf1ca4 2023-04-08 benni
55 33bf1ca4 2023-04-08 benni static int diskcount (void)
56 33bf1ca4 2023-04-08 benni {
57 33bf1ca4 2023-04-08 benni const int mib[2] = { CTL_HW, HW_DISKCOUNT };
58 33bf1ca4 2023-04-08 benni int diskcount;
59 33bf1ca4 2023-04-08 benni size_t len = sizeof diskcount;
60 33bf1ca4 2023-04-08 benni
61 33bf1ca4 2023-04-08 benni if (sysctl (mib, 2, &diskcount, &len, NULL, 0) == -1)
62 33bf1ca4 2023-04-08 benni die ("sysctl(hw.diskcount)");
63 33bf1ca4 2023-04-08 benni
64 33bf1ca4 2023-04-08 benni return diskcount;
65 33bf1ca4 2023-04-08 benni }
66 33bf1ca4 2023-04-08 benni
67 33bf1ca4 2023-04-08 benni static char *disknames (void)
68 33bf1ca4 2023-04-08 benni {
69 33bf1ca4 2023-04-08 benni const int num = diskcount ();
70 33bf1ca4 2023-04-08 benni const int mib[2] = { CTL_HW, HW_DISKNAMES };
71 33bf1ca4 2023-04-08 benni size_t len = 32 * num;
72 33bf1ca4 2023-04-08 benni char *buffer = malloc (len);
73 33bf1ca4 2023-04-08 benni
74 33bf1ca4 2023-04-08 benni if (sysctl (mib, 2, buffer, &len, NULL, 0) == -1)
75 33bf1ca4 2023-04-08 benni die ("sysctl(hw.disknames)");
76 33bf1ca4 2023-04-08 benni
77 33bf1ca4 2023-04-08 benni return buffer;
78 33bf1ca4 2023-04-08 benni }
79 33bf1ca4 2023-04-08 benni
80 9c5d8ecc 2023-05-02 benni static char *stripdisk (char *n)
81 33bf1ca4 2023-04-08 benni {
82 9c5d8ecc 2023-05-02 benni const char sufx[] = " disk";
83 9c5d8ecc 2023-05-02 benni const size_t ln = strnlen (n, 16);
84 9c5d8ecc 2023-05-02 benni const size_t ls = sizeof sufx - 1;
85 9c5d8ecc 2023-05-02 benni
86 9c5d8ecc 2023-05-02 benni if (!memcmp (n + ln - ls, sufx, ls)) {
87 9c5d8ecc 2023-05-02 benni n[ln - ls] = '\0';
88 9c5d8ecc 2023-05-02 benni }
89 9c5d8ecc 2023-05-02 benni
90 9c5d8ecc 2023-05-02 benni return n;
91 9c5d8ecc 2023-05-02 benni }
92 9c5d8ecc 2023-05-02 benni
93 9c5d8ecc 2023-05-02 benni static void print_size (uint64_t sz)
94 9c5d8ecc 2023-05-02 benni {
95 33bf1ca4 2023-04-08 benni struct unit {
96 33bf1ca4 2023-04-08 benni char sym;
97 33bf1ca4 2023-04-08 benni uint64_t factor;
98 33bf1ca4 2023-04-08 benni };
99 33bf1ca4 2023-04-08 benni
100 33bf1ca4 2023-04-08 benni const struct unit units[] = {
101 33bf1ca4 2023-04-08 benni { 'P', 1ull << 50 },
102 33bf1ca4 2023-04-08 benni { 'T', 1ull << 40 },
103 33bf1ca4 2023-04-08 benni { 'G', 1ull << 30 },
104 33bf1ca4 2023-04-08 benni { 'M', 1ull << 20 },
105 33bf1ca4 2023-04-08 benni { 'K', 1ull << 10 },
106 33bf1ca4 2023-04-08 benni { '0', 0 },
107 33bf1ca4 2023-04-08 benni };
108 33bf1ca4 2023-04-08 benni
109 33bf1ca4 2023-04-08 benni char sym = 'B';
110 33bf1ca4 2023-04-08 benni uint64_t factor = 1;
111 33bf1ca4 2023-04-08 benni
112 33bf1ca4 2023-04-08 benni for (const struct unit *u = &units[0]; u->factor; ++u) {
113 33bf1ca4 2023-04-08 benni if (sz >= (u->factor * 9 / 10)) {
114 33bf1ca4 2023-04-08 benni sym = u->sym;
115 33bf1ca4 2023-04-08 benni factor = u->factor;
116 33bf1ca4 2023-04-08 benni break;
117 33bf1ca4 2023-04-08 benni }
118 33bf1ca4 2023-04-08 benni }
119 33bf1ca4 2023-04-08 benni
120 33bf1ca4 2023-04-08 benni const unsigned scaled10 = sz * 10 / factor;
121 33bf1ca4 2023-04-08 benni const unsigned scaled = sz / factor;
122 33bf1ca4 2023-04-08 benni if (scaled10 >= 1000) {
123 8a374bef 2023-04-08 benni printf ("%u", scaled);
124 33bf1ca4 2023-04-08 benni } else if (scaled10 >= 100) {
125 8a374bef 2023-04-08 benni printf (" %u", scaled);
126 33bf1ca4 2023-04-08 benni } else {
127 8a374bef 2023-04-08 benni printf ("%u.%u", scaled, scaled10 % 10);
128 33bf1ca4 2023-04-08 benni }
129 33bf1ca4 2023-04-08 benni
130 33bf1ca4 2023-04-08 benni putchar (sym);
131 9c5d8ecc 2023-05-02 benni putchar (' ');
132 33bf1ca4 2023-04-08 benni }
133 33bf1ca4 2023-04-08 benni
134 9c5d8ecc 2023-05-02 benni enum {
135 9c5d8ecc 2023-05-02 benni FIELD_NAME = 0x01,
136 2b650bba 2023-05-04 benni FIELD_SIZE = 0x02,
137 2b650bba 2023-05-04 benni FIELD_USED = 0x04,
138 2b650bba 2023-05-04 benni FIELD_FREE = 0x08,
139 2b650bba 2023-05-04 benni FIELD_TYPE = 0x10,
140 2b650bba 2023-05-04 benni FIELD_LMNT = 0x20,
141 9c5d8ecc 2023-05-02 benni
142 2b650bba 2023-05-04 benni FIELD_DEFAULT = FIELD_NAME | FIELD_SIZE | FIELD_TYPE | FIELD_LMNT,
143 9c5d8ecc 2023-05-02 benni };
144 9c5d8ecc 2023-05-02 benni
145 9c5d8ecc 2023-05-02 benni struct my_partinfo {
146 9c5d8ecc 2023-05-02 benni char name[5];
147 9c5d8ecc 2023-05-02 benni uint64_t size;
148 9c5d8ecc 2023-05-02 benni uint64_t fssize;
149 9c5d8ecc 2023-05-02 benni uint64_t free;
150 9c5d8ecc 2023-05-02 benni const char *fstype;
151 9c5d8ecc 2023-05-02 benni const char *mount;
152 9c5d8ecc 2023-05-02 benni };
153 9c5d8ecc 2023-05-02 benni
154 9c5d8ecc 2023-05-02 benni struct my_diskinfo {
155 9c5d8ecc 2023-05-02 benni char type[16];
156 9c5d8ecc 2023-05-02 benni char label[16];
157 9c5d8ecc 2023-05-02 benni char name[4];
158 9c5d8ecc 2023-05-02 benni uint64_t size;
159 9c5d8ecc 2023-05-02 benni uint64_t used;
160 9c5d8ecc 2023-05-02 benni uint8_t num_parts;
161 9c5d8ecc 2023-05-02 benni struct my_partinfo parts[MAXPARTITIONS];
162 9c5d8ecc 2023-05-02 benni };
163 9c5d8ecc 2023-05-02 benni
164 9c5d8ecc 2023-05-02 benni static void print_header (int fields)
165 33bf1ca4 2023-04-08 benni {
166 9c5d8ecc 2023-05-02 benni if (fields & FIELD_NAME)
167 9c5d8ecc 2023-05-02 benni printf ("%-6s ", "NAME");
168 9c5d8ecc 2023-05-02 benni
169 9c5d8ecc 2023-05-02 benni if (fields & FIELD_SIZE)
170 9c5d8ecc 2023-05-02 benni printf ("%-4s ", "SIZE");
171 9c5d8ecc 2023-05-02 benni
172 9c5d8ecc 2023-05-02 benni if (fields & FIELD_USED)
173 9c5d8ecc 2023-05-02 benni printf ("%-4s ", "USED");
174 9c5d8ecc 2023-05-02 benni
175 9c5d8ecc 2023-05-02 benni if (fields & FIELD_FREE)
176 9c5d8ecc 2023-05-02 benni printf ("%-4s ", "FREE");
177 9c5d8ecc 2023-05-02 benni
178 9c5d8ecc 2023-05-02 benni if (fields & FIELD_TYPE)
179 9c5d8ecc 2023-05-02 benni printf ("%-8s ", "TYPE");
180 9c5d8ecc 2023-05-02 benni
181 2b650bba 2023-05-04 benni if (fields & FIELD_LMNT)
182 2b650bba 2023-05-04 benni printf ("LABEL/MOUNT ");
183 9c5d8ecc 2023-05-02 benni
184 9c5d8ecc 2023-05-02 benni putchar ('\n');
185 33bf1ca4 2023-04-08 benni }
186 33bf1ca4 2023-04-08 benni
187 9c5d8ecc 2023-05-02 benni static void print_part (const struct my_partinfo *part, int fields)
188 3103dec4 2023-05-01 benni {
189 9c5d8ecc 2023-05-02 benni if (fields & FIELD_NAME)
190 9c5d8ecc 2023-05-02 benni printf (" %s ", part->name);
191 3103dec4 2023-05-01 benni
192 9c5d8ecc 2023-05-02 benni if (fields & FIELD_SIZE)
193 9c5d8ecc 2023-05-02 benni print_size (part->size);
194 9c5d8ecc 2023-05-02 benni
195 9c5d8ecc 2023-05-02 benni if (fields & FIELD_USED) {
196 9c5d8ecc 2023-05-02 benni if (part->fssize) {
197 9c5d8ecc 2023-05-02 benni print_size (part->fssize - part->free);
198 9c5d8ecc 2023-05-02 benni } else {
199 9c5d8ecc 2023-05-02 benni printf (" N/A ");
200 9c5d8ecc 2023-05-02 benni }
201 3103dec4 2023-05-01 benni }
202 3103dec4 2023-05-01 benni
203 9c5d8ecc 2023-05-02 benni if (fields & FIELD_FREE) {
204 9c5d8ecc 2023-05-02 benni if (part->fssize) {
205 9c5d8ecc 2023-05-02 benni print_size (part->free);
206 9c5d8ecc 2023-05-02 benni } else {
207 9c5d8ecc 2023-05-02 benni printf (" N/A ");
208 9c5d8ecc 2023-05-02 benni }
209 9c5d8ecc 2023-05-02 benni }
210 9c5d8ecc 2023-05-02 benni
211 9c5d8ecc 2023-05-02 benni if (fields & FIELD_TYPE)
212 9c5d8ecc 2023-05-02 benni printf ("%-8.16s ", part->fstype);
213 9c5d8ecc 2023-05-02 benni
214 2b650bba 2023-05-04 benni if (fields & FIELD_LMNT && part->mount)
215 9c5d8ecc 2023-05-02 benni printf ("%s ", part->mount);
216 9c5d8ecc 2023-05-02 benni
217 9c5d8ecc 2023-05-02 benni putchar ('\n');
218 9c5d8ecc 2023-05-02 benni }
219 9c5d8ecc 2023-05-02 benni
220 9c5d8ecc 2023-05-02 benni static void print_disk (const struct my_diskinfo *disk, int fields)
221 9c5d8ecc 2023-05-02 benni {
222 9c5d8ecc 2023-05-02 benni if (fields & FIELD_NAME)
223 9c5d8ecc 2023-05-02 benni printf ("%s ", disk->name);
224 9c5d8ecc 2023-05-02 benni
225 9c5d8ecc 2023-05-02 benni if (fields & FIELD_SIZE)
226 9c5d8ecc 2023-05-02 benni print_size (disk->size);
227 9c5d8ecc 2023-05-02 benni
228 9c5d8ecc 2023-05-02 benni if (fields & FIELD_USED)
229 9c5d8ecc 2023-05-02 benni print_size (disk->used);
230 9c5d8ecc 2023-05-02 benni
231 9c5d8ecc 2023-05-02 benni if (fields & FIELD_FREE)
232 9c5d8ecc 2023-05-02 benni print_size (disk->size - disk->used);
233 9c5d8ecc 2023-05-02 benni
234 9c5d8ecc 2023-05-02 benni // Pad only upto 8 characters because most disk types are <=8 bytes long.
235 9c5d8ecc 2023-05-02 benni if (fields & FIELD_TYPE)
236 9c5d8ecc 2023-05-02 benni printf ("%-8.16s ", disk->type);
237 9c5d8ecc 2023-05-02 benni
238 2b650bba 2023-05-04 benni if (fields & FIELD_LMNT)
239 2b650bba 2023-05-04 benni printf ("%.16s ", disk->label);
240 9c5d8ecc 2023-05-02 benni
241 9c5d8ecc 2023-05-02 benni putchar ('\n');
242 9c5d8ecc 2023-05-02 benni
243 9c5d8ecc 2023-05-02 benni for (uint8_t i = 0; i < disk->num_parts; ++i)
244 9c5d8ecc 2023-05-02 benni print_part (&disk->parts[i], fields);
245 9c5d8ecc 2023-05-02 benni }
246 9c5d8ecc 2023-05-02 benni
247 9c5d8ecc 2023-05-02 benni static const struct statfs *find_mount (const char *dev)
248 9c5d8ecc 2023-05-02 benni {
249 9c5d8ecc 2023-05-02 benni static struct statfs *mounts = NULL;
250 9c5d8ecc 2023-05-02 benni static int n_mounts;
251 9c5d8ecc 2023-05-02 benni
252 9c5d8ecc 2023-05-02 benni if (!mounts) {
253 9c5d8ecc 2023-05-02 benni n_mounts = getmntinfo (&mounts, MNT_NOWAIT);
254 9c5d8ecc 2023-05-02 benni if (n_mounts == 0)
255 9c5d8ecc 2023-05-02 benni die ("getmntinfo()");
256 9c5d8ecc 2023-05-02 benni }
257 9c5d8ecc 2023-05-02 benni
258 9c5d8ecc 2023-05-02 benni for (int i = 0; i < n_mounts; ++i) {
259 9c5d8ecc 2023-05-02 benni if (!strcmp (dev, mounts[i].f_mntfromname))
260 9c5d8ecc 2023-05-02 benni return &mounts[i];
261 9c5d8ecc 2023-05-02 benni }
262 9c5d8ecc 2023-05-02 benni
263 9c5d8ecc 2023-05-02 benni return NULL;
264 3103dec4 2023-05-01 benni }
265 3103dec4 2023-05-01 benni
266 9c5d8ecc 2023-05-02 benni static struct my_diskinfo read_disk (const char *name)
267 9c5d8ecc 2023-05-02 benni {
268 9c5d8ecc 2023-05-02 benni struct my_diskinfo disk;
269 9c5d8ecc 2023-05-02 benni struct disklabel label;
270 9c5d8ecc 2023-05-02 benni
271 9c5d8ecc 2023-05-02 benni bzero (&disk, sizeof disk);
272 9c5d8ecc 2023-05-02 benni
273 9c5d8ecc 2023-05-02 benni { // Read disklabel.
274 9c5d8ecc 2023-05-02 benni char path[5 + 4 + 1];
275 9c5d8ecc 2023-05-02 benni int fd;
276 9c5d8ecc 2023-05-02 benni
277 9c5d8ecc 2023-05-02 benni snprintf (path, sizeof path, "/dev/%.3sc", name);
278 9c5d8ecc 2023-05-02 benni fd = open (path, O_RDONLY);
279 9c5d8ecc 2023-05-02 benni if (fd < 0)
280 9c5d8ecc 2023-05-02 benni die ("open(%s)", path);
281 9c5d8ecc 2023-05-02 benni if (ioctl (fd, DIOCGDINFO, &label) < 0)
282 9c5d8ecc 2023-05-02 benni die ("ioctl(%s, DIOCGDINFO)", path);
283 9c5d8ecc 2023-05-02 benni close (fd);
284 9c5d8ecc 2023-05-02 benni }
285 9c5d8ecc 2023-05-02 benni
286 9c5d8ecc 2023-05-02 benni memcpy (disk.name, name, 3);
287 9c5d8ecc 2023-05-02 benni disk.name[3] = '\0';
288 9c5d8ecc 2023-05-02 benni disk.size = DL_GETDSIZE (&label) * label.d_secsize;
289 9c5d8ecc 2023-05-02 benni memcpy (disk.type, label.d_typename, 16);
290 9c5d8ecc 2023-05-02 benni stripdisk (disk.type);
291 9c5d8ecc 2023-05-02 benni memcpy (disk.label, label.d_packname, 16);
292 9c5d8ecc 2023-05-02 benni disk.num_parts = 0;
293 9c5d8ecc 2023-05-02 benni
294 9c5d8ecc 2023-05-02 benni for (uint16_t i = 0; i < label.d_npartitions; ++i) {
295 9c5d8ecc 2023-05-02 benni const struct partition *p = &label.d_partitions[i];
296 9c5d8ecc 2023-05-02 benni const struct statfs *mnt;
297 9c5d8ecc 2023-05-02 benni struct my_partinfo part;
298 9c5d8ecc 2023-05-02 benni char path[5 + 4 + 1];
299 9c5d8ecc 2023-05-02 benni
300 9c5d8ecc 2023-05-02 benni bzero (&part, sizeof part);
301 9c5d8ecc 2023-05-02 benni
302 9c5d8ecc 2023-05-02 benni part.size = DL_GETPSIZE (p) * label.d_secsize;
303 9c5d8ecc 2023-05-02 benni
304 9c5d8ecc 2023-05-02 benni if (!part.size)
305 9c5d8ecc 2023-05-02 benni continue;
306 9c5d8ecc 2023-05-02 benni
307 9c5d8ecc 2023-05-02 benni memcpy (part.name, disk.name, 3);
308 9c5d8ecc 2023-05-02 benni part.name[3] = 'a' + i;
309 9c5d8ecc 2023-05-02 benni part.name[4] = '\0';
310 9c5d8ecc 2023-05-02 benni
311 9c5d8ecc 2023-05-02 benni snprintf (path, sizeof path, "/dev/%s", part.name);
312 9c5d8ecc 2023-05-02 benni mnt = find_mount (path);
313 9c5d8ecc 2023-05-02 benni
314 9c5d8ecc 2023-05-02 benni if (mnt) {
315 9c5d8ecc 2023-05-02 benni const uint64_t bs = mnt->f_bsize;
316 9c5d8ecc 2023-05-02 benni part.mount = mnt->f_mntonname;
317 9c5d8ecc 2023-05-02 benni part.fssize = mnt->f_blocks * bs;
318 9c5d8ecc 2023-05-02 benni part.free = mnt->f_bfree * bs;
319 9c5d8ecc 2023-05-02 benni }
320 9c5d8ecc 2023-05-02 benni
321 9c5d8ecc 2023-05-02 benni part.fstype = fstypenames[p->p_fstype];
322 9c5d8ecc 2023-05-02 benni if (i != 2)
323 9c5d8ecc 2023-05-02 benni disk.used += part.size;
324 9c5d8ecc 2023-05-02 benni disk.parts[disk.num_parts++] = part;
325 9c5d8ecc 2023-05-02 benni }
326 9c5d8ecc 2023-05-02 benni
327 9c5d8ecc 2023-05-02 benni return disk;
328 9c5d8ecc 2023-05-02 benni }
329 9c5d8ecc 2023-05-02 benni
330 9c5d8ecc 2023-05-02 benni static int usage (void)
331 9c5d8ecc 2023-05-02 benni {
332 2b650bba 2023-05-04 benni fputs ("Usage: lsblk [-Vanu]\n", stderr);
333 9c5d8ecc 2023-05-02 benni return 1;
334 9c5d8ecc 2023-05-02 benni }
335 9c5d8ecc 2023-05-02 benni
336 33bf1ca4 2023-04-08 benni int main (int argc, char *argv[])
337 33bf1ca4 2023-04-08 benni {
338 8380cc51 2023-05-01 benni int option;
339 8380cc51 2023-05-01 benni bool header = true;
340 9c5d8ecc 2023-05-02 benni int fields = FIELD_DEFAULT;
341 8380cc51 2023-05-01 benni
342 aff15c23 2023-04-30 benni if (unveil ("/dev", "r") == -1)
343 aff15c23 2023-04-30 benni die ("unveil(/dev)");
344 aff15c23 2023-04-30 benni
345 aff15c23 2023-04-30 benni if (unveil (NULL, NULL) == -1)
346 aff15c23 2023-04-30 benni die ("unveil()");
347 aff15c23 2023-04-30 benni
348 2b650bba 2023-05-04 benni while ((option = getopt (argc, argv, ":Vanu")) != -1) {
349 33bf1ca4 2023-04-08 benni switch (option) {
350 33bf1ca4 2023-04-08 benni case 'V':
351 33bf1ca4 2023-04-08 benni puts ("lsblk-" VERSION);
352 33bf1ca4 2023-04-08 benni return 0;
353 bf0e6461 2023-05-02 benni case 'a':
354 bf0e6461 2023-05-02 benni fields = -1;
355 8380cc51 2023-05-01 benni break;
356 bf0e6461 2023-05-02 benni case 'n':
357 bf0e6461 2023-05-02 benni header = false;
358 bf0e6461 2023-05-02 benni break;
359 9c5d8ecc 2023-05-02 benni case 'u':
360 9c5d8ecc 2023-05-02 benni fields |= FIELD_USED | FIELD_FREE;
361 9c5d8ecc 2023-05-02 benni break;
362 33bf1ca4 2023-04-08 benni default:
363 33bf1ca4 2023-04-08 benni return usage ();
364 33bf1ca4 2023-04-08 benni }
365 33bf1ca4 2023-04-08 benni }
366 33bf1ca4 2023-04-08 benni
367 33bf1ca4 2023-04-08 benni if (argc != optind)
368 33bf1ca4 2023-04-08 benni return usage ();
369 33bf1ca4 2023-04-08 benni
370 33bf1ca4 2023-04-08 benni struct statfs *mounts;
371 33bf1ca4 2023-04-08 benni char *names = disknames ();
372 33bf1ca4 2023-04-08 benni
373 33bf1ca4 2023-04-08 benni if (pledge ("stdio rpath disklabel", NULL) == -1)
374 33bf1ca4 2023-04-08 benni die ("pledge()");
375 33bf1ca4 2023-04-08 benni
376 33bf1ca4 2023-04-08 benni const int n_mounts = getmntinfo (&mounts, MNT_NOWAIT);
377 33bf1ca4 2023-04-08 benni if (n_mounts == 0)
378 33bf1ca4 2023-04-08 benni die ("getmntinfo()");
379 33bf1ca4 2023-04-08 benni
380 9c5d8ecc 2023-05-02 benni size_t cap_disks = 10;
381 9c5d8ecc 2023-05-02 benni size_t num_disks = 0;
382 9c5d8ecc 2023-05-02 benni struct my_diskinfo *disks = calloc (cap_disks, sizeof (struct my_diskinfo));
383 8380cc51 2023-05-01 benni
384 9c5d8ecc 2023-05-02 benni for (char *disk; (disk = strsep (&names, ",")) != NULL; ) {
385 9c5d8ecc 2023-05-02 benni if (num_disks == cap_disks) {
386 9c5d8ecc 2023-05-02 benni cap_disks = cap_disks * 13 / 8;
387 9c5d8ecc 2023-05-02 benni disks = reallocarray (disks, cap_disks, sizeof (struct my_diskinfo));
388 33bf1ca4 2023-04-08 benni }
389 9c5d8ecc 2023-05-02 benni disks[num_disks++] = read_disk (disk);
390 33bf1ca4 2023-04-08 benni }
391 33bf1ca4 2023-04-08 benni
392 33bf1ca4 2023-04-08 benni free (names);
393 9c5d8ecc 2023-05-02 benni
394 9c5d8ecc 2023-05-02 benni if (header)
395 9c5d8ecc 2023-05-02 benni print_header (fields);
396 9c5d8ecc 2023-05-02 benni
397 9c5d8ecc 2023-05-02 benni for (size_t i = 0; i < num_disks; ++i) {
398 9c5d8ecc 2023-05-02 benni print_disk (&disks[i], fields);
399 9c5d8ecc 2023-05-02 benni }
400 33bf1ca4 2023-04-08 benni return 0;
401 33bf1ca4 2023-04-08 benni }