1 /*************************************************************************** 2 * 3 * osspec.c : Solaris HAL backend entry points 4 * 5 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 6 * Use is subject to license terms. 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 <unistd.h> 18 #include <strings.h> 19 #include <port.h> 20 #include <sys/stat.h> 21 #include <fcntl.h> 22 #include <sys/types.h> 23 #include <sys/mntent.h> 24 #include <sys/mnttab.h> 25 26 #include "../osspec.h" 27 #include "../logger.h" 28 #include "../hald.h" 29 #include "../hald_dbus.h" 30 #include "../device_info.h" 31 #include "../util.h" 32 #include "../ids.h" 33 #include "osspec_solaris.h" 34 #include "hotplug.h" 35 #include "sysevent.h" 36 #include "devinfo.h" 37 #include "devinfo_storage.h" 38 39 static void mnttab_event_init (); 40 static gboolean mnttab_event (GIOChannel *channel, GIOCondition cond, gpointer user_data); 41 42 void 43 osspec_init (void) 44 { 45 ids_init (); 46 sysevent_init (); 47 mnttab_event_init (); 48 } 49 50 void 51 hotplug_queue_now_empty (void) 52 { 53 if (hald_is_initialising) { 54 osspec_probe_done (); 55 } 56 } 57 58 void 59 osspec_probe (void) 60 { 61 /* add entire device tree */ 62 devinfo_add (NULL, "/"); 63 64 /* start processing events */ 65 hotplug_event_process_queue (); 66 } 67 68 gboolean 69 osspec_device_rescan (HalDevice *d) 70 { 71 return (devinfo_device_rescan (d)); 72 } 73 74 gboolean 75 osspec_device_reprobe (HalDevice *d) 76 { 77 return FALSE; 78 } 79 80 DBusHandlerResult 81 osspec_filter_function (DBusConnection *connection, DBusMessage *message, void *user_data) 82 { 83 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 84 } 85 86 /** Find the closest ancestor by looking at devfs paths 87 * 88 * @param devfs_path Path into devfs, e.g. /pci@0,0/pci1025,57@10,2/storage@1 89 * @return Parent Hal Device Object or #NULL if there is none 90 */ 91 HalDevice * 92 hal_util_find_closest_ancestor (const gchar *devfs_path, gchar **ancestor_devfs_path, gchar **hotplug_devfs_path) 93 { 94 gchar buf[512]; 95 gchar c; 96 HalDevice *parent; 97 98 parent = NULL; 99 100 strncpy (buf, devfs_path, sizeof (buf)); 101 do { 102 char *p; 103 104 p = strrchr (buf, '/'); 105 if (p == NULL) 106 break; 107 c = *p; 108 *p = '\0'; 109 110 parent = hal_device_store_match_key_value_string (hald_get_gdl (), 111 "solaris.devfs_path", 112 buf); 113 if (parent != NULL) { 114 if (ancestor_devfs_path != NULL) { 115 *ancestor_devfs_path = g_strdup (buf); 116 } 117 if (hotplug_devfs_path != NULL) { 118 *p = c; 119 *hotplug_devfs_path = g_strdup (buf); 120 } 121 break; 122 } 123 124 } while (TRUE); 125 126 return parent; 127 } 128 129 char * 130 dsk_to_rdsk(char *dsk) 131 { 132 int len, pos; 133 char *p; 134 char *rdsk; 135 136 if ((len = strlen (dsk)) < sizeof ("/dev/dsk/cN") - 1) { 137 return (strdup("")); 138 } 139 if ((p = strstr (dsk, "/dsk/")) == NULL) { 140 if ((p = strstr (dsk, "/lofi/")) == NULL) { 141 p = strstr (dsk, "/diskette"); 142 } 143 } 144 if (p == NULL) { 145 return (strdup("")); 146 } 147 148 pos = (uintptr_t)p - (uintptr_t)dsk; 149 if ((rdsk = (char *)calloc (len + 2, 1)) != NULL) { 150 strncpy (rdsk, dsk, pos + 1); 151 rdsk[pos + 1] = 'r'; 152 strcpy (rdsk + pos + 2, dsk + pos + 1); 153 } 154 155 return (rdsk); 156 } 157 158 /* 159 * Setup to watch mnttab changes 160 * 161 * When mnttab changes, POLLRDBAND is set. However, glib does not 162 * support POLLRDBAND, so we use Solaris ports (see port_create(3C)) 163 * to "map" POLLRDBAND to POLLIN: 164 * 165 * - create a port 166 * - associate the port with mnttab file descriptor and POLLRDBAND 167 * - now polling for POLLIN on the port descriptor will unblock when 168 * the associated file descriptor receives POLLRDBAND 169 */ 170 static int mnttab_fd; 171 static int mnttab_port; 172 static GIOChannel *mnttab_channel; 173 174 static void 175 mnttab_event_init () 176 { 177 char buf[81]; 178 179 if ((mnttab_fd = open (MNTTAB, O_RDONLY)) < 0) { 180 return; 181 } 182 if ((mnttab_port = port_create ()) < 0) { 183 (void) close (mnttab_fd); 184 return; 185 } 186 if (port_associate (mnttab_port, PORT_SOURCE_FD, mnttab_fd, POLLRDBAND, 187 NULL) != 0) { 188 (void) close (mnttab_port); 189 (void) close (mnttab_fd); 190 return; 191 } 192 193 /* suppress initial event */ 194 (void) read(mnttab_fd, buf, (size_t)(sizeof (buf) - 1)); 195 (void) lseek(mnttab_fd, 0, SEEK_SET); 196 197 mnttab_channel = g_io_channel_unix_new (mnttab_port); 198 g_io_add_watch (mnttab_channel, G_IO_IN, mnttab_event, NULL); 199 } 200 201 static gboolean 202 mnttab_event (GIOChannel *channel, GIOCondition cond, gpointer user_data) 203 { 204 port_event_t pe; 205 timespec_t timeout; 206 char buf[81]; 207 208 /* if (cond & ~G_IO_ERR) 209 return TRUE; 210 */ 211 HAL_INFO (("mnttab event")); 212 213 /* we have to re-associate port with fd every time */ 214 timeout.tv_sec = timeout.tv_nsec = 0; 215 (void) port_get(mnttab_port, &pe, &timeout); 216 (void) port_associate(mnttab_port, PORT_SOURCE_FD, 217 mnttab_fd, POLLRDBAND, NULL); 218 219 if (!hald_is_initialising) { 220 devinfo_storage_mnttab_event (NULL); 221 } 222 223 (void) lseek(mnttab_fd, 0, SEEK_SET); 224 (void) read(mnttab_fd, buf, (size_t)(sizeof (buf) - 1)); 225 226 return TRUE; 227 } 228 229 void 230 osspec_refresh_mount_state_for_block_device (HalDevice *d) 231 { 232 devinfo_storage_mnttab_event (d); 233 } 234