~ubuntu-branches/debian/squeeze/devicekit-disks/squeeze

« back to all changes in this revision

Viewing changes to src/devkit-disks-device.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Biebl, Martin Pitt, Michael Biebl
  • Date: 2009-11-05 14:26:06 UTC
  • mfrom: (1.2.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20091105142606-gv7df6uk7s7voro1
Tags: 009-1
[ Martin Pitt ]
* New upstream release.
* 08-dont-probe-dm-devices.patch: Update for new release.
* Drop 07-media-player-icon.patch as well, it was included upstream in 008.
* debian/devicekit-disks.postinst: Update udev after installation to pick up
  (changes of) our udev rules. (Closes: #548758)
* debian/control: Add missing udev dependency.
* debian/control: Add dependencies to various file system tools which DK-D
  uses to implement its functionality:
  - Recommends: dosfstools, mtools, ntfs-3g (the more popular ones)
  - Suggests: xfsprogs, reiserfsprogs, mdadm, cryptsetup
* Add 00git-lv-nopolicy.patch: Fix LVM LVs to have NOPOLICY=1 again.
  (Accepted into upstream trunk.)

[ Michael Biebl ]
* debian/patches/08-dont-probe-dm-devices.patch
  - Skip probing dm devices (using devkit-disks-part-id) for which DM_HIDE
    is set. (Closes: #545032)
  - Instead of checking for DKD_DM_STATE, test if DM_NAME is setup.
* Add debian/README.source which refers to the quilt documentation.
* debian/control: Add Recommends on ntfsprogs for proper NTFS support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
83
83
 
84
84
static gboolean devkit_disks_device_local_partitions_are_busy (DevkitDisksDevice *device);
85
85
static gboolean devkit_disks_device_local_logical_partitions_are_busy (DevkitDisksDevice *device);
 
86
static gboolean devkit_disks_device_has_logical_partitions (DevkitDisksDevice *device);
86
87
 
87
88
 
88
89
static gboolean luks_get_uid_from_dm_name (const char *dm_name, uid_t *out_uid);
226
227
        PROP_DRIVE_ATA_SMART_BLOB,
227
228
 
228
229
        PROP_LINUX_MD_COMPONENT_LEVEL,
 
230
        PROP_LINUX_MD_COMPONENT_POSITION,
229
231
        PROP_LINUX_MD_COMPONENT_NUM_RAID_DEVICES,
230
232
        PROP_LINUX_MD_COMPONENT_UUID,
231
233
        PROP_LINUX_MD_COMPONENT_HOME_HOST,
564
566
        case PROP_LINUX_MD_COMPONENT_LEVEL:
565
567
                g_value_set_string (value, device->priv->linux_md_component_level);
566
568
                break;
 
569
        case PROP_LINUX_MD_COMPONENT_POSITION:
 
570
                g_value_set_int (value, device->priv->linux_md_component_position);
 
571
                break;
567
572
        case PROP_LINUX_MD_COMPONENT_NUM_RAID_DEVICES:
568
573
                g_value_set_int (value, device->priv->linux_md_component_num_raid_devices);
569
574
                break;
1014
1019
                g_param_spec_string ("linux-md-component-level", NULL, NULL, NULL, G_PARAM_READABLE));
1015
1020
        g_object_class_install_property (
1016
1021
                object_class,
 
1022
                PROP_LINUX_MD_COMPONENT_POSITION,
 
1023
                g_param_spec_int ("linux-md-component-position", NULL, NULL, 0, G_MAXINT, 0, G_PARAM_READABLE));
 
1024
        g_object_class_install_property (
 
1025
                object_class,
1017
1026
                PROP_LINUX_MD_COMPONENT_NUM_RAID_DEVICES,
1018
1027
                g_param_spec_int ("linux-md-component-num-raid-devices", NULL, NULL, 0, G_MAXINT, 0, G_PARAM_READABLE));
1019
1028
        g_object_class_install_property (
1125
1134
        device = DEVKIT_DISKS_DEVICE (object);
1126
1135
        g_return_if_fail (device->priv != NULL);
1127
1136
 
1128
 
        g_debug ("finalizing %s", device->priv->native_path);
 
1137
        /* g_debug ("finalizing %s", device->priv->native_path); */
1129
1138
 
1130
1139
        g_object_unref (device->priv->d);
1131
1140
        g_object_unref (device->priv->daemon);
1283
1292
 
1284
1293
        device->priv->object_path = compute_object_path (device->priv->native_path);
1285
1294
 
 
1295
        /* safety first */
1286
1296
        if (dbus_g_connection_lookup_g_object (device->priv->system_bus_connection,
1287
1297
                                               device->priv->object_path) != NULL) {
1288
 
                /* TODO: see devkit_disks_device_removed() for where we want to unregister the object but
1289
 
                 * we're missing the API. So do it manually here if we are forced to do so...
1290
 
                 */
1291
 
 
1292
 
                g_print ("**** HACK: Wanting to register object at path `%s' but there is already an "
1293
 
                         "object there. Using a hack to move it out of the way.\n",
 
1298
                g_error ("**** HACK: Wanting to register object at path `%s' but there is already an "
 
1299
                         "object there. This is an internal error in the daemon. Aborting.\n",
1294
1300
                         device->priv->object_path);
1295
 
 
1296
 
                dbus_connection_unregister_object_path (dbus_g_connection_get_connection (device->priv->system_bus_connection),
1297
 
                                                        device->priv->object_path);
1298
1301
        }
1299
1302
 
1300
1303
        dbus_g_connection_register_g_object (device->priv->system_bus_connection,
1624
1627
update_info_id (DevkitDisksDevice *device)
1625
1628
{
1626
1629
        gchar *decoded_string;
 
1630
        const gchar *partition_scheme;
 
1631
        gint partition_type;
 
1632
 
 
1633
        partition_scheme = g_udev_device_get_property (device->priv->d, "DKD_PARTITION_SCHEME");
 
1634
        partition_type = g_udev_device_get_property_as_int (device->priv->d, "DKD_PARTITION_TYPE");
 
1635
        if (g_strcmp0 (partition_scheme, "mbr") == 0 &&
 
1636
            (partition_type == 0x05 || partition_type == 0x0f || partition_type == 0x85)) {
 
1637
                devkit_disks_device_set_id_usage (device, "");
 
1638
                devkit_disks_device_set_id_type (device, "");
 
1639
                devkit_disks_device_set_id_version (device, "");
 
1640
                devkit_disks_device_set_id_label (device, "");
 
1641
                devkit_disks_device_set_id_uuid (device, "");
 
1642
                goto out;
 
1643
        }
1627
1644
 
1628
1645
        devkit_disks_device_set_id_usage (device, g_udev_device_get_property (device->priv->d, "ID_FS_USAGE"));
1629
1646
        devkit_disks_device_set_id_type (device, g_udev_device_get_property (device->priv->d, "ID_FS_TYPE"));
1637
1654
        }
1638
1655
        devkit_disks_device_set_id_uuid (device, g_udev_device_get_property (device->priv->d, "ID_FS_UUID"));
1639
1656
 
 
1657
 out:
1640
1658
        return TRUE;
1641
1659
}
1642
1660
 
2255
2273
                const gchar *md_comp_version;
2256
2274
                gchar *md_name;
2257
2275
                gchar *s;
 
2276
                int md_comp_position;
 
2277
 
 
2278
                md_comp_position = -1;
2258
2279
 
2259
2280
                devkit_disks_device_set_device_is_linux_md_component (device, TRUE);
2260
2281
 
2271
2292
                                gchar *dev_name;
2272
2293
                                gchar *md_dev_path;
2273
2294
                                gchar *state_contents;
 
2295
                                gchar *slot_contents;
 
2296
                                gint slot_number;
 
2297
                                gchar *endp;
2274
2298
 
2275
2299
                                dev_name = g_path_get_basename (device->priv->native_path);
2276
2300
                                md_dev_path = g_strdup_printf ("%s/md/dev-%s", holder->priv->native_path, dev_name);
2278
2302
                                g_strstrip (state_contents);
2279
2303
                                state_tokens = g_strsplit (state_contents, ",", 0);
2280
2304
 
 
2305
                                slot_contents = sysfs_get_string (md_dev_path, "slot");
 
2306
                                g_strstrip (slot_contents);
 
2307
                                slot_number = strtol (slot_contents, &endp, 0);
 
2308
                                if (endp != NULL && *endp == '\0') {
 
2309
                                        md_comp_position = slot_number;
 
2310
                                }
 
2311
 
 
2312
                                g_free (slot_contents);
2281
2313
                                g_free (state_contents);
2282
2314
                                g_free (md_dev_path);
2283
2315
                                g_free (dev_name);
2310
2342
                md_comp_version = device->priv->id_version;
2311
2343
 
2312
2344
                devkit_disks_device_set_linux_md_component_level (device, md_comp_level);
 
2345
                devkit_disks_device_set_linux_md_component_position (device, md_comp_position);
2313
2346
                devkit_disks_device_set_linux_md_component_num_raid_devices (device, md_comp_num_raid_devices);
2314
2347
                devkit_disks_device_set_linux_md_component_uuid (device, md_comp_uuid);
2315
2348
                devkit_disks_device_set_linux_md_component_home_host (device, md_comp_home_host);
2320
2353
        } else {
2321
2354
                devkit_disks_device_set_device_is_linux_md_component (device, FALSE);
2322
2355
                devkit_disks_device_set_linux_md_component_level (device, NULL);
 
2356
                devkit_disks_device_set_linux_md_component_position (device, -1);
2323
2357
                devkit_disks_device_set_linux_md_component_num_raid_devices (device, 0);
2324
2358
                devkit_disks_device_set_linux_md_component_uuid (device, NULL);
2325
2359
                devkit_disks_device_set_linux_md_component_home_host (device, NULL);
2831
2865
 
2832
2866
/* ---------------------------------------------------------------------------------------------------- */
2833
2867
 
 
2868
typedef struct {
 
2869
        guint idle_id;
 
2870
        DevkitDisksDevice *device;
 
2871
} UpdateInfoInIdleData;
 
2872
 
 
2873
static void
 
2874
update_info_in_idle_device_unreffed (gpointer user_data,
 
2875
                                     GObject *where_the_object_was)
 
2876
{
 
2877
        UpdateInfoInIdleData *data = user_data;
 
2878
        g_source_remove (data->idle_id);
 
2879
}
 
2880
 
 
2881
static void
 
2882
update_info_in_idle_data_free (UpdateInfoInIdleData *data)
 
2883
{
 
2884
        g_object_weak_unref (G_OBJECT (data->device),
 
2885
                             update_info_in_idle_device_unreffed,
 
2886
                             data);
 
2887
        g_free (data);
 
2888
}
 
2889
 
 
2890
static gboolean
 
2891
update_info_in_idle_cb (gpointer user_data)
 
2892
{
 
2893
        UpdateInfoInIdleData *data = user_data;
 
2894
 
 
2895
        /* this indirectly calls update_info and also removes the device
 
2896
         * if it wants to be removed (e.g. if update_info() returns FALSE)
 
2897
         */
 
2898
        devkit_disks_daemon_local_synthesize_changed (data->device->priv->daemon, data->device);
 
2899
 
 
2900
        return FALSE; /* remove source */
 
2901
}
 
2902
 
 
2903
/**
 
2904
 * update_info_in_idle:
 
2905
 * @device: A #DevkitDisksDevice.
 
2906
 *
 
2907
 * Like update_info() but does the update in idle. Takes a weak ref to
 
2908
 * @device and cancels the update if @device is unreffed.
 
2909
 */
 
2910
static void
 
2911
update_info_in_idle (DevkitDisksDevice *device)
 
2912
{
 
2913
        UpdateInfoInIdleData *data;
 
2914
 
 
2915
        data = g_new0 (UpdateInfoInIdleData, 1);
 
2916
        data->device = device;
 
2917
        data->idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE,
 
2918
                                         update_info_in_idle_cb,
 
2919
                                         data,
 
2920
                                         (GDestroyNotify) update_info_in_idle_data_free);
 
2921
 
 
2922
        g_object_weak_ref (G_OBJECT (device),
 
2923
                           update_info_in_idle_device_unreffed,
 
2924
                           data);
 
2925
}
 
2926
 
2834
2927
/**
2835
2928
 * update_info:
2836
2929
 * @device: the device
2891
2984
                goto out;
2892
2985
        }
2893
2986
 
 
2987
        /* ignore dm devices that are not active */
 
2988
        if (g_str_has_prefix (g_udev_device_get_name (device->priv->d), "dm-") &&
 
2989
            g_udev_device_get_property (device->priv->d, "DKD_DM_STATE") == NULL)
 
2990
                goto out;
 
2991
 
2894
2992
        major = g_udev_device_get_property_as_int (device->priv->d, "MAJOR");
2895
2993
        minor = g_udev_device_get_property_as_int (device->priv->d, "MINOR");
2896
2994
        device->priv->dev = makedev (major, minor);
3172
3270
         * We have to do this because the kernel doesn't generate any 'change' event
3173
3271
         * when slaves/ or holders/ change. This is unfortunate because we *need* such
3174
3272
         * a change event to update properties devices (for example: luks_holder).
 
3273
         *
 
3274
         * We do the update in idle because the update may depend on the device
 
3275
         * currently being processed being added.
3175
3276
         */
3176
3277
 
3177
3278
        cur_slaves_objpath = dup_list_from_ptrarray (device->priv->slaves_objpath);
3192
3293
                //g_debug ("### %s added slave %s", device->priv->object_path, objpath2);
3193
3294
                device2 = devkit_disks_daemon_local_find_by_object_path (device->priv->daemon, objpath2);
3194
3295
                if (device2 != NULL) {
3195
 
                        update_info (device2);
 
3296
                        update_info_in_idle (device2);
3196
3297
                } else {
3197
3298
                        g_print ("**** NOTE: %s added non-existant slave %s\n", device->priv->object_path, objpath2);
3198
3299
                }
3204
3305
                //g_debug ("### %s removed slave %s", device->priv->object_path, objpath2);
3205
3306
                device2 = devkit_disks_daemon_local_find_by_object_path (device->priv->daemon, objpath2);
3206
3307
                if (device2 != NULL) {
3207
 
                        update_info (device2);
 
3308
                        update_info_in_idle (device2);
3208
3309
                } else {
3209
3310
                        //g_debug ("### %s removed non-existant slave %s", device->priv->object_path, objpath2);
3210
3311
                }
3222
3323
                //g_debug ("### %s added holder %s", device->priv->object_path, objpath2);
3223
3324
                device2 = devkit_disks_daemon_local_find_by_object_path (device->priv->daemon, objpath2);
3224
3325
                if (device2 != NULL) {
3225
 
                        update_info (device2);
 
3326
                        update_info_in_idle (device2);
3226
3327
                } else {
3227
3328
                        g_print ("**** NOTE: %s added non-existant holder %s\n", device->priv->object_path, objpath2);
3228
3329
                }
3234
3335
                //g_debug ("### %s removed holder %s", device->priv->object_path, objpath2);
3235
3336
                device2 = devkit_disks_daemon_local_find_by_object_path (device->priv->daemon, objpath2);
3236
3337
                if (device2 != NULL) {
3237
 
                        update_info (device2);
 
3338
                        update_info_in_idle (device2);
3238
3339
                } else {
3239
3340
                        //g_debug ("### %s removed non-existant holder %s", device->priv->object_path, objpath2);
3240
3341
                }
3397
3498
        return ret;
3398
3499
}
3399
3500
 
 
3501
static gboolean
 
3502
devkit_disks_device_has_logical_partitions (DevkitDisksDevice *device)
 
3503
{
 
3504
        gboolean ret;
 
3505
        GList *l;
 
3506
        GList *devices;
 
3507
 
 
3508
        ret = FALSE;
 
3509
 
 
3510
        devices = devkit_disks_daemon_local_get_all_devices (device->priv->daemon);
 
3511
        for (l = devices; l != NULL; l = l->next) {
 
3512
                DevkitDisksDevice *d = DEVKIT_DISKS_DEVICE (l->data);
 
3513
 
 
3514
                if (d->priv->device_is_partition &&
 
3515
                    d->priv->partition_slave != NULL &&
 
3516
                    g_strcmp0 (d->priv->partition_slave, device->priv->object_path) == 0 &&
 
3517
                    g_strcmp0 (d->priv->partition_scheme, "mbr") == 0 &&
 
3518
                    d->priv->partition_number >= 5) {
 
3519
 
 
3520
                        ret = TRUE;
 
3521
                }
 
3522
        }
 
3523
 
 
3524
        g_list_free (devices);
 
3525
 
 
3526
        return ret;
 
3527
}
 
3528
 
3400
3529
void
3401
3530
devkit_disks_device_removed (DevkitDisksDevice *device)
3402
3531
{
3404
3533
 
3405
3534
        device->priv->removed = TRUE;
3406
3535
 
3407
 
        /* TODO: this is in a yet to be released version of dbus-glib, use it when available
3408
 
 
3409
3536
        dbus_g_connection_unregister_g_object (device->priv->system_bus_connection,
3410
3537
                                               G_OBJECT (device));
3411
 
        */
 
3538
        g_assert (dbus_g_connection_lookup_g_object (device->priv->system_bus_connection,
 
3539
                                                     device->priv->object_path) == NULL);
3412
3540
 
3413
3541
        /* device is now removed; update all slaves and holders */
3414
3542
        for (n = 0; n < device->priv->slaves_objpath->len; n++) {
3674
3802
        gpointer user_data;
3675
3803
        GDestroyNotify user_data_destroy_func;
3676
3804
        gboolean was_cancelled;
 
3805
        gboolean udev_settle;
 
3806
        int status;
3677
3807
 
3678
3808
        int stderr_fd;
3679
3809
        GIOChannel *error_channel;
3725
3855
}
3726
3856
 
3727
3857
static void
3728
 
job_child_watch_cb (GPid pid, int status, gpointer user_data)
 
3858
job_complete (Job *job)
3729
3859
{
3730
 
        char *buf;
3731
 
        gsize buf_size;
3732
 
        Job *job = user_data;
3733
 
 
3734
 
        if (g_io_channel_read_to_end (job->error_channel, &buf, &buf_size, NULL) == G_IO_STATUS_NORMAL) {
3735
 
                g_string_append_len (job->error_string, buf, buf_size);
3736
 
                g_free (buf);
3737
 
        }
3738
 
        if (g_io_channel_read_to_end (job->out_channel, &buf, &buf_size, NULL) == G_IO_STATUS_NORMAL) {
3739
 
                g_string_append_len (job->stdout_string, buf, buf_size);
3740
 
                g_free (buf);
3741
 
        }
3742
 
 
3743
 
        g_print ("helper(pid %5d): completed with exit code %d\n", job->pid, WEXITSTATUS (status));
3744
 
 
3745
3860
        if (job->device != NULL && job->job_id != NULL) {
3746
3861
                job->device->priv->job_in_progress = FALSE;
3747
3862
                g_free (job->device->priv->job_id);
3756
3871
        job->job_completed_func (job->context,
3757
3872
                                 job->device,
3758
3873
                                 job->was_cancelled,
3759
 
                                 status,
 
3874
                                 job->status,
3760
3875
                                 job->error_string->str,
3761
3876
                                 job->stdout_string->str,
3762
3877
                                 job->user_data);
3764
3879
        if (job->device != NULL && job->job_id != NULL) {
3765
3880
                emit_job_changed (job->device);
3766
3881
        }
 
3882
 
3767
3883
        job_free (job);
3768
3884
}
3769
3885
 
3770
3886
static void
 
3887
job_udevadm_settle_child_cb (GPid     pid,
 
3888
                             gint     status,
 
3889
                             gpointer user_data)
 
3890
{
 
3891
        Job *job = user_data;
 
3892
        job_complete (job);
 
3893
}
 
3894
 
 
3895
static void
 
3896
job_child_watch_cb (GPid pid, int status, gpointer user_data)
 
3897
{
 
3898
        char *buf;
 
3899
        gsize buf_size;
 
3900
        Job *job = user_data;
 
3901
 
 
3902
        if (g_io_channel_read_to_end (job->error_channel, &buf, &buf_size, NULL) == G_IO_STATUS_NORMAL) {
 
3903
                g_string_append_len (job->error_string, buf, buf_size);
 
3904
                g_free (buf);
 
3905
        }
 
3906
        if (g_io_channel_read_to_end (job->out_channel, &buf, &buf_size, NULL) == G_IO_STATUS_NORMAL) {
 
3907
                g_string_append_len (job->stdout_string, buf, buf_size);
 
3908
                g_free (buf);
 
3909
        }
 
3910
 
 
3911
        g_print ("helper(pid %5d): completed with exit code %d\n", job->pid, WEXITSTATUS (status));
 
3912
 
 
3913
        job->status = status;
 
3914
 
 
3915
        /* if requested, run 'udevadm settle' on success */
 
3916
        if (!job->was_cancelled && WIFEXITED (status) && WEXITSTATUS (status) == 0 && job->udev_settle) {
 
3917
                GError *error;
 
3918
                gchar *argv[] = {"udevadm", "settle", "--quiet", NULL};
 
3919
                GPid udevadm_pid;
 
3920
 
 
3921
                error = NULL;
 
3922
                if (!g_spawn_async (NULL,
 
3923
                                    argv,
 
3924
                                    NULL,
 
3925
                                    G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
 
3926
                                    NULL,
 
3927
                                    NULL,
 
3928
                                    &udevadm_pid,
 
3929
                                    &error)) {
 
3930
                        g_warning ("Error running 'udevadm settle --quiet': %s", error->message);
 
3931
                        g_error_free (error);
 
3932
 
 
3933
                        job_complete (job);
 
3934
                } else {
 
3935
                        g_child_watch_add (udevadm_pid,
 
3936
                                           job_udevadm_settle_child_cb,
 
3937
                                           job);
 
3938
                }
 
3939
        } else {
 
3940
                /* return immediately on error */
 
3941
                job_complete (job);
 
3942
        }
 
3943
}
 
3944
 
 
3945
static void
3771
3946
job_cancel (DevkitDisksDevice *device)
3772
3947
{
3773
3948
        g_return_if_fail (device->priv->job != NULL);
3904
4079
         char                 **argv,
3905
4080
         const char            *stdin_str,
3906
4081
         JobCompletedFunc       job_completed_func,
 
4082
         gboolean               udev_settle, /* if TRUE, runs udevsettle before returning if the command succeeded */
3907
4083
         gpointer               user_data,
3908
4084
         GDestroyNotify         user_data_destroy_func)
3909
4085
{
3936
4112
        job->stdin_cursor = job->stdin_str;
3937
4113
        job->stdout_string = g_string_sized_new (1024);
3938
4114
        job->job_id = g_strdup (job_id);
 
4115
        job->udev_settle = udev_settle;
3939
4116
 
3940
4117
        if (device != NULL && job_id != NULL) {
3941
4118
                g_free (job->device->priv->job_id);
4445
4622
                        throw_error (context,
4446
4623
                                     DEVKIT_DISKS_ERROR_CANCELLED,
4447
4624
                                     "Job was cancelled");
 
4625
                } else if (WEXITSTATUS (status) == 32) {
 
4626
                    throw_error (context,
 
4627
                            DEVKIT_DISKS_ERROR_FILESYSTEM_DRIVER_MISSING ,
 
4628
                            "Error mounting: %s",
 
4629
                            stderr);
4448
4630
                } else {
4449
4631
                        throw_error (context,
4450
4632
                                     DEVKIT_DISKS_ERROR_FAILED,
4661
4843
                      argv,
4662
4844
                      NULL,
4663
4845
                      filesystem_mount_completed_cb,
 
4846
                      FALSE,
4664
4847
                      filesystem_mount_data_new (mount_point, remove_dir_on_unmount),
4665
4848
                      (GDestroyNotify) filesystem_mount_data_free)) {
4666
4849
                if (remove_dir_on_unmount) {
4846
5029
                      argv,
4847
5030
                      NULL,
4848
5031
                      filesystem_unmount_completed_cb,
 
5032
                      FALSE,
4849
5033
                      g_strdup (mount_path),
4850
5034
                      g_free)) {
4851
5035
                goto out;
5036
5220
                      argv,
5037
5221
                      NULL,
5038
5222
                      filesystem_list_open_files_completed_cb,
 
5223
                      FALSE,
5039
5224
                      NULL,
5040
5225
                      NULL)) {
5041
5226
                goto out;
5156
5341
                      argv,
5157
5342
                      NULL,
5158
5343
                      drive_eject_completed_cb,
 
5344
                      FALSE,
5159
5345
                      NULL,
5160
5346
                      NULL)) {
5161
5347
                goto out;
5281
5467
                      argv,
5282
5468
                      NULL,
5283
5469
                      drive_detach_completed_cb,
 
5470
                      FALSE,
5284
5471
                      NULL,
5285
5472
                      NULL)) {
5286
5473
                goto out;
5396
5583
                      argv,
5397
5584
                      NULL,
5398
5585
                      filesystem_check_completed_cb,
 
5586
                      FALSE,
5399
5587
                      NULL,
5400
5588
                      NULL)) {
5401
5589
                goto out;
5474
5662
        char *size_as_string;
5475
5663
        char *part_number_as_string;
5476
5664
        DevkitDisksDevice *enclosing_device;
 
5665
        const gchar *partition_scheme;
 
5666
        gint partition_type;
5477
5667
 
5478
5668
        offset_as_string = NULL;
5479
5669
        size_as_string = NULL;
5508
5698
                goto out;
5509
5699
        }
5510
5700
 
 
5701
        /* don't allow deleting an extended partition if we have any logical partitions */
 
5702
        partition_scheme = g_udev_device_get_property (device->priv->d, "DKD_PARTITION_SCHEME");
 
5703
        partition_type = g_udev_device_get_property_as_int (device->priv->d, "DKD_PARTITION_TYPE");
 
5704
        if (g_strcmp0 (partition_scheme, "mbr") == 0 &&
 
5705
            (partition_type == 0x05 || partition_type == 0x0f || partition_type == 0x85)) {
 
5706
                if (devkit_disks_device_has_logical_partitions (enclosing_device)) {
 
5707
                        throw_error (context,
 
5708
                                     DEVKIT_DISKS_ERROR_FAILED,
 
5709
                                     "Cannot delete extended partition while logical partitions exist");
 
5710
                        goto out;
 
5711
                }
 
5712
        }
 
5713
 
5511
5714
        offset_as_string = g_strdup_printf ("%" G_GINT64_FORMAT "", device->priv->partition_offset);
5512
5715
        size_as_string = g_strdup_printf ("%" G_GINT64_FORMAT "", device->priv->partition_size);
5513
5716
        part_number_as_string = g_strdup_printf ("%d", device->priv->partition_number);
5538
5741
                      argv,
5539
5742
                      NULL,
5540
5743
                      partition_delete_completed_cb,
 
5744
                      FALSE,
5541
5745
                      g_object_ref (enclosing_device),
5542
5746
                      g_object_unref)) {
5543
5747
                goto out;
5605
5809
                        throw_error (context,
5606
5810
                                     DEVKIT_DISKS_ERROR_CANCELLED,
5607
5811
                                     "Job was cancelled");
 
5812
                } else if (WEXITSTATUS (status) == 3) {
 
5813
                    throw_error (context,
 
5814
                            DEVKIT_DISKS_ERROR_FILESYSTEM_TOOLS_MISSING ,
 
5815
                            "Error creating file system: Cannot run mkfs: %s",
 
5816
                            stderr);
5608
5817
                } else {
5609
5818
                        throw_error (context,
5610
5819
                                     DEVKIT_DISKS_ERROR_FAILED,
5856
6065
                                      argv,
5857
6066
                                      passphrase_stdin,
5858
6067
                                      filesystem_create_create_luks_device_completed_cb,
 
6068
                                      FALSE,
5859
6069
                                      mkfse_data,
5860
6070
                                      (GDestroyNotify) mkfse_data_unref)) {
5861
6071
                                goto out;
5888
6098
                      argv,
5889
6099
                      options_for_stdin,
5890
6100
                      filesystem_create_completed_cb,
 
6101
                      FALSE,
5891
6102
                      mkfs_data,
5892
6103
                      (GDestroyNotify) mkfs_data_unref)) {
5893
6104
                goto out;
6336
6547
                      argv,
6337
6548
                      NULL,
6338
6549
                      partition_create_completed_cb,
 
6550
                      FALSE,
6339
6551
                      partition_create_data_new (context, device, offset, size, fstype, fsoptions),
6340
6552
                      (GDestroyNotify) partition_create_data_unref)) {
6341
6553
                goto out;
6551
6763
                      argv,
6552
6764
                      NULL,
6553
6765
                      partition_modify_completed_cb,
 
6766
                      FALSE,
6554
6767
                      partition_modify_data_new (context, device, enclosing_device, type, label, flags),
6555
6768
                      (GDestroyNotify) partition_modify_data_unref)) {
6556
6769
                goto out;
6739
6952
                                                          guint                  num_user_data,
6740
6953
                                                          gpointer              *user_data_elements)
6741
6954
{
6742
 
        const char            *scheme  = user_data_elements[0];
6743
 
        char                 **options = user_data_elements[1];
 
6955
        const char *scheme  = user_data_elements[0];
 
6956
        char **options = user_data_elements[1];
6744
6957
        int n;
6745
6958
        int m;
6746
6959
        char *argv[128];
6761
6974
                goto out;
6762
6975
        }
6763
6976
 
6764
 
        if (g_strcmp0 (device->priv->partition_table_scheme, scheme) == 0) {
6765
 
                throw_error (context,
6766
 
                             DEVKIT_DISKS_ERROR_FAILED,
6767
 
                             "device already has a partition table of given scheme");
6768
 
                goto out;
6769
 
        }
6770
 
 
6771
6977
        n = 0;
6772
6978
        argv[n++] = PACKAGE_LIBEXEC_DIR "/devkit-disks-helper-create-partition-table";
6773
6979
        argv[n++] = device->priv->device_file;
6791
6997
                      argv,
6792
6998
                      NULL,
6793
6999
                      partition_table_create_completed_cb,
 
7000
                      FALSE,
6794
7001
                      partition_table_create_data_new (context, device, scheme),
6795
7002
                      (GDestroyNotify) partition_table_create_data_unref)) {
6796
7003
                goto out;
6855
7062
        int refcount;
6856
7063
 
6857
7064
        gulong device_added_signal_handler_id;
 
7065
        gulong device_changed_signal_handler_id;
6858
7066
        guint device_added_timeout_id;
6859
7067
 
6860
7068
        DBusGMethodInvocation *context;
6902
7110
 
6903
7111
static void
6904
7112
luks_unlock_device_added_cb (DevkitDisksDaemon *daemon,
6905
 
                                  const char *object_path,
6906
 
                                  gpointer user_data)
 
7113
                             const char *object_path,
 
7114
                             gpointer user_data)
6907
7115
{
6908
7116
        UnlockEncryptionData *data = user_data;
6909
7117
        DevkitDisksDevice *device;
6915
7123
            device->priv->device_is_luks_cleartext &&
6916
7124
            strcmp (device->priv->luks_cleartext_slave, data->device->priv->object_path) == 0) {
6917
7125
 
 
7126
                g_signal_handler_disconnect (daemon, data->device_added_signal_handler_id);
 
7127
                g_signal_handler_disconnect (daemon, data->device_changed_signal_handler_id);
 
7128
                g_source_remove (data->device_added_timeout_id);
 
7129
 
6918
7130
                /* update and emit a Changed() signal on the holder since the luks-holder
6919
7131
                 * property indicates the cleartext device
6920
7132
                 */
6927
7139
                        dbus_g_method_return (data->context, object_path);
6928
7140
                }
6929
7141
 
6930
 
                g_signal_handler_disconnect (daemon, data->device_added_signal_handler_id);
6931
 
                g_source_remove (data->device_added_timeout_id);
6932
7142
                unlock_encryption_data_unref (data);
6933
7143
        }
6934
7144
}
6938
7148
{
6939
7149
        UnlockEncryptionData *data = user_data;
6940
7150
 
 
7151
        g_signal_handler_disconnect (data->device->priv->daemon, data->device_added_signal_handler_id);
 
7152
        g_signal_handler_disconnect (data->device->priv->daemon, data->device_changed_signal_handler_id);
 
7153
 
6941
7154
        throw_error (data->context,
6942
7155
                     DEVKIT_DISKS_ERROR_FAILED,
6943
7156
                     "Error unlocking device: timeout (10s) waiting for cleartext device to show up");
6946
7159
                data->hook_func (data->context, NULL, data->hook_user_data);
6947
7160
        }
6948
7161
 
6949
 
        if (data->device_added_signal_handler_id > 0)
6950
 
                g_signal_handler_disconnect (data->device->priv->daemon, data->device_added_signal_handler_id);
6951
 
 
6952
7162
        unlock_encryption_data_unref (data);
6953
7163
        return FALSE;
6954
7164
}
6955
7165
 
6956
 
static gboolean
6957
 
luks_unlock_start_waiting_for_cleartext_device (gpointer user_data)
 
7166
static void
 
7167
luks_unlock_start_waiting_for_cleartext_device (UnlockEncryptionData *data)
6958
7168
{
6959
 
        UnlockEncryptionData *data = user_data;
6960
7169
        DevkitDisksDevice *cleartext_device;
6961
7170
 
6962
7171
        cleartext_device = find_cleartext_device (data->device);
6980
7189
                                                                               "device-added",
6981
7190
                                                                               (GCallback) luks_unlock_device_added_cb,
6982
7191
                                                                               data);
 
7192
                data->device_changed_signal_handler_id = g_signal_connect_after (data->device->priv->daemon,
 
7193
                                                                                 "device-changed",
 
7194
                                                                                 (GCallback) luks_unlock_device_added_cb,
 
7195
                                                                                 data);
6983
7196
 
6984
7197
                /* set up timeout for error reporting if waiting failed */
6985
 
                data->device_added_timeout_id = g_timeout_add (10 * 1000,
 
7198
                data->device_added_timeout_id = g_timeout_add (15 * 1000,
6986
7199
                                                               luks_unlock_device_not_seen_cb,
6987
7200
                                                               data);
6988
7201
 
6989
7202
                /* Note that the signal and timeout handlers share the ref to data - one will cancel the other */
6990
7203
        }
6991
 
 
6992
 
        return FALSE;
6993
7204
}
6994
7205
 
6995
7206
 
6996
7207
static void
6997
7208
luks_unlock_completed_cb (DBusGMethodInvocation *context,
6998
 
                               DevkitDisksDevice *device,
6999
 
                               gboolean job_was_cancelled,
7000
 
                               int status,
7001
 
                               const char *stderr,
7002
 
                               const char *stdout,
7003
 
                               gpointer user_data)
 
7209
                          DevkitDisksDevice *device,
 
7210
                          gboolean job_was_cancelled,
 
7211
                          int status,
 
7212
                          const char *stderr,
 
7213
                          const char *stdout,
 
7214
                          gpointer user_data)
7004
7215
{
7005
7216
        UnlockEncryptionData *data = user_data;
7006
7217
 
7007
7218
        if (WEXITSTATUS (status) == 0 && !job_was_cancelled) {
7008
7219
 
7009
 
                /* yay, so it turns out /sbin/cryptsetup returns way too early; what happens is this
7010
 
                 *
7011
 
                 * - invoke /sbin/cryptsetup
7012
 
                 *   - temporary dm node with name temporary-cryptsetup-* appears. We ignore these,
7013
 
                 *     see above
7014
 
                 *   - temporary dm node removed
7015
 
                 * - /sbin/cryptsetup returns with success (brings us here)
7016
 
                 *   - proper dm node appears
7017
 
                 *     - with the name we requested, e.g. devkit-disks-luks-uuid-%s-uid%d
7018
 
                 *   - proper dm node disappears
7019
 
                 *   - proper dm node reappears
7020
 
                 *
7021
 
                 * Obiviously /sbin/cryptsetup shouldn't return before the dm node we are
7022
 
                 * looking for is really there.
7023
 
                 *
7024
 
                 * TODO: file a bug against /sbin/cryptsetup, probably fix it too. This probably
7025
 
                 *       involves fixing device-mapper as well
7026
 
                 *
7027
 
                 * CURRENT WORKAROUND: Basically, we just sleep two seconds before waiting for the
7028
 
                 *                     cleartext device to appear. That way we can ignore the initial
7029
 
                 *                     nodes.
7030
 
                 */
7031
 
 
7032
 
                g_timeout_add (2 * 1000,
7033
 
                               luks_unlock_start_waiting_for_cleartext_device,
7034
 
                               unlock_encryption_data_ref (data));
 
7220
                luks_unlock_start_waiting_for_cleartext_device (unlock_encryption_data_ref (data));
7035
7221
 
7036
7222
        } else {
7037
7223
                if (job_was_cancelled) {
7097
7283
 
7098
7284
        n = 0;
7099
7285
        argv[n++] = "cryptsetup";
 
7286
        argv[n++] = "-T";
 
7287
        argv[n++] = "1";
7100
7288
        argv[n++] = "luksOpen";
7101
7289
        argv[n++] = device->priv->device_file;
7102
7290
        argv[n++] = luks_name;
7103
7291
        argv[n++] = NULL;
7104
7292
 
 
7293
        /* yay, so it turns out /sbin/cryptsetup returns way too early; what happens is this
 
7294
         *
 
7295
         * - invoke /sbin/cryptsetup
 
7296
         *   - temporary dm node with name temporary-cryptsetup-* appears. We ignore these,
 
7297
         *     see above
 
7298
         *   - temporary dm node removed
 
7299
         * - /sbin/cryptsetup returns with success (brings us here)
 
7300
         *   - proper dm node appears
 
7301
         *     - with the name we requested, e.g. devkit-disks-luks-uuid-%s-uid%d
 
7302
         *   - proper dm node disappears
 
7303
         *   - proper dm node reappears
 
7304
         *
 
7305
         * Obiviously /sbin/cryptsetup shouldn't return before the dm node we are
 
7306
         * looking for is really there or ready to use. But that's not how things
 
7307
         * work.
 
7308
         *
 
7309
         * This bug has been reported here:
 
7310
         *
 
7311
         *  https://bugzilla.redhat.com/show_bug.cgi?id=530721
 
7312
         *
 
7313
         * WORKAROUND: wait for the udev queue to settle before returning. Long
 
7314
         *             term fix is device-mapper/udev integration.
 
7315
         */
7105
7316
        if (!job_new (context,
7106
7317
                      "LuksUnlock",
7107
7318
                      FALSE,
7109
7320
                      argv,
7110
7321
                      secret_as_stdin,
7111
7322
                      luks_unlock_completed_cb,
 
7323
                      TRUE, /* see note above */
7112
7324
                      unlock_encryption_data_new (context, device, hook_func, hook_user_data),
7113
7325
                      (GDestroyNotify) unlock_encryption_data_unref)) {
7114
7326
                    goto out;
7394
7606
                      argv,
7395
7607
                      NULL,
7396
7608
                      luks_lock_completed_cb,
 
7609
                      FALSE,
7397
7610
                      lock_encryption_data_new (context, device, cleartext_device),
7398
7611
                      (GDestroyNotify) lock_encryption_data_unref)) {
7399
7612
                    goto out;
7482
7695
                        throw_error (context,
7483
7696
                                     DEVKIT_DISKS_ERROR_CANCELLED,
7484
7697
                                     "Job was cancelled");
 
7698
                } else if (WEXITSTATUS (status) == 3) {
 
7699
                    throw_error (context,
 
7700
                            DEVKIT_DISKS_ERROR_FILESYSTEM_TOOLS_MISSING ,
 
7701
                            "Error changing fs label: tool not available: %s",
 
7702
                            stderr);
7485
7703
                } else {
7486
7704
                        throw_error (context,
7487
7705
                                     DEVKIT_DISKS_ERROR_FAILED,
7530
7748
                      argv,
7531
7749
                      secrets_as_stdin,
7532
7750
                      luks_change_passphrase_completed_cb,
 
7751
                      FALSE,
7533
7752
                      NULL,
7534
7753
                      NULL)) {
7535
7754
                goto out;
7668
7887
                      argv,
7669
7888
                      NULL,
7670
7889
                      filesystem_set_label_completed_cb,
 
7890
                      FALSE,
7671
7891
                      g_strdup (new_label),
7672
7892
                      g_free)) {
7673
7893
                goto out;
7891
8111
                      argv,
7892
8112
                      NULL,
7893
8113
                      drive_ata_smart_refresh_data_completed_cb,
 
8114
                      FALSE,
7894
8115
                      NULL,
7895
8116
                      NULL)) {
7896
8117
                goto out;
8011
8232
                      argv,
8012
8233
                      NULL,
8013
8234
                      drive_ata_smart_initiate_selftest_completed_cb,
 
8235
                      FALSE,
8014
8236
                      NULL,
8015
8237
                      NULL)) {
8016
8238
                goto out;
8111
8333
                      argv,
8112
8334
                      NULL,
8113
8335
                      linux_md_stop_completed_cb,
 
8336
                      FALSE,
8114
8337
                      NULL,
8115
8338
                      NULL)) {
8116
8339
                goto out;
8232
8455
                      argv,
8233
8456
                      NULL,
8234
8457
                      linux_md_check_completed_cb,
 
8458
                      FALSE,
8235
8459
                      NULL,
8236
8460
                      NULL)) {
8237
8461
                goto out;
8372
8596
                      argv,
8373
8597
                      NULL,
8374
8598
                      linux_md_add_component_completed_cb,
 
8599
                      FALSE,
8375
8600
                      g_object_ref (slave),
8376
8601
                      g_object_unref)) {
8377
8602
                goto out;
8618
8843
                      argv,
8619
8844
                      NULL,
8620
8845
                      linux_md_remove_component_completed_cb,
 
8846
                      FALSE,
8621
8847
                      remove_component_data_new (context, slave, options),
8622
8848
                      (GDestroyNotify) remove_component_data_unref)) {
8623
8849
                goto out;
8945
9171
                      argv,
8946
9172
                      NULL,
8947
9173
                      linux_md_start_completed_cb,
 
9174
                      FALSE,
8948
9175
                      linux_md_start_data_new (context, daemon, uuid),
8949
9176
                      (GDestroyNotify) linux_md_start_data_unref)) {
8950
9177
                goto out;
9296
9523
        }
9297
9524
        argv[n++] = NULL;
9298
9525
 
9299
 
        for (m = 0; argv[m] != NULL; m++)
9300
 
                g_debug ("arg[%d] = `%s'", m, argv[m]);
 
9526
        //for (m = 0; argv[m] != NULL; m++)
 
9527
        //        g_debug ("arg[%d] = `%s'", m, argv[m]);
9301
9528
 
9302
9529
        if (!job_new (context,
9303
9530
                      "LinuxMdCreate",
9306
9533
                      argv,
9307
9534
                      NULL,
9308
9535
                      linux_md_create_completed_cb,
 
9536
                      FALSE,
9309
9537
                      linux_md_create_data_new (context, daemon, components_as_strv[0]),
9310
9538
                      (GDestroyNotify) linux_md_create_data_unref)) {
9311
9539
                goto out;
9432
9660
                      argv,
9433
9661
                      NULL,
9434
9662
                      force_unmount_completed_cb,
 
9663
                      FALSE,
9435
9664
                      force_unmount_data_new (mount_path, callback, user_data),
9436
9665
                      (GDestroyNotify) force_unmount_data_unref)) {
9437
9666
                g_warning ("Couldn't spawn unmount for force unmounting %s", mount_path);
9532
9761
                      argv,
9533
9762
                      NULL,
9534
9763
                      force_luks_teardown_completed_cb,
 
9764
                      FALSE,
9535
9765
                      data,
9536
9766
                      (GDestroyNotify) force_luks_teardown_data_unref)) {
9537
9767
 
9805
10035
                      argv,
9806
10036
                      NULL,
9807
10037
                      drive_poll_media_completed_cb,
 
10038
                      FALSE,
9808
10039
                      NULL,
9809
10040
                      NULL)) {
9810
10041
                goto out;