/*************************************************************************** * * osspec.c : Solaris HAL backend entry points * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Licensed under the Academic Free License version 2.1 * **************************************************************************/ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include "../osspec.h" #include "../logger.h" #include "../hald.h" #include "../hald_dbus.h" #include "../device_info.h" #include "../util.h" #include "../ids.h" #include "osspec_solaris.h" #include "hotplug.h" #include "sysevent.h" #include "devinfo.h" #include "devinfo_storage.h" static void mnttab_event_init (); static gboolean mnttab_event (GIOChannel *channel, GIOCondition cond, gpointer user_data); void osspec_init (void) { ids_init (); sysevent_init (); mnttab_event_init (); } void hotplug_queue_now_empty (void) { if (hald_is_initialising) { osspec_probe_done (); } } void osspec_probe (void) { /* add entire device tree */ devinfo_add (NULL, "/"); /* start processing events */ hotplug_event_process_queue (); } gboolean osspec_device_rescan (HalDevice *d) { return (devinfo_device_rescan (d)); } gboolean osspec_device_reprobe (HalDevice *d) { return FALSE; } DBusHandlerResult osspec_filter_function (DBusConnection *connection, DBusMessage *message, void *user_data) { return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } /** Find the closest ancestor by looking at devfs paths * * @param devfs_path Path into devfs, e.g. /pci@0,0/pci1025,57@10,2/storage@1 * @return Parent Hal Device Object or #NULL if there is none */ HalDevice * hal_util_find_closest_ancestor (const gchar *devfs_path, gchar **ancestor_devfs_path, gchar **hotplug_devfs_path) { gchar buf[512]; gchar c; HalDevice *parent; parent = NULL; strncpy (buf, devfs_path, sizeof (buf)); do { char *p; p = strrchr (buf, '/'); if (p == NULL) break; c = *p; *p = '\0'; parent = hal_device_store_match_key_value_string (hald_get_gdl (), "solaris.devfs_path", buf); if (parent != NULL) { if (ancestor_devfs_path != NULL) { *ancestor_devfs_path = g_strdup (buf); } if (hotplug_devfs_path != NULL) { *p = c; *hotplug_devfs_path = g_strdup (buf); } break; } } while (TRUE); return parent; } char * dsk_to_rdsk(char *dsk) { int len, pos; char *p; char *rdsk; if ((len = strlen (dsk)) < sizeof ("/dev/dsk/cN") - 1) { return (strdup("")); } if ((p = strstr (dsk, "/dsk/")) == NULL) { if ((p = strstr (dsk, "/lofi/")) == NULL) { p = strstr (dsk, "/diskette"); } } if (p == NULL) { return (strdup("")); } pos = (uintptr_t)p - (uintptr_t)dsk; if ((rdsk = (char *)calloc (len + 2, 1)) != NULL) { strncpy (rdsk, dsk, pos + 1); rdsk[pos + 1] = 'r'; strcpy (rdsk + pos + 2, dsk + pos + 1); } return (rdsk); } /* * Setup to watch mnttab changes * * When mnttab changes, POLLRDBAND is set. However, glib does not * support POLLRDBAND, so we use Solaris ports (see port_create(3C)) * to "map" POLLRDBAND to POLLIN: * * - create a port * - associate the port with mnttab file descriptor and POLLRDBAND * - now polling for POLLIN on the port descriptor will unblock when * the associated file descriptor receives POLLRDBAND */ static int mnttab_fd; static int mnttab_port; static GIOChannel *mnttab_channel; static void mnttab_event_init () { char buf[81]; if ((mnttab_fd = open (MNTTAB, O_RDONLY)) < 0) { return; } if ((mnttab_port = port_create ()) < 0) { (void) close (mnttab_fd); return; } if (port_associate (mnttab_port, PORT_SOURCE_FD, mnttab_fd, POLLRDBAND, NULL) != 0) { (void) close (mnttab_port); (void) close (mnttab_fd); return; } /* suppress initial event */ (void) read(mnttab_fd, buf, (size_t)(sizeof (buf) - 1)); (void) lseek(mnttab_fd, 0, SEEK_SET); mnttab_channel = g_io_channel_unix_new (mnttab_port); g_io_add_watch (mnttab_channel, G_IO_IN, mnttab_event, NULL); } static gboolean mnttab_event (GIOChannel *channel, GIOCondition cond, gpointer user_data) { port_event_t pe; timespec_t timeout; char buf[81]; /* if (cond & ~G_IO_ERR) return TRUE; */ HAL_INFO (("mnttab event")); /* we have to re-associate port with fd every time */ timeout.tv_sec = timeout.tv_nsec = 0; (void) port_get(mnttab_port, &pe, &timeout); (void) port_associate(mnttab_port, PORT_SOURCE_FD, mnttab_fd, POLLRDBAND, NULL); if (!hald_is_initialising) { devinfo_storage_mnttab_event (NULL); } (void) lseek(mnttab_fd, 0, SEEK_SET); (void) read(mnttab_fd, buf, (size_t)(sizeof (buf) - 1)); return TRUE; } void osspec_refresh_mount_state_for_block_device (HalDevice *d) { devinfo_storage_mnttab_event (d); }