17 static struct udev
*udev
;
20 void lsblk_device_free_properties(struct lsblk_devprop
*p
)
47 static struct lsblk_devprop
*get_properties_by_udev(struct lsblk_device
*dev
48 __attribute__((__unused__
)))
53 static struct lsblk_devprop
*get_properties_by_udev(struct lsblk_device
*ld
)
55 struct udev_device
*dev
;
57 if (ld
->udev_requested
)
58 return ld
->properties
;
61 udev
= udev_new(); /* global handler */
65 dev
= udev_device_new_from_subsystem_sysname(udev
, "block", ld
->name
);
68 struct lsblk_devprop
*prop
;
71 lsblk_device_free_properties(ld
->properties
);
72 prop
= ld
->properties
= xcalloc(1, sizeof(*ld
->properties
));
74 if ((data
= udev_device_get_property_value(dev
, "ID_FS_LABEL_ENC"))) {
75 prop
->label
= xstrdup(data
);
76 unhexmangle_string(prop
->label
);
78 if ((data
= udev_device_get_property_value(dev
, "ID_FS_UUID_ENC"))) {
79 prop
->uuid
= xstrdup(data
);
80 unhexmangle_string(prop
->uuid
);
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
);
90 if ((data
= udev_device_get_property_value(dev
, "ID_FS_TYPE")))
91 prop
->fstype
= xstrdup(data
);
92 if ((data
= udev_device_get_property_value(dev
, "ID_FS_VERSION")))
93 prop
->fsversion
= xstrdup(data
);
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
);
101 data
= udev_device_get_property_value(dev
, "ID_WWN_WITH_EXTENSION");
103 data
= udev_device_get_property_value(dev
, "ID_WWN");
105 prop
->wwn
= xstrdup(data
);
107 data
= udev_device_get_property_value(dev
, "ID_SCSI_SERIAL");
109 data
= udev_device_get_property_value(dev
, "ID_SERIAL_SHORT");
111 prop
->serial
= xstrdup(data
);
113 if ((data
= udev_device_get_property_value(dev
, "ID_MODEL")))
114 prop
->model
= xstrdup(data
);
116 udev_device_unref(dev
);
117 DBG(DEV
, ul_debugobj(ld
, "%s: found udev properties", ld
->name
));
121 ld
->udev_requested
= 1;
123 DBG(DEV
, ul_debugobj(ld
, " from udev"));
124 return ld
->properties
;
126 #endif /* HAVE_LIBUDEV */
129 static int lookup(char *buf
, char *pattern
, char **value
)
134 /* do not re-fill value */
138 len
= strlen(pattern
);
139 if (strncmp(buf
, pattern
, len
))
146 if (!*p
|| *p
== '\n')
149 for (; *p
&& *p
!= '\n'; p
++) ;
157 /* read device properties from fake text file (used on --sysroot) */
158 static struct lsblk_devprop
*get_properties_by_file(struct lsblk_device
*ld
)
160 struct lsblk_devprop
*prop
;
166 assert(lsblk
->sysroot
);
168 if (ld
->file_requested
)
169 return ld
->properties
;
171 if (ld
->properties
|| ld
->filename
) {
172 lsblk_device_free_properties(ld
->properties
);
173 ld
->properties
= NULL
;
176 pc
= ul_new_path("/");
179 if (ul_path_set_prefix(pc
, lsblk
->sysroot
) != 0)
181 if (ul_path_stat(pc
, &sb
, ld
->filename
) != 0 || !S_ISREG(sb
.st_mode
))
184 fp
= ul_path_fopen(pc
, "r", ld
->filename
);
188 prop
= ld
->properties
;
190 prop
= ld
->properties
= xcalloc(1, sizeof(*ld
->properties
));
192 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
194 if (lookup(buf
, "ID_FS_LABEL_ENC", &prop
->label
))
195 unhexmangle_string(prop
->label
);
196 else if (lookup(buf
, "ID_FS_UUID_ENC", &prop
->uuid
))
197 unhexmangle_string(prop
->uuid
);
198 else if (lookup(buf
, "ID_PART_ENTRY_NAME", &prop
->partlabel
))
199 unhexmangle_string(prop
->partlabel
);
200 else if (lookup(buf
, "ID_PART_TABLE_UUID", &prop
->ptuuid
)) ;
201 else if (lookup(buf
, "ID_PART_TABLE_TYPE", &prop
->pttype
)) ;
202 else if (lookup(buf
, "ID_FS_TYPE", &prop
->fstype
)) ;
203 else if (lookup(buf
, "ID_FS_VERSION", &prop
->fsversion
)) ;
204 else if (lookup(buf
, "ID_PART_ENTRY_TYPE", &prop
->parttype
)) ;
205 else if (lookup(buf
, "ID_PART_ENTRY_UUID", &prop
->partuuid
)) ;
206 else if (lookup(buf
, "ID_PART_ENTRY_FLAGS", &prop
->partflags
)) ;
207 else if (lookup(buf
, "ID_MODEL", &prop
->model
)) ;
208 else if (lookup(buf
, "ID_WWN_WITH_EXTENSION", &prop
->wwn
)) ;
209 else if (lookup(buf
, "ID_WWN", &prop
->wwn
)) ;
210 else if (lookup(buf
, "ID_SCSI_SERIAL", &prop
->serial
)) ;
211 else if (lookup(buf
, "ID_SERIAL_SHORT", &prop
->serial
)) ;
214 else if (lookup(buf
, "MODE", &prop
->mode
)) ;
215 else if (lookup(buf
, "OWNER", &prop
->owner
)) ;
216 else if (lookup(buf
, "GROUP", &prop
->group
)) ;
225 ld
->file_requested
= 1;
227 DBG(DEV
, ul_debugobj(ld
, " from fake-file"));
228 return ld
->properties
;
232 static struct lsblk_devprop
*get_properties_by_blkid(struct lsblk_device
*dev
)
234 blkid_probe pr
= NULL
;
236 if (dev
->blkid_requested
)
237 return dev
->properties
;
242 goto done
;; /* no permissions to read from the device */
244 pr
= blkid_new_probe_from_filename(dev
->filename
);
248 blkid_probe_enable_superblocks(pr
, 1);
249 blkid_probe_set_superblocks_flags(pr
, BLKID_SUBLKS_LABEL
|
252 blkid_probe_enable_partitions(pr
, 1);
253 blkid_probe_set_partitions_flags(pr
, BLKID_PARTS_ENTRY_DETAILS
);
255 if (!blkid_do_safeprobe(pr
)) {
256 const char *data
= NULL
;
257 struct lsblk_devprop
*prop
;
260 lsblk_device_free_properties(dev
->properties
);
261 prop
= dev
->properties
= xcalloc(1, sizeof(*dev
->properties
));
263 if (!blkid_probe_lookup_value(pr
, "TYPE", &data
, NULL
))
264 prop
->fstype
= xstrdup(data
);
265 if (!blkid_probe_lookup_value(pr
, "UUID", &data
, NULL
))
266 prop
->uuid
= xstrdup(data
);
267 if (!blkid_probe_lookup_value(pr
, "PTUUID", &data
, NULL
))
268 prop
->ptuuid
= xstrdup(data
);
269 if (!blkid_probe_lookup_value(pr
, "PTTYPE", &data
, NULL
))
270 prop
->pttype
= xstrdup(data
);
271 if (!blkid_probe_lookup_value(pr
, "LABEL", &data
, NULL
))
272 prop
->label
= xstrdup(data
);
273 if (!blkid_probe_lookup_value(pr
, "VERSION", &data
, NULL
))
274 prop
->fsversion
= xstrdup(data
);
275 if (!blkid_probe_lookup_value(pr
, "PART_ENTRY_TYPE", &data
, NULL
))
276 prop
->parttype
= xstrdup(data
);
277 if (!blkid_probe_lookup_value(pr
, "PART_ENTRY_UUID", &data
, NULL
))
278 prop
->partuuid
= xstrdup(data
);
279 if (!blkid_probe_lookup_value(pr
, "PART_ENTRY_NAME", &data
, NULL
))
280 prop
->partlabel
= xstrdup(data
);
281 if (!blkid_probe_lookup_value(pr
, "PART_ENTRY_FLAGS", &data
, NULL
))
282 prop
->partflags
= xstrdup(data
);
284 DBG(DEV
, ul_debugobj(dev
, "%s: found blkid properties", dev
->name
));
288 blkid_free_probe(pr
);
290 DBG(DEV
, ul_debugobj(dev
, " from blkid"));
291 dev
->blkid_requested
= 1;
292 return dev
->properties
;
295 struct lsblk_devprop
*lsblk_device_get_properties(struct lsblk_device
*dev
)
297 struct lsblk_devprop
*p
= NULL
;
299 DBG(DEV
, ul_debugobj(dev
, "%s: properties requested", dev
->filename
));
301 return get_properties_by_file(dev
);
303 p
= get_properties_by_udev(dev
);
305 p
= get_properties_by_blkid(dev
);
309 void lsblk_properties_deinit(void)
321 struct lsblk_parttype
{
322 unsigned int code
; /* type as number or zero */
323 char *name
; /* description */
324 char *typestr
; /* type as string or NULL */
327 static const struct lsblk_parttype mbr_types
[] =
329 #include "pt-mbr-partnames.h"
332 #define DEF_GUID(_u, _n) \
337 static const struct lsblk_parttype gpt_types
[] =
339 #include "pt-gpt-partnames.h"
342 const char *lsblk_parttype_code_to_string(const char *code
, const char *pttype
)
346 if (!code
|| !pttype
)
349 if (strcmp(pttype
, "dos") == 0 || strcmp(pttype
, "mbr") == 0) {
354 xcode
= strtol(code
, &end
, 16);
356 if (errno
|| *end
!= '\0')
359 for (i
= 0; i
< ARRAY_SIZE(mbr_types
); i
++) {
360 const struct lsblk_parttype
*t
= &mbr_types
[i
];
362 if (t
->name
&& t
->code
== xcode
)
366 } else if (strcmp(pttype
, "gpt") == 0) {
367 for (i
= 0; i
< ARRAY_SIZE(gpt_types
); i
++) {
368 const struct lsblk_parttype
*t
= &gpt_types
[i
];
370 if (t
->name
&& t
->typestr
&&
371 strcasecmp(code
, t
->typestr
) == 0)