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