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 data
= udev_device_get_property_value(dev
, "ID_SERIAL");
113 prop
->serial
= xstrdup(data
);
115 if ((data
= udev_device_get_property_value(dev
, "ID_MODEL")))
116 prop
->model
= xstrdup(data
);
118 udev_device_unref(dev
);
119 DBG(DEV
, ul_debugobj(ld
, "%s: found udev properties", ld
->name
));
123 ld
->udev_requested
= 1;
125 DBG(DEV
, ul_debugobj(ld
, " from udev"));
126 return ld
->properties
;
128 #endif /* HAVE_LIBUDEV */
131 static int lookup(char *buf
, char *pattern
, char **value
)
136 /* do not re-fill value */
140 len
= strlen(pattern
);
141 if (strncmp(buf
, pattern
, len
) != 0)
148 if (!*p
|| *p
== '\n')
151 for (; *p
&& *p
!= '\n'; p
++) ;
159 /* read device properties from fake text file (used on --sysroot) */
160 static struct lsblk_devprop
*get_properties_by_file(struct lsblk_device
*ld
)
162 struct lsblk_devprop
*prop
;
168 assert(lsblk
->sysroot
);
170 if (ld
->file_requested
)
171 return ld
->properties
;
173 if (ld
->properties
|| ld
->filename
) {
174 lsblk_device_free_properties(ld
->properties
);
175 ld
->properties
= NULL
;
178 pc
= ul_new_path("/");
181 if (ul_path_set_prefix(pc
, lsblk
->sysroot
) != 0)
183 if (ul_path_stat(pc
, &sb
, ld
->filename
) != 0 || !S_ISREG(sb
.st_mode
))
186 fp
= ul_path_fopen(pc
, "r", ld
->filename
);
190 prop
= ld
->properties
;
192 prop
= ld
->properties
= xcalloc(1, sizeof(*ld
->properties
));
194 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
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
)) ;
205 else if (lookup(buf
, "ID_FS_VERSION", &prop
->fsversion
)) ;
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_IDENT_SERIAL", &prop
->serial
)) ; /* serial from sg3_utils */
213 else if (lookup(buf
, "ID_SCSI_SERIAL", &prop
->serial
)) ;
214 else if (lookup(buf
, "ID_SERIAL_SHORT", &prop
->serial
)) ;
215 else if (lookup(buf
, "ID_SERIAL", &prop
->serial
)) ;
218 else if (lookup(buf
, "MODE", &prop
->mode
)) ;
219 else if (lookup(buf
, "OWNER", &prop
->owner
)) ;
220 else if (lookup(buf
, "GROUP", &prop
->group
)) ;
229 ld
->file_requested
= 1;
231 DBG(DEV
, ul_debugobj(ld
, " from fake-file"));
232 return ld
->properties
;
236 static struct lsblk_devprop
*get_properties_by_blkid(struct lsblk_device
*dev
)
238 blkid_probe pr
= NULL
;
240 if (dev
->blkid_requested
)
241 return dev
->properties
;
246 goto done
;; /* no permissions to read from the device */
248 pr
= blkid_new_probe_from_filename(dev
->filename
);
252 blkid_probe_enable_superblocks(pr
, 1);
253 blkid_probe_set_superblocks_flags(pr
, BLKID_SUBLKS_LABEL
|
256 blkid_probe_enable_partitions(pr
, 1);
257 blkid_probe_set_partitions_flags(pr
, BLKID_PARTS_ENTRY_DETAILS
);
259 if (!blkid_do_safeprobe(pr
)) {
260 const char *data
= NULL
;
261 struct lsblk_devprop
*prop
;
264 lsblk_device_free_properties(dev
->properties
);
265 prop
= dev
->properties
= xcalloc(1, sizeof(*dev
->properties
));
267 if (!blkid_probe_lookup_value(pr
, "TYPE", &data
, NULL
))
268 prop
->fstype
= xstrdup(data
);
269 if (!blkid_probe_lookup_value(pr
, "UUID", &data
, NULL
))
270 prop
->uuid
= xstrdup(data
);
271 if (!blkid_probe_lookup_value(pr
, "PTUUID", &data
, NULL
))
272 prop
->ptuuid
= xstrdup(data
);
273 if (!blkid_probe_lookup_value(pr
, "PTTYPE", &data
, NULL
))
274 prop
->pttype
= xstrdup(data
);
275 if (!blkid_probe_lookup_value(pr
, "LABEL", &data
, NULL
))
276 prop
->label
= xstrdup(data
);
277 if (!blkid_probe_lookup_value(pr
, "VERSION", &data
, NULL
))
278 prop
->fsversion
= xstrdup(data
);
279 if (!blkid_probe_lookup_value(pr
, "PART_ENTRY_TYPE", &data
, NULL
))
280 prop
->parttype
= xstrdup(data
);
281 if (!blkid_probe_lookup_value(pr
, "PART_ENTRY_UUID", &data
, NULL
))
282 prop
->partuuid
= xstrdup(data
);
283 if (!blkid_probe_lookup_value(pr
, "PART_ENTRY_NAME", &data
, NULL
))
284 prop
->partlabel
= xstrdup(data
);
285 if (!blkid_probe_lookup_value(pr
, "PART_ENTRY_FLAGS", &data
, NULL
))
286 prop
->partflags
= xstrdup(data
);
288 DBG(DEV
, ul_debugobj(dev
, "%s: found blkid properties", dev
->name
));
292 blkid_free_probe(pr
);
294 DBG(DEV
, ul_debugobj(dev
, " from blkid"));
295 dev
->blkid_requested
= 1;
296 return dev
->properties
;
299 struct lsblk_devprop
*lsblk_device_get_properties(struct lsblk_device
*dev
)
301 struct lsblk_devprop
*p
= NULL
;
303 DBG(DEV
, ul_debugobj(dev
, "%s: properties requested", dev
->filename
));
305 return get_properties_by_file(dev
);
307 p
= get_properties_by_udev(dev
);
309 p
= get_properties_by_blkid(dev
);
313 void lsblk_properties_deinit(void)
325 struct lsblk_parttype
{
326 unsigned int code
; /* type as number or zero */
327 char *name
; /* description */
328 char *typestr
; /* type as string or NULL */
331 static const struct lsblk_parttype mbr_types
[] =
333 #include "pt-mbr-partnames.h"
336 #define DEF_GUID(_u, _n) \
341 static const struct lsblk_parttype gpt_types
[] =
343 #include "pt-gpt-partnames.h"
346 const char *lsblk_parttype_code_to_string(const char *code
, const char *pttype
)
350 if (!code
|| !pttype
)
353 if (strcmp(pttype
, "dos") == 0 || strcmp(pttype
, "mbr") == 0) {
358 xcode
= strtol(code
, &end
, 16);
360 if (errno
|| *end
!= '\0')
363 for (i
= 0; i
< ARRAY_SIZE(mbr_types
); i
++) {
364 const struct lsblk_parttype
*t
= &mbr_types
[i
];
366 if (t
->name
&& t
->code
== xcode
)
370 } else if (strcmp(pttype
, "gpt") == 0) {
371 for (i
= 0; i
< ARRAY_SIZE(gpt_types
); i
++) {
372 const struct lsblk_parttype
*t
= &gpt_types
[i
];
374 if (t
->name
&& t
->typestr
&&
375 strcasecmp(code
, t
->typestr
) == 0)