aboutsummaryrefslogblamecommitdiffstats
path: root/plugins/ipod-sync/ipod.c
blob: 3519951c5d02ec75d12020afe3f0e1e4e0d192d9 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12











                                              
                   
































































































































































































































                                                                                                                    
/*
 * ipod.c - Find an iPod mount point using HAL
 *
 * (C)2004 Justin Wake <jwake@iinet.net.au>
 *
 * Licensed under the GNU GPL v2. See COPYING.
 *
 */

#include "config.h"
#include "evolution-ipod-sync.h"
#include <unistd.h>
#include <string.h>

/**
 * Ensure that HAL is running before we try to use it.
 * From gnome-volume-manager's src/properties.c
 */
gboolean
check_hal (void)
{
    LibHalContext *ctx;
    char **devices;
    int num;
    DBusConnection *conn;
    
    conn = dbus_bus_get (DBUS_BUS_SYSTEM, NULL);

    ctx = libhal_ctx_new ();
    libhal_ctx_set_dbus_connection (ctx, conn);
    if (!libhal_ctx_init(ctx, NULL))
        return FALSE;
    devices = libhal_get_all_devices (ctx, &num, NULL);
    if (!devices)
    {
        libhal_ctx_shutdown (ctx, NULL);
        return FALSE;
    }
    libhal_free_string_array (devices);

    libhal_ctx_shutdown (ctx, NULL);
    return TRUE;
}

#define MOUNT "/bin/mount"
#define UMOUNT "/bin/umount"

/**
 * Try to mount a given device.
 */
static gboolean
try_mount (char *device)
{
    char *argv[3];
    GError *err = NULL;
    gint exit_status;

    argv[0] = MOUNT;
    argv[1] = device;
    argv[2] = NULL;

    if (!g_spawn_sync (g_get_home_dir (), argv, NULL, 0, NULL, NULL, NULL,
                             NULL, &exit_status, &err))
    {
        warn ("try_mount failed: %s", err->message);
        return FALSE;
    }

    return (exit_status == 0);
}

/**
 * Try to unmount a given device.
 */
gboolean
try_umount (char *device)
{
    char *argv[3];
    GError *err = NULL;
    gint exit_status;

    argv[0] = UMOUNT;
    argv[1] = device;
    argv[2] = NULL;

    sync ();

    if (!g_spawn_sync (g_get_home_dir (), argv, NULL, 0, NULL, NULL, NULL,
                             NULL, &exit_status, &err))
    {
        warn ("try_umount failed: %s", err->message);
        return FALSE;
    }

    return (exit_status == 0);
}

/**
 * See if a given mount point contains an iPod.
 *
 * Do this by checking for the presence of an iTunes
 * database at <mount_point>/iPod_Control/iTunes/.
 */
static gboolean
is_ipod (char *mount_point)
{
    gboolean ret = FALSE;
    
    char *itunes_path;

    itunes_path = g_build_path (G_DIR_SEPARATOR_S, mount_point,
                                         "iPod_Control", "iTunes",
                                         NULL);

    if (!g_file_test (itunes_path, G_FILE_TEST_IS_DIR))
        goto out;
    
    ret = TRUE;

out:
    g_free (itunes_path);
    return ret;
}

/**
 * Try to find a mount point for an iPod.
 */
char *
find_ipod_mount_point (LibHalContext *ctx)
{
    char **apple_devices = NULL;
    char **volumes = NULL;
    char *udi, *udi2, *device, *fsusage, *mount_point = NULL;
    char *retval = NULL;
    int apple_count = 0;
    int volume_count = 0;
    int has_fs = 0;
    int i, j;

    /* First, we look for things made by Apple. */
    apple_devices = libhal_manager_find_device_string_match (ctx,
                            "info.vendor",
                            "Apple",
                            &apple_count,
                            NULL);

    for (i = 0; i < apple_count; i++)
    {
        udi = apple_devices[i];
        
        volumes = NULL;
        volumes = libhal_manager_find_device_string_match (ctx,
                            "info.parent",
                            udi,
                            &volume_count,
                            NULL);

        for (j = 0; j < volume_count; j++)
        {
            udi2 = volumes[j];

            /* Only interested if it has a filesystem. */
            has_fs = 0;
            
            if (!libhal_device_property_exists (ctx, udi2,
                                "volume.is_filesystem", NULL) ||
                  !libhal_device_get_property_bool (ctx, udi2,
                                "volume.is_filesystem", NULL))
            {
                has_fs = 1;
            }
            
            fsusage = libhal_device_get_property_string (ctx, udi2,
                                "volume.fsusage", NULL);

            if (strncmp (fsusage, "filesystem", 10) == 0)
            {
                has_fs = 1;
            }

            libhal_free_string (fsusage);

            if (has_fs == 0)
                continue;
                
            device = libhal_device_get_property_string (ctx, udi2,
                                    "block.device", NULL);

            /* Let's see if it's mounted. */
            if (!libhal_device_property_exists (ctx, udi2,
                                "volume.is_mounted", NULL) ||
                 !libhal_device_get_property_bool (ctx, udi2,
                                "volume.is_mounted", NULL))
            {
                /* It isn't, so let's attempt to mount it */
                if (device != NULL)
                {
                    try_mount (device); 
                }
            }

            if (!libhal_device_property_exists (ctx, udi2,
                                "volume.mount_point", NULL))
            {
                libhal_free_string (device);
                continue;
            }

            libhal_free_string (device);
            
            mount_point = libhal_device_get_property_string (ctx, udi2,
                                            "volume.mount_point", NULL);
            
            if (is_ipod (mount_point))
            {
                goto out;
            }

            libhal_free_string (mount_point);
            mount_point = NULL;
        }
    }

out:
    if (volumes != NULL)
        libhal_free_string_array (volumes);
    
    if (apple_devices != NULL)
        libhal_free_string_array (apple_devices);
    
    if (mount_point != NULL)
    {
        retval = g_strdup (mount_point);
        libhal_free_string (mount_point);
    }
    
    return (retval);
}