~ubuntu-branches/ubuntu/trusty/thunar-volman/trusty-proposed

1.1.2 by Lionel Le Folgoc
Import upstream version 0.3.80
1
/* $Id: tvm-block-device.c 5216 2008-08-12 08:54:28Z kelnos $ */
1 by Yves-Alexis Perez
Import upstream version 0.1.2
2
/*-
1.1.2 by Lionel Le Folgoc
Import upstream version 0.3.80
3
 * Copyright (c) 2007-2008 Benedikt Meurer <benny@xfce.org>.
1 by Yves-Alexis Perez
Import upstream version 0.1.2
4
 *
5
 * This program is free software; you can redistribute it and/or modify it
6
 * under the terms of the GNU General Public License as published by the Free
7
 * Software Foundation; either version 2 of the License, or (at your option)
8
 * any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful, but WITHOUT
11
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13
 * more details.
14
 *
15
 * You should have received a copy of the GNU General Public License along with
16
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17
 * Place, Suite 330, Boston, MA  02111-1307  USA
18
 */
19
20
#ifdef HAVE_CONFIG_H
21
#include <config.h>
22
#endif
23
24
#ifdef HAVE_SYS_TYPES_H
25
#include <sys/types.h>
26
#endif
27
#ifdef HAVE_SYS_STAT_H
28
#include <sys/stat.h>
29
#endif
30
#ifdef HAVE_SYS_WAIT_H
31
#include <sys/wait.h>
32
#endif
33
34
#ifdef HAVE_MEMORY_H
35
#include <memory.h>
36
#endif
37
#include <stdio.h>
38
#ifdef HAVE_STRING_H
39
#include <string.h>
40
#endif
41
42
#include <dbus/dbus-glib-lowlevel.h>
43
44
#include <thunar-volman/tvm-block-device.h>
1.1.2 by Lionel Le Folgoc
Import upstream version 0.3.80
45
#include <thunar-volman/tvm-crypto-volume.h>
1 by Yves-Alexis Perez
Import upstream version 0.1.2
46
#include <thunar-volman/tvm-prompt.h>
47
#include <thunar-volman/tvm-run.h>
48
49
50
1.1.1 by Lionel Le Folgoc
Import upstream version 0.2.0
51
static gboolean tvm_file_test               (const gchar    *directory,
52
                                             const gchar    *filename,
53
                                             GFileTest       test);
1 by Yves-Alexis Perez
Import upstream version 0.1.2
54
static gboolean tvm_block_device_autoipod   (TvmPreferences *preferences,
55
                                             LibHalContext  *context,
56
                                             const gchar    *udi,
57
                                             const gchar    *device_file,
58
                                             const gchar    *mount_point,
59
                                             GError        **error);
60
static gboolean tvm_block_device_autophoto  (TvmPreferences *preferences,
61
                                             LibHalContext  *context,
62
                                             const gchar    *udi,
63
                                             const gchar    *device_file,
64
                                             const gchar    *mount_point,
65
                                             GError        **error);
66
static gboolean tvm_block_device_autorun    (TvmPreferences *preferences,
67
                                             LibHalContext  *context,
68
                                             const gchar    *udi,
69
                                             const gchar    *device_file,
70
                                             const gchar    *mount_point,
71
                                             GError        **error);
72
static gboolean tvm_block_device_mount      (TvmPreferences *preferences,
73
                                             LibHalContext  *context,
74
                                             const gchar    *udi,
75
                                             GError        **error);
76
static gboolean tvm_block_device_mounted    (TvmPreferences *preferences,
77
                                             LibHalContext  *context,
78
                                             const gchar    *udi,
79
                                             const gchar    *device_file,
80
                                             const gchar    *mount_point,
81
                                             GError        **error);
82
83
84
85
static gboolean
1.1.1 by Lionel Le Folgoc
Import upstream version 0.2.0
86
tvm_file_test (const gchar *directory,
87
               const gchar *filename,
88
               GFileTest    test)
89
{
90
  const gchar *name;
91
  gboolean     result = FALSE;
92
  gchar       *path;
93
  GDir        *dp;
94
95
  /* try to open the specified directory */
96
  dp = g_dir_open (directory, 0, NULL);
97
  if (G_LIKELY (dp != NULL))
98
    {
99
      while (!result)
100
        {
101
          /* read the next entry */
102
          name = g_dir_read_name (dp);
103
          if (G_UNLIKELY (name == NULL))
104
            break;
105
106
          /* check if we have a potential match */
107
          if (g_ascii_strcasecmp (name, filename) == 0)
108
            {
109
              /* check if test condition met */
110
              path = g_build_filename (directory, name, NULL);
111
              result = g_file_test (path, test);
112
              g_free (path);
113
            }
114
        }
115
116
      /* cleanup */
117
      g_dir_close (dp);
118
    }
119
120
  return result;
121
}
122
123
124
125
static gboolean
1 by Yves-Alexis Perez
Import upstream version 0.1.2
126
tvm_block_device_autoipod (TvmPreferences *preferences,
127
                           LibHalContext  *context,
128
                           const gchar    *udi,
129
                           const gchar    *device_file,
130
                           const gchar    *mount_point,
131
                           GError        **error)
132
{
133
  gboolean result = FALSE;
134
  gboolean autoipod;
1.1.2 by Lionel Le Folgoc
Import upstream version 0.3.80
135
  gboolean is_audio_player = FALSE;
1 by Yves-Alexis Perez
Import upstream version 0.1.2
136
  gchar   *autoipod_command;
137
  gchar   *autophoto_command;
138
  gchar   *storage_udi;
139
  gchar   *path_dcim = NULL;
140
  gchar   *product;
1.1.2 by Lionel Le Folgoc
Import upstream version 0.3.80
141
  gint     response = TVM_RESPONSE_NONE;
1 by Yves-Alexis Perez
Import upstream version 0.1.2
142
143
  /* check if music players should be handled automatically */
144
  g_object_get (G_OBJECT (preferences), "autoipod", &autoipod, "autoipod-command", &autoipod_command, NULL);
145
  if (G_LIKELY (autoipod && autoipod_command != NULL && *autoipod_command != '\0'))
146
    {
147
      /* determine the storage device UDI */
148
      storage_udi = libhal_device_get_property_string (context, udi, "block.storage_device", NULL);
149
      if (G_LIKELY (storage_udi != NULL))
150
        {
151
          /* check if we have a portable audio player here */
152
          if (libhal_device_query_capability (context, storage_udi, "portable_audio_player", NULL))
153
            {
1.1.2 by Lionel Le Folgoc
Import upstream version 0.3.80
154
	      is_audio_player = TRUE;
1 by Yves-Alexis Perez
Import upstream version 0.1.2
155
              /* check if we have an iPod here */
156
              product = libhal_device_get_property_string (context, storage_udi, "info.product", NULL);
157
              if (product != NULL && strcmp (product, "iPod") != 0)
158
                {
159
                  /* an iPod may have photos */
160
                  path_dcim = g_build_filename (mount_point, "dcim", NULL);
161
                  if (!g_file_test (path_dcim, G_FILE_TEST_IS_DIR))
162
                    {
163
                      /* no photos */
164
                      g_free (path_dcim);
165
                      path_dcim = NULL;
166
                    }
167
                  else
168
                    {
169
                      /* add the "content.photos" capability to this device */
170
                      libhal_device_add_capability (context, udi, "content.photos", NULL);
171
                    }
172
                }
173
              libhal_free_string (product);
174
            }
175
176
          /* check if autophoto command is specified, else we cannot handle the photos on the iPod anyway */
177
          g_object_get (G_OBJECT (preferences), "autophoto-command", &autophoto_command, NULL);
178
          if (G_UNLIKELY (autophoto_command == NULL || *autophoto_command == '\0'))
179
            {
180
              /* cannot handle photos */
181
              g_free (path_dcim);
182
              path_dcim = NULL;
183
            }
184
185
          /* iPods can carry both music and photos... */
186
          if (G_LIKELY (path_dcim != NULL))
187
            {
188
              /* ...so we need to prompt what to do */
189
              response = tvm_prompt (context, udi, "gnome-dev-ipod", _("Photos and Music"),
190
                                     _("Photos were found on your portable music player."),
191
                                     _("Would you like to import the photos or manage the music?"),
192
                                     _("Ig_nore"), GTK_RESPONSE_CANCEL,
193
                                     _("Import _Photos"), TVM_RESPONSE_PHOTOS,
194
                                     _("Manage _Music"), TVM_RESPONSE_MUSIC,
195
                                     NULL);
196
            }
197
          else
198
            {
199
              /* no photos, so we can manage only music */
1.1.2 by Lionel Le Folgoc
Import upstream version 0.3.80
200
              if(is_audio_player)
201
		      response = TVM_RESPONSE_MUSIC;
1 by Yves-Alexis Perez
Import upstream version 0.1.2
202
            }
203
204
          /* check what to do */
205
          if (response == TVM_RESPONSE_MUSIC)
206
            {
207
              /* run the preferred application to manage music players */
208
              result = tvm_run_command (context, udi, autoipod_command, device_file, mount_point, error);
209
            }
210
          else if (response == TVM_RESPONSE_PHOTOS)
211
            {
212
              /* run the preferred application to manage photos */
213
              result = tvm_run_command (context, udi, autophoto_command, device_file, mount_point, error);
214
            }
215
216
          /* cleanup */
217
          libhal_free_string (storage_udi);
218
          g_free (autophoto_command);
219
          g_free (path_dcim);
220
        }
221
    }
222
223
  /* cleanup */
224
  g_free (autoipod_command);
225
226
  return result;
227
}
228
229
230
231
static gboolean
232
tvm_block_device_autophoto (TvmPreferences *preferences,
233
                            LibHalContext  *context,
234
                            const gchar    *udi,
235
                            const gchar    *device_file,
236
                            const gchar    *mount_point,
237
                            GError        **error)
238
{
239
  gboolean result = FALSE;
240
  gboolean autophoto;
241
  gchar   *autophoto_command;
242
  gint     response;
243
244
  /* check autophoto support is enabled */
245
  g_object_get (G_OBJECT (preferences), "autophoto", &autophoto, "autophoto-command", &autophoto_command, NULL);
246
  if (G_LIKELY (autophoto && autophoto_command != NULL && *autophoto_command != '\0'))
247
    {
248
      /* check if we have photos on the volume */
1.1.1 by Lionel Le Folgoc
Import upstream version 0.2.0
249
      if (tvm_file_test (mount_point, "dcim", G_FILE_TEST_IS_DIR))
1 by Yves-Alexis Perez
Import upstream version 0.1.2
250
        {
251
          /* add the "content.photos" capability to this device */
252
          libhal_device_add_capability (context, udi, "content.photos", NULL);
253
254
          /* ask the user whether to import photos */
255
          response = tvm_prompt (context, udi, "camera-photo", _("Photo Import"),
256
                                 _("A photo card has been detected."),
257
                                 _("There are photos on the card. Would you like to add these photos to your album?"),
258
                                 _("Ig_nore"), GTK_RESPONSE_CANCEL,
259
                                 _("Import _Photos"), TVM_RESPONSE_PHOTOS,
260
                                 NULL);
261
          if (G_LIKELY (response == TVM_RESPONSE_PHOTOS))
262
            {
263
              /* run the preferred application to manage photos */
264
              result = tvm_run_command (context, udi, autophoto_command, device_file, mount_point, error);
265
            }
266
          else
267
            {
268
              /* pretend that we handled the device */
269
              result = TRUE;
270
            }
271
        }
272
    }
273
  g_free (autophoto_command);
274
275
  return result;
276
}
277
278
279
280
static gboolean
281
tvm_block_device_autorun (TvmPreferences *preferences,
282
                          LibHalContext  *context,
283
                          const gchar    *udi,
284
                          const gchar    *device_file,
285
                          const gchar    *mount_point,
286
                          GError        **error)
287
{
288
  struct stat statb_mount_point;
289
  struct stat statb_autoopen;
290
  gboolean    result;
291
  gboolean    autoopen;
292
  gboolean    autoplay;
293
  gboolean    autorun;
294
  gchar      *autoplay_command;
295
  gchar      *path_autoopen;
296
  gchar       line[1024];
297
  gchar      *message;
298
  gchar      *wine;
299
  gchar     **argv;
300
  FILE       *fp;
301
  gint        response;
302
  gint        n;
303
304
  /* check if autoplay video CDs/DVDs is enabled */
305
  g_object_get (G_OBJECT (preferences), "autoplay-video-cd", &autoplay, "autoplay-video-cd-command", &autoplay_command, NULL);
306
  if (G_LIKELY (autoplay))
307
    {
308
      /* check if we have a video CD or video DVD here */
1.1.1 by Lionel Le Folgoc
Import upstream version 0.2.0
309
      if (tvm_file_test (mount_point, "vcd", G_FILE_TEST_IS_DIR) || tvm_file_test (mount_point, "video_ts", G_FILE_TEST_IS_DIR))
1 by Yves-Alexis Perez
Import upstream version 0.1.2
310
        {
311
          /* try to spawn the preferred video CD/DVD-Player */
312
          result = tvm_run_command (context, udi, autoplay_command, device_file, mount_point, error);
313
          g_free (autoplay_command);
314
          return result;
315
        }
316
    }
317
  g_free (autoplay_command);
318
319
  /* check if autorun support is enabled */
320
  g_object_get (G_OBJECT (preferences), "autorun", &autorun, NULL);
321
  if (G_LIKELY (autorun))
322
    {
323
      /* "Autostart Files" (Desktop Application Autostart Specification) */
324
      static const gchar *AUTORUN[] = { ".autorun", "autorun", "autorun.sh" };
325
      for (n = 0; n < G_N_ELEMENTS (AUTORUN); ++n)
326
        {
327
          /* check if one of the autorun files is present and executable */
1.1.1 by Lionel Le Folgoc
Import upstream version 0.2.0
328
          if (tvm_file_test (mount_point, AUTORUN[n], G_FILE_TEST_IS_EXECUTABLE)
329
              && tvm_file_test (mount_point, AUTORUN[n], G_FILE_TEST_IS_REGULAR))
1 by Yves-Alexis Perez
Import upstream version 0.1.2
330
            {
331
              /* prompt the user whether to execute this file */
332
              message = g_strdup_printf (_("Would you like to allow \"%s\" to run?"), AUTORUN[n]);
333
              response = tvm_prompt (context, udi, "gnome-fs-executable", _("Auto-Run Confirmation"),
334
                                     _("Auto-Run capability detected"), message,
335
                                     _("Ig_nore"), GTK_RESPONSE_CANCEL,
336
                                     _("_Allow Auto-Run"), TVM_RESPONSE_AUTORUN,
337
                                     NULL);
338
              g_free (message);
339
340
              /* check if we should autorun */
341
              if (response == TVM_RESPONSE_AUTORUN)
342
                {
343
                  /* prepare argv to launch autorun file */
344
                  argv = g_new (gchar *, 2);
1.1.1 by Lionel Le Folgoc
Import upstream version 0.2.0
345
                  argv[0] = g_build_filename (mount_point, AUTORUN[n], NULL);
1 by Yves-Alexis Perez
Import upstream version 0.1.2
346
                  argv[1] = NULL;
347
348
                  /* try to launch the autorun file */
349
                  result = g_spawn_async (mount_point, argv, NULL, 0, NULL, NULL, NULL, error);
350
351
                  /* cleanup */
352
                  g_strfreev (argv);
353
354
                  /* outa here */
355
                  return result;
356
                }
357
            }
358
        }
359
360
      /* check if wine is present */
361
      wine = g_find_program_in_path ("wine");
362
      if (G_UNLIKELY (wine != NULL))
363
        {
364
          /* check if we have an autorun.exe file */
1.1.1 by Lionel Le Folgoc
Import upstream version 0.2.0
365
          if (tvm_file_test (mount_point, "autorun.exe", G_FILE_TEST_IS_REGULAR))
1 by Yves-Alexis Perez
Import upstream version 0.1.2
366
            {
367
              /* prompt the user whether to execute this file */
368
              message = g_strdup_printf (_("Would you like to allow \"%s\" to run?"), "autorun.exe");
369
              response = tvm_prompt (context, udi, "gnome-fs-executable", _("Auto-Run Confirmation"),
370
                                     _("Auto-Run capability detected"), message,
371
                                     _("Ig_nore"), GTK_RESPONSE_CANCEL,
372
                                     _("_Allow Auto-Run"), TVM_RESPONSE_AUTORUN,
373
                                     NULL);
374
              g_free (message);
375
376
              /* check if we should autorun */
377
              if (response == TVM_RESPONSE_AUTORUN)
378
                {
379
                  /* prepare argv to launch autorun.exe file */
380
                  argv = g_new (gchar *, 3);
381
                  argv[0] = wine;
382
                  argv[1] = g_strdup ("autorun.exe");
383
                  argv[2] = NULL;
384
385
                  /* try to launch the autorun.exe file via wine */
386
                  result = g_spawn_async (mount_point, argv, NULL, 0, NULL, NULL, NULL, error);
387
388
                  /* cleanup */
389
                  g_strfreev (argv);
390
391
                  /* outa here */
392
                  return result;
393
                }
394
            }
395
        }
396
      g_free (wine);
397
    }
398
399
  /* check if autoopen support is enabled */
400
  g_object_get (G_OBJECT (preferences), "autoopen", &autoopen, NULL);
401
  if (G_LIKELY (autoopen))
402
    {
403
      /* "Autoopen Files" (Desktop Application Autostart Specification) */
404
      static const gchar *AUTOOPEN[] = { ".autoopen", "autoopen" };
405
      for (n = 0; n < G_N_ELEMENTS (AUTOOPEN); ++n)
406
        {
407
          /* check if one of the autoopen files is present */
408
          path_autoopen = g_build_filename (mount_point, AUTOOPEN[n], NULL);
409
          fp = fopen (path_autoopen, "r");
410
          g_free (path_autoopen);
411
412
          /* check if the file could be opened */
413
          if (G_UNLIKELY (fp != NULL))
414
            {
415
              /* read the first line of the file (MUST NOT be an absolute path) */
416
              if (fgets (line, sizeof (line), fp) != NULL && !g_path_is_absolute (line))
417
                {
418
                  /* determine the absolute path of the file */
419
                  path_autoopen = g_build_filename (mount_point, line, NULL);
420
421
                  /* the file must exist on exactly this device */
422
                  if (stat (mount_point, &statb_mount_point) == 0 && stat (path_autoopen, &statb_autoopen) == 0
423
                      && S_ISREG (statb_autoopen.st_mode) && (statb_autoopen.st_mode & 0111) == 0
424
                      && (statb_mount_point.st_dev == statb_autoopen.st_dev))
425
                    {
426
                      /* prompt the user whether to autoopen this file */
427
                      message = g_strdup_printf (_("Would you like to open \"%s\"?"), AUTOOPEN[n]);
428
                      response = tvm_prompt (context, udi, "gnome-fs-executable", _("Auto-Open Confirmation"),
429
                                             _("Auto-Open capability detected"), message,
430
                                             _("Ig_nore"), GTK_RESPONSE_CANCEL,
431
                                             _("_Open"), TVM_RESPONSE_AUTOOPEN,
432
                                             NULL);
433
                      g_free (message);
434
435
                      /* check if we should autoopen */
436
                      if (response == TVM_RESPONSE_AUTOOPEN)
437
                        {
438
                          /* prepare the command to autoopen */
439
                          argv = g_new (gchar *, 3);
440
                          argv[0] = g_strdup ("Thunar");
441
                          argv[1] = path_autoopen;
442
                          argv[2] = NULL;
443
444
                          /* let Thunar open the file */
445
                          result = g_spawn_async (mount_point, argv, NULL, 0, NULL, NULL, NULL, error);
446
447
                          /* cleanup */
448
                          g_free (path_autoopen);
449
                          fclose (fp);
450
                          return result;
451
                        }
452
                    }
453
454
                  /* cleanup */
455
                  g_free (path_autoopen);
456
                }
457
458
              /* close the file handle */
459
              fclose (fp);
460
            }
461
        }
462
    }
463
464
  /* not handled */
465
  return FALSE;
466
}
467
468
469
470
static gboolean
471
tvm_block_device_mount (TvmPreferences *preferences,
472
                        LibHalContext  *context,
473
                        const gchar    *udi,
474
                        GError        **error)
475
{
476
  DBusError derror;
477
  gboolean  result = FALSE;
478
  GSList   *mount_points;
479
  gchar    *device_file;
480
  gchar    *argv[4];
481
  gint      status;
482
483
  /* check if we should ignore the volume, if so, pretend that we succeed */
484
  if (libhal_device_get_property_bool (context, udi, "volume.ignore", NULL))
485
    return TRUE;
486
487
  /* generate the command to mount the device */
488
  argv[0] = (gchar *) "exo-mount";
489
  argv[1] = (gchar *) "--hal-udi";
490
  argv[2] = (gchar *) udi;
491
  argv[3] = NULL;
492
493
  /* let exo-mount mount the device */
494
  if (!g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL, &status, error))
495
    {
496
      /* failed to spawn the exo-mount command */
497
      return FALSE;
498
    }
499
  else if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
500
    {
501
      /* exo-mount failed, but already displayed an error */
502
      return TRUE;
503
    }
504
505
  /* initalize D-Bus error */
506
  dbus_error_init (&derror);
507
508
  /* successfully mounted the device, determine the device file */
509
  device_file = libhal_device_get_property_string (context, udi, "block.device", &derror);
510
  if (G_UNLIKELY (device_file == NULL))
511
    {
512
      /* propagate the error */
513
      dbus_set_g_error (error, &derror);
514
      return FALSE;
515
    }
516
517
  /* determine the active mount point(s) for the device from the kernel */
518
  mount_points = exo_mount_point_list_matched (EXO_MOUNT_POINT_MATCH_ACTIVE | EXO_MOUNT_POINT_MATCH_DEVICE, device_file, NULL, NULL, error);
519
  if (G_LIKELY (mount_points != NULL))
520
    {
521
      /* try to handled the mounted volume */
522
      result = tvm_block_device_mounted (preferences, context, udi, device_file, ((ExoMountPoint *) mount_points->data)->folder, error);
523
524
      /* release the mount points */
525
      g_slist_foreach (mount_points, (GFunc) exo_mount_point_free, NULL);
526
      g_slist_free (mount_points);
527
    }
528
529
  /* release the device file */
530
  libhal_free_string (device_file);
531
532
  return result;
533
}
534
535
536
537
538
static gboolean
539
tvm_block_device_mounted (TvmPreferences *preferences,
540
                          LibHalContext  *context,
541
                          const gchar    *udi,
542
                          const gchar    *device_file,
543
                          const gchar    *mount_point,
544
                          GError        **error)
545
{
546
  gboolean autobrowse;
547
  gboolean result;
548
  GError  *err = NULL;
549
550
  /* check if we have a portable media player here */
551
  result = tvm_block_device_autoipod (preferences, context, udi, device_file, mount_point, &err);
552
  if (G_LIKELY (!result && err == NULL))
553
    {
554
      /* check if we have a digital photo camera here */
555
      result = tvm_block_device_autophoto (preferences, context, udi, device_file, mount_point, &err);
556
      if (G_LIKELY (!result && err == NULL))
557
        {
558
          /* try autorun (video CD/DVD, autoopen, etc.) first */
559
          result = tvm_block_device_autorun (preferences, context, udi, device_file, mount_point, &err);
560
          if (G_LIKELY (!result && err == NULL))
561
            {
562
              /* check if we should autobrowse the mount point folder */
563
              g_object_get (G_OBJECT (preferences), "autobrowse", &autobrowse, NULL);
564
              if (G_LIKELY (autobrowse))
565
                {
566
                  /* open the mount point folder in Thunar */
567
                  result = tvm_run_command (context, udi, "Thunar %m", device_file, mount_point, &err);
568
                }
569
            }
570
        }
571
    }
572
573
  /* check if we need to propagate an error */
574
  if (G_UNLIKELY (err != NULL))
575
    {
576
      /* propagate the error */
577
      g_propagate_error (error, err);
578
      result = FALSE;
579
    }
580
581
  return result;
582
}
583
584
585
586
/**
587
 * tvm_block_device_added:
588
 * @preferences : a #TvmPreferences.
589
 * @context     : a #LibHalContext.
590
 * @udi         : the HAL device UDI of the newly added block device.
591
 * @capability  : the capability, which caused this handler to be run.
592
 * @error       : return location for errors or %NULL.
593
 *
594
 * See #TvmDeviceCallback for further information.
595
 *
596
 * Return value: %TRUE if handled, %FALSE if not handled or an
597
 *               unrecoverable error occurred.
598
 **/
599
gboolean
600
tvm_block_device_added (TvmPreferences *preferences,
601
                        LibHalContext  *context,
602
                        const gchar    *udi,
603
                        const gchar    *capability,
604
                        GError        **error)
605
{
606
  DBusError derror;
607
  gboolean  disc_has_audio;
608
  gboolean  disc_has_data;
609
  gboolean  automount;
610
  gboolean  autoplay;
611
  gboolean  is_cdrom;
1.1.1 by Lionel Le Folgoc
Import upstream version 0.2.0
612
  gboolean  has_filesystem;
1.1.2 by Lionel Le Folgoc
Import upstream version 0.3.80
613
  gboolean  has_crypto;
1 by Yves-Alexis Perez
Import upstream version 0.1.2
614
  gchar    *storage_udi;
615
  gchar    *drive_type;
1.1.1 by Lionel Le Folgoc
Import upstream version 0.2.0
616
  gchar    *fsusage;
1 by Yves-Alexis Perez
Import upstream version 0.1.2
617
  gint      response;
618
619
  g_return_val_if_fail (exo_hal_udi_validate (udi, -1, NULL), FALSE);
620
  g_return_val_if_fail (TVM_IS_PREFERENCES (preferences), FALSE);
621
  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
622
  g_return_val_if_fail (capability != NULL, FALSE);
623
  g_return_val_if_fail (context != NULL, FALSE);
624
625
  /* initialize D-Bus error */
626
  dbus_error_init (&derror);
627
628
  /* verify that we have a mountable volume here */
629
  if (!libhal_device_get_property_bool (context, udi, "block.is_volume", &derror))
630
    {
631
err0: /* check if we have an error to propagate */
632
      if (dbus_error_is_set (&derror))
633
        {
634
          /* propagate the error */
635
          dbus_set_g_error (error, &derror);
636
          dbus_error_free (&derror);
637
        }
638
639
      return FALSE;
640
    }
641
642
  /* determine the HAL UDI of the backing storage device */
643
  storage_udi = libhal_device_get_property_string (context, udi, "block.storage_device", &derror);
644
  if (G_UNLIKELY (storage_udi == NULL))
645
    goto err0;
646
647
  /* if the partition_table_changed flag is set, we don't want to mount as a partitioning tool might be modifying this device */
648
  if (libhal_device_get_property_bool (context, storage_udi, "storage.partition_table_changed", NULL))
649
    {
650
err1: libhal_free_string (storage_udi);
651
      goto err0;
652
    }
653
654
  /* check if this device supports removable media */
655
  if (libhal_device_get_property_bool (context, storage_udi, "storage.removable", NULL))
656
    {
657
      /* check if the device is locked */
658
      if (libhal_device_get_property_bool (context, storage_udi, "info.locked", NULL))
659
        {
660
          /* pretend that we handled the device */
661
          libhal_free_string (storage_udi);
662
          return TRUE;
663
        }
664
665
      /* determine the drive type */
666
      drive_type = libhal_device_get_property_string (context, storage_udi, "storage.drive_type", &derror);
667
      if (G_UNLIKELY (drive_type == NULL))
668
        goto err1;
669
670
      /* check if we have a CD-ROM here */
671
      is_cdrom = (strcmp (drive_type, "cdrom") == 0);
672
673
      /* we don't need the storage UDI any more */
674
      libhal_free_string (storage_udi);
675
676
      /* free the drive type */
677
      libhal_free_string (drive_type);
678
679
      /* CD-ROMs deserve special handling */
680
      if (G_LIKELY (is_cdrom))
681
        {
682
          /* check for blank discs */
683
          if (libhal_device_get_property_bool (context, udi, "volume.disc.is_blank", NULL))
684
            {
685
              /* run the preferred CD-Burner application */
686
              return tvm_run_cdburner (preferences, context, udi, error);
687
            }
688
          else
689
            {
690
              /* check if we have DATA/AUDIO tracks */
691
              disc_has_audio = libhal_device_get_property_bool (context, udi, "volume.disc.has_audio", NULL);
692
              disc_has_data = libhal_device_get_property_bool (context, udi, "volume.disc.has_data", NULL);
693
              if (G_UNLIKELY (disc_has_audio && disc_has_data))
694
                {
695
                  /* check if we need to prompt the user */
696
                  g_object_get (G_OBJECT (preferences), "automount-media", &automount, "autoplay-audio-cd", &autoplay, NULL);
697
                  if (G_LIKELY (automount && autoplay))
698
                    {
699
                      /* ask what do with the mixed audio/data disc */
700
                      response = tvm_prompt (context, udi, "gnome-dev-cdrom-audio", _("Audio / Data CD"),
701
                                             _("The CD in the drive contains both music and files."),
702
	                                           _("Would you like to listen to music or browse the files?"),
703
                                             _("Ig_nore"), GTK_RESPONSE_CANCEL,
704
                                             _("_Browse Files"), TVM_RESPONSE_BROWSE,
705
                                             _("_Play CD"), TVM_RESPONSE_PLAY,
706
                                             NULL);
707
                      switch (response)
708
                        {
709
                        case TVM_RESPONSE_PLAY:
710
                          goto autoplay_disc;
711
712
                        case TVM_RESPONSE_BROWSE:
713
                          goto automount_disc;
714
715
                        default:
716
                          break;
717
                        }
718
                    }
719
                  else if (automount)
720
                    {
721
                      /* just automount the media */
722
                      goto automount_disc;
723
                    }
724
                  else if (autoplay)
725
                    {
726
                      /* just autoplay the disc */
727
                      goto autoplay_disc;
728
                    }
729
                }
730
              else if (G_LIKELY (disc_has_audio))
731
                {
732
autoplay_disc:    /* run the preferred CD-Player application */
733
                  return tvm_run_cdplayer (preferences, context, udi, error);
734
                }
735
              else if (G_LIKELY (disc_has_data))
736
                {
737
automount_disc:   /* check if we should automount removable media */
738
                  g_object_get (G_OBJECT (preferences), "automount-media", &automount, NULL);
739
                  if (G_LIKELY (automount))
740
                    {
741
                      /* try to mount the CD-ROM in the disc */
742
                      return tvm_block_device_mount (preferences, context, udi, error);
743
                    }
744
                }
745
            }
746
        }
747
    }
748
  else
749
    {
750
      /* we don't need the storage UDI any more */
751
      libhal_free_string (storage_udi);
752
    }
753
1.1.2 by Lionel Le Folgoc
Import upstream version 0.3.80
754
  /* determine the file system usage of the volume */
1.1.1 by Lionel Le Folgoc
Import upstream version 0.2.0
755
  fsusage = libhal_device_get_property_string (context, udi, "volume.fsusage", NULL);
1.1.2 by Lionel Le Folgoc
Import upstream version 0.3.80
756
  has_crypto = (G_UNLIKELY (fsusage != NULL && strcmp (fsusage, "crypto") == 0));
757
  has_filesystem = (G_LIKELY (fsusage != NULL && strcmp (fsusage, "filesystem") == 0));
1.1.1 by Lionel Le Folgoc
Import upstream version 0.2.0
758
  libhal_free_string (fsusage);
1.1.2 by Lionel Le Folgoc
Import upstream version 0.3.80
759
760
  /* check if we have a crypto volume to setup here */
761
  if (G_UNLIKELY (has_crypto))
762
    {
763
      /* try to setup the crypto volume */
764
      return tvm_crypto_volume_setup (preferences, context, udi, error);
765
    }
766
  else if (G_LIKELY (has_filesystem))
767
    {
768
      /* check if we should automount drives, otherwise, we're done here */
769
      g_object_get (G_OBJECT (preferences), "automount-drives", &automount, NULL);
770
      if (G_UNLIKELY (!automount))
771
        return FALSE;
772
773
      /* try to mount the block device */
774
      return tvm_block_device_mount (preferences, context, udi, error);
775
    }
776
777
  return FALSE;
1 by Yves-Alexis Perez
Import upstream version 0.1.2
778
}
779
780
781
782