1 /***************************************************************************
2 *
3 * devinfo_storage.c : storage devices
4 *
5 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
6 * Copyright 2013 Garrett D'Amore <garrett@damore.org>
7 *
8 * Licensed under the Academic Free License version 2.1
9 *
10 **************************************************************************/
11
12 #ifdef HAVE_CONFIG_H
13 # include <config.h>
14 #endif
15
16 #include <stdio.h>
17 #include <string.h>
18 #include <strings.h>
19 #include <ctype.h>
20 #include <libdevinfo.h>
21 #include <sys/types.h>
22 #include <sys/mkdev.h>
23 #include <sys/stat.h>
24 #include <sys/mntent.h>
25 #include <sys/mnttab.h>
26
27 #include "../osspec.h"
28 #include "../logger.h"
29 #include "../hald.h"
30 #include "../hald_dbus.h"
31 #include "../device_info.h"
32 #include "../util.h"
33 #include "../hald_runner.h"
34 #include "hotplug.h"
35 #include "devinfo.h"
36 #include "devinfo_misc.h"
37 #include "devinfo_storage.h"
38 #include "osspec_solaris.h"
39
40 #ifdef sparc
41 #define WHOLE_DISK "s2"
42 #else
43 #define WHOLE_DISK "p0"
44 #endif
45
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
49
50 typedef struct devinfo_storage_minor {
51 char *devpath;
52 char *devlink;
53 char *slice;
54 dev_t dev;
55 int dosnum; /* dos disk number or -1 */
56 } devinfo_storage_minor_t;
57
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);
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);
695 free (raw);
696 hal_device_property_set_bool (d, "block.is_volume", FALSE);
697
698 devinfo_add_enqueue (d, minor_path, &devinfo_storage_handler);
699
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);
704
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);
713 }
714 free (doslink);
715 }
716 }
717
718 void
719 devinfo_lofi_remove_minor(char *parent_devfs_path, char *name)
720 {
721 GSList *i;
722 GSList *devices;
723 HalDevice *d = NULL;
724 const char *devfs_path;
725
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")) {
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)) {
848 continue;
849 }
850 if ((devlink = get_devlink(devlink_hdl, NULL, minor_path)) == NULL) {
851 di_devfs_path_free (minor_path);
852 continue;
853 }
854
855 slice = devinfo_volume_get_slice_name (devlink);
856 if (strlen (slice) < 2) {
857 free (devlink);
858 di_devfs_path_free (minor_path);
859 continue;
860 }
861
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)) {
865 free (devlink);
866 di_devfs_path_free (minor_path);
867 continue;
868 }
869
870 m = devinfo_storage_new_minor(minor_path, slice, devlink, dev, -1);
871 if (m == NULL) {
872 free (devlink);
873 di_devfs_path_free (minor_path);
874 continue;
875 }
876
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);
882 }
883 maindev_path = minor_path;
884 maindev = m;
885 g_queue_push_head (mq, maindev);
886 } else {
887 di_devfs_path_free (minor_path);
888 g_queue_push_tail (mq, m);
889 }
898 devinfo_storage_free_minor (g_queue_pop_head (mq));
899 }
900 goto err;
901 }
902
903 /* first enqueue main storage device */
904 if (!rescan) {
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);
910 free (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);
914 }
915
916 /* add virtual dos volumes to enable pcfs probing */
917 if (!is_cdrom) {
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);
925 }
926 free (doslink);
927 }
928 }
929
930 maindev_is_d0 = (strcmp (maindev->slice, "d0") == 0);
931
932 /* enqueue all volumes */
933 while (!g_queue_is_empty (mq)) {
934 m = g_queue_pop_head (mq);
935
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);
939 continue;
940 }
941 /* don't do p0 on cdrom */
942 if (is_cdrom && (strcmp (m->slice, "p0") == 0)) {
1386
1387 if ((part != NULL) && (part > slice) && (part > disk)) {
1388 s = part;
1389 } else if ((slice != NULL) && (slice > disk)) {
1390 s = slice;
1391 } else {
1392 s = disk;
1393 }
1394 if ((s != NULL) && isdigit(s[1])) {
1395 return (s);
1396 } else {
1397 return ("");
1398 }
1399 }
1400
1401 static gboolean
1402 is_dos_path(char *path, int *partnum)
1403 {
1404 char *p;
1405
1406 if ((p = strrchr (path, ':')) == NULL) {
1407 return (FALSE);
1408 }
1409 return ((*partnum = atoi(p + 1)) != 0);
1410 }
1411
1412 static gboolean
1413 dos_to_dev(char *path, char **devpath, int *partnum)
1414 {
1415 char *p;
1416
1417 if ((p = strrchr (path, ':')) == NULL) {
1418 return (FALSE);
1419 }
1420 if ((*partnum = atoi(p + 1)) == 0) {
1421 return (FALSE);
1422 }
1423 p[0] = '\0';
1424 *devpath = strdup(path);
1425 p[0] = ':';
1426 return (*devpath != NULL);
1427 }
1428
1429 static void
1430 devinfo_storage_cleanup_mountpoint_cb (HalDevice *d, guint32 exit_type,
1431 gint return_code, gchar **error,
1432 gpointer data1, gpointer data2)
1433 {
1434 char *mount_point = (char *) data1;
1435
1436 HAL_INFO (("Cleaned up mount point '%s'", mount_point));
1437 g_free (mount_point);
1438 }
1439
1440
1441 void
1442 devinfo_storage_mnttab_event (HalDevice *hal_volume)
1443 {
1444 FILE *fp = NULL;
1445 struct extmnttab m;
|
1 /***************************************************************************
2 *
3 * devinfo_storage.c : storage devices
4 *
5 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
6 * Copyright 2013 Garrett D'Amore <garrett@damore.org>
7 * Copyright 2014 Andrew Stormont.
8 *
9 * Licensed under the Academic Free License version 2.1
10 *
11 **************************************************************************/
12
13 #ifdef HAVE_CONFIG_H
14 # include <config.h>
15 #endif
16
17 #include <stdio.h>
18 #include <string.h>
19 #include <strings.h>
20 #include <ctype.h>
21 #include <libdevinfo.h>
22 #include <sys/types.h>
23 #include <sys/mkdev.h>
24 #include <sys/stat.h>
25 #include <sys/mntent.h>
26 #include <sys/mnttab.h>
27
28 #include "../osspec.h"
29 #include "../logger.h"
30 #include "../hald.h"
31 #include "../hald_dbus.h"
32 #include "../device_info.h"
33 #include "../util.h"
34 #include "../hald_runner.h"
35 #include "hotplug.h"
36 #include "devinfo.h"
37 #include "devinfo_misc.h"
38 #include "devinfo_storage.h"
39 #include "osspec_solaris.h"
40
41 #ifdef sparc
42 #define WHOLE_DISK "s2"
43 #define DOS_SEPERATOR ":"
44 #define DOS_FORMAT "s2:%d"
45 #define DOS_TEMPLATE ":NN"
46 #else
47 #define WHOLE_DISK "p0"
48 #define DOS_SEPERATOR "p"
49 #define DOS_FORMAT "p%d"
50 #define DOS_TEMPLATE "pNN"
51 #endif
52
53 /* some devices,especially CDROMs, may take a while to be probed (values in ms) */
54 #define DEVINFO_PROBE_STORAGE_TIMEOUT 60000
55 #define DEVINFO_PROBE_VOLUME_TIMEOUT 60000
56
57 typedef struct devinfo_storage_minor {
58 char *devpath;
59 char *devlink;
60 char *slice;
61 dev_t dev;
62 int dosnum; /* dos disk number or -1 */
63 } devinfo_storage_minor_t;
64
65 HalDevice *devinfo_ide_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
66 static HalDevice *devinfo_ide_host_add(HalDevice *parent, di_node_t node, char *devfs_path);
67 static HalDevice *devinfo_ide_device_add(HalDevice *parent, di_node_t node, char *devfs_path);
68 static HalDevice *devinfo_ide_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
69 HalDevice *devinfo_scsi_add(HalDevice *parent, di_node_t node, char *devfs_path, char *device_type);
70 static HalDevice *devinfo_scsi_storage_add(HalDevice *parent, di_node_t node, char *devfs_path);
692 hal_device_property_set_bool (d, "storage.hotpluggable", TRUE);
693 hal_device_property_set_bool (d, "storage.removable", FALSE);
694 hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
695 hal_device_property_set_string (d, "storage.drive_type", "disk");
696 hal_device_add_capability (d, "block");
697 hal_device_property_set_int (d, "block.major", major(dev));
698 hal_device_property_set_int (d, "block.minor", minor(dev));
699 hal_device_property_set_string (d, "block.device", devlink);
700 raw = dsk_to_rdsk (devlink);
701 hal_device_property_set_string (d, "block.solaris.raw_device", raw);
702 free (raw);
703 hal_device_property_set_bool (d, "block.is_volume", FALSE);
704
705 devinfo_add_enqueue (d, minor_path, &devinfo_storage_handler);
706
707 /* add volumes: one on main device and a few pcfs candidates */
708 m = devinfo_storage_new_minor(minor_path, WHOLE_DISK, devlink, dev, -1);
709 devinfo_volume_add (d, node, m);
710 devinfo_storage_free_minor (m);
711
712 doslink = (char *)calloc (1, strlen (devlink) + sizeof (DOS_TEMPLATE) + 1);
713 if (doslink != NULL) {
714 for (i = 1; i < 16; i++) {
715 snprintf(dospath, sizeof (dospath), DOS_FORMAT, i);
716 sprintf(doslink, "%s"DOS_SEPERATOR"%d", devlink, i);
717 m = devinfo_storage_new_minor(minor_path, dospath, doslink, dev, i);
718 devinfo_volume_add (d, node, m);
719 devinfo_storage_free_minor (m);
720 }
721 free (doslink);
722 }
723 }
724
725 void
726 devinfo_lofi_remove_minor(char *parent_devfs_path, char *name)
727 {
728 GSList *i;
729 GSList *devices;
730 HalDevice *d = NULL;
731 const char *devfs_path;
732
733 devices = hal_device_store_match_multiple_key_value_string (hald_get_gdl(),
734 "block.solaris.raw_device", name);
735 for (i = devices; i != NULL; i = g_slist_next (i)) {
736 if (hal_device_has_capability (HAL_DEVICE (i->data), "storage")) {
849 while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
850 dev = di_minor_devt(minor);
851 if ((major != major(dev)) ||
852 (di_minor_type(minor) != DDM_MINOR) ||
853 (di_minor_spectype(minor) != S_IFBLK) ||
854 ((minor_path = di_devfs_minor_path(minor)) == NULL)) {
855 continue;
856 }
857 if ((devlink = get_devlink(devlink_hdl, NULL, minor_path)) == NULL) {
858 di_devfs_path_free (minor_path);
859 continue;
860 }
861
862 slice = devinfo_volume_get_slice_name (devlink);
863 if (strlen (slice) < 2) {
864 free (devlink);
865 di_devfs_path_free (minor_path);
866 continue;
867 }
868
869 m = devinfo_storage_new_minor(minor_path, slice, devlink, dev, -1);
870 if (m == NULL) {
871 free (devlink);
872 di_devfs_path_free (minor_path);
873 continue;
874 }
875
876 /* main device is either s2/p0 or d0, the latter taking precedence */
877 if ((strcmp (slice, "d0") == 0) ||
878 (((strcmp (slice, whole_disk) == 0) && (maindev == NULL)))) {
879 if (maindev_path != NULL) {
880 di_devfs_path_free (maindev_path);
881 }
882 maindev_path = minor_path;
883 maindev = m;
884 g_queue_push_head (mq, maindev);
885 } else {
886 di_devfs_path_free (minor_path);
887 g_queue_push_tail (mq, m);
888 }
897 devinfo_storage_free_minor (g_queue_pop_head (mq));
898 }
899 goto err;
900 }
901
902 /* first enqueue main storage device */
903 if (!rescan) {
904 hal_device_property_set_int (parent, "block.major", major);
905 hal_device_property_set_int (parent, "block.minor", minor(maindev->dev));
906 hal_device_property_set_string (parent, "block.device", maindev->devlink);
907 raw = dsk_to_rdsk (maindev->devlink);
908 hal_device_property_set_string (parent, "block.solaris.raw_device", raw);
909 free (raw);
910 hal_device_property_set_bool (parent, "block.is_volume", FALSE);
911 hal_device_property_set_string (parent, "solaris.devfs_path", maindev_path);
912 devinfo_add_enqueue (parent, maindev_path, &devinfo_storage_handler);
913 }
914
915 /* add virtual dos volumes to enable pcfs probing */
916 if (!is_cdrom) {
917 doslink_len = strlen (maindev->devlink) + sizeof (DOS_TEMPLATE) + 1;
918 if ((doslink = (char *)calloc (1, doslink_len)) != NULL) {
919 for (i = 1; i < 16; i++) {
920 snprintf(dospath, sizeof (dospath), "%s"DOS_SEPERATOR"%d", maindev->slice, i);
921 snprintf(doslink, doslink_len, "%s"DOS_SEPERATOR"%d", maindev->devlink, i);
922 m = devinfo_storage_new_minor(maindev_path, dospath, doslink, maindev->dev, i);
923 g_queue_push_tail (mq, m);
924 }
925 free (doslink);
926 }
927 }
928
929 maindev_is_d0 = (strcmp (maindev->slice, "d0") == 0);
930
931 /* enqueue all volumes */
932 while (!g_queue_is_empty (mq)) {
933 m = g_queue_pop_head (mq);
934
935 /* if main device is d0, we'll throw away s2/p0 */
936 if (maindev_is_d0 && (strcmp (m->slice, whole_disk) == 0)) {
937 devinfo_storage_free_minor (m);
938 continue;
939 }
940 /* don't do p0 on cdrom */
941 if (is_cdrom && (strcmp (m->slice, "p0") == 0)) {
1385
1386 if ((part != NULL) && (part > slice) && (part > disk)) {
1387 s = part;
1388 } else if ((slice != NULL) && (slice > disk)) {
1389 s = slice;
1390 } else {
1391 s = disk;
1392 }
1393 if ((s != NULL) && isdigit(s[1])) {
1394 return (s);
1395 } else {
1396 return ("");
1397 }
1398 }
1399
1400 static gboolean
1401 is_dos_path(char *path, int *partnum)
1402 {
1403 char *p;
1404
1405 if ((p = strrchr (path, DOS_SEPERATOR)) == NULL) {
1406 return (FALSE);
1407 }
1408 return ((*partnum = atoi(p + 1)) != 0);
1409 }
1410
1411 static gboolean
1412 dos_to_dev(char *path, char **devpath, int *partnum)
1413 {
1414 char *p;
1415
1416 if ((p = strrchr (path, DOS_SEPERATOR)) == NULL) {
1417 return (FALSE);
1418 }
1419 if ((*partnum = atoi(p + 1)) == 0) {
1420 return (FALSE);
1421 }
1422 p[0] = '\0';
1423 *devpath = strdup(path);
1424 p[0] = DOS_SEPERATOR;
1425 return (*devpath != NULL);
1426 }
1427
1428 static void
1429 devinfo_storage_cleanup_mountpoint_cb (HalDevice *d, guint32 exit_type,
1430 gint return_code, gchar **error,
1431 gpointer data1, gpointer data2)
1432 {
1433 char *mount_point = (char *) data1;
1434
1435 HAL_INFO (("Cleaned up mount point '%s'", mount_point));
1436 g_free (mount_point);
1437 }
1438
1439
1440 void
1441 devinfo_storage_mnttab_event (HalDevice *hal_volume)
1442 {
1443 FILE *fp = NULL;
1444 struct extmnttab m;
|