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