]> git.ipfire.org Git - thirdparty/util-linux.git/blob - misc-utils/lsblk-properties.c
Merge branch 'meson-more-build-options' of https://github.com/jwillikers/util-linux
[thirdparty/util-linux.git] / misc-utils / lsblk-properties.c
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"
11
12 #include "lsblk.h"
13
14 #ifdef HAVE_LIBUDEV
15 static struct udev *udev;
16 #endif
17
18 void lsblk_device_free_properties(struct lsblk_devprop *p)
19 {
20 if (!p)
21 return;
22
23 free(p->fstype);
24 free(p->uuid);
25 free(p->ptuuid);
26 free(p->pttype);
27 free(p->label);
28 free(p->parttype);
29 free(p->partuuid);
30 free(p->partlabel);
31 free(p->wwn);
32 free(p->serial);
33 free(p->model);
34
35 free(p);
36 }
37
38 #ifndef HAVE_LIBUDEV
39 static struct lsblk_devprop *get_properties_by_udev(struct lsblk_device *dev
40 __attribute__((__unused__)))
41 {
42 return NULL;
43 }
44 #else
45 static struct lsblk_devprop *get_properties_by_udev(struct lsblk_device *ld)
46 {
47 struct udev_device *dev;
48
49 if (ld->udev_requested)
50 return ld->properties;
51
52 if (lsblk->sysroot)
53 goto done;
54 if (!udev)
55 udev = udev_new(); /* global handler */
56 if (!udev)
57 goto done;
58
59 dev = udev_device_new_from_subsystem_sysname(udev, "block", ld->name);
60 if (dev) {
61 const char *data;
62 struct lsblk_devprop *prop;
63
64 if (ld->properties)
65 lsblk_device_free_properties(ld->properties);
66 prop = ld->properties = xcalloc(1, sizeof(*ld->properties));
67
68 if ((data = udev_device_get_property_value(dev, "ID_FS_LABEL_ENC"))) {
69 prop->label = xstrdup(data);
70 unhexmangle_string(prop->label);
71 }
72 if ((data = udev_device_get_property_value(dev, "ID_FS_UUID_ENC"))) {
73 prop->uuid = xstrdup(data);
74 unhexmangle_string(prop->uuid);
75 }
76 if ((data = udev_device_get_property_value(dev, "ID_PART_TABLE_UUID")))
77 prop->ptuuid = xstrdup(data);
78 if ((data = udev_device_get_property_value(dev, "ID_PART_TABLE_TYPE")))
79 prop->pttype = xstrdup(data);
80 if ((data = udev_device_get_property_value(dev, "ID_PART_ENTRY_NAME"))) {
81 prop->partlabel = xstrdup(data);
82 unhexmangle_string(prop->partlabel);
83 }
84 if ((data = udev_device_get_property_value(dev, "ID_FS_TYPE")))
85 prop->fstype = xstrdup(data);
86 if ((data = udev_device_get_property_value(dev, "ID_PART_ENTRY_TYPE")))
87 prop->parttype = xstrdup(data);
88 if ((data = udev_device_get_property_value(dev, "ID_PART_ENTRY_UUID")))
89 prop->partuuid = xstrdup(data);
90 if ((data = udev_device_get_property_value(dev, "ID_PART_ENTRY_FLAGS")))
91 prop->partflags = xstrdup(data);
92
93 data = udev_device_get_property_value(dev, "ID_WWN_WITH_EXTENSION");
94 if (!data)
95 data = udev_device_get_property_value(dev, "ID_WWN");
96 if (data)
97 prop->wwn = xstrdup(data);
98
99 data = udev_device_get_property_value(dev, "ID_SCSI_SERIAL");
100 if(!data)
101 data = udev_device_get_property_value(dev, "ID_SERIAL_SHORT");
102 if (data)
103 prop->serial = xstrdup(data);
104
105 if ((data = udev_device_get_property_value(dev, "ID_MODEL")))
106 prop->model = xstrdup(data);
107
108 udev_device_unref(dev);
109 DBG(DEV, ul_debugobj(ld, "%s: found udev properties", ld->name));
110 }
111
112 done:
113 ld->udev_requested = 1;
114 return ld->properties;
115 }
116 #endif /* HAVE_LIBUDEV */
117
118 static struct lsblk_devprop *get_properties_by_blkid(struct lsblk_device *dev)
119 {
120 blkid_probe pr = NULL;
121
122 if (dev->blkid_requested)
123 return dev->properties;
124
125 if (!dev->size)
126 goto done;
127 if (getuid() != 0)
128 goto done;; /* no permissions to read from the device */
129
130 pr = blkid_new_probe_from_filename(dev->filename);
131 if (!pr)
132 goto done;
133
134 blkid_probe_enable_superblocks(pr, 1);
135 blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_LABEL |
136 BLKID_SUBLKS_UUID |
137 BLKID_SUBLKS_TYPE);
138 blkid_probe_enable_partitions(pr, 1);
139 blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS);
140
141 if (!blkid_do_safeprobe(pr)) {
142 const char *data = NULL;
143 struct lsblk_devprop *prop;
144
145 if (dev->properties)
146 lsblk_device_free_properties(dev->properties);
147 prop = dev->properties = xcalloc(1, sizeof(*dev->properties));
148
149 if (!blkid_probe_lookup_value(pr, "TYPE", &data, NULL))
150 prop->fstype = xstrdup(data);
151 if (!blkid_probe_lookup_value(pr, "UUID", &data, NULL))
152 prop->uuid = xstrdup(data);
153 if (!blkid_probe_lookup_value(pr, "PTUUID", &data, NULL))
154 prop->ptuuid = xstrdup(data);
155 if (!blkid_probe_lookup_value(pr, "PTTYPE", &data, NULL))
156 prop->pttype = xstrdup(data);
157 if (!blkid_probe_lookup_value(pr, "LABEL", &data, NULL))
158 prop->label = xstrdup(data);
159 if (!blkid_probe_lookup_value(pr, "PART_ENTRY_TYPE", &data, NULL))
160 prop->parttype = xstrdup(data);
161 if (!blkid_probe_lookup_value(pr, "PART_ENTRY_UUID", &data, NULL))
162 prop->partuuid = xstrdup(data);
163 if (!blkid_probe_lookup_value(pr, "PART_ENTRY_NAME", &data, NULL))
164 prop->partlabel = xstrdup(data);
165 if (!blkid_probe_lookup_value(pr, "PART_ENTRY_FLAGS", &data, NULL))
166 prop->partflags = xstrdup(data);
167
168 DBG(DEV, ul_debugobj(dev, "%s: found blkid properties", dev->name));
169 }
170
171 done:
172 blkid_free_probe(pr);
173
174 dev->blkid_requested = 1;
175 return dev->properties;
176 }
177
178 struct lsblk_devprop *lsblk_device_get_properties(struct lsblk_device *dev)
179 {
180 struct lsblk_devprop *p = get_properties_by_udev(dev);
181
182 if (!p)
183 p = get_properties_by_blkid(dev);
184 return p;
185 }
186
187 void lsblk_properties_deinit(void)
188 {
189 #ifdef HAVE_LIBUDEV
190 udev_unref(udev);
191 #endif
192 }