xref: /illumos-gate/usr/src/cmd/hal/hald/solaris/osspec.c (revision ed5289f91b9bf164dccd6c75398362be77a4478d)
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