1 /***************************************************************************
3 * devinfo_storage.c : storage devices
5 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
6 * Copyright 2013 Garrett D'Amore <garrett@damore.org>
8 * Licensed under the Academic Free License version 2.1
10 **************************************************************************/
20 #include <libdevinfo.h>
21 #include <sys/types.h>
22 #include <sys/mkdev.h>
24 #include <sys/mntent.h>
25 #include <sys/mnttab.h>
27 #include "../osspec.h"
28 #include "../logger.h"
30 #include "../hald_dbus.h"
31 #include "../device_info.h"
33 #include "../hald_runner.h"
36 #include "devinfo_misc.h"
37 #include "devinfo_storage.h"
38 #include "osspec_solaris.h"
41 #define WHOLE_DISK "s2"
43 #define WHOLE_DISK "p0"
46 /* some devices,especially CDROMs, may take a while to be probed (values in ms) */
47 #define DEVINFO_PROBE_STORAGE_TIMEOUT 60000
48 #define DEVINFO_PROBE_VOLUME_TIMEOUT 60000
50 typedef struct devinfo_storage_minor
{
55 int dosnum
; /* dos disk number or -1 */
56 } devinfo_storage_minor_t
;
58 HalDevice
*devinfo_ide_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
, char *device_type
);
59 static HalDevice
*devinfo_ide_host_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
);
60 static HalDevice
*devinfo_ide_device_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
);
61 static HalDevice
*devinfo_ide_storage_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
);
62 HalDevice
*devinfo_scsi_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
, char *device_type
);
63 static HalDevice
*devinfo_scsi_storage_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
);
64 HalDevice
*devinfo_blkdev_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
, char *device_type
);
65 static HalDevice
*devinfo_blkdev_storage_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
);
66 HalDevice
*devinfo_floppy_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
, char *device_type
);
67 static void devinfo_floppy_add_volume(HalDevice
*parent
, di_node_t node
);
68 static HalDevice
*devinfo_lofi_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
, char *device_type
);
69 static void devinfo_lofi_add_minor(HalDevice
*parent
, di_node_t node
, char *minor_path
, char *devlink
, dev_t dev
);
70 static void devinfo_storage_minors(HalDevice
*parent
, di_node_t node
, gchar
*devfs_path
, gboolean
);
71 static struct devinfo_storage_minor
*devinfo_storage_new_minor(char *maindev_path
, char *slice
,
72 char *devlink
, dev_t dev
, int dosnum
);
73 static void devinfo_storage_free_minor(struct devinfo_storage_minor
*m
);
74 HalDevice
*devinfo_volume_add(HalDevice
*parent
, di_node_t node
, devinfo_storage_minor_t
*m
);
75 static void devinfo_volume_preprobing_done(HalDevice
*d
, gpointer userdata1
, gpointer userdata2
);
76 static void devinfo_volume_hotplug_begin_add (HalDevice
*d
, HalDevice
*parent
, DevinfoDevHandler
*handler
, void *end_token
);
77 static void devinfo_storage_hotplug_begin_add (HalDevice
*d
, HalDevice
*parent
, DevinfoDevHandler
*handler
, void *end_token
);
78 static void devinfo_storage_probing_done (HalDevice
*d
, guint32 exit_type
, gint return_code
, char **error
, gpointer userdata1
, gpointer userdata2
);
79 const gchar
*devinfo_volume_get_prober (HalDevice
*d
, int *timeout
);
80 const gchar
*devinfo_storage_get_prober (HalDevice
*d
, int *timeout
);
82 static char *devinfo_scsi_dtype2str(int dtype
);
83 static char *devinfo_volume_get_slice_name (char *devlink
);
84 static gboolean
dos_to_dev(char *path
, char **devpath
, int *partnum
);
85 static gboolean
is_dos_path(char *path
, int *partnum
);
87 static void devinfo_storage_set_nicknames (HalDevice
*d
);
89 DevinfoDevHandler devinfo_ide_handler
= {
97 DevinfoDevHandler devinfo_scsi_handler
= {
105 DevinfoDevHandler devinfo_blkdev_handler
= {
113 DevinfoDevHandler devinfo_floppy_handler
= {
121 DevinfoDevHandler devinfo_lofi_handler
= {
129 DevinfoDevHandler devinfo_storage_handler
= {
132 devinfo_storage_hotplug_begin_add
,
134 devinfo_storage_probing_done
,
135 devinfo_storage_get_prober
137 DevinfoDevHandler devinfo_volume_handler
= {
140 devinfo_volume_hotplug_begin_add
,
143 devinfo_volume_get_prober
149 devinfo_ide_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
, char *device_type
)
153 if ((device_type
!= NULL
) && (strcmp(device_type
, "ide") == 0)) {
154 return (devinfo_ide_host_add(parent
, node
, devfs_path
));
157 if ((di_prop_lookup_strings (DDI_DEV_T_ANY
, node
, "class", &s
) > 0) &&
158 (strcmp (s
, "dada") == 0)) {
159 return (devinfo_ide_device_add(parent
, node
, devfs_path
));
166 devinfo_ide_host_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
)
170 d
= hal_device_new ();
172 devinfo_set_default_properties (d
, parent
, node
, devfs_path
);
173 hal_device_property_set_string (d
, "info.product", "IDE host controller");
174 hal_device_property_set_string (d
, "info.subsystem", "ide_host");
175 hal_device_property_set_int (d
, "ide_host.number", 0); /* XXX */
177 devinfo_add_enqueue (d
, devfs_path
, &devinfo_ide_handler
);
183 devinfo_ide_device_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
)
187 d
= hal_device_new();
189 devinfo_set_default_properties (d
, parent
, node
, devfs_path
);
190 hal_device_property_set_string (parent
, "info.product", "IDE device");
191 hal_device_property_set_string (parent
, "info.subsystem", "ide");
192 hal_device_property_set_int (parent
, "ide.host", 0); /* XXX */
193 hal_device_property_set_int (parent
, "ide.channel", 0);
195 devinfo_add_enqueue (d
, devfs_path
, &devinfo_ide_handler
);
197 return (devinfo_ide_storage_add (d
, node
, devfs_path
));
201 devinfo_ide_storage_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
)
207 char udi
[HAL_PATH_MAX
];
209 if ((driver_name
= di_driver_name (node
)) == NULL
) {
213 d
= hal_device_new ();
215 devinfo_set_default_properties (d
, parent
, node
, devfs_path
);
216 hal_device_property_set_string (d
, "info.category", "storage");
218 hal_util_compute_udi (hald_get_gdl (), udi
, sizeof (udi
),
219 "%s/%s%d", hal_device_get_udi (parent
), driver_name
, di_instance (node
));
220 hal_device_set_udi (d
, udi
);
221 hal_device_property_set_string (d
, "info.udi", udi
);
222 PROP_STR(d
, node
, s
, "devid", "info.product");
224 hal_device_add_capability (d
, "storage");
225 hal_device_property_set_string (d
, "storage.bus", "ide");
226 hal_device_property_set_int (d
, "storage.lun", 0);
227 hal_device_property_set_string (d
, "storage.drive_type", "disk");
229 PROP_BOOL(d
, node
, i
, "hotpluggable", "storage.hotpluggable");
230 PROP_BOOL(d
, node
, i
, "removable-media", "storage.removable");
232 hal_device_property_set_bool (d
, "storage.media_check_enabled", FALSE
);
235 hal_device_property_set_bool (d
, "storage.requires_eject", FALSE
);
237 hal_device_add_capability (d
, "block");
239 devinfo_storage_minors (d
, node
, (char *)devfs_path
, FALSE
);
247 devinfo_scsi_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
, char *device_type
)
252 char udi
[HAL_PATH_MAX
];
254 driver_name
= di_driver_name (node
);
255 if ((driver_name
== NULL
) || (strcmp (driver_name
, "sd") != 0)) {
259 d
= hal_device_new ();
261 devinfo_set_default_properties (d
, parent
, node
, devfs_path
);
262 hal_device_property_set_string (d
, "info.subsystem", "scsi");
264 hal_util_compute_udi (hald_get_gdl (), udi
, sizeof (udi
),
265 "%s/%s%d", hal_device_get_udi (parent
), di_node_name(node
), di_instance (node
));
266 hal_device_set_udi (d
, udi
);
267 hal_device_property_set_string (d
, "info.udi", udi
);
269 hal_device_property_set_int (d
, "scsi.host",
270 hal_device_property_get_int (parent
, "scsi_host.host"));
271 hal_device_property_set_int (d
, "scsi.bus", 0);
272 PROP_INT(d
, node
, i
, "target", "scsi.target");
273 PROP_INT(d
, node
, i
, "lun", "scsi.lun");
274 hal_device_property_set_string (d
, "info.product", "SCSI Device");
276 devinfo_add_enqueue (d
, devfs_path
, &devinfo_scsi_handler
);
278 return (devinfo_scsi_storage_add (d
, node
, devfs_path
));
282 devinfo_scsi_storage_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
)
287 char udi
[HAL_PATH_MAX
];
289 d
= hal_device_new ();
291 devinfo_set_default_properties (d
, parent
, node
, devfs_path
);
292 hal_device_property_set_string (d
, "info.category", "storage");
294 hal_util_compute_udi (hald_get_gdl (), udi
, sizeof (udi
),
295 "%s/sd%d", hal_device_get_udi (parent
), di_instance (node
));
296 hal_device_set_udi (d
, udi
);
297 hal_device_property_set_string (d
, "info.udi", udi
);
298 PROP_STR(d
, node
, s
, "inquiry-product-id", "info.product");
300 hal_device_add_capability (d
, "storage");
302 hal_device_property_set_int (d
, "storage.lun",
303 hal_device_property_get_int (parent
, "scsi.lun"));
304 PROP_BOOL(d
, node
, i
, "hotpluggable", "storage.hotpluggable");
305 PROP_BOOL(d
, node
, i
, "removable-media", "storage.removable");
306 hal_device_property_set_bool (d
, "storage.requires_eject", FALSE
);
309 * We have to enable polling not only for drives with removable media,
310 * but also for hotpluggable devices, because when a disk is
311 * unplugged while busy/mounted, there is not sysevent generated.
312 * Instead, the HBA driver (scsa2usb, scsa1394) will notify sd driver
313 * and the latter will report DKIO_DEV_GONE via DKIOCSTATE ioctl.
314 * So we have to enable media check so that hald-addon-storage notices
315 * the "device gone" condition and unmounts all associated volumes.
317 hal_device_property_set_bool (d
, "storage.media_check_enabled",
318 ((di_prop_lookup_ints(DDI_DEV_T_ANY
, node
, "removable-media", &i
) >= 0) ||
319 (di_prop_lookup_ints(DDI_DEV_T_ANY
, node
, "hotpluggable", &i
) >= 0)));
321 if (di_prop_lookup_ints(DDI_DEV_T_ANY
, node
, "inquiry-device-type",
323 s
= devinfo_scsi_dtype2str (*i
);
324 hal_device_property_set_string (d
, "storage.drive_type", s
);
326 if (strcmp (s
, "cdrom") == 0) {
327 hal_device_add_capability (d
, "storage.cdrom");
328 hal_device_property_set_bool (d
, "storage.no_partitions_hint", TRUE
);
329 hal_device_property_set_bool (d
, "storage.requires_eject", TRUE
);
333 hal_device_add_capability (d
, "block");
335 devinfo_storage_minors (d
, node
, devfs_path
, FALSE
);
341 devinfo_scsi_dtype2str(int dtype
)
343 char *dtype2str
[] = {
344 "disk" , /* DTYPE_DIRECT 0x00 */
345 "tape" , /* DTYPE_SEQUENTIAL 0x01 */
346 "printer", /* DTYPE_PRINTER 0x02 */
347 "processor", /* DTYPE_PROCESSOR 0x03 */
348 "worm" , /* DTYPE_WORM 0x04 */
349 "cdrom" , /* DTYPE_RODIRECT 0x05 */
350 "scanner", /* DTYPE_SCANNER 0x06 */
351 "cdrom" , /* DTYPE_OPTICAL 0x07 */
352 "changer", /* DTYPE_CHANGER 0x08 */
353 "comm" , /* DTYPE_COMM 0x09 */
354 "scsi" , /* DTYPE_??? 0x0A */
355 "scsi" , /* DTYPE_??? 0x0B */
356 "array_ctrl", /* DTYPE_ARRAY_CTRL 0x0C */
357 "esi" , /* DTYPE_ESI 0x0D */
358 "disk" /* DTYPE_RBC 0x0E */
361 if (dtype
< NELEM(dtype2str
)) {
362 return (dtype2str
[dtype
]);
372 devinfo_blkdev_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
, char *device_type
)
377 char udi
[HAL_PATH_MAX
];
379 driver_name
= di_driver_name (node
);
380 if ((driver_name
== NULL
) || (strcmp (driver_name
, "blkdev") != 0)) {
384 d
= hal_device_new ();
386 devinfo_set_default_properties (d
, parent
, node
, devfs_path
);
387 hal_device_property_set_string (d
, "info.subsystem", "pseudo");
389 hal_util_compute_udi (hald_get_gdl (), udi
, sizeof (udi
),
390 "%s/%s%d", hal_device_get_udi (parent
), di_node_name(node
), di_instance (node
));
391 hal_device_set_udi (d
, udi
);
392 hal_device_property_set_string (d
, "info.udi", udi
);
393 hal_device_property_set_string (d
, "info.product", "Block Device");
395 devinfo_add_enqueue (d
, devfs_path
, &devinfo_blkdev_handler
);
397 return (devinfo_blkdev_storage_add (d
, node
, devfs_path
));
401 devinfo_blkdev_storage_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
)
407 char udi
[HAL_PATH_MAX
];
409 d
= hal_device_new ();
411 devinfo_set_default_properties (d
, parent
, node
, devfs_path
);
412 hal_device_property_set_string (d
, "info.category", "storage");
414 hal_util_compute_udi (hald_get_gdl (), udi
, sizeof (udi
),
415 "%s/blkdev%d", hal_device_get_udi (parent
), di_instance (node
));
416 hal_device_set_udi (d
, udi
);
417 hal_device_property_set_string (d
, "info.udi", udi
);
419 hal_device_add_capability (d
, "storage");
421 hal_device_property_set_int (d
, "storage.lun", 0);
423 PROP_BOOL(d
, node
, i
, "hotpluggable", "storage.hotpluggable");
424 PROP_BOOL(d
, node
, i
, "removable-media", "storage.removable");
426 hal_device_property_set_bool (d
, "storage.requires_eject", FALSE
);
427 hal_device_property_set_bool (d
, "storage.media_check_enabled", TRUE
);
428 hal_device_property_set_string (d
, "storage.drive_type", "disk");
430 hal_device_add_capability (d
, "block");
432 devinfo_storage_minors (d
, node
, devfs_path
, FALSE
);
440 devinfo_floppy_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
, char *device_type
)
444 char udi
[HAL_PATH_MAX
];
445 di_devlink_handle_t devlink_hdl
;
450 char *minor_path
= NULL
;
451 char *devlink
= NULL
;
453 driver_name
= di_driver_name (node
);
454 if ((driver_name
== NULL
) || (strcmp (driver_name
, "fd") != 0)) {
459 * The only minor node we're interested in is /dev/diskette*
461 major
= di_driver_major(node
);
462 if ((devlink_hdl
= di_devlink_init(NULL
, 0)) == NULL
) {
465 minor
= DI_MINOR_NIL
;
466 while ((minor
= di_minor_next(node
, minor
)) != DI_MINOR_NIL
) {
467 dev
= di_minor_devt(minor
);
468 if ((major
!= major(dev
)) ||
469 (di_minor_type(minor
) != DDM_MINOR
) ||
470 (di_minor_spectype(minor
) != S_IFBLK
) ||
471 ((minor_path
= di_devfs_minor_path(minor
)) == NULL
)) {
474 if ((devlink
= get_devlink(devlink_hdl
, "diskette.+" , minor_path
)) != NULL
) {
477 di_devfs_path_free (minor_path
);
482 di_devlink_fini (&devlink_hdl
);
484 if ((devlink
== NULL
) || (minor_path
== NULL
)) {
485 HAL_INFO (("floppy devlink not found %s", devfs_path
));
489 d
= hal_device_new ();
491 devinfo_set_default_properties (d
, parent
, node
, devfs_path
);
492 hal_device_property_set_string (d
, "info.category", "storage");
493 hal_device_add_capability (d
, "storage");
494 hal_device_property_set_string (d
, "storage.bus", "platform");
495 hal_device_property_set_bool (d
, "storage.hotpluggable", FALSE
);
496 hal_device_property_set_bool (d
, "storage.removable", TRUE
);
497 hal_device_property_set_bool (d
, "storage.requires_eject", TRUE
);
498 hal_device_property_set_bool (d
, "storage.media_check_enabled", FALSE
);
499 hal_device_property_set_string (d
, "storage.drive_type", "floppy");
501 hal_device_add_capability (d
, "block");
502 hal_device_property_set_bool (d
, "block.is_volume", FALSE
);
503 hal_device_property_set_int (d
, "block.major", major(dev
));
504 hal_device_property_set_int (d
, "block.minor", minor(dev
));
505 hal_device_property_set_string (d
, "block.device", devlink
);
506 raw
= dsk_to_rdsk (devlink
);
507 hal_device_property_set_string (d
, "block.solaris.raw_device", raw
);
510 devinfo_add_enqueue (d
, devfs_path
, &devinfo_storage_handler
);
512 /* trigger initial probe-volume */
513 devinfo_floppy_add_volume(d
, node
);
516 di_devfs_path_free (minor_path
);
523 devinfo_floppy_add_volume(HalDevice
*parent
, di_node_t node
)
529 struct devinfo_storage_minor
*m
;
531 devfs_path
= (char *)hal_device_property_get_string (parent
, "solaris.devfs_path");
532 devlink
= (char *)hal_device_property_get_string (parent
, "block.device");
533 major
= hal_device_property_get_int (parent
, "block.major");
534 minor
= hal_device_property_get_int (parent
, "block.minor");
535 dev
= makedev (major
, minor
);
537 m
= devinfo_storage_new_minor (devfs_path
, WHOLE_DISK
, devlink
, dev
, -1);
538 devinfo_volume_add (parent
, node
, m
);
539 devinfo_storage_free_minor (m
);
543 * After reprobing storage, reprobe its volumes.
546 devinfo_floppy_rescan_probing_done (HalDevice
*d
, guint32 exit_type
, gint return_code
,
547 char **error
, gpointer userdata1
, gpointer userdata2
)
549 void *end_token
= (void *) userdata1
;
550 const char *devfs_path
;
554 if (!hal_device_property_get_bool (d
, "storage.removable.media_available")) {
555 HAL_INFO (("no floppy media", hal_device_get_udi (d
)));
557 /* remove child (can only be single volume) */
558 if (((v
= hal_device_store_match_key_value_string (hald_get_gdl(),
559 "info.parent", hal_device_get_udi (d
))) != NULL
) &&
560 ((devfs_path
= hal_device_property_get_string (v
,
561 "solaris.devfs_path")) != NULL
)) {
562 devinfo_remove_enqueue ((char *)devfs_path
, NULL
);
565 HAL_INFO (("floppy media found", hal_device_get_udi (d
)));
567 if ((devfs_path
= hal_device_property_get_string(d
, "solaris.devfs_path")) == NULL
) {
568 HAL_INFO (("no devfs_path", hal_device_get_udi (d
)));
569 hotplug_event_process_queue ();
572 if ((node
= di_init (devfs_path
, DINFOCPYALL
)) == DI_NODE_NIL
) {
573 HAL_INFO (("di_init %s failed %d", devfs_path
, errno
));
574 hotplug_event_process_queue ();
578 devinfo_floppy_add_volume (d
, node
);
583 hotplug_event_process_queue ();
589 devinfo_lofi_add(HalDevice
*parent
, di_node_t node
, char *devfs_path
, char *device_type
)
591 return (devinfo_lofi_add_major(parent
,node
, devfs_path
, device_type
, FALSE
, NULL
));
595 devinfo_lofi_add_major(HalDevice
*parent
, di_node_t node
, char *devfs_path
, char *device_type
,
596 gboolean rescan
, HalDevice
*lofi_d
)
600 char udi
[HAL_PATH_MAX
];
601 di_devlink_handle_t devlink_hdl
;
605 char *minor_path
= NULL
;
606 char *devlink
= NULL
;
608 driver_name
= di_driver_name (node
);
609 if ((driver_name
== NULL
) || (strcmp (driver_name
, "lofi") != 0)) {
614 d
= hal_device_new ();
616 devinfo_set_default_properties (d
, parent
, node
, devfs_path
);
617 hal_device_property_set_string (d
, "info.subsystem", "pseudo");
619 hal_util_compute_udi (hald_get_gdl (), udi
, sizeof (udi
),
620 "%s/%s%d", hal_device_get_udi (parent
), di_node_name(node
), di_instance (node
));
621 hal_device_set_udi (d
, udi
);
622 hal_device_property_set_string (d
, "info.udi", udi
);
624 devinfo_add_enqueue (d
, devfs_path
, &devinfo_lofi_handler
);
630 * Unlike normal storage, as in devinfo_storage_minors(), where
631 * sd instance -> HAL storage, sd minor node -> HAL volume,
632 * lofi always has one instance, lofi minor -> HAL storage.
633 * lofi storage never has slices, but it can have
634 * embedded pcfs partitions that fstyp would recognize
636 major
= di_driver_major(node
);
637 if ((devlink_hdl
= di_devlink_init(NULL
, 0)) == NULL
) {
640 minor
= DI_MINOR_NIL
;
641 while ((minor
= di_minor_next(node
, minor
)) != DI_MINOR_NIL
) {
642 dev
= di_minor_devt(minor
);
643 if ((major
!= major(dev
)) ||
644 (di_minor_type(minor
) != DDM_MINOR
) ||
645 (di_minor_spectype(minor
) != S_IFBLK
) ||
646 ((minor_path
= di_devfs_minor_path(minor
)) == NULL
)) {
649 if ((devlink
= get_devlink(devlink_hdl
, NULL
, minor_path
)) == NULL
) {
650 di_devfs_path_free (minor_path
);
655 (hal_device_store_match_key_value_string (hald_get_gdl (),
656 "solaris.devfs_path", minor_path
) == NULL
)) {
657 devinfo_lofi_add_minor(d
, node
, minor_path
, devlink
, dev
);
660 di_devfs_path_free (minor_path
);
663 di_devlink_fini (&devlink_hdl
);
669 devinfo_lofi_add_minor(HalDevice
*parent
, di_node_t node
, char *minor_path
, char *devlink
, dev_t dev
)
675 struct devinfo_storage_minor
*m
;
679 d
= hal_device_new ();
681 devinfo_set_default_properties (d
, parent
, node
, minor_path
);
682 hal_device_property_set_string (d
, "info.category", "storage");
683 hal_device_add_capability (d
, "storage");
684 hal_device_property_set_string (d
, "storage.bus", "lofi");
685 hal_device_property_set_bool (d
, "storage.hotpluggable", TRUE
);
686 hal_device_property_set_bool (d
, "storage.removable", FALSE
);
687 hal_device_property_set_bool (d
, "storage.requires_eject", FALSE
);
688 hal_device_property_set_string (d
, "storage.drive_type", "disk");
689 hal_device_add_capability (d
, "block");
690 hal_device_property_set_int (d
, "block.major", major(dev
));
691 hal_device_property_set_int (d
, "block.minor", minor(dev
));
692 hal_device_property_set_string (d
, "block.device", devlink
);
693 raw
= dsk_to_rdsk (devlink
);
694 hal_device_property_set_string (d
, "block.solaris.raw_device", raw
);
696 hal_device_property_set_bool (d
, "block.is_volume", FALSE
);
698 devinfo_add_enqueue (d
, minor_path
, &devinfo_storage_handler
);
700 /* add volumes: one on main device and a few pcfs candidates */
701 m
= devinfo_storage_new_minor(minor_path
, WHOLE_DISK
, devlink
, dev
, -1);
702 devinfo_volume_add (d
, node
, m
);
703 devinfo_storage_free_minor (m
);
705 doslink
= (char *)calloc (1, strlen (devlink
) + sizeof (":NNN") + 1);
706 if (doslink
!= NULL
) {
707 for (i
= 1; i
< 16; i
++) {
708 snprintf(dospath
, sizeof (dospath
), WHOLE_DISK
":%d", i
);
709 sprintf(doslink
, "%s:%d", devlink
, i
);
710 m
= devinfo_storage_new_minor(minor_path
, dospath
, doslink
, dev
, i
);
711 devinfo_volume_add (d
, node
, m
);
712 devinfo_storage_free_minor (m
);
719 devinfo_lofi_remove_minor(char *parent_devfs_path
, char *name
)
724 const char *devfs_path
;
726 devices
= hal_device_store_match_multiple_key_value_string (hald_get_gdl(),
727 "block.solaris.raw_device", name
);
728 for (i
= devices
; i
!= NULL
; i
= g_slist_next (i
)) {
729 if (hal_device_has_capability (HAL_DEVICE (i
->data
), "storage")) {
730 d
= HAL_DEVICE (i
->data
);
734 g_slist_free (devices
);
737 HAL_INFO (("device not found %s", name
));
741 if ((devfs_path
= hal_device_property_get_string (d
,
742 "solaris.devfs_path")) == NULL
) {
743 HAL_INFO (("devfs_path not found %s", hal_device_get_udi (d
)));
748 devinfo_remove_branch ((char *)devfs_path
, d
);
755 devinfo_storage_free_minor(struct devinfo_storage_minor
*m
)
765 static struct devinfo_storage_minor
*
766 devinfo_storage_new_minor(char *maindev_path
, char *slice
, char *devlink
, dev_t dev
, int dosnum
)
768 struct devinfo_storage_minor
*m
;
772 m
= (struct devinfo_storage_minor
*)calloc (sizeof (struct devinfo_storage_minor
), 1);
775 * For volume's devfs_path we'll use minor_path/slice instead of
776 * minor_path which we use for parent storage device.
778 pathlen
= strlen (maindev_path
) + strlen (slice
) + 2;
779 devpath
= (char *)calloc (1, pathlen
);
780 snprintf(devpath
, pathlen
, "%s/%s", maindev_path
, slice
);
782 m
->devpath
= devpath
;
783 m
->devlink
= strdup (devlink
);
784 m
->slice
= strdup (slice
);
787 if ((m
->devpath
== NULL
) || (m
->devlink
== NULL
)) {
788 devinfo_storage_free_minor (m
);
796 * Storage minor nodes are potential "volume" objects.
797 * This function also completes building the parent object (main storage device).
800 devinfo_storage_minors(HalDevice
*parent
, di_node_t node
, gchar
*devfs_path
, gboolean rescan
)
802 di_devlink_handle_t devlink_hdl
;
804 const char *whole_disk
;
808 char *minor_path
= NULL
;
809 char *maindev_path
= NULL
;
810 char *devpath
, *devlink
;
818 boolean_t maindev_is_d0
;
821 struct devinfo_storage_minor
*m
;
822 struct devinfo_storage_minor
*maindev
= NULL
;
824 /* for cdroms whole disk is always s2 */
825 is_cdrom
= hal_device_has_capability (parent
, "storage.cdrom");
826 whole_disk
= is_cdrom
? "s2" : WHOLE_DISK
;
828 major
= di_driver_major(node
);
830 /* the "whole disk" p0/s2/d0 node must come first in the hotplug queue
831 * so we put other minor nodes on the local queue and move to the
832 * hotplug queue up in the end
834 if ((mq
= g_queue_new()) == NULL
) {
837 if ((devlink_hdl
= di_devlink_init(NULL
, 0)) == NULL
) {
841 minor
= DI_MINOR_NIL
;
842 while ((minor
= di_minor_next(node
, minor
)) != DI_MINOR_NIL
) {
843 dev
= di_minor_devt(minor
);
844 if ((major
!= major(dev
)) ||
845 (di_minor_type(minor
) != DDM_MINOR
) ||
846 (di_minor_spectype(minor
) != S_IFBLK
) ||
847 ((minor_path
= di_devfs_minor_path(minor
)) == NULL
)) {
850 if ((devlink
= get_devlink(devlink_hdl
, NULL
, minor_path
)) == NULL
) {
851 di_devfs_path_free (minor_path
);
855 slice
= devinfo_volume_get_slice_name (devlink
);
856 if (strlen (slice
) < 2) {
858 di_devfs_path_free (minor_path
);
862 /* ignore p1..N - we'll use p0:N instead */
863 if ((strlen (slice
) > 1) && (slice
[0] == 'p') && isdigit(slice
[1]) &&
864 ((atol(&slice
[1])) > 0)) {
866 di_devfs_path_free (minor_path
);
870 m
= devinfo_storage_new_minor(minor_path
, slice
, devlink
, dev
, -1);
873 di_devfs_path_free (minor_path
);
877 /* main device is either s2/p0 or d0, the latter taking precedence */
878 if ((strcmp (slice
, "d0") == 0) ||
879 (((strcmp (slice
, whole_disk
) == 0) && (maindev
== NULL
)))) {
880 if (maindev_path
!= NULL
) {
881 di_devfs_path_free (maindev_path
);
883 maindev_path
= minor_path
;
885 g_queue_push_head (mq
, maindev
);
887 di_devfs_path_free (minor_path
);
888 g_queue_push_tail (mq
, m
);
893 di_devlink_fini (&devlink_hdl
);
895 if (maindev
== NULL
) {
896 /* shouldn't typically happen */
897 while (!g_queue_is_empty (mq
)) {
898 devinfo_storage_free_minor (g_queue_pop_head (mq
));
903 /* first enqueue main storage device */
905 hal_device_property_set_int (parent
, "block.major", major
);
906 hal_device_property_set_int (parent
, "block.minor", minor(maindev
->dev
));
907 hal_device_property_set_string (parent
, "block.device", maindev
->devlink
);
908 raw
= dsk_to_rdsk (maindev
->devlink
);
909 hal_device_property_set_string (parent
, "block.solaris.raw_device", raw
);
911 hal_device_property_set_bool (parent
, "block.is_volume", FALSE
);
912 hal_device_property_set_string (parent
, "solaris.devfs_path", maindev_path
);
913 devinfo_add_enqueue (parent
, maindev_path
, &devinfo_storage_handler
);
916 /* add virtual dos volumes to enable pcfs probing */
918 doslink_len
= strlen (maindev
->devlink
) + sizeof (":NNN") + 1;
919 if ((doslink
= (char *)calloc (1, doslink_len
)) != NULL
) {
920 for (i
= 1; i
< 16; i
++) {
921 snprintf(dospath
, sizeof (dospath
), "%s:%d", maindev
->slice
, i
);
922 snprintf(doslink
, doslink_len
, "%s:%d", maindev
->devlink
, i
);
923 m
= devinfo_storage_new_minor(maindev_path
, dospath
, doslink
, maindev
->dev
, i
);
924 g_queue_push_tail (mq
, m
);
930 maindev_is_d0
= (strcmp (maindev
->slice
, "d0") == 0);
932 /* enqueue all volumes */
933 while (!g_queue_is_empty (mq
)) {
934 m
= g_queue_pop_head (mq
);
936 /* if main device is d0, we'll throw away s2/p0 */
937 if (maindev_is_d0
&& (strcmp (m
->slice
, whole_disk
) == 0)) {
938 devinfo_storage_free_minor (m
);
941 /* don't do p0 on cdrom */
942 if (is_cdrom
&& (strcmp (m
->slice
, "p0") == 0)) {
943 devinfo_storage_free_minor (m
);
947 /* in rescan mode, don't reprobe existing volumes */
948 /* XXX detect volume removal? */
949 volume
= hal_device_store_match_key_value_string (hald_get_gdl (),
950 "solaris.devfs_path", m
->devpath
);
951 if ((volume
== NULL
) || !hal_device_has_capability(volume
, "volume")) {
952 devinfo_volume_add (parent
, node
, m
);
954 HAL_INFO(("rescan volume exists %s", m
->devpath
));
957 devinfo_volume_add (parent
, node
, m
);
959 devinfo_storage_free_minor (m
);
962 if (maindev_path
!= NULL
) {
963 di_devfs_path_free (maindev_path
);
969 if (maindev_path
!= NULL
) {
970 di_devfs_path_free (maindev_path
);
973 devinfo_add_enqueue (parent
, devfs_path
, &devinfo_storage_handler
);
978 devinfo_volume_add(HalDevice
*parent
, di_node_t node
, devinfo_storage_minor_t
*m
)
982 char udi
[HAL_PATH_MAX
];
983 char *devfs_path
= m
->devpath
;
984 char *devlink
= m
->devlink
;
986 int dosnum
= m
->dosnum
;
987 char *slice
= m
->slice
;
989 HAL_INFO (("volume_add: devfs_path=%s devlink=%s", devfs_path
, devlink
));
990 d
= hal_device_new ();
992 devinfo_set_default_properties (d
, parent
, node
, devfs_path
);
993 hal_device_property_set_string (d
, "info.category", "volume");
995 hal_util_compute_udi (hald_get_gdl (), udi
, sizeof (udi
),
996 "%s/%s", hal_device_get_udi (parent
), slice
);
997 hal_device_set_udi (d
, udi
);
998 hal_device_property_set_string (d
, "info.udi", udi
);
999 hal_device_property_set_string (d
, "info.product", slice
);
1001 hal_device_add_capability (d
, "volume");
1002 hal_device_add_capability (d
, "block");
1003 hal_device_property_set_int (d
, "block.major", major (dev
));
1004 hal_device_property_set_int (d
, "block.minor", minor (dev
));
1005 hal_device_property_set_string (d
, "block.device", devlink
);
1006 raw
= dsk_to_rdsk (devlink
);
1007 hal_device_property_set_string (d
, "block.solaris.raw_device", raw
);
1009 hal_device_property_set_string (d
, "block.solaris.slice", slice
);
1010 hal_device_property_set_bool (d
, "block.is_volume", TRUE
); /* XXX */
1012 hal_device_property_set_string (d
, "block.storage_device", hal_device_get_udi (parent
));
1014 /* set volume defaults */
1015 hal_device_property_set_string (d
, "volume.fstype", "");
1016 hal_device_property_set_string (d
, "volume.fsusage", "");
1017 hal_device_property_set_string (d
, "volume.fsversion", "");
1018 hal_device_property_set_string (d
, "volume.uuid", "");
1019 hal_device_property_set_string (d
, "volume.label", "");
1020 hal_device_property_set_string (d
, "volume.mount_point", "");
1021 hal_device_property_set_bool (d
, "volume.is_mounted", FALSE
);
1022 if (strcmp (hal_device_property_get_string (parent
, "storage.drive_type"), "cdrom") == 0) {
1023 hal_device_property_set_bool (d
, "volume.is_disc", TRUE
);
1024 hal_device_add_capability (d
, "volume.disc");
1026 hal_device_property_set_bool (d
, "volume.is_disc", FALSE
);
1030 hal_device_property_set_bool (d
, "volume.is_partition", TRUE
);
1031 hal_device_property_set_int (d
, "volume.partition.number", dosnum
);
1033 hal_device_property_set_bool (d
, "volume.is_partition", FALSE
);
1036 /* prober may override these */
1037 hal_device_property_set_int (d
, "volume.block_size", 512);
1039 devinfo_add_enqueue (d
, devfs_path
, &devinfo_volume_handler
);
1045 devinfo_volume_preprobing_done (HalDevice
*d
, gpointer userdata1
, gpointer userdata2
)
1047 void *end_token
= (void *) userdata1
;
1050 const char *storage_udi
;
1051 HalDevice
*storage_d
;
1055 if (hal_device_property_get_bool (d
, "info.ignore")) {
1056 HAL_INFO (("Preprobing merged info.ignore==TRUE %s", hal_device_get_udi (d
)));
1061 * Optimizations: only probe if there's a chance to find something
1063 block_device
= (char *)hal_device_property_get_string (d
, "block.device");
1064 storage_udi
= hal_device_property_get_string (d
, "block.storage_device");
1065 slice
= hal_device_property_get_string(d
, "block.solaris.slice");
1066 if ((block_device
== NULL
) || (storage_udi
== NULL
) ||
1067 (slice
== NULL
) || (strlen (slice
) < 2)) {
1068 HAL_INFO (("Malformed volume properties %s", hal_device_get_udi (d
)));
1071 storage_d
= hal_device_store_match_key_value_string (hald_get_gdl (), "info.udi", storage_udi
);
1072 if (storage_d
== NULL
) {
1073 HAL_INFO (("Storage device not found %s", hal_device_get_udi (d
)));
1077 whole_disk
= hal_device_has_capability (storage_d
,
1078 "storage.cdrom") ? "s2" : WHOLE_DISK
;
1080 if (is_dos_path(block_device
, &dos_num
)) {
1081 /* don't probe more dos volumes than probe-storage found */
1082 if ((hal_device_property_get_bool (storage_d
, "storage.no_partitions_hint") ||
1083 (dos_num
> hal_device_property_get_int (storage_d
, "storage.solaris.num_dos_partitions")))) {
1084 HAL_INFO (("%d > %d %s", dos_num
, hal_device_property_get_int (storage_d
,
1085 "storage.solaris.num_dos_partitions"), hal_device_get_udi (storage_d
)));
1089 /* if no VTOC slices found, don't probe slices except s2 */
1090 if ((slice
[0] == 's') && (isdigit(slice
[1])) && ((strcmp (slice
, whole_disk
)) != 0) &&
1091 !hal_device_property_get_bool (storage_d
, "storage.solaris.vtoc_slices")) {
1092 HAL_INFO (("Not probing slice %s", hal_device_get_udi (d
)));
1097 HAL_INFO(("Probing udi=%s", hal_device_get_udi (d
)));
1099 "hald-probe-volume", NULL
,
1100 DEVINFO_PROBE_VOLUME_TIMEOUT
,
1101 devinfo_callouts_probing_done
,
1102 (gpointer
) end_token
, userdata2
);
1107 hal_device_store_remove (hald_get_tdl (), d
);
1109 hotplug_event_end (end_token
);
1113 devinfo_volume_hotplug_begin_add (HalDevice
*d
, HalDevice
*parent
, DevinfoDevHandler
*handler
, void *end_token
)
1115 HAL_INFO(("Preprobing volume udi=%s", hal_device_get_udi (d
)));
1117 if (parent
== NULL
) {
1118 HAL_INFO (("no parent %s", hal_device_get_udi (d
)));
1122 if (hal_device_property_get_bool (parent
, "info.ignore")) {
1123 HAL_INFO (("Ignoring volume: parent's info.ignore is TRUE"));
1127 /* add to TDL so preprobing callouts and prober can access it */
1128 hal_device_store_add (hald_get_tdl (), d
);
1130 /* Process preprobe fdi files */
1131 di_search_and_merge (d
, DEVICE_INFO_TYPE_PREPROBE
);
1133 /* Run preprobe callouts */
1134 hal_util_callout_device_preprobe (d
, devinfo_volume_preprobing_done
, end_token
, handler
);
1140 hotplug_event_end (end_token
);
1144 devinfo_storage_hotplug_begin_add (HalDevice
*d
, HalDevice
*parent
, DevinfoDevHandler
*handler
, void *end_token
)
1146 const char *drive_type
;
1149 HalDevice
*phys_d
= NULL
;
1150 const char *phys_bus
;
1152 static const char *busses
[] = { "usb", "ide", "scsi", "ieee1394",
1156 HAL_INFO (("Preprobing udi=%s", hal_device_get_udi (d
)));
1158 if (parent
== NULL
) {
1159 HAL_INFO (("no parent %s", hal_device_get_udi (d
)));
1164 * figure out physical device and bus, except for floppy
1166 drive_type
= hal_device_property_get_string (d
, "storage.drive_type");
1167 if ((drive_type
!= NULL
) && (strcmp (drive_type
, "floppy") == 0)) {
1173 bus
= hal_device_property_get_string (p_d
, "info.subsystem");
1175 for (i
= 0; i
< NELEM(busses
); i
++) {
1176 if (strcmp(bus
, busses
[i
]) == 0) {
1178 phys_bus
= busses
[i
];
1184 p_udi
= hal_device_property_get_string (p_d
, "info.parent");
1185 if (p_udi
== NULL
) {
1188 p_d
= hal_device_store_find (hald_get_gdl (), p_udi
);
1190 if (phys_d
== NULL
) {
1191 HAL_INFO (("no physical device %s", hal_device_get_udi (d
)));
1193 hal_device_property_set_string (d
, "storage.physical_device", hal_device_get_udi (phys_d
));
1194 hal_device_property_set_string (d
, "storage.bus", phys_bus
);
1199 /* add to TDL so preprobing callouts and prober can access it */
1200 hal_device_store_add (hald_get_tdl (), d
);
1202 /* Process preprobe fdi files */
1203 di_search_and_merge (d
, DEVICE_INFO_TYPE_PREPROBE
);
1205 /* Run preprobe callouts */
1206 hal_util_callout_device_preprobe (d
, devinfo_callouts_preprobing_done
, end_token
, handler
);
1212 hotplug_event_end (end_token
);
1216 devinfo_storage_probing_done (HalDevice
*d
, guint32 exit_type
, gint return_code
, char **error
, gpointer userdata1
, gpointer userdata2
)
1218 void *end_token
= (void *) userdata1
;
1220 HAL_INFO (("devinfo_storage_probing_done %s", hal_device_get_udi (d
)));
1222 /* Discard device if probing reports failure */
1223 if (exit_type
!= HALD_RUN_SUCCESS
|| return_code
!= 0) {
1224 HAL_INFO (("devinfo_storage_probing_done returning exit_type=%d return_code=%d", exit_type
, return_code
));
1225 hal_device_store_remove (hald_get_tdl (), d
);
1227 hotplug_event_end (end_token
);
1231 devinfo_storage_set_nicknames (d
);
1233 /* Merge properties from .fdi files */
1234 di_search_and_merge (d
, DEVICE_INFO_TYPE_INFORMATION
);
1235 di_search_and_merge (d
, DEVICE_INFO_TYPE_POLICY
);
1237 hal_util_callout_device_add (d
, devinfo_callouts_add_done
, end_token
, NULL
);
1241 devinfo_storage_get_prober (HalDevice
*d
, int *timeout
)
1243 *timeout
= DEVINFO_PROBE_STORAGE_TIMEOUT
;
1244 return "hald-probe-storage";
1248 devinfo_volume_get_prober (HalDevice
*d
, int *timeout
)
1250 *timeout
= DEVINFO_PROBE_VOLUME_TIMEOUT
;
1251 return "hald-probe-volume";
1255 * After reprobing storage, reprobe its volumes.
1258 devinfo_storage_rescan_probing_done (HalDevice
*d
, guint32 exit_type
, gint return_code
, char **error
, gpointer userdata1
, gpointer userdata2
)
1260 void *end_token
= (void *) userdata1
;
1261 const char *devfs_path_orig
= NULL
;
1262 char *devfs_path
= NULL
;
1266 HAL_INFO (("devinfo_storage_rescan_probing_done %s", hal_device_get_udi (d
)));
1268 devfs_path_orig
= hal_device_property_get_string (d
, "solaris.devfs_path");
1269 if (devfs_path_orig
== NULL
) {
1270 HAL_INFO (("device has no solaris.devfs_path"));
1271 hotplug_event_process_queue ();
1275 /* strip trailing minor part if any */
1276 if (strrchr(devfs_path_orig
, ':') != NULL
) {
1277 if ((devfs_path
= strdup (devfs_path_orig
)) != NULL
) {
1278 p
= strrchr(devfs_path
, ':');
1282 devfs_path
= (char *)devfs_path_orig
;
1285 if ((node
= di_init (devfs_path
, DINFOCPYALL
)) == DI_NODE_NIL
) {
1286 HAL_INFO (("di_init %s failed %d %s", devfs_path
, errno
, hal_device_get_udi (d
)));
1287 hotplug_event_process_queue ();
1290 devinfo_storage_minors (d
, node
, (char *)devfs_path
, TRUE
);
1294 if (devfs_path
!= devfs_path_orig
) {
1298 hotplug_event_process_queue ();
1302 * For removable media devices, check for "storage.removable.media_available".
1303 * For non-removable media devices, assume media is always there.
1305 * If media is gone, enqueue remove events for all children volumes.
1306 * If media is there, first reprobe storage, then probe for new volumes (but leave existing volumes alone).
1309 devinfo_storage_device_rescan (HalDevice
*d
)
1314 gchar
*v_devfs_path
;
1315 const char *drive_type
;
1317 gboolean media_available
;
1319 HAL_INFO (("devinfo_storage_device_rescan udi=%s", hal_device_get_udi (d
)));
1321 if (hal_device_property_get_bool (d
, "block.is_volume")) {
1322 HAL_INFO (("nothing to do for volume"));
1326 drive_type
= hal_device_property_get_string (d
, "storage.drive_type");
1327 is_floppy
= (drive_type
!= NULL
) && (strcmp (drive_type
, "floppy") == 0);
1329 media_available
= !hal_device_property_get_bool (d
, "storage.removable") ||
1330 hal_device_property_get_bool (d
, "storage.removable.media_available");
1332 if (!media_available
&& !is_floppy
) {
1333 HAL_INFO (("media gone %s", hal_device_get_udi (d
)));
1335 volumes
= hal_device_store_match_multiple_key_value_string (hald_get_gdl(),
1336 "block.storage_device", hal_device_get_udi (d
));
1337 for (i
= volumes
; i
!= NULL
; i
= g_slist_next (i
)) {
1338 v
= HAL_DEVICE (i
->data
);
1339 v_devfs_path
= (gchar
*)hal_device_property_get_string (v
, "solaris.devfs_path");
1340 HAL_INFO (("child volume %s", hal_device_get_udi (v
)));
1341 if ((v_devfs_path
!= NULL
) && hal_device_has_capability (v
, "volume")) {
1342 HAL_INFO (("removing volume %s", hal_device_get_udi (v
)));
1343 devinfo_remove_enqueue (v_devfs_path
, NULL
);
1345 HAL_INFO (("not a volume %s", hal_device_get_udi (v
)));
1348 g_slist_free (volumes
);
1350 hotplug_event_process_queue ();
1351 } else if (is_floppy
) {
1352 HAL_INFO (("rescanning floppy %s", hal_device_get_udi (d
)));
1355 "hald-probe-storage --only-check-for-media", NULL
,
1356 DEVINFO_PROBE_STORAGE_TIMEOUT
,
1357 devinfo_floppy_rescan_probing_done
,
1360 HAL_INFO (("media available %s", hal_device_get_udi (d
)));
1363 "hald-probe-storage --only-check-for-media", NULL
,
1364 DEVINFO_PROBE_STORAGE_TIMEOUT
,
1365 devinfo_storage_rescan_probing_done
,
1373 devinfo_volume_get_slice_name (char *devlink
)
1375 char *part
, *slice
, *disk
;
1379 if ((p
= strstr(devlink
, "/lofi/")) != 0) {
1380 return (p
+ sizeof ("/lofi/") - 1);
1383 part
= strrchr(devlink
, 'p');
1384 slice
= strrchr(devlink
, 's');
1385 disk
= strrchr(devlink
, 'd');
1387 if ((part
!= NULL
) && (part
> slice
) && (part
> disk
)) {
1389 } else if ((slice
!= NULL
) && (slice
> disk
)) {
1394 if ((s
!= NULL
) && isdigit(s
[1])) {
1402 is_dos_path(char *path
, int *partnum
)
1406 if ((p
= strrchr (path
, ':')) == NULL
) {
1409 return ((*partnum
= atoi(p
+ 1)) != 0);
1413 dos_to_dev(char *path
, char **devpath
, int *partnum
)
1417 if ((p
= strrchr (path
, ':')) == NULL
) {
1420 if ((*partnum
= atoi(p
+ 1)) == 0) {
1424 *devpath
= strdup(path
);
1426 return (*devpath
!= NULL
);
1430 devinfo_storage_cleanup_mountpoint_cb (HalDevice
*d
, guint32 exit_type
,
1431 gint return_code
, gchar
**error
,
1432 gpointer data1
, gpointer data2
)
1434 char *mount_point
= (char *) data1
;
1436 HAL_INFO (("Cleaned up mount point '%s'", mount_point
));
1437 g_free (mount_point
);
1442 devinfo_storage_mnttab_event (HalDevice
*hal_volume
)
1449 GSList
*volumes
= NULL
;
1452 dbus_bool_t is_partition
;
1454 int partition_number
;
1456 if (hal_volume
!= NULL
) {
1457 volumes
= g_slist_append (NULL
, hal_volume
);
1459 volumes
= hal_device_store_match_multiple_key_value_string (hald_get_gdl (), "info.category", "volume");
1461 if (volumes
== NULL
) {
1465 if ((fp
= fopen(MNTTAB
, "r")) == NULL
) {
1466 HAL_ERROR (("Open failed %s errno %d", MNTTAB
, errno
));
1470 while (getextmntent(fp
, &m
, 1) == 0) {
1471 for (v
= volumes
; v
!= NULL
; v
= g_slist_next (v
)) {
1472 d
= HAL_DEVICE (v
->data
);
1473 major
= hal_device_property_get_int (d
, "block.major");
1474 minor
= hal_device_property_get_int (d
, "block.minor");
1477 * special handling for pcfs, which encodes logical
1478 * drive number into the 6 upper bits of the minor
1480 is_partition
= hal_device_property_get_bool (d
, "volume.is_partition");
1481 partition_number
= hal_device_property_get_int (d
, "volume.partition.number");
1482 fstype
= hal_device_property_get_string (d
, "volume.fstype");
1484 if (is_partition
&& (partition_number
> 0) && (strcmp (fstype
, "pcfs") == 0)) {
1485 minor
|= partition_number
<< 12;
1488 if (m
.mnt_major
!= major
|| m
.mnt_minor
!= minor
) {
1492 /* this volume matches the mnttab entry */
1493 device_property_atomic_update_begin ();
1494 hal_device_property_set_bool (d
, "volume.is_mounted", TRUE
);
1495 hal_device_property_set_bool (d
, "volume.is_mounted_read_only",
1496 hasmntopt ((struct mnttab
*)&m
, "ro") ? TRUE
: FALSE
);
1497 hal_device_property_set_string (d
, "volume.mount_point", m
.mnt_mountp
);
1498 device_property_atomic_update_end ();
1500 HAL_INFO (("set %s to be mounted at %s",
1501 hal_device_get_udi (d
), m
.mnt_mountp
));
1502 volumes
= g_slist_delete_link (volumes
, v
);
1506 /* all remaining volumes are not mounted */
1507 for (v
= volumes
; v
!= NULL
; v
= g_slist_next (v
)) {
1508 d
= HAL_DEVICE (v
->data
);
1509 mount_point
= g_strdup (hal_device_property_get_string (d
, "volume.mount_point"));
1510 if (mount_point
== NULL
|| strlen (mount_point
) == 0) {
1511 g_free (mount_point
);
1515 device_property_atomic_update_begin ();
1516 hal_device_property_set_bool (d
, "volume.is_mounted", FALSE
);
1517 hal_device_property_set_bool (d
, "volume.is_mounted_read_only", FALSE
);
1518 hal_device_property_set_string (d
, "volume.mount_point", "");
1519 device_property_atomic_update_end ();
1521 HAL_INFO (("set %s to unmounted", hal_device_get_udi (d
)));
1523 /* cleanup if was mounted by us */
1524 if (hal_util_is_mounted_by_hald (mount_point
)) {
1525 char *cleanup_stdin
;
1528 HAL_INFO (("Cleaning up '%s'", mount_point
));
1530 extra_env
[0] = g_strdup_printf ("HALD_CLEANUP=%s", mount_point
);
1531 extra_env
[1] = NULL
;
1532 cleanup_stdin
= "\n";
1534 hald_runner_run_method (d
,
1535 "hal-storage-cleanup-mountpoint",
1537 cleanup_stdin
, TRUE
,
1539 devinfo_storage_cleanup_mountpoint_cb
,
1540 g_strdup (mount_point
), NULL
);
1542 g_free (extra_env
[0]);
1545 g_free (mount_point
);
1547 g_slist_free (volumes
);
1553 devinfo_volume_force_unmount_cb (HalDevice
*d
, guint32 exit_type
,
1554 gint return_code
, gchar
**error
,
1555 gpointer data1
, gpointer data2
)
1557 void *end_token
= (void *) data1
;
1559 HAL_INFO (("devinfo_volume_force_unmount_cb for udi='%s', exit_type=%d, return_code=%d", hal_device_get_udi (d
), exit_type
, return_code
));
1561 if (exit_type
== HALD_RUN_SUCCESS
&& error
!= NULL
&&
1562 error
[0] != NULL
&& error
[1] != NULL
) {
1563 char *exp_name
= NULL
;
1564 char *exp_detail
= NULL
;
1566 exp_name
= error
[0];
1567 if (error
[0] != NULL
) {
1568 exp_detail
= error
[1];
1570 HAL_INFO (("failed with '%s' '%s'", exp_name
, exp_detail
));
1573 hal_util_callout_device_remove (d
, devinfo_callouts_remove_done
, end_token
, NULL
);
1577 devinfo_volume_force_unmount (HalDevice
*d
, void *end_token
)
1579 const char *mount_point
;
1580 char *unmount_stdin
;
1582 extra_env
[0] = "HAL_METHOD_INVOKED_BY_UID=0";
1583 extra_env
[1] = NULL
;
1585 mount_point
= hal_device_property_get_string (d
, "volume.mount_point");
1587 if (mount_point
== NULL
|| strlen (mount_point
) == 0 || !hal_util_is_mounted_by_hald (mount_point
)) {
1588 hal_util_callout_device_remove (d
, devinfo_callouts_remove_done
, end_token
, NULL
);
1592 HAL_INFO (("devinfo_volume_force_unmount for udi='%s'", hal_device_get_udi (d
)));
1594 unmount_stdin
= "\n";
1596 hald_runner_run_method (d
,
1597 "hal-storage-unmount",
1599 unmount_stdin
, TRUE
,
1601 devinfo_volume_force_unmount_cb
,
1606 devinfo_volume_hotplug_begin_remove (HalDevice
*d
, char *devfs_path
, void *end_token
)
1608 if (hal_device_property_get_bool (d
, "volume.is_mounted")) {
1609 devinfo_volume_force_unmount (d
, end_token
);
1611 hal_util_callout_device_remove (d
, devinfo_callouts_remove_done
, end_token
, NULL
);
1622 static const char *legacy_media_str
[] = {
1634 devinfo_storage_get_legacy_media(HalDevice
*d
)
1636 const char *drive_type
;
1638 if (hal_device_has_capability (d
, "storage.cdrom")) {
1639 return (LEGACY_CDROM
);
1640 } else if (((drive_type
= hal_device_property_get_string (d
,
1641 "storage.drive_type")) != NULL
) && (strcmp (drive_type
, "floppy") == 0)) {
1642 return (LEGACY_FLOPPY
);
1643 } else if (hal_device_property_get_bool (d
, "storage.removable") ||
1644 hal_device_property_get_bool (d
, "storage.hotpluggable")) {
1645 return (LEGACY_RMDISK
);
1652 devinfo_storage_foreach_nick (HalDeviceStore
*store
, HalDevice
*d
, gpointer user_data
)
1654 struct enum_nick
*en
= (struct enum_nick
*) user_data
;
1655 const char *media_type
;
1658 media_type
= hal_device_property_get_string (d
, "storage.solaris.legacy.media_type");
1659 media_num
= hal_device_property_get_int (d
, "storage.solaris.legacy.media_num");
1660 if ((media_type
!= NULL
) && (strcmp (media_type
, en
->type
) == 0) &&
1662 en
->nums
= g_slist_prepend (en
->nums
, (gpointer
)media_num
);
1668 devinfo_storage_append_nickname (HalDevice
*d
, const char *media_type
, int media_num
)
1672 if (media_num
== 0) {
1673 hal_device_property_strlist_append (d
, "storage.solaris.nicknames", media_type
);
1675 snprintf(buf
, sizeof (buf
), "%s%d", media_type
, media_num
);
1676 hal_device_property_strlist_append (d
, "storage.solaris.nicknames", buf
);
1680 devinfo_storage_set_nicknames (HalDevice
*d
)
1683 const char *media_type
;
1686 struct enum_nick en
;
1689 if ((media
= devinfo_storage_get_legacy_media (d
)) < 0) {
1692 media_type
= legacy_media_str
[media
];
1694 /* enumerate all storage devices of this media type */
1695 en
.type
= media_type
;
1697 hal_device_store_foreach (hald_get_gdl (), devinfo_storage_foreach_nick
, &en
);
1699 /* find a free number */
1700 for (media_num
= 0; ; media_num
++) {
1701 for (i
= en
.nums
; i
!= NULL
; i
= g_slist_next (i
)) {
1702 if ((intptr_t)(i
->data
) == media_num
) {
1710 g_slist_free (en
.nums
);
1712 hal_device_property_set_string (d
, "storage.solaris.legacy.media_type", media_type
);
1713 hal_device_property_set_int (d
, "storage.solaris.legacy.media_num", media_num
);
1715 /* primary nickname, and also vold-style symdev */
1716 snprintf(buf
, sizeof (buf
), "%s%d", media_type
, media_num
);
1717 hal_device_property_set_string (d
, "storage.solaris.legacy.symdev", buf
);
1718 devinfo_storage_append_nickname(d
, media_type
, media_num
);
1720 /* additional nicknames */
1721 if (media
== LEGACY_CDROM
) {
1722 devinfo_storage_append_nickname(d
, "cd", media_num
);
1723 devinfo_storage_append_nickname(d
, "sr", media_num
);
1724 } else if (media
== LEGACY_FLOPPY
) {
1725 devinfo_storage_append_nickname(d
, "fd", media_num
);
1726 devinfo_storage_append_nickname(d
, "diskette", media_num
);
1727 devinfo_storage_append_nickname(d
, "rdiskette", media_num
);