~ubuntu-core-dev/update-notifier/ubuntu

« back to all changes in this revision

Viewing changes to src/hal.c

  • Committer: Michael Vogt
  • Date: 2008-11-10 18:04:02 UTC
  • Revision ID: michael.vogt@ubuntu.com-20081110180402-lvolg0ct1xr4vqoi
* debian/update-notifier-common.install:
  - move apt-check, apt-cdrom-check and cdromdistupgrade
    into update-notifier-common

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
1
#ifdef HAVE_CONFIG_H
3
2
#include "config.h"
4
3
#endif
5
 
#ifdef HAVE_GDU
 
4
 
6
5
#include <glib.h>
7
 
#include <glib-object.h>
8
 
 
9
6
#include <sys/types.h>
10
7
#include <sys/wait.h>
11
8
 
 
9
 
12
10
#include "update-notifier.h"
13
 
#define GDU_API_IS_SUBJECT_TO_CHANGE
14
 
#include <gdu/gdu.h>
15
 
#include "gdu.h"
 
11
#include "hal.h"
16
12
 
17
13
#define CDROM_CHECKER PACKAGE_LIB_DIR"/update-notifier/apt-cdrom-check"
18
14
 
39
35
   CD_WITH_APTONCD   
40
36
};
41
37
 
42
 
void distro_cd_detected(UpgradeNotifier *un, 
43
 
                        int cdtype, 
44
 
                        const char *mount_point)
 
38
static LibHalContext *hal_ctx;
 
39
static DBusConnection *dbus_connection;
 
40
 
 
41
void distro_cd_detected(UpgradeNotifier *un, int cdtype, char *mount_point)
45
42
{
46
43
   GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
47
44
                                              GTK_MESSAGE_QUESTION, 
50
47
   gchar *title, *markup;
51
48
   switch(cdtype) {
52
49
   case CD_WITH_PACKAGES:
53
 
      title = _("Software Packages Volume Detected");
 
50
      title = _("Software packages volume detected");
54
51
      markup = _("<span weight=\"bold\" size=\"larger\">"
55
52
            "A volume with software packages has "
56
53
            "been detected.</span>\n\n"
59
56
      gtk_dialog_add_buttons(GTK_DIALOG(dialog), 
60
57
                             GTK_STOCK_CANCEL,
61
58
                             GTK_RESPONSE_REJECT,
62
 
                             _("Start Package Manager"), 
 
59
                             _("Start package manager"), 
63
60
                             RES_START_PM,
64
61
                             NULL);
65
62
      gtk_dialog_set_default_response (GTK_DIALOG(dialog), RES_START_PM);
130
127
      break;
131
128
   case RES_DIST_UPGRADER:
132
129
      argv[0] = "/usr/lib/update-notifier/cddistupgrader";
133
 
      argv[1] = (gchar *)mount_point;
 
130
      argv[1] = mount_point;
134
131
      argv[2] = NULL;
135
132
      g_spawn_async (NULL, argv, NULL, 0, NULL, NULL, NULL, NULL);
136
133
      break;
146
143
   gtk_widget_destroy (dialog);
147
144
}
148
145
 
149
 
void 
150
 
up_check_mount_point_for_packages (const char *mount_point, gpointer data)
151
 
{
152
 
   if (!mount_point)
153
 
      return;
 
146
/** Invoked by GLib in response to a D-BUS disconnect event.
 
147
 *
 
148
 * @param  data                 Context pointer
 
149
 */
 
150
static gboolean
 
151
up_reconnect_to_hal (gpointer data __attribute__((__unused__)))
 
152
{
 
153
        static unsigned int retries = 0;
 
154
 
 
155
        g_message ("Trying a reconnect ...");
 
156
        hal_ctx = up_do_hal_init ();
 
157
        if (hal_ctx != NULL) {
 
158
                g_message ("Reconnected OK.");
 
159
                retries = 0;
 
160
                return FALSE;
 
161
        } else if (dbus_connection) { 
 
162
           dbus_connection_unref (dbus_connection);
 
163
           dbus_connection = NULL;
 
164
        }
 
165
 
 
166
        /* Retry later if it failed. */
 
167
        if (retries++ < 6000)
 
168
                return TRUE;
 
169
 
 
170
        /* Too many retries; clean up and bail. */
 
171
        g_warning ("gvm_reconnect_to_hal: no reconnection after 6000 retries, "
 
172
                   "exiting\n");
 
173
 
 
174
        /* Too many retries; clean up and bail. */
 
175
        gtk_main_quit ();
 
176
        return FALSE;
 
177
}
 
178
 
 
179
static DBusHandlerResult
 
180
up_do_filter_dbus_msg (DBusConnection *connection __attribute__((__unused__)),
 
181
                        DBusMessage *message,
 
182
                        void *user_data __attribute__((__unused__)))
 
183
{
 
184
        DBusError error;
 
185
 
 
186
        if (dbus_message_is_signal (message,
 
187
                                    DBUS_INTERFACE_LOCAL,
 
188
                                    "Disconnected")) {
 
189
                g_timeout_add(1000, up_reconnect_to_hal, NULL);
 
190
                libhal_ctx_shutdown (hal_ctx, &error);
 
191
                libhal_ctx_free (hal_ctx);
 
192
                hal_ctx = NULL;
 
193
                dbus_connection_unref (dbus_connection);
 
194
                dbus_connection = NULL;
 
195
                return DBUS_HANDLER_RESULT_HANDLED;
 
196
        }
 
197
        else
 
198
                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
199
}
 
200
 
 
201
static dbus_bool_t
 
202
hal_mainloop_integration (LibHalContext *ctx, 
 
203
                           DBusError *error)
 
204
                          
 
205
{
 
206
 
 
207
        dbus_connection = dbus_bus_get (DBUS_BUS_SYSTEM, error);
 
208
 
 
209
        if (dbus_error_is_set (error))
 
210
                return FALSE;
 
211
 
 
212
        dbus_connection_set_exit_on_disconnect (dbus_connection, FALSE);
 
213
 
 
214
        dbus_connection_setup_with_g_main (dbus_connection, NULL);
 
215
        dbus_connection_add_filter (dbus_connection, up_do_filter_dbus_msg, 
 
216
                                    NULL, NULL);
 
217
        
 
218
        libhal_ctx_set_dbus_connection (ctx, dbus_connection);
 
219
        
 
220
        return TRUE;
 
221
}
 
222
 
 
223
/** callback when a property of a device changes. 
 
224
 *
 
225
 *  @param  udi                 Unique Device Id
 
226
 *  @param  key                 Name of the property that has changed
 
227
 *  @param  is_removed          Property removed
 
228
 *  @param  is_added            Property added
 
229
 */
 
230
void 
 
231
hal_property_modified(LibHalContext *ctx, const char *udi, const char *key,
 
232
                      dbus_bool_t is_removed, dbus_bool_t is_added)
 
233
{
 
234
   //g_print("hal_device_changed(): %s\n",key);
 
235
 
 
236
   /* we are only interessted in mount events from the cdrom*/
 
237
   if (g_strcasecmp (key, "volume.is_mounted") != 0)
 
238
      return;
 
239
   if(!libhal_device_get_property_bool(ctx, udi, key, NULL))
 
240
      return;
 
241
 
 
242
   up_check_device_for_packages (ctx, udi);
 
243
}
 
244
 
 
245
/** check if the given udi contains package files
 
246
 *
 
247
 *  @param  udi                 Unique Device Id
 
248
 */
 
249
void 
 
250
up_check_device_for_packages (LibHalContext *ctx, const char *udi)
 
251
{
 
252
   gchar *mount_point, *storage_device, *media_type;
 
253
 
 
254
   storage_device = libhal_device_get_property_string (ctx, udi,
 
255
                                                    "block.storage_device",
 
256
                                                             NULL);
 
257
   if (!storage_device) {
 
258
      g_warning("cannot get storage_device\n");
 
259
      return;
 
260
   }
 
261
   media_type = libhal_device_get_property_string (ctx, storage_device, 
 
262
                                                   "storage.drive_type",
 
263
                                                   NULL);
 
264
   if(!media_type) {
 
265
      g_warning("cannot get storage.drive_type\n");
 
266
      return;
 
267
   }
 
268
   if (g_ascii_strcasecmp(media_type, "cdrom") != 0) {
 
269
      //g_warning("no cdrom: %s\n",media_type);
 
270
      return;
 
271
   }
 
272
      
 
273
   mount_point = libhal_device_get_property_string (ctx, udi, 
 
274
                                                    "volume.mount_point",
 
275
                                                    NULL);
 
276
   //g_print("mounted: %s on %s\n", udi, mount_point);
154
277
 
155
278
   char *ubuntu_dir = g_strdup_printf("%s/ubuntu",mount_point);
156
279
   char *aptoncd_file = g_strdup_printf("%s/aptoncd.info",mount_point);
180
303
   //g_print("retval: %i \n", WEXITSTATUS(retval));
181
304
   int cdtype = WEXITSTATUS(retval);
182
305
   if(cdtype > 0) {
183
 
      distro_cd_detected(data, cdtype, mount_point);
 
306
     distro_cd_detected(libhal_ctx_get_user_data(ctx), cdtype, mount_point);
184
307
   }
185
308
 
186
309
   g_free(cmd);
187
310
}
188
311
 
189
 
void 
190
 
up_device_changed (GduPool *pool, GduDevice *device, gpointer data)
191
 
{
192
 
   //g_print("up_device_changed %s\n", gdu_device_get_device_file (device));
193
 
 
194
 
   // check if that is a removable device
195
 
   if (!gdu_device_is_removable(device))
196
 
      return;
197
 
 
198
 
   // we only care about the first mount point
199
 
   const gchar *p = gdu_device_get_mount_path (device);
200
 
   //g_print("checking mount point %s\n", p);
201
 
   up_check_mount_point_for_packages (p, data);
202
 
}
203
 
 
204
 
 
205
 
void
206
 
up_check_mounted_devices (GduPool *pool, gpointer data)
207
 
{
208
 
   GList *devices = gdu_pool_get_devices (pool);
 
312
gboolean
 
313
up_check_mounted_devices (gpointer data)
 
314
{
 
315
   LibHalContext *hal_ctx;
 
316
   gchar **devices;
 
317
   int nr, i;
 
318
 
 
319
   hal_ctx = data;
 
320
 
 
321
   devices = libhal_get_all_devices (hal_ctx, &nr, NULL);
 
322
   /* Now go over the devices and check for CDROMs
 
323
    */
 
324
   for(i=0; i<nr; i++) {
 
325
      if(libhal_device_get_property_bool (hal_ctx, devices[i], "volume.is_mounted", NULL))
 
326
         up_check_device_for_packages (hal_ctx, devices[i]);
 
327
   }
209
328
   
210
 
   while(devices != NULL) {
211
 
      up_device_changed (pool, devices->data, data);
212
 
      devices = g_list_next(devices);
213
 
   }
214
 
   g_list_free(devices);
215
 
}
216
 
 
217
 
gboolean
218
 
up_do_hal_init (UpgradeNotifier *un)
219
 
{
220
 
   GduPool *pool = gdu_pool_new ();
221
 
   if (pool == NULL)
222
 
      return FALSE;
223
 
 
224
 
   g_signal_connect (pool, "device_changed", (GCallback)up_device_changed, un);
225
 
   // now check what devices we have
226
 
   up_check_mounted_devices(pool, un);
227
 
 
228
 
   return TRUE;
229
 
}
230
 
 
231
 
 
232
 
#else
233
 
#include <glib.h>
234
 
 
235
 
#include "update-notifier.h"
236
 
 
237
 
gboolean
238
 
up_do_hal_init (UpgradeNotifier *un)
239
 
{
240
 
    g_warning("Detection and monitoring of CD-ROMs disabled.");
241
 
    return FALSE;
242
 
}
243
 
#endif // HAVE_GUDEV
 
329
   libhal_free_string_array (devices);
 
330
   return FALSE;
 
331
}
 
332
 
 
333
/** Internal UP initialization function
 
334
 *
 
335
 * @functions                   The LibHalFunctions to register as callbacks.
 
336
 * @return                      The LibHalContext of the HAL connection or
 
337
 *                              NULL on error.
 
338
 */
 
339
LibHalContext *
 
340
up_do_hal_init ()
 
341
{
 
342
        DBusError error;
 
343
        char **devices;
 
344
        int nr;
 
345
 
 
346
        hal_ctx = libhal_ctx_new ();
 
347
        if (!hal_ctx) {
 
348
                g_warning ("failed to initialize HAL!\n");
 
349
                return NULL;
 
350
        }
 
351
 
 
352
        dbus_error_init (&error);
 
353
        if (!hal_mainloop_integration (hal_ctx, &error)) {
 
354
                g_warning ("hal_initialize failed: %s\n", error.message);
 
355
                dbus_error_free (&error);
 
356
                return NULL;
 
357
        }
 
358
 
 
359
        libhal_ctx_set_device_property_modified (hal_ctx,
 
360
                                                 hal_property_modified);
 
361
 
 
362
        if (!libhal_device_property_watch_all (hal_ctx, &error)) {
 
363
                g_warning ("failed to watch all HAL properties!: %s\n", error.message);
 
364
                libhal_ctx_shutdown (hal_ctx, &error);
 
365
                return NULL;
 
366
        }
 
367
 
 
368
        if (!libhal_ctx_init (hal_ctx, &error)) {
 
369
                g_warning ("hal_initialize failed: %s\n", error.message);
 
370
                dbus_error_free (&error);
 
371
                libhal_ctx_free (hal_ctx);
 
372
                return NULL;
 
373
        }
 
374
 
 
375
        /*
 
376
         * Do something to ping the HAL daemon - the above functions will
 
377
         * succeed even if hald is not running, so long as DBUS is.  But we
 
378
         * want to exit silently if hald is not running, to behave on
 
379
         * pre-2.6 systems.
 
380
         */
 
381
        devices = libhal_get_all_devices (hal_ctx, &nr, &error);
 
382
        if (!devices) {
 
383
                g_warning ("seems that HAL is not running\n");
 
384
                libhal_ctx_shutdown (hal_ctx, &error);
 
385
                if (dbus_error_is_set (&error))
 
386
                        dbus_error_free (&error);
 
387
                libhal_ctx_free (hal_ctx);
 
388
                return NULL;
 
389
        }
 
390
        libhal_free_string_array (devices);
 
391
        
 
392
        // check for already mounted media for new package CDs
 
393
        // (after a small delay)
 
394
        g_timeout_add (5000, up_check_mounted_devices, hal_ctx);
 
395
 
 
396
        return hal_ctx;
 
397
}