osspec.c revision 2912:85ea316d9c18
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
41static void mnttab_event_init ();
42static gboolean mnttab_event (GIOChannel *channel, GIOCondition cond, gpointer user_data);
43
44void
45osspec_init (void)
46{
47	ids_init ();
48	sysevent_init ();
49	mnttab_event_init ();
50}
51
52void
53hotplug_queue_now_empty (void)
54{
55        if (hald_is_initialising) {
56                osspec_probe_done ();
57	}
58}
59
60void
61osspec_probe (void)
62{
63	/* add entire device tree */
64	devinfo_add (NULL, "/");
65
66	/* start processing events */
67	hotplug_event_process_queue ();
68}
69
70gboolean
71osspec_device_rescan (HalDevice *d)
72{
73	   return (devinfo_device_rescan (d));
74}
75
76gboolean
77osspec_device_reprobe (HalDevice *d)
78{
79	   return FALSE;
80}
81
82DBusHandlerResult
83osspec_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 */
93HalDevice *
94hal_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
131char *
132dsk_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 */
172static int	mnttab_fd;
173static int	mnttab_port;
174static GIOChannel *mnttab_channel;
175
176static void
177mnttab_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
203static gboolean
204mnttab_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
231void
232osspec_refresh_mount_state_for_block_device (HalDevice *d)
233{
234	devinfo_storage_mnttab_event (d);
235}
236