]> git.ipfire.org Git - thirdparty/util-linux.git/blame - misc-utils/lsblk-properties.c
dmesg: add --follow-new
[thirdparty/util-linux.git] / misc-utils / lsblk-properties.c
CommitLineData
ccafadb7
KZ
1
2#include <blkid.h>
3
4#ifdef HAVE_LIBUDEV
5# include <libudev.h>
6#endif
7
8#include "c.h"
9#include "xalloc.h"
10#include "mangle.h"
7408a5d9 11#include "path.h"
107e9559 12#include "nls.h"
ccafadb7
KZ
13
14#include "lsblk.h"
15
16#ifdef HAVE_LIBUDEV
17static struct udev *udev;
18#endif
19
20void lsblk_device_free_properties(struct lsblk_devprop *p)
21{
22 if (!p)
23 return;
24
25 free(p->fstype);
9cca1ef2 26 free(p->fsversion);
ccafadb7
KZ
27 free(p->uuid);
28 free(p->ptuuid);
29 free(p->pttype);
30 free(p->label);
31 free(p->parttype);
32 free(p->partuuid);
33 free(p->partlabel);
34 free(p->wwn);
35 free(p->serial);
36 free(p->model);
7408a5d9 37 free(p->partflags);
ccafadb7 38
6f74ede5
KZ
39 free(p->mode);
40 free(p->owner);
41 free(p->group);
42
ccafadb7
KZ
43 free(p);
44}
45
46#ifndef HAVE_LIBUDEV
fed34a1e 47static struct lsblk_devprop *get_properties_by_udev(struct lsblk_device *dev
ccafadb7
KZ
48 __attribute__((__unused__)))
49{
50 return NULL;
51}
52#else
fed34a1e 53static struct lsblk_devprop *get_properties_by_udev(struct lsblk_device *ld)
ccafadb7
KZ
54{
55 struct udev_device *dev;
56
fed34a1e
KZ
57 if (ld->udev_requested)
58 return ld->properties;
ccafadb7 59
ccafadb7
KZ
60 if (!udev)
61 udev = udev_new(); /* global handler */
62 if (!udev)
63 goto done;
64
fed34a1e 65 dev = udev_device_new_from_subsystem_sysname(udev, "block", ld->name);
ccafadb7
KZ
66 if (dev) {
67 const char *data;
68 struct lsblk_devprop *prop;
69
fed34a1e
KZ
70 if (ld->properties)
71 lsblk_device_free_properties(ld->properties);
72 prop = ld->properties = xcalloc(1, sizeof(*ld->properties));
ccafadb7
KZ
73
74 if ((data = udev_device_get_property_value(dev, "ID_FS_LABEL_ENC"))) {
75 prop->label = xstrdup(data);
76 unhexmangle_string(prop->label);
77 }
78 if ((data = udev_device_get_property_value(dev, "ID_FS_UUID_ENC"))) {
79 prop->uuid = xstrdup(data);
80 unhexmangle_string(prop->uuid);
81 }
82 if ((data = udev_device_get_property_value(dev, "ID_PART_TABLE_UUID")))
83 prop->ptuuid = xstrdup(data);
84 if ((data = udev_device_get_property_value(dev, "ID_PART_TABLE_TYPE")))
85 prop->pttype = xstrdup(data);
86 if ((data = udev_device_get_property_value(dev, "ID_PART_ENTRY_NAME"))) {
87 prop->partlabel = xstrdup(data);
88 unhexmangle_string(prop->partlabel);
89 }
90 if ((data = udev_device_get_property_value(dev, "ID_FS_TYPE")))
91 prop->fstype = xstrdup(data);
9cca1ef2
KZ
92 if ((data = udev_device_get_property_value(dev, "ID_FS_VERSION")))
93 prop->fsversion = xstrdup(data);
ccafadb7
KZ
94 if ((data = udev_device_get_property_value(dev, "ID_PART_ENTRY_TYPE")))
95 prop->parttype = xstrdup(data);
96 if ((data = udev_device_get_property_value(dev, "ID_PART_ENTRY_UUID")))
97 prop->partuuid = xstrdup(data);
98 if ((data = udev_device_get_property_value(dev, "ID_PART_ENTRY_FLAGS")))
99 prop->partflags = xstrdup(data);
100
101 data = udev_device_get_property_value(dev, "ID_WWN_WITH_EXTENSION");
102 if (!data)
103 data = udev_device_get_property_value(dev, "ID_WWN");
104 if (data)
105 prop->wwn = xstrdup(data);
106
c2f6513c
SW
107 data = udev_device_get_property_value(dev, "ID_SCSI_SERIAL");
108 if(!data)
109 data = udev_device_get_property_value(dev, "ID_SERIAL_SHORT");
e81d0f80
SW
110 if(!data)
111 data = udev_device_get_property_value(dev, "ID_SERIAL");
c2f6513c 112 if (data)
ccafadb7 113 prop->serial = xstrdup(data);
c2f6513c 114
ccafadb7
KZ
115 if ((data = udev_device_get_property_value(dev, "ID_MODEL")))
116 prop->model = xstrdup(data);
117
118 udev_device_unref(dev);
fed34a1e 119 DBG(DEV, ul_debugobj(ld, "%s: found udev properties", ld->name));
ccafadb7
KZ
120 }
121
122done:
fed34a1e 123 ld->udev_requested = 1;
7408a5d9
KZ
124
125 DBG(DEV, ul_debugobj(ld, " from udev"));
fed34a1e 126 return ld->properties;
ccafadb7
KZ
127}
128#endif /* HAVE_LIBUDEV */
129
7408a5d9
KZ
130
131static int lookup(char *buf, char *pattern, char **value)
132{
133 char *p, *v;
134 int len;
135
136 /* do not re-fill value */
137 if (!buf || *value)
138 return 0;
139
140 len = strlen(pattern);
ad296391 141 if (strncmp(buf, pattern, len) != 0)
7408a5d9
KZ
142 return 0;
143
144 p = buf + len;
145 if (*p != '=')
146 return 0;
147 p++;
148 if (!*p || *p == '\n')
149 return 0;
150 v = p;
151 for (; *p && *p != '\n'; p++) ;
152 if (*p == '\n')
153 *p = '\0';
154
155 *value = xstrdup(v);
156 return 1;
157}
158
159/* read device properties from fake text file (used on --sysroot) */
160static struct lsblk_devprop *get_properties_by_file(struct lsblk_device *ld)
161{
162 struct lsblk_devprop *prop;
163 struct path_cxt *pc;
164 FILE *fp = NULL;
165 struct stat sb;
166 char buf[BUFSIZ];
167
eea06b92
KZ
168 assert(lsblk->sysroot);
169
7408a5d9
KZ
170 if (ld->file_requested)
171 return ld->properties;
172
7408a5d9
KZ
173 if (ld->properties || ld->filename) {
174 lsblk_device_free_properties(ld->properties);
175 ld->properties = NULL;
176 }
177
178 pc = ul_new_path("/");
179 if (!pc)
180 return NULL;
181 if (ul_path_set_prefix(pc, lsblk->sysroot) != 0)
182 goto done;
183 if (ul_path_stat(pc, &sb, ld->filename) != 0 || !S_ISREG(sb.st_mode))
184 goto done;
185
186 fp = ul_path_fopen(pc, "r", ld->filename);
187 if (!fp)
188 goto done;
189
190 prop = ld->properties;
191 if (!prop)
192 prop = ld->properties = xcalloc(1, sizeof(*ld->properties));
193
194 while (fgets(buf, sizeof(buf), fp) != NULL) {
6f74ede5 195 /* udev based */
7408a5d9
KZ
196 if (lookup(buf, "ID_FS_LABEL_ENC", &prop->label))
197 unhexmangle_string(prop->label);
198 else if (lookup(buf, "ID_FS_UUID_ENC", &prop->uuid))
199 unhexmangle_string(prop->uuid);
200 else if (lookup(buf, "ID_PART_ENTRY_NAME", &prop->partlabel))
201 unhexmangle_string(prop->partlabel);
202 else if (lookup(buf, "ID_PART_TABLE_UUID", &prop->ptuuid)) ;
203 else if (lookup(buf, "ID_PART_TABLE_TYPE", &prop->pttype)) ;
204 else if (lookup(buf, "ID_FS_TYPE", &prop->fstype)) ;
9cca1ef2 205 else if (lookup(buf, "ID_FS_VERSION", &prop->fsversion)) ;
7408a5d9
KZ
206 else if (lookup(buf, "ID_PART_ENTRY_TYPE", &prop->parttype)) ;
207 else if (lookup(buf, "ID_PART_ENTRY_UUID", &prop->partuuid)) ;
208 else if (lookup(buf, "ID_PART_ENTRY_FLAGS", &prop->partflags)) ;
209 else if (lookup(buf, "ID_MODEL", &prop->model)) ;
210 else if (lookup(buf, "ID_WWN_WITH_EXTENSION", &prop->wwn)) ;
211 else if (lookup(buf, "ID_WWN", &prop->wwn)) ;
212 else if (lookup(buf, "ID_SCSI_SERIAL", &prop->serial)) ;
213 else if (lookup(buf, "ID_SERIAL_SHORT", &prop->serial)) ;
e81d0f80 214 else if (lookup(buf, "ID_SERIAL", &prop->serial)) ;
6f74ede5
KZ
215
216 /* lsblk specific */
217 else if (lookup(buf, "MODE", &prop->mode)) ;
218 else if (lookup(buf, "OWNER", &prop->owner)) ;
219 else if (lookup(buf, "GROUP", &prop->group)) ;
220
7408a5d9
KZ
221 else
222 continue;
223 }
224done:
225 if (fp)
226 fclose(fp);
227 ul_unref_path(pc);
228 ld->file_requested = 1;
229
230 DBG(DEV, ul_debugobj(ld, " from fake-file"));
231 return ld->properties;
232}
233
234
fed34a1e 235static struct lsblk_devprop *get_properties_by_blkid(struct lsblk_device *dev)
ccafadb7
KZ
236{
237 blkid_probe pr = NULL;
238
fed34a1e
KZ
239 if (dev->blkid_requested)
240 return dev->properties;
ccafadb7 241
fed34a1e 242 if (!dev->size)
ccafadb7
KZ
243 goto done;
244 if (getuid() != 0)
245 goto done;; /* no permissions to read from the device */
246
fed34a1e 247 pr = blkid_new_probe_from_filename(dev->filename);
ccafadb7
KZ
248 if (!pr)
249 goto done;
250
251 blkid_probe_enable_superblocks(pr, 1);
252 blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_LABEL |
253 BLKID_SUBLKS_UUID |
254 BLKID_SUBLKS_TYPE);
255 blkid_probe_enable_partitions(pr, 1);
256 blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS);
257
258 if (!blkid_do_safeprobe(pr)) {
259 const char *data = NULL;
260 struct lsblk_devprop *prop;
261
fed34a1e
KZ
262 if (dev->properties)
263 lsblk_device_free_properties(dev->properties);
264 prop = dev->properties = xcalloc(1, sizeof(*dev->properties));
ccafadb7
KZ
265
266 if (!blkid_probe_lookup_value(pr, "TYPE", &data, NULL))
267 prop->fstype = xstrdup(data);
268 if (!blkid_probe_lookup_value(pr, "UUID", &data, NULL))
269 prop->uuid = xstrdup(data);
270 if (!blkid_probe_lookup_value(pr, "PTUUID", &data, NULL))
271 prop->ptuuid = xstrdup(data);
272 if (!blkid_probe_lookup_value(pr, "PTTYPE", &data, NULL))
273 prop->pttype = xstrdup(data);
274 if (!blkid_probe_lookup_value(pr, "LABEL", &data, NULL))
275 prop->label = xstrdup(data);
9cca1ef2
KZ
276 if (!blkid_probe_lookup_value(pr, "VERSION", &data, NULL))
277 prop->fsversion = xstrdup(data);
ccafadb7
KZ
278 if (!blkid_probe_lookup_value(pr, "PART_ENTRY_TYPE", &data, NULL))
279 prop->parttype = xstrdup(data);
280 if (!blkid_probe_lookup_value(pr, "PART_ENTRY_UUID", &data, NULL))
281 prop->partuuid = xstrdup(data);
282 if (!blkid_probe_lookup_value(pr, "PART_ENTRY_NAME", &data, NULL))
283 prop->partlabel = xstrdup(data);
284 if (!blkid_probe_lookup_value(pr, "PART_ENTRY_FLAGS", &data, NULL))
285 prop->partflags = xstrdup(data);
286
fed34a1e 287 DBG(DEV, ul_debugobj(dev, "%s: found blkid properties", dev->name));
ccafadb7
KZ
288 }
289
290done:
291 blkid_free_probe(pr);
292
7408a5d9 293 DBG(DEV, ul_debugobj(dev, " from blkid"));
fed34a1e
KZ
294 dev->blkid_requested = 1;
295 return dev->properties;
ccafadb7
KZ
296}
297
fed34a1e 298struct lsblk_devprop *lsblk_device_get_properties(struct lsblk_device *dev)
ccafadb7 299{
7408a5d9 300 struct lsblk_devprop *p = NULL;
ccafadb7 301
7408a5d9
KZ
302 DBG(DEV, ul_debugobj(dev, "%s: properties requested", dev->filename));
303 if (lsblk->sysroot)
eea06b92
KZ
304 return get_properties_by_file(dev);
305
306 p = get_properties_by_udev(dev);
ccafadb7 307 if (!p)
fed34a1e 308 p = get_properties_by_blkid(dev);
ccafadb7
KZ
309 return p;
310}
311
312void lsblk_properties_deinit(void)
313{
314#ifdef HAVE_LIBUDEV
315 udev_unref(udev);
316#endif
317}
107e9559
KZ
318
319
320
321/*
322 * Partition types
323 */
324struct lsblk_parttype {
325 unsigned int code; /* type as number or zero */
326 char *name; /* description */
327 char *typestr; /* type as string or NULL */
328};
329
330static const struct lsblk_parttype mbr_types[] =
331{
332 #include "pt-mbr-partnames.h"
333};
334
335#define DEF_GUID(_u, _n) \
336 { \
337 .typestr = (_u), \
338 .name = (_n), \
339 }
340static const struct lsblk_parttype gpt_types[] =
341{
342 #include "pt-gpt-partnames.h"
343};
344
345const char *lsblk_parttype_code_to_string(const char *code, const char *pttype)
346{
347 size_t i;
348
349 if (!code || !pttype)
350 return NULL;
351
352 if (strcmp(pttype, "dos") == 0 || strcmp(pttype, "mbr") == 0) {
353 char *end = NULL;
354 unsigned int xcode;
355
356 errno = 0;
357 xcode = strtol(code, &end, 16);
358
359 if (errno || *end != '\0')
360 return NULL;
361
362 for (i = 0; i < ARRAY_SIZE(mbr_types); i++) {
363 const struct lsblk_parttype *t = &mbr_types[i];
364
365 if (t->name && t->code == xcode)
366 return t->name;
367 }
368
369 } else if (strcmp(pttype, "gpt") == 0) {
370 for (i = 0; i < ARRAY_SIZE(gpt_types); i++) {
371 const struct lsblk_parttype *t = &gpt_types[i];
372
373 if (t->name && t->typestr &&
374 strcasecmp(code, t->typestr) == 0)
375 return t->name;
376 }
377 }
378
379 return NULL;
380}