~ubuntu-branches/ubuntu/raring/hal/raring

« back to all changes in this revision

Viewing changes to .pc/66-missing-types_h.patch/hald/linux/addons/addon-storage.c

  • Committer: Package Import Robot
  • Author(s): Daniel T Chen
  • Date: 2013-04-21 17:30:57 UTC
  • Revision ID: package-import@ubuntu.com-20130421173057-57w5lu1dw8ys2s2i
Tags: 0.5.14-8ubuntu1
Added missing preprocessor directive, fixing FTBFS
(Closes: #701432).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 * CVSID: $Id$
 
3
 *
 
4
 * addon-storage.c : Poll storage devices for media changes
 
5
 *
 
6
 * Copyright (C) 2004 David Zeuthen, <david@fubar.dk>
 
7
 *
 
8
 * Licensed under the Academic Free License version 2.1
 
9
 *
 
10
 * This program is free software; you can redistribute it and/or modify
 
11
 * it under the terms of the GNU General Public License as published by
 
12
 * the Free Software Foundation; either version 2 of the License, or
 
13
 * (at your option) any later version.
 
14
 *
 
15
 * This program is distributed in the hope that it will be useful,
 
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 * GNU General Public License for more details.
 
19
 *
 
20
 * You should have received a copy of the GNU General Public License
 
21
 * along with this program; if not, write to the Free Software
 
22
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
23
 *
 
24
 **************************************************************************/
 
25
 
 
26
#ifdef HAVE_CONFIG_H
 
27
#  include <config.h>
 
28
#endif
 
29
 
 
30
#include <errno.h>
 
31
#include <fcntl.h>
 
32
#include <linux/cdrom.h>
 
33
#include <linux/fs.h>
 
34
#include <mntent.h>
 
35
#include <scsi/sg.h>
 
36
#include <stdint.h>
 
37
#include <stdio.h>
 
38
#include <stdlib.h>
 
39
#include <string.h>
 
40
#include <sys/ioctl.h>
 
41
#include <unistd.h>
 
42
#include <glib.h>
 
43
#include <dbus/dbus-glib.h>
 
44
#include <dbus/dbus-glib-lowlevel.h>
 
45
 
 
46
#include "libhal/libhal.h"
 
47
 
 
48
#include "../../logger.h"
 
49
#include "../../util_helper.h"
 
50
 
 
51
 
 
52
static char *udi;
 
53
static char *device_file;
 
54
static int media_status;
 
55
static int is_cdrom;
 
56
static int support_media_changed;
 
57
static LibHalContext *ctx = NULL;
 
58
static DBusConnection *con = NULL;
 
59
static guint poll_timer = -1;
 
60
static GMainLoop *loop;
 
61
static gboolean system_is_idle = FALSE;
 
62
static gboolean check_lock_state = TRUE;
 
63
 
 
64
static gboolean polling_disabled = FALSE;
 
65
 
 
66
static void 
 
67
force_unmount (LibHalContext *ctx, const char *udi)
 
68
{
 
69
        DBusError error;
 
70
        DBusMessage *msg = NULL;
 
71
        DBusMessage *reply = NULL;
 
72
        char **options = NULL;
 
73
        unsigned int num_options = 0;
 
74
        DBusConnection *dbus_connection;
 
75
        char *device_file;
 
76
 
 
77
        dbus_connection = libhal_ctx_get_dbus_connection (ctx);
 
78
 
 
79
        msg = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
 
80
                                            "org.freedesktop.Hal.Device.Volume",
 
81
                                            "Unmount");
 
82
        if (msg == NULL) {
 
83
                HAL_ERROR (("Could not create dbus message for %s", udi));
 
84
                goto out;
 
85
        }
 
86
 
 
87
 
 
88
        options = calloc (1, sizeof (char *));
 
89
        if (options == NULL) {
 
90
                HAL_ERROR (("Could not allocate options array"));
 
91
                goto out;
 
92
        }
 
93
 
 
94
        options[0] = "lazy";
 
95
        num_options = 1;
 
96
 
 
97
        device_file = libhal_device_get_property_string (ctx, udi, "block.device", NULL);
 
98
        if (device_file != NULL) {
 
99
                HAL_INFO(("forcibly attempting to lazy unmount %s as media was removed", device_file));
 
100
                libhal_free_string (device_file);
 
101
        }
 
102
 
 
103
        if (!dbus_message_append_args (msg, 
 
104
                                       DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options,
 
105
                                       DBUS_TYPE_INVALID)) {
 
106
                HAL_ERROR (("Could not append args to dbus message for %s", udi));
 
107
                goto out;
 
108
        }
 
109
        
 
110
        dbus_error_init (&error);
 
111
        if (!(reply = dbus_connection_send_with_reply_and_block (dbus_connection, msg, -1, &error))) {
 
112
                HAL_ERROR (("Unmount failed for %s: %s : %s\n", udi, error.name, error.message));
 
113
                dbus_error_free (&error);
 
114
                goto out;
 
115
        }
 
116
 
 
117
        if (dbus_error_is_set (&error)) {
 
118
                HAL_ERROR (("Unmount failed for %s\n%s : %s\n", udi, error.name, error.message));
 
119
                dbus_error_free (&error);
 
120
                goto out;
 
121
        }
 
122
 
 
123
        HAL_DEBUG (("Succesfully unmounted udi '%s'", udi));
 
124
 
 
125
out:
 
126
        if (options != NULL)
 
127
                free (options);
 
128
        if (msg != NULL)
 
129
                dbus_message_unref (msg);
 
130
        if (reply != NULL)
 
131
                dbus_message_unref (reply);
 
132
}
 
133
 
 
134
static dbus_bool_t
 
135
unmount_cleartext_devices (LibHalContext *ctx, const char *udi)
 
136
{
 
137
        DBusError error;
 
138
        char **clear_devices;
 
139
        int num_clear_devices;
 
140
        dbus_bool_t ret;
 
141
 
 
142
        ret = FALSE;
 
143
 
 
144
        /* check if the volume we back is mounted.. if it is.. unmount it */
 
145
        dbus_error_init (&error);
 
146
        clear_devices = libhal_manager_find_device_string_match (ctx,
 
147
                                                                 "volume.crypto_luks.clear.backing_volume",
 
148
                                                                 udi,
 
149
                                                                 &num_clear_devices,
 
150
                                                                 &error);
 
151
 
 
152
        if (clear_devices != NULL && num_clear_devices > 0) {
 
153
                int i;
 
154
 
 
155
                ret = TRUE;
 
156
 
 
157
                for (i = 0; i < num_clear_devices; i++) {
 
158
                        char *clear_udi;
 
159
                        clear_udi = clear_devices[i];
 
160
                        LIBHAL_FREE_DBUS_ERROR (&error);
 
161
                        if (libhal_device_get_property_bool (ctx, clear_udi, "volume.is_mounted", &error)) {
 
162
                                HAL_DEBUG (("Forcing unmount of child '%s' (crypto)", clear_udi));
 
163
                                force_unmount (ctx, clear_udi);
 
164
                        }
 
165
                }
 
166
                libhal_free_string_array (clear_devices);
 
167
        }
 
168
 
 
169
        LIBHAL_FREE_DBUS_ERROR (&error);
 
170
        return ret;
 
171
}
 
172
 
 
173
static void 
 
174
unmount_childs (LibHalContext *ctx, const char *udi)
 
175
{
 
176
        int num_volumes;
 
177
        char **volumes;
 
178
        DBusError error;
 
179
 
 
180
        /* need to force unmount all partitions */
 
181
        dbus_error_init (&error);
 
182
        if ((volumes = libhal_manager_find_device_string_match (ctx, "block.storage_device", udi, &num_volumes, &error)) != NULL) {
 
183
                int i;
 
184
 
 
185
                for (i = 0; i < num_volumes; i++) {
 
186
                        char *vol_udi;
 
187
 
 
188
                        vol_udi = volumes[i];
 
189
                        LIBHAL_FREE_DBUS_ERROR (&error);
 
190
 
 
191
                        if (libhal_device_get_property_bool (ctx, vol_udi, "block.is_volume", &error)) {
 
192
                                dbus_bool_t is_crypto;
 
193
 
 
194
                                /* unmount all cleartext devices associated with us */
 
195
                                is_crypto = unmount_cleartext_devices (ctx, vol_udi);
 
196
 
 
197
                                LIBHAL_FREE_DBUS_ERROR (&error);
 
198
                                if (libhal_device_get_property_bool (ctx, vol_udi, "volume.is_mounted", &error)) {
 
199
                                        HAL_DEBUG (("Forcing unmount of child '%s'", vol_udi));
 
200
                                        force_unmount (ctx, vol_udi);
 
201
                                }
 
202
 
 
203
                                /* teardown crypto */
 
204
                                if (is_crypto) {
 
205
                                        DBusMessage *msg = NULL;
 
206
                                        DBusMessage *reply = NULL;
 
207
 
 
208
                                        /* tear down mapping */
 
209
                                        HAL_DEBUG (("Teardown crypto for '%s'", vol_udi));
 
210
 
 
211
                                        msg = dbus_message_new_method_call ("org.freedesktop.Hal", vol_udi,
 
212
                                                                            "org.freedesktop.Hal.Device.Volume.Crypto",
 
213
                                                                            "Teardown");
 
214
                                        if (msg == NULL) {
 
215
                                                HAL_ERROR (("Could not create dbus message for %s", vol_udi));
 
216
                                                goto teardown_failed;
 
217
                                        }
 
218
 
 
219
                                        LIBHAL_FREE_DBUS_ERROR (&error);
 
220
 
 
221
                                        if (!(reply = dbus_connection_send_with_reply_and_block (
 
222
                                                      libhal_ctx_get_dbus_connection (ctx), msg, -1, &error)) || 
 
223
                                            dbus_error_is_set (&error)) {
 
224
                                                HAL_DEBUG (("Teardown failed for %s: %s : %s\n", udi, error.name, error.message));
 
225
                                                dbus_error_free (&error);
 
226
                                        }
 
227
 
 
228
                                teardown_failed:
 
229
                                        if (msg != NULL)
 
230
                                                dbus_message_unref (msg);
 
231
                                        if (reply != NULL)
 
232
                                                dbus_message_unref (reply);
 
233
                                }
 
234
 
 
235
                        }
 
236
 
 
237
                }
 
238
                libhal_free_string_array (volumes);
 
239
        }
 
240
        LIBHAL_FREE_DBUS_ERROR (&error);
 
241
}
 
242
 
 
243
/** Check if a filesystem on a special device file is mounted
 
244
 *
 
245
 *  @param  device_file         Special device file, e.g. /dev/cdrom
 
246
 *  @return                     TRUE iff there is a filesystem system mounted
 
247
 *                              on the special device file
 
248
 */
 
249
static dbus_bool_t
 
250
is_mounted (const char *device_file)
 
251
{
 
252
        FILE *f;
 
253
        dbus_bool_t rc;
 
254
        struct mntent mnt;
 
255
        char buf[512];
 
256
 
 
257
        rc = FALSE;
 
258
 
 
259
        if ((f = setmntent ("/etc/mtab", "r")) == NULL)
 
260
                goto out;
 
261
 
 
262
        while (getmntent_r (f, &mnt, buf, sizeof(buf)) != NULL) {
 
263
                if (strcmp (device_file, mnt.mnt_fsname) == 0) {
 
264
                        rc = TRUE;
 
265
                        goto out1;
 
266
                }
 
267
        }
 
268
 
 
269
out1:
 
270
        endmntent (f);
 
271
out:
 
272
        return rc;
 
273
}
 
274
 
 
275
 
 
276
enum {
 
277
        MEDIA_STATUS_UNKNOWN = 0,
 
278
        MEDIA_STATUS_GOT_MEDIA = 1,
 
279
        MEDIA_STATUS_NO_MEDIA = 2
 
280
};
 
281
 
 
282
static gboolean poll_for_media (gpointer user_data);
 
283
static gboolean poll_for_media_force (void);
 
284
 
 
285
static int interval_in_seconds = 2;
 
286
 
 
287
static gboolean is_locked_by_hal = FALSE;
 
288
static gboolean is_locked_via_o_excl = FALSE;
 
289
 
 
290
static void
 
291
update_proc_title (void)
 
292
{
 
293
 
 
294
        if (polling_disabled) {
 
295
                hal_set_proc_title ("hald-addon-storage: no polling on %s because it is explicitly disabled", device_file);
 
296
        } else if (is_locked_by_hal) {
 
297
                if (is_locked_via_o_excl) {
 
298
                        hal_set_proc_title ("hald-addon-storage: no polling because %s is locked via HAL and O_EXCL", device_file);
 
299
                } else {
 
300
                        hal_set_proc_title ("hald-addon-storage: no polling because %s is locked via HAL", device_file);
 
301
                }
 
302
        } else if (is_locked_via_o_excl) {
 
303
                hal_set_proc_title ("hald-addon-storage: no polling because %s is locked via O_EXCL", device_file);
 
304
        } else {
 
305
                hal_set_proc_title ("hald-addon-storage: polling %s (every %d sec)", device_file, interval_in_seconds);
 
306
        }
 
307
}
 
308
 
 
309
static void
 
310
update_polling_interval (void)
 
311
{
 
312
        /* TODO: ideally we want all things that do polling to do it
 
313
         * at the same time.. such as to minimize battery
 
314
         * usage. Suppose we want to wake up to do poll_for_media()
 
315
         * every N seconds.  Suppose M is the number of seconds since
 
316
         * epoch. The fix is to wake up at exactly when M is divisible
 
317
         * by N... plus some system wide offset (ideally read from
 
318
         * /sys so kernel threads can use the same offset) to make Xen
 
319
         * + friends work.... 
 
320
         *
 
321
         * Also, the polling intervals should be powers of two to
 
322
         * ensure that wakeup's with different intervals happen at the
 
323
         * same time when possible.
 
324
         *
 
325
         * This is sorta-kinda what g_timeout_source_new_seconds()
 
326
         * tries to achieve, not enough I think, and it's only
 
327
         * available in glib >= 2.14. Too little, too late? *shrug*
 
328
         */
 
329
 
 
330
        if (system_is_idle)
 
331
                interval_in_seconds = 16;
 
332
        else
 
333
                interval_in_seconds = 2;
 
334
 
 
335
        if (poll_timer > 0)
 
336
                g_source_remove (poll_timer);
 
337
 
 
338
#ifdef HAVE_GLIB_2_14
 
339
        poll_timer = g_timeout_add_seconds (interval_in_seconds, poll_for_media, NULL);
 
340
#else
 
341
        poll_timer = g_timeout_add (interval_in_seconds * 1000, poll_for_media, NULL);
 
342
#endif
 
343
 
 
344
        update_proc_title ();
 
345
}
 
346
 
 
347
static gboolean
 
348
poll_for_media (gpointer user_data)
 
349
{
 
350
        if (check_lock_state) {
 
351
                DBusError error;
 
352
                dbus_bool_t should_poll;
 
353
 
 
354
                check_lock_state = FALSE;
 
355
 
 
356
                HAL_INFO (("Checking whether device %s is locked on HAL", device_file));
 
357
                dbus_error_init (&error);
 
358
                if (libhal_device_is_locked_by_others (ctx, udi, "org.freedesktop.Hal.Device.Storage", &error)) {
 
359
                        HAL_INFO (("... device %s is locked on HAL", device_file));
 
360
                        is_locked_by_hal = TRUE;
 
361
                        update_proc_title ();
 
362
                        LIBHAL_FREE_DBUS_ERROR (&error);
 
363
                        goto skip_check;
 
364
                } else {
 
365
                        HAL_INFO (("... device %s is not locked on HAL", device_file));
 
366
                        is_locked_by_hal = FALSE;
 
367
                }
 
368
 
 
369
                LIBHAL_FREE_DBUS_ERROR (&error);
 
370
 
 
371
                should_poll = libhal_device_get_property_bool (ctx, udi, "storage.media_check_enabled", &error);
 
372
                LIBHAL_FREE_DBUS_ERROR (&error);
 
373
                polling_disabled = !should_poll;
 
374
                update_proc_title ();
 
375
        }
 
376
 
 
377
        /* TODO: we could remove the timeout completely... */
 
378
        if (is_locked_by_hal || polling_disabled)
 
379
                goto skip_check;
 
380
 
 
381
        poll_for_media_force ();
 
382
 
 
383
skip_check:
 
384
        return TRUE;
 
385
}
 
386
 
 
387
/* returns: whether the state changed */
 
388
static gboolean
 
389
poll_for_media_force (void)
 
390
{
 
391
        int fd;
 
392
        int got_media;
 
393
        int old_media_status;
 
394
 
 
395
        got_media = FALSE;
 
396
 
 
397
        old_media_status = media_status;
 
398
        if (is_cdrom) {
 
399
                int drive;
 
400
                
 
401
                fd = open (device_file, O_RDONLY | O_NONBLOCK | O_EXCL);
 
402
                
 
403
                if (fd < 0 && errno == EBUSY) {
 
404
                        /* this means the disc is mounted or some other app,
 
405
                         * like a cd burner, has already opened O_EXCL */
 
406
                        
 
407
                        /* HOWEVER, when starting hald, a disc may be
 
408
                         * mounted; so check /etc/mtab to see if it
 
409
                         * actually is mounted. If it is we retry to open
 
410
                         * without O_EXCL
 
411
                         */
 
412
                        if (!is_mounted (device_file)) {
 
413
                                if (!is_locked_via_o_excl) {
 
414
                                        is_locked_via_o_excl = TRUE;
 
415
                                        update_proc_title ();
 
416
                                } else {
 
417
                                        is_locked_via_o_excl = TRUE;
 
418
                                }
 
419
                                goto skip_check;
 
420
                        }
 
421
                        
 
422
                        fd = open (device_file, O_RDONLY | O_NONBLOCK);
 
423
                }
 
424
                
 
425
                if (fd < 0) {
 
426
                        HAL_ERROR (("open failed for %s: %s", device_file, strerror (errno))); 
 
427
                        goto skip_check;
 
428
                }
 
429
 
 
430
                if (is_locked_via_o_excl) {
 
431
                        is_locked_via_o_excl = FALSE;
 
432
                        update_proc_title ();
 
433
                }
 
434
                
 
435
                
 
436
                /* Check if a disc is in the drive
 
437
                 *
 
438
                 * @todo Use MMC-2 API if applicable
 
439
                 */
 
440
                drive = ioctl (fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
 
441
                switch (drive) {
 
442
                case CDS_NO_INFO:
 
443
                case CDS_NO_DISC:
 
444
                case CDS_TRAY_OPEN:
 
445
                case CDS_DRIVE_NOT_READY:
 
446
                        break;
 
447
                        
 
448
                case CDS_DISC_OK:
 
449
                        /* some CD-ROMs report CDS_DISK_OK even with an open
 
450
                         * tray; if media check has the same value two times in
 
451
                         * a row then this seems to be the case and we must not
 
452
                         * report that there is a media in it. */
 
453
                        if (support_media_changed &&
 
454
                            ioctl (fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT) && 
 
455
                            ioctl (fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT)) {
 
456
                        } else {
 
457
                                got_media = TRUE;
 
458
                        }
 
459
                        break;
 
460
                        
 
461
                case -1:
 
462
                        HAL_ERROR (("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno)));
 
463
                        break;
 
464
                        
 
465
                default:
 
466
                        break;
 
467
                }
 
468
                
 
469
                /* check if eject button was pressed */
 
470
                if (got_media) {
 
471
                        unsigned char cdb[10] = { 0x4a, 1, 0, 0, 16, 0, 0, 0, 8, 0};
 
472
                        unsigned char buffer[8];
 
473
                        struct sg_io_hdr sg_h;
 
474
                        int retval;
 
475
                        
 
476
                        memset(buffer, 0, sizeof(buffer));
 
477
                        memset(&sg_h, 0, sizeof(struct sg_io_hdr));
 
478
                        sg_h.interface_id = 'S';
 
479
                        sg_h.cmd_len = sizeof(cdb);
 
480
                        sg_h.dxfer_direction = SG_DXFER_FROM_DEV;
 
481
                        sg_h.dxfer_len = sizeof(buffer);
 
482
                        sg_h.dxferp = buffer;
 
483
                        sg_h.cmdp = cdb;
 
484
                        sg_h.timeout = 5000;
 
485
                        retval = ioctl(fd, SG_IO, &sg_h);
 
486
                        if (retval == 0 && sg_h.status == 0 && (buffer[4] & 0x0f) == 0x01) {
 
487
                                DBusError error;
 
488
                                
 
489
                                /* emit signal from drive device object */
 
490
                                dbus_error_init (&error);
 
491
                                libhal_device_emit_condition (ctx, udi, "EjectPressed", "", &error);
 
492
                                LIBHAL_FREE_DBUS_ERROR (&error);
 
493
                        }
 
494
                }
 
495
                close (fd);
 
496
        } else {
 
497
                fd = open (device_file, O_RDONLY);
 
498
                if (fd < 0 && errno == ENOMEDIUM) {
 
499
                        got_media = FALSE;
 
500
                } else if (fd >= 0) {
 
501
                        got_media = TRUE;
 
502
                        close (fd);
 
503
                } else {
 
504
                        HAL_ERROR (("open failed for %s: %s", device_file, strerror (errno))); 
 
505
                        goto skip_check;
 
506
                }
 
507
        }
 
508
        
 
509
        /* set correct state on startup, this avoid endless loops if there was a media in the device on startup */
 
510
        if (media_status == MEDIA_STATUS_UNKNOWN) {
 
511
                if (got_media) 
 
512
                        media_status = MEDIA_STATUS_NO_MEDIA;
 
513
                else 
 
514
                        media_status = MEDIA_STATUS_GOT_MEDIA;  
 
515
        }
 
516
 
 
517
        switch (media_status) {
 
518
        case MEDIA_STATUS_GOT_MEDIA:
 
519
                if (!got_media) {
 
520
                        DBusError error;
 
521
                        
 
522
                        HAL_DEBUG (("Media removal detected on %s", device_file));
 
523
                        libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", FALSE, NULL);
 
524
                        libhal_device_set_property_string (ctx, udi, "storage.partitioning_scheme", "", NULL);
 
525
                        
 
526
                        
 
527
                        /* attempt to unmount all childs */
 
528
                        unmount_childs (ctx, udi);
 
529
                        
 
530
                        /* could have a fs on the main block device; do a rescan to remove it */
 
531
                        dbus_error_init (&error);
 
532
                        libhal_device_rescan (ctx, udi, &error);
 
533
                        LIBHAL_FREE_DBUS_ERROR (&error);
 
534
                        
 
535
                        /* have to this to trigger appropriate hotplug events */
 
536
                        fd = open (device_file, O_RDONLY | O_NONBLOCK);
 
537
                        if (fd >= 0) {
 
538
                                ioctl (fd, BLKRRPART);
 
539
                                close (fd);
 
540
                        }
 
541
                }
 
542
                break;
 
543
                
 
544
        case MEDIA_STATUS_NO_MEDIA:
 
545
                if (got_media) {
 
546
                        DBusError error;
 
547
                        
 
548
                        HAL_DEBUG (("Media insertion detected on %s", device_file));
 
549
                        
 
550
                        /* our probe will trigger the appropriate hotplug events */
 
551
                        libhal_device_set_property_bool (
 
552
                                ctx, udi, "storage.removable.media_available", TRUE, NULL);
 
553
                        
 
554
                        /* could have a fs on the main block device; do a rescan to add it */
 
555
                        dbus_error_init (&error);
 
556
                        libhal_device_rescan (ctx, udi, &error);
 
557
                        LIBHAL_FREE_DBUS_ERROR (&error);
 
558
                }
 
559
                break;
 
560
                
 
561
        case MEDIA_STATUS_UNKNOWN:
 
562
        default:
 
563
                break;
 
564
        }
 
565
        
 
566
        /* update our current status */
 
567
        if (got_media)
 
568
                media_status = MEDIA_STATUS_GOT_MEDIA;
 
569
        else
 
570
                media_status = MEDIA_STATUS_NO_MEDIA;
 
571
        
 
572
        /*HAL_DEBUG (("polling %s; got media=%d", device_file, got_media));*/
 
573
        
 
574
skip_check:
 
575
        return old_media_status != media_status;
 
576
}
 
577
 
 
578
#ifdef HAVE_CONKIT
 
579
static gboolean
 
580
get_system_idle_from_ck (void)
 
581
{
 
582
       gboolean ret;
 
583
       DBusError error;
 
584
       DBusMessage *message;
 
585
       DBusMessage *reply;
 
586
 
 
587
       ret = FALSE;
 
588
 
 
589
       message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", 
 
590
                                               "/org/freedesktop/ConsoleKit/Manager",
 
591
                                               "org.freedesktop.ConsoleKit.Manager",
 
592
                                               "GetSystemIdleHint");
 
593
       dbus_error_init (&error);
 
594
       reply = dbus_connection_send_with_reply_and_block (con, message, -1, &error);
 
595
       if (reply == NULL || dbus_error_is_set (&error)) {
 
596
               HAL_ERROR (("Error doing Manager.GetSystemIdleHint on ConsoleKit: %s: %s", error.name, error.message));
 
597
               dbus_message_unref (message);
 
598
               if (reply != NULL)
 
599
                       dbus_message_unref (reply);
 
600
               goto error;
 
601
       }
 
602
       if (!dbus_message_get_args (reply, NULL,
 
603
                                   DBUS_TYPE_BOOLEAN, &(system_is_idle),
 
604
                                   DBUS_TYPE_INVALID)) {
 
605
               HAL_ERROR (("Invalid GetSystemIdleHint reply from CK"));
 
606
               goto error;
 
607
       }
 
608
       dbus_message_unref (message);
 
609
       dbus_message_unref (reply);
 
610
 
 
611
       ret = TRUE;
 
612
 
 
613
error:
 
614
       LIBHAL_FREE_DBUS_ERROR (&error);
 
615
       return ret;
 
616
}
 
617
#endif /* HAVE_CONKIT */
 
618
 
 
619
 
 
620
static DBusHandlerResult
 
621
direct_filter_function (DBusConnection *connection, DBusMessage *message, void *user_data)
 
622
{
 
623
        if (dbus_message_is_method_call (message, 
 
624
                                         "org.freedesktop.Hal.Device.Storage.Removable", 
 
625
                                         "CheckForMedia")) {
 
626
                DBusMessage *reply;
 
627
                dbus_bool_t call_had_sideeffect;
 
628
 
 
629
                HAL_INFO (("Forcing poll for media becusse CheckForMedia() was called"));
 
630
 
 
631
                call_had_sideeffect = poll_for_media_force ();
 
632
 
 
633
                reply = dbus_message_new_method_return (message);
 
634
                dbus_message_append_args (reply,
 
635
                                          DBUS_TYPE_BOOLEAN, &call_had_sideeffect,
 
636
                                          DBUS_TYPE_INVALID);
 
637
                dbus_connection_send (connection, reply, NULL);
 
638
                dbus_message_unref (reply);
 
639
        }
 
640
 
 
641
        return DBUS_HANDLER_RESULT_HANDLED;
 
642
}
 
643
 
 
644
static DBusHandlerResult
 
645
dbus_filter_function (DBusConnection *connection, DBusMessage *message, void *user_data)
 
646
{
 
647
#ifdef HAVE_CONKIT
 
648
        gboolean system_is_idle_new;
 
649
 
 
650
        if (dbus_message_is_signal (message, 
 
651
                                    "org.freedesktop.ConsoleKit.Manager", 
 
652
                                    "SystemIdleHintChanged")) {
 
653
                if (!dbus_message_get_args (message, NULL,
 
654
                                            DBUS_TYPE_BOOLEAN, &system_is_idle_new,
 
655
                                            DBUS_TYPE_INVALID)) {
 
656
                        HAL_ERROR (("Invalid SystemIdleHintChanged signal from CK"));
 
657
                        goto out;
 
658
                }
 
659
 
 
660
                if (system_is_idle_new != system_is_idle) {
 
661
                        system_is_idle = system_is_idle_new;
 
662
                        update_polling_interval ();
 
663
                }
 
664
        }
 
665
 
 
666
out:
 
667
#endif /* HAVE_CONKIT */
 
668
 
 
669
        /* Check, just before the next poll, whether lock state have changed; 
 
670
         * 
 
671
         * Note that we get called on at least these signals
 
672
         *
 
673
         * 1. CK.Manager  - SystemIdleHintChanged
 
674
         * 2. CK.Seat     - ActiveSessionChanged
 
675
         * 2. HAL.Manager - GlobalLockAcquired, GlobalLockReleased
 
676
         * 3. HAL.Device  - LockAcquired, LockReleased
 
677
         *
 
678
         * meaning that every time the locking situation changes, we
 
679
         * will get updated.
 
680
         */
 
681
        check_lock_state = TRUE;
 
682
 
 
683
        return DBUS_HANDLER_RESULT_HANDLED;
 
684
}
 
685
 
 
686
int
 
687
main (int argc, char *argv[])
 
688
{
 
689
        DBusError error;
 
690
        LibHalContext *ctx_direct;
 
691
        DBusConnection *con_direct;
 
692
        char *bus;
 
693
        char *drive_type;
 
694
        char *support_media_changed_str;
 
695
        char *str;
 
696
 
 
697
        hal_set_proc_title_init (argc, argv);
 
698
 
 
699
        /* We could drop privs if we know that the haldaemon user is
 
700
         * to be able to access block devices...
 
701
         */
 
702
        /*drop_privileges (1);*/
 
703
 
 
704
        if ((udi = getenv ("UDI")) == NULL)
 
705
                goto out;
 
706
        if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL)
 
707
                goto out;
 
708
        if ((bus = getenv ("HAL_PROP_STORAGE_BUS")) == NULL)
 
709
                goto out;
 
710
        if ((drive_type = getenv ("HAL_PROP_STORAGE_DRIVE_TYPE")) == NULL)
 
711
                goto out;
 
712
 
 
713
        setup_logger ();
 
714
 
 
715
        support_media_changed_str = getenv ("HAL_PROP_STORAGE_CDROM_SUPPORT_MEDIA_CHANGED");
 
716
        if (support_media_changed_str != NULL && strcmp (support_media_changed_str, "true") == 0)
 
717
                support_media_changed = TRUE;
 
718
        else
 
719
                support_media_changed = FALSE;
 
720
 
 
721
        dbus_error_init (&error);
 
722
        con = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
 
723
        if (con == NULL) {
 
724
                HAL_ERROR (("Cannot connect to system bus"));
 
725
                goto out;
 
726
        }
 
727
        loop = g_main_loop_new (NULL, FALSE);
 
728
        dbus_connection_setup_with_g_main (con, NULL);
 
729
        dbus_connection_set_exit_on_disconnect (con, 0);
 
730
 
 
731
        if ((ctx_direct = libhal_ctx_init_direct (&error)) == NULL) {
 
732
                HAL_ERROR (("Cannot connect to hald"));
 
733
                goto out;
 
734
        }
 
735
        if (!libhal_device_addon_is_ready (ctx_direct, udi, &error)) {
 
736
                goto out;
 
737
        }
 
738
        con_direct = libhal_ctx_get_dbus_connection (ctx_direct);
 
739
        dbus_connection_setup_with_g_main (con_direct, NULL);
 
740
        dbus_connection_set_exit_on_disconnect (con_direct, 0);
 
741
        dbus_connection_add_filter (con_direct, direct_filter_function, NULL, NULL);
 
742
 
 
743
 
 
744
        if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
 
745
                goto out;
 
746
 
 
747
        if (!libhal_device_addon_is_ready (ctx, udi, &error))
 
748
                goto out;
 
749
 
 
750
        HAL_DEBUG (("**************************************************"));
 
751
        HAL_DEBUG (("Doing addon-storage for %s (bus %s) (drive_type %s) (udi %s)", device_file, bus, drive_type, udi));
 
752
        HAL_DEBUG (("**************************************************"));
 
753
 
 
754
        if (strcmp (drive_type, "cdrom") == 0)
 
755
                is_cdrom = 1;
 
756
        else
 
757
                is_cdrom = 0;
 
758
 
 
759
        media_status = MEDIA_STATUS_UNKNOWN;
 
760
 
 
761
 
 
762
#ifdef HAVE_CONKIT
 
763
        /* TODO: ideally we should track the sessions on the seats on
 
764
         * which the device belongs to. But right now we don't really
 
765
         * do multi-seat so I'm going to punt on this for now.
 
766
         */
 
767
        get_system_idle_from_ck ();
 
768
 
 
769
        dbus_bus_add_match (con,
 
770
                            "type='signal'"
 
771
                            ",interface='org.freedesktop.ConsoleKit.Manager'"
 
772
                            ",sender='org.freedesktop.ConsoleKit'"
 
773
                            ",member='SystemIdleHintChanged'",
 
774
                            NULL);
 
775
        dbus_bus_add_match (con,
 
776
                            "type='signal'"
 
777
                            ",interface='org.freedesktop.ConsoleKit.Seat'"
 
778
                            ",sender='org.freedesktop.ConsoleKit'"
 
779
                            ",member='ActiveSessionChanged'",
 
780
                            NULL);
 
781
#endif
 
782
 
 
783
        /* this is a bit weird; but we want to listen to signals about
 
784
         * locking from hald.. and signals are not pushed over direct
 
785
         * connections (for a good reason).
 
786
         */
 
787
        dbus_bus_add_match (con,
 
788
                            "type='signal'"
 
789
                            ",interface='org.freedesktop.Hal.Manager'"
 
790
                            ",sender='org.freedesktop.Hal'",
 
791
                            NULL);
 
792
        dbus_bus_add_match (con,
 
793
                            "type='signal'"
 
794
                            ",interface='org.freedesktop.Hal.Manager'"
 
795
                            ",sender='org.freedesktop.Hal'",
 
796
                            NULL);
 
797
        str = g_strdup_printf ("type='signal'"
 
798
                               ",interface='org.freedesktop.Hal.Device'"
 
799
                               ",sender='org.freedesktop.Hal'"
 
800
                               ",path='%s'",
 
801
                               udi);
 
802
        dbus_bus_add_match (con,
 
803
                            str,
 
804
                            NULL);
 
805
        g_free (str);
 
806
        dbus_connection_add_filter (con, dbus_filter_function, NULL, NULL);
 
807
 
 
808
        if (!libhal_device_claim_interface (ctx,
 
809
                                            udi, 
 
810
                                            "org.freedesktop.Hal.Device.Storage.Removable", 
 
811
                                            "    <method name=\"CheckForMedia\">\n"
 
812
                                            "      <arg name=\"call_had_sideeffect\" direction=\"out\" type=\"b\"/>\n"
 
813
                                            "    </method>\n",
 
814
                                            &error)) {
 
815
                HAL_ERROR (("Cannot claim interface 'org.freedesktop.Hal.Device.Storage.Removable'"));
 
816
                goto out;
 
817
        }
 
818
 
 
819
 
 
820
        update_polling_interval ();
 
821
        g_main_loop_run (loop);
 
822
 
 
823
out:
 
824
        HAL_DEBUG (("An error occured, exiting cleanly"));
 
825
 
 
826
        LIBHAL_FREE_DBUS_ERROR (&error);
 
827
 
 
828
        if (ctx != NULL) {
 
829
                libhal_ctx_shutdown (ctx, &error);
 
830
                LIBHAL_FREE_DBUS_ERROR (&error);
 
831
                libhal_ctx_free (ctx);
 
832
        }
 
833
 
 
834
        return 0;
 
835
}