diff options
author | Jorg Schuler <jcsjcs@users.sourceforge.net> | 2006-03-16 15:34:34 +0000 |
---|---|---|
committer | Jorg Schuler <jcsjcs@users.sourceforge.net> | 2006-03-16 15:34:34 +0000 |
commit | ace89adce995bd158ef49390a6438c093bf306b3 (patch) | |
tree | c5a18421b35013c3fcd1ac5dbe72daa649a30b2b /src/ipod-device.c | |
parent | 86f4c354d7fa66d864b434169c633f85ed516e5c (diff) | |
download | libgpod-ace89adce995bd158ef49390a6438c093bf306b3.tar.gz libgpod-ace89adce995bd158ef49390a6438c093bf306b3.tar.xz libgpod-ace89adce995bd158ef49390a6438c093bf306b3.zip |
* itdb_device.[ch]: rewrote ipod-device.c, removed all hal-code,
removed all code irrelevant to writing the iTunesDB and
ArtworkDB.
* autodetect iControl directory now also works for ArtworkDB.
* db-artwork-parser.c (ipod_db_get_artwork_db_path): create
Artwork directory if not already present.
* itdb.h: Itdb_iTunesDB: moved mountpoint and musicdirs into
private Itdb_Device. Use itdb_set_mountpoint() and
itdb_get_mountpoint() to access the mountpoint.
git-svn-id: https://gtkpod.svn.sf.net/svnroot/gtkpod/libgpod/trunk@1220 f01d2545-417e-4e96-918e-98f8d0dbbcb6
Diffstat (limited to 'src/ipod-device.c')
-rw-r--r-- | src/ipod-device.c | 1832 |
1 files changed, 0 insertions, 1832 deletions
diff --git a/src/ipod-device.c b/src/ipod-device.c deleted file mode 100644 index 411b182..0000000 --- a/src/ipod-device.c +++ /dev/null @@ -1,1832 +0,0 @@ -/* Time-stamp: <2006-03-09 21:50:38 jcs> -| -| Copyright (C) 2005 Jorg Schuler <jcsjcs at users sourceforge net> -| Part of the gtkpod project. -| -| URL: http://www.gtkpod.org/ -| URL: http://gtkpod.sourceforge.net/ -| -| -| The source is taken from libipoddevice, CVS version October 8 2005 -| (http://64.14.94.162/index.php/Libipoddevice). -| -| I decided not to make libgpod dependent on libipoddevice because -| the latter depends on libraries not widely available yet (libhal >= -| 0.5.2, glib >= 2.8). It is planned to replace these files with a -| libipoddevice dependence at some later time. -| -| The following changes were done: -| -| - libhal becomes optional (see #ifdef HAVE_LIBHAL sections) -| - g_mkdir_with_parents() is provided if not available (glib < 2.8) -| - publicly available functions were renamed from ipod_device_...() -| to itdb_device_...() -| -| Because of these changes only a limited amount of functionality is -| available. See ipod-device.h for summary. -| -| -| -| -| $Id$ -*/ -/* ex: set ts=4: */ -/*************************************************************************** -* ipod-device.c -* Copyright (C) 2005 Novell -* Written by Aaron Bockover <aaron@aaronbock.net> -****************************************************************************/ - -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2.1 of the GNU Lesser General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - - -/* JCS: Change from ipod_device... to itdb_device for public functions */ -#define ipod_device_get_type itdb_device_get_type -#define ipod_device_new itdb_device_new -#define ipod_device_rescan_disk itdb_device_rescan_disk -#define ipod_device_eject itdb_device_eject -#define ipod_device_reboot itdb_device_reboot -#define ipod_device_debug itdb_device_debug -#define ipod_device_save itdb_device_save -#define ipod_device_list_devices itdb_device_list_devices -#define ipod_device_list_device_udis itdb_device_list_device_udis - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include "glib-compat.h" - -#include <stdlib.h> -#include <stdio.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> - -#include "hal-common.h" -#include "ipod-device.h" - -#define GB 1024 - -typedef struct _IpodModel { - const gchar *model_number; - const guint64 capacity; - guint model_type; - guint generation; -} IpodModel; - - -static const IpodModel ipod_model_table [] = { - /* Handle idiots who hose their iPod file system, or - lucky people with iPods we don't yet know about*/ - {"Invalid", 0, MODEL_TYPE_INVALID, UNKNOWN_GENERATION}, - {"Unknown", 0, MODEL_TYPE_UNKNOWN, UNKNOWN_GENERATION}, - - /* First Generation */ - {"8513", 5 * GB, MODEL_TYPE_REGULAR, FIRST_GENERATION}, - {"8541", 5 * GB, MODEL_TYPE_REGULAR, FIRST_GENERATION}, - {"8697", 5 * GB, MODEL_TYPE_REGULAR, FIRST_GENERATION}, - {"8709", 10 * GB, MODEL_TYPE_REGULAR, FIRST_GENERATION}, - - /* Second Generation */ - {"8737", 10 * GB, MODEL_TYPE_REGULAR, SECOND_GENERATION}, - {"8740", 10 * GB, MODEL_TYPE_REGULAR, SECOND_GENERATION}, - {"8738", 20 * GB, MODEL_TYPE_REGULAR, SECOND_GENERATION}, - {"8741", 20 * GB, MODEL_TYPE_REGULAR, SECOND_GENERATION}, - - /* Third Generation */ - {"8976", 10 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, - {"8946", 15 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, - {"9460", 15 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, - {"9244", 20 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, - {"8948", 30 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, - {"9245", 40 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, - - - /* Fourth Generation */ - {"9282", 20 * GB, MODEL_TYPE_REGULAR, FOURTH_GENERATION}, - {"9787", 25 * GB, MODEL_TYPE_REGULAR_U2, FOURTH_GENERATION}, - {"9268", 40 * GB, MODEL_TYPE_REGULAR, FOURTH_GENERATION}, - {"A079", 20 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, - {"A127", 20 * GB, MODEL_TYPE_COLOR_U2, FOURTH_GENERATION}, - {"9830", 60 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, - - /* First Generation Mini */ - {"9160", 4 * GB, MODEL_TYPE_MINI, FIRST_GENERATION}, - {"9436", 4 * GB, MODEL_TYPE_MINI_BLUE, FIRST_GENERATION}, - {"9435", 4 * GB, MODEL_TYPE_MINI_PINK, FIRST_GENERATION}, - {"9434", 4 * GB, MODEL_TYPE_MINI_GREEN, FIRST_GENERATION}, - {"9437", 4 * GB, MODEL_TYPE_MINI_GOLD, FIRST_GENERATION}, - - /* Second Generation Mini */ - {"9800", 4 * GB, MODEL_TYPE_MINI, SECOND_GENERATION}, - {"9802", 4 * GB, MODEL_TYPE_MINI_BLUE, SECOND_GENERATION}, - {"9804", 4 * GB, MODEL_TYPE_MINI_PINK, SECOND_GENERATION}, - {"9806", 4 * GB, MODEL_TYPE_MINI_GREEN, SECOND_GENERATION}, - {"9801", 6 * GB, MODEL_TYPE_MINI, SECOND_GENERATION}, - {"9803", 6 * GB, MODEL_TYPE_MINI_BLUE, SECOND_GENERATION}, - {"9805", 6 * GB, MODEL_TYPE_MINI_PINK, SECOND_GENERATION}, - {"9807", 6 * GB, MODEL_TYPE_MINI_GREEN, SECOND_GENERATION}, - - /* Photo / Fourth Generation */ - {"9829", 30 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, - {"9585", 40 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, - {"9586", 60 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, - {"9830", 60 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, - - /* Shuffle / Fourth Generation */ - {"9724", GB / 2, MODEL_TYPE_SHUFFLE, FOURTH_GENERATION}, - {"9725", GB, MODEL_TYPE_SHUFFLE, FOURTH_GENERATION}, - - /* Nano / Fifth Generation */ - {"A350", GB * 1, MODEL_TYPE_NANO_WHITE, FIFTH_GENERATION}, - {"A352", GB * 1, MODEL_TYPE_NANO_BLACK, FIFTH_GENERATION}, - {"A004", GB * 2, MODEL_TYPE_NANO_WHITE, FIFTH_GENERATION}, - {"A099", GB * 2, MODEL_TYPE_NANO_BLACK, FIFTH_GENERATION}, - {"A005", GB * 4, MODEL_TYPE_NANO_WHITE, FIFTH_GENERATION}, - {"A107", GB * 4, MODEL_TYPE_NANO_BLACK, FIFTH_GENERATION}, - - /* Video / Fifth Generation */ - {"A002", GB * 30, MODEL_TYPE_VIDEO_WHITE, FIFTH_GENERATION}, - {"A146", GB * 30, MODEL_TYPE_VIDEO_BLACK, FIFTH_GENERATION}, - {"A003", GB * 60, MODEL_TYPE_VIDEO_WHITE, FIFTH_GENERATION}, - {"A147", GB * 60, MODEL_TYPE_VIDEO_BLACK, FIFTH_GENERATION}, - - /* HP iPods, need contributions for this table */ - {"E436", 40 * GB, MODEL_TYPE_REGULAR, FOURTH_GENERATION}, - {"S492", 30 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, - - {NULL, 0, 0, 0} -}; - -static const gchar *ipod_model_name_table [] = { - "Invalid", - "Unknown", - "Color", - "Color U2", - "Grayscale", - "Grayscale U2", - "Mini (Silver)", - "Mini (Blue)", - "Mini (Pink)", - "Mini (Green)", - "Mini (Gold)", - "Shuffle", - "Nano (White)", - "Nano (Black)", - "Video (White)", - "Video (Black)", - NULL -}; - -static const IpodArtworkFormat ipod_color_artwork_info[] = { - {IPOD_COVER_SMALL, 56, 56, 1017}, - {IPOD_COVER_LARGE, 140, 140, 1016}, - {IPOD_PHOTO_SMALL, 42, 30, 1009}, - {IPOD_PHOTO_LARGE, 130, 88, 1015}, - {IPOD_PHOTO_FULL_SCREEN, 220, 176, 1013}, - {IPOD_PHOTO_TV_SCREEN, 720, 480, 1019}, - {-1, -1, -1, -1} -}; - -static const IpodArtworkFormat ipod_nano_artwork_info[] = { - {IPOD_COVER_SMALL, 42, 42, 1031}, - {IPOD_COVER_LARGE, 100, 100, 1027}, - {IPOD_PHOTO_LARGE, 42, 37, 1032}, - {IPOD_PHOTO_FULL_SCREEN, 176, 132, 1023}, - {-1, -1, -1, -1} -}; - -static const IpodArtworkFormat ipod_video_artwork_info[] = { - {IPOD_COVER_SMALL, 100, 100, 1028}, - {IPOD_COVER_LARGE, 200, 200, 1029}, - {IPOD_PHOTO_SMALL, 50, 41, 1036}, - {IPOD_PHOTO_LARGE, 130, 88, 1015}, - {IPOD_PHOTO_FULL_SCREEN, 320, 240, 1024}, - {IPOD_PHOTO_TV_SCREEN, 720, 480, 1019}, - {-1, -1, -1, -1} -}; - -/* This will be indexed using a value from the MODEL_TYPE enum */ -static const IpodArtworkFormat *ipod_artwork_info_table[] = { - NULL, /* Invalid */ - NULL, /* Unknown */ - ipod_color_artwork_info, /* Color */ - ipod_color_artwork_info, /* Color U2 */ - NULL, /* Grayscale */ - NULL, /* Grayscale U2 */ - NULL, /* Mini (Silver) */ - NULL, /* Mini (Blue) */ - NULL, /* Mini (Pink) */ - NULL, /* Mini (Green) */ - NULL, /* Mini (Gold) */ - NULL, /* Shuffle */ - ipod_nano_artwork_info, /* Nano (White) */ - ipod_nano_artwork_info, /* Nano (Black) */ - ipod_video_artwork_info, /* Video (White) */ - ipod_video_artwork_info /* Video (Black) */ -}; - - -#define g_free_if_not_null(o) \ - if(o != NULL) { \ - g_free(o); \ - o = NULL; \ - } - -static const gchar *sysinfo_field_names [] = { - "pszSerialNumber", - "ModelNumStr", - "visibleBuildID", - NULL -}; - -static gchar *sysinfo_arr_get_dup(gchar *arr[], const gchar *key) -{ - gint i = 0; - - for(i = 0; sysinfo_field_names[i] != NULL; i++) { - if(g_strcasecmp(sysinfo_field_names[i], key) == 0) - return g_strdup(arr[i]); - } - - return NULL; -} - - -#if ((GLIB_MAJOR_VERSION <= 2) && (GLIB_MINOR_VERSION < 8)) -/** - * g_mkdir_with_parents: - * @pathname: a pathname in the GLib file name encoding - * @mode: permissions to use for newly created directories - * - * Create a directory if it doesn't already exist. Create intermediate - * parent directories as needed, too. - * - * Returns: 0 if the directory already exists, or was successfully - * created. Returns -1 if an error occurred, with errno set. - * - * Since: 2.8 (copied from GLIB version 2.8 - JCS) - */ -static int -g_mkdir_with_parents (const gchar *pathname, - int mode) -{ - gchar *fn, *p; - - if (pathname == NULL || *pathname == '\0') - { - errno = EINVAL; - return -1; - } - - fn = g_strdup (pathname); - - if (g_path_is_absolute (fn)) - p = (gchar *) g_path_skip_root (fn); - else - p = fn; - - do - { - while (*p && !G_IS_DIR_SEPARATOR (*p)) - p++; - - if (!*p) - p = NULL; - else - *p = '\0'; - - if (!g_file_test (fn, G_FILE_TEST_EXISTS)) - { - if (g_mkdir (fn, mode) == -1) - { - int errno_save = errno; - g_free (fn); - errno = errno_save; - return -1; - } - } - else if (!g_file_test (fn, G_FILE_TEST_IS_DIR)) - { - g_free (fn); - errno = ENOTDIR; - return -1; - } - if (p) - { - *p++ = G_DIR_SEPARATOR; - while (*p && G_IS_DIR_SEPARATOR (*p)) - p++; - } - } - while (p); - - g_free (fn); - - return 0; -} -#endif - - -static void ipod_device_class_init(IpodDeviceClass *klass); -static void ipod_device_init(IpodDevice *sp); -static void ipod_device_finalize(GObject *object); - -static gchar *ipod_device_read_device_info_string(FILE *fd); -static void ipod_device_write_device_info_string(gchar *str, FILE *fd); - -static gboolean ipod_device_reload(IpodDevice *device); -static void ipod_device_construct_paths(IpodDevice *device); -static gboolean ipod_device_info_load(IpodDevice *device); -static guint ipod_device_detect_model(IpodDevice *device); -static gboolean ipod_device_detect_volume_info(IpodDevice *device); -static LibHalContext *ipod_device_hal_initialize(void); -static void ipod_device_detect_volume_used(IpodDevice *device); -static guint64 ipod_device_dir_size(const gchar *path); -static gboolean ipod_device_read_sysinfo(IpodDevice *device); -static gboolean ipod_device_detect_writeable(IpodDevice *device); -static void ipod_device_restore_reboot_preferences(IpodDevice *device); - -struct IpodDevicePrivate { - LibHalContext *hal_context; - - /* Paths */ - gchar *device_path; - gchar *mount_point; - gchar *control_path; - gchar *hal_volume_id; - - gchar *adv_capacity; - guint model_index; - - /* DeviceInfo Fields (All Devices) */ - gchar *device_name; - gchar *user_name; - gchar *host_name; - - /* Volume Size/Usage */ - guint64 volume_size; - guint64 volume_available; - guint64 volume_used; - - /* System Info */ - gchar *serial_number; - gchar *model_number; - gchar *firmware_version; - - gchar *volume_uuid; - gchar *volume_label; - - /* Fresh from the factory/restore? */ - gboolean is_new; - - /* Safety */ - gboolean is_ipod; - gboolean can_write; -}; - -static GObjectClass *parent_class = NULL; - -/* GObject Class Specific Methods */ - -GType -ipod_device_get_type() -{ - static GType type = 0; - - if(type == 0) { - static const GTypeInfo our_info = { - sizeof (IpodDeviceClass), - NULL, - NULL, - (GClassInitFunc)ipod_device_class_init, - NULL, - NULL, - sizeof (IpodDevice), - 0, - (GInstanceInitFunc)ipod_device_init, - }; - - type = g_type_register_static(G_TYPE_OBJECT, - "IpodDevice", &our_info, 0); - } - - return type; -} - -static void -ipod_device_get_property(GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - IpodDevice *device = IPOD_DEVICE(object); - - switch(prop_id) { - case PROP_HAL_CONTEXT: - g_value_set_pointer(value, device->priv->hal_context); - break; - case PROP_HAL_VOLUME_ID: - g_value_set_string(value, device->priv->hal_volume_id); - break; - case PROP_MOUNT_POINT: - g_value_set_string(value, device->priv->mount_point); - break; - case PROP_DEVICE_PATH: - g_value_set_string(value, device->priv->device_path); - break; - case PROP_CONTROL_PATH: - g_value_set_string(value, device->priv->control_path); - break; - case PROP_DEVICE_MODEL: - g_value_set_uint(value, - ipod_model_table[device->priv->model_index].model_type); - break; - case PROP_DEVICE_MODEL_STRING: - g_value_set_string(value, - ipod_model_name_table[ipod_model_table[ - device->priv->model_index].model_type]); - break; - case PROP_DEVICE_GENERATION: - g_value_set_uint(value, - ipod_model_table[device->priv->model_index].generation); - break; - case PROP_ADVERTISED_CAPACITY: - g_value_set_string(value, device->priv->adv_capacity); - break; - case PROP_DEVICE_NAME: - g_value_set_string(value, device->priv->device_name); - break; - case PROP_USER_NAME: - g_value_set_string(value, device->priv->user_name); - break; - case PROP_HOST_NAME: - g_value_set_string(value, device->priv->host_name); - break; - case PROP_VOLUME_SIZE: - g_value_set_uint64(value, device->priv->volume_size); - break; - case PROP_VOLUME_AVAILABLE: - g_value_set_uint64(value, device->priv->volume_available); - break; - case PROP_VOLUME_USED: - g_value_set_uint64(value, device->priv->volume_used); - break; - case PROP_IS_IPOD: - g_value_set_boolean(value, device->priv->is_ipod); - break; - case PROP_IS_NEW: - g_value_set_boolean(value, device->priv->is_new); - break; - case PROP_SERIAL_NUMBER: - g_value_set_string(value, device->priv->serial_number); - break; - case PROP_MODEL_NUMBER: - g_value_set_string(value, device->priv->model_number); - break; - case PROP_FIRMWARE_VERSION: - g_value_set_string(value, device->priv->firmware_version); - break; - case PROP_VOLUME_UUID: - g_value_set_string(value, device->priv->volume_uuid); - break; - case PROP_VOLUME_LABEL: - g_value_set_string(value, device->priv->volume_label); - break; - case PROP_CAN_WRITE: - g_value_set_boolean(value, device->priv->can_write); - break; - case PROP_ARTWORK_FORMAT: - g_value_set_pointer(value, - (gpointer)ipod_artwork_info_table[ipod_model_table[ - device->priv->model_index].model_type]); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -ipod_device_set_property(GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - IpodDevice *device = IPOD_DEVICE(object); - const gchar *str; - gchar **volumes; - gint volume_count; - - g_return_if_fail (device); - - switch(prop_id) { - case PROP_MOUNT_POINT: - case PROP_DEVICE_PATH: - case PROP_HAL_VOLUME_ID: - str = g_value_get_string(value); - volumes = NULL; - if (device->priv->hal_context) - { - volumes = libhal_manager_find_device_string_match( - device->priv->hal_context, "block.device", str, - &volume_count, NULL); - if(volume_count == 0) - { - libhal_free_string_array(volumes); - volumes = libhal_manager_find_device_string_match( - device->priv->hal_context, "volume.mount_point", - str, &volume_count, NULL); - } - if(volume_count >= 1) - { - str = volumes[0]; - } - } -#ifdef HAVE_LIBHAL - g_free_if_not_null(device->priv->hal_volume_id); - device->priv->hal_volume_id = g_strdup (str); -#else -/* JCS for libgpod */ - g_free (device->priv->mount_point); - device->priv->mount_point = g_strdup (str); -/* end JCS for libgpod */ -#endif - if (volumes) - libhal_free_string_array(volumes); - device->priv->is_ipod = ipod_device_reload(device); - break; - case PROP_DEVICE_NAME: - str = g_value_get_string(value); - g_free_if_not_null(device->priv->device_name); - device->priv->device_name = g_strdup(str); - break; - case PROP_USER_NAME: - str = g_value_get_string(value); - g_free_if_not_null(device->priv->user_name); - device->priv->user_name = g_strdup(str); - break; - case PROP_HOST_NAME: - str = g_value_get_string(value); - g_free_if_not_null(device->priv->host_name); - device->priv->host_name = g_strdup(str); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -ipod_device_class_init(IpodDeviceClass *klass) -{ - GParamSpec *hal_context_param; - GParamSpec *hal_volume_id_param; - GParamSpec *mount_point_param; - GParamSpec *device_path_param; - GParamSpec *control_path_param; - GParamSpec *device_model_param; - GParamSpec *device_model_string_param; - GParamSpec *device_name_param; - GParamSpec *user_name_param; - GParamSpec *host_name_param; - GParamSpec *volume_size_param; - GParamSpec *volume_available_param; - GParamSpec *volume_used_param; - GParamSpec *is_ipod_param; - GParamSpec *is_new_param; - GParamSpec *serial_number_param; - GParamSpec *model_number_param; - GParamSpec *firmware_version_param; - GParamSpec *volume_uuid_param; - GParamSpec *volume_label_param; - GParamSpec *can_write_param; - GParamSpec *device_generation_param; - GParamSpec *advertised_capacity_param; - GParamSpec *artwork_format_param; - - GObjectClass *class = G_OBJECT_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - class->finalize = ipod_device_finalize; - - hal_context_param = g_param_spec_pointer("hal-context", "HAL Context", - "LibHalContext handle", G_PARAM_READABLE); - - hal_volume_id_param = g_param_spec_string("hal-volume-id", "HAL Volume ID", - "Volume ID of a device in HAL", - NULL, G_PARAM_READWRITE); - - mount_point_param = g_param_spec_string("mount-point", "Mount Point", - "Where iPod is mounted (parent of an iPod_Control directory)", - NULL, G_PARAM_READWRITE); - - device_path_param = g_param_spec_string("device-path", "Device Path", - "Path to raw iPod Device (/dev/sda2, for example)", - NULL, G_PARAM_READWRITE); - - control_path_param = g_param_spec_string("control-path", - "iPod_Control Path","Full path to iPod_Control", - NULL, G_PARAM_READABLE); - - device_model_param = g_param_spec_uint("device-model", "Device Model", - "Type of iPod (Regular, Photo, Shuffle)", 0, 2, 0, G_PARAM_READABLE); - - device_model_string_param = g_param_spec_string("device-model-string", - "Device Model String", "String type of iPod (Regular, Shuffle)", - NULL, G_PARAM_READABLE); - - device_name_param = g_param_spec_string("device-name", "Device Name", - "The user-assigned name of their iPod", NULL, G_PARAM_READWRITE); - - user_name_param = g_param_spec_string("user-name", "User Name", - "On Windows, Maybe Mac, the user account owning the iPod", - NULL, G_PARAM_READWRITE); - - host_name_param = g_param_spec_string("host-name", "Host Name", - "On Windows, Maybe Mac, the host/computer name owning the iPod", - NULL, G_PARAM_READWRITE); - - volume_size_param = g_param_spec_uint64("volume-size", "Volume Size", - "Total size of the iPod's hard drive", 0, G_MAXLONG, 0, - G_PARAM_READABLE); - - volume_available_param = g_param_spec_uint64("volume-available", - "Volume Available", "Available space on the iPod", - 0, G_MAXLONG, 0, G_PARAM_READABLE); - - volume_used_param = g_param_spec_uint64("volume-used", "Volume Used", - "How much space has been used", 0, G_MAXLONG, 0, G_PARAM_READABLE); - - is_ipod_param = g_param_spec_boolean("is-ipod", "Is iPod", - "If all device checks are okay, then this is true", - FALSE, G_PARAM_READABLE); - - is_new_param = g_param_spec_boolean("is-new", "Is iPod", - "If device is fresh from factory/restore, this is true", - FALSE, G_PARAM_READABLE); - - serial_number_param = g_param_spec_string("serial-number", "Serial Number", - "Serial Number of the iPod", - NULL, G_PARAM_READABLE); - - model_number_param = g_param_spec_string("model-number", "Model Number", - "Model Number of the iPod", - NULL, G_PARAM_READABLE); - - firmware_version_param = g_param_spec_string("firmware-version", - "Firmware Version", "iPod Firmware Version", - NULL, G_PARAM_READABLE); - - volume_uuid_param = g_param_spec_string("volume-uuid", "Volume UUID", - "Volume UUID of the iPod", - NULL, G_PARAM_READABLE); - - volume_label_param = g_param_spec_string("volume-label", "Volume Label", - "Volume Label of the iPod", - NULL, G_PARAM_READABLE); - - can_write_param = g_param_spec_boolean("can-write", "Can Write", - "True if device can be written to (mounted read/write)", - FALSE, G_PARAM_READABLE); - - advertised_capacity_param = g_param_spec_string("advertised-capacity", - "Advertised Capacity", "Apple Marketed/Advertised Capacity String", - NULL, G_PARAM_READABLE); - - device_generation_param = g_param_spec_uint("device-generation", - "Generation", "Generation of the iPod", - 0, G_MAXUINT, 0, G_PARAM_READABLE); - - artwork_format_param = g_param_spec_pointer("artwork-formats", - "Artwork Format", "Support Artwork Formats", G_PARAM_READABLE); - - class->set_property = ipod_device_set_property; - class->get_property = ipod_device_get_property; - g_object_class_install_property(class, PROP_HAL_CONTEXT, - hal_context_param); - - g_object_class_install_property(class, PROP_HAL_VOLUME_ID, - hal_volume_id_param); - - g_object_class_install_property(class, PROP_MOUNT_POINT, - mount_point_param); - - g_object_class_install_property(class, PROP_DEVICE_PATH, - device_path_param); - - g_object_class_install_property(class, PROP_CONTROL_PATH, - control_path_param); - - g_object_class_install_property(class, PROP_DEVICE_MODEL, - device_model_param); - - g_object_class_install_property(class, PROP_DEVICE_MODEL_STRING, - device_model_string_param); - - g_object_class_install_property(class, PROP_DEVICE_NAME, - device_name_param); - - g_object_class_install_property(class, PROP_USER_NAME, - user_name_param); - - g_object_class_install_property(class, PROP_HOST_NAME, - host_name_param); - - g_object_class_install_property(class, PROP_VOLUME_SIZE, - volume_size_param); - - g_object_class_install_property(class, PROP_VOLUME_AVAILABLE, - volume_available_param); - - g_object_class_install_property(class, PROP_VOLUME_USED, - volume_used_param); - - g_object_class_install_property(class, PROP_IS_IPOD, is_ipod_param); - - g_object_class_install_property(class, PROP_IS_NEW, is_new_param); - - g_object_class_install_property(class, PROP_SERIAL_NUMBER, - serial_number_param); - - g_object_class_install_property(class, PROP_MODEL_NUMBER, - model_number_param); - - g_object_class_install_property(class, PROP_FIRMWARE_VERSION, - firmware_version_param); - - g_object_class_install_property(class, PROP_VOLUME_UUID, - volume_uuid_param); - - g_object_class_install_property(class, PROP_VOLUME_LABEL, - volume_label_param); - - g_object_class_install_property(class, PROP_CAN_WRITE, - can_write_param); - - g_object_class_install_property(class, PROP_DEVICE_GENERATION, - device_generation_param); - - g_object_class_install_property(class, PROP_ADVERTISED_CAPACITY, - advertised_capacity_param); - - g_object_class_install_property(class, PROP_ARTWORK_FORMAT, - artwork_format_param); - -} - -static void -ipod_device_init(IpodDevice *device) -{ - device->priv = g_new0(IpodDevicePrivate, 1); - - device->priv->hal_context = ipod_device_hal_initialize(); - - device->priv->hal_volume_id = NULL; - device->priv->mount_point = NULL; - device->priv->device_path = NULL; - device->priv->control_path = NULL; - device->priv->device_name = NULL; - device->priv->user_name = NULL; - device->priv->host_name = NULL; - device->priv->adv_capacity = NULL; - device->priv->serial_number = NULL; - device->priv->model_number = NULL; - device->priv->firmware_version = NULL; - device->priv->volume_uuid = NULL; - device->priv->volume_label = NULL; - - device->priv->volume_size = 0; - device->priv->volume_available = 0; - device->priv->volume_used = 0; - - device->priv->is_new = FALSE; - device->priv->can_write = FALSE; -} - -static void -ipod_device_finalize(GObject *object) -{ - IpodDevice *device = IPOD_DEVICE(object); - - /* Free private members, etc. */ - g_free_if_not_null(device->priv->hal_volume_id); - g_free_if_not_null(device->priv->device_path); - g_free_if_not_null(device->priv->mount_point); - g_free_if_not_null(device->priv->control_path); - g_free_if_not_null(device->priv->device_name); - g_free_if_not_null(device->priv->user_name); - g_free_if_not_null(device->priv->host_name); - g_free_if_not_null(device->priv->adv_capacity); - g_free_if_not_null(device->priv->serial_number); - g_free_if_not_null(device->priv->model_number); - g_free_if_not_null(device->priv->firmware_version); - g_free_if_not_null(device->priv->volume_uuid); - g_free_if_not_null(device->priv->volume_label); - - if(device->priv->hal_context != NULL) { - libhal_ctx_shutdown(device->priv->hal_context, NULL); - libhal_ctx_free(device->priv->hal_context); - } - g_free(device->priv); - G_OBJECT_CLASS(parent_class)->finalize(object); -} - -/* PRIVATE METHODS */ - -LibHalContext * -ipod_device_hal_initialize() -{ -#ifdef HAVE_LIBHAL - LibHalContext *hal_context; - DBusError error; - DBusConnection *dbus_connection; - char **devices; - gint device_count; - - hal_context = libhal_ctx_new(); - if(hal_context == NULL) - return NULL; - - dbus_error_init(&error); - dbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); - if(dbus_error_is_set(&error)) { - dbus_error_free(&error); - libhal_ctx_free(hal_context); - return NULL; - } - - libhal_ctx_set_dbus_connection(hal_context, dbus_connection); - - if(!libhal_ctx_init(hal_context, &error)) { - dbus_error_free(&error); - libhal_ctx_free(hal_context); - return NULL; - } - - devices = libhal_get_all_devices(hal_context, &device_count, NULL); - if(devices == NULL) { - libhal_ctx_shutdown(hal_context, NULL); - libhal_ctx_free(hal_context); - hal_context = NULL; - return NULL; - } - - libhal_free_string_array(devices); - - return hal_context; -#else - return NULL; -#endif -} - -gboolean -ipod_device_reload(IpodDevice *device) -{ - g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE); - - device->priv->model_index = 0; - - if(!ipod_device_detect_volume_info(device)) - return FALSE; - - ipod_device_construct_paths(device); - - device->priv->is_new = !ipod_device_info_load(device); - - ipod_device_detect_volume_used(device); - ipod_device_detect_writeable(device); - ipod_device_read_sysinfo(device); - ipod_device_detect_model(device); - ipod_device_restore_reboot_preferences(device); - - return device->priv->model_index != 0; -} - -void -ipod_device_construct_paths(IpodDevice *device) -{ - int len; - - g_return_if_fail(IS_IPOD_DEVICE(device)); - g_return_if_fail(device->priv->mount_point != NULL); - - len = strlen(device->priv->mount_point); - if(device->priv->mount_point[len - 1] == '/') - device->priv->mount_point[len - 1] = '\0'; - - if(strlen(device->priv->mount_point) == 0) - return; - - device->priv->control_path = g_strdup_printf("%s/%s", - device->priv->mount_point, "iPod_Control/"); -} - -gchar * -ipod_device_read_device_info_string(FILE *fd) -{ - gshort length; - gunichar2 *utf16; - gchar *utf8; - - if (fread(&length, sizeof(gshort), 1, fd) != 1) - return NULL; - - if(length <= 0) - return NULL; - - utf16 = (gunichar2 *)g_malloc(length * sizeof(gunichar2)); - if (fread(utf16, sizeof(gunichar2), length, fd) != length) - return NULL; - - if(utf16 == NULL) - return NULL; - - utf8 = g_utf16_to_utf8(utf16, length, NULL, NULL, NULL); - - g_free(utf16); - utf16 = NULL; - - return utf8; -} - -void -ipod_device_write_device_info_string(gchar *str, FILE *fd) -{ - gunichar2 *unistr; - gshort length; - size_t res; - - if(str == NULL) - return; - - length = strlen(str); - unistr = g_utf8_to_utf16(str, length, NULL, NULL, NULL); - - length = length > 0x198 ? 0x198 : length; - - /* FIXME: we do not check if the write was successful */ - res = fwrite(&length, 2, 1, fd); - res = fwrite(unistr, 2, length, fd); - - g_free(unistr); -} - -gboolean -ipod_device_read_sysinfo(IpodDevice *device) -{ - gchar *field_values[sizeof(sysinfo_field_names) + 1]; - gchar *tmp, *path, buf[512]; - gint i, name_len; - FILE *fd; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE); - - path = g_strdup_printf("%sDevice/SysInfo", - device->priv->control_path); - - fd = fopen(path, "r"); - if(fd == NULL) { - g_free(path); - return FALSE; - } - - while(fgets(buf, sizeof(buf), fd)) { - buf[strlen(buf) - 1] = '\0'; - - for(i = 0; sysinfo_field_names[i] != NULL; i++) { - name_len = strlen(sysinfo_field_names[i]); - if(strncasecmp(buf, sysinfo_field_names[i], name_len) == 0) { - field_values[i] = strdup(buf + name_len + 2); - if(strncasecmp(field_values[i], "0x", 2) == 0) { - if((tmp = strstr(field_values[i], "(")) != NULL) { - field_values[i] = tmp + 1; - field_values[i][strlen(field_values[i]) - 1] = '\0'; - } - } - - field_values[i] = g_strdup(field_values[i]); - } - } - } - - fclose(fd); - - device->priv->serial_number = sysinfo_arr_get_dup(field_values, - "pszSerialNumber"); - device->priv->model_number = sysinfo_arr_get_dup(field_values, - "ModelNumStr"); - device->priv->firmware_version = sysinfo_arr_get_dup(field_values, - "visibleBuildID"); - - g_free(path); - - return TRUE; -} - -gboolean -ipod_device_info_load(IpodDevice *device) -{ - gchar *path; - FILE *fd; - gint intres; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE); - - path = g_strdup_printf("%siTunes/DeviceInfo", - device->priv->control_path); - - fd = fopen(path, "r"); - if(fd == NULL) { - g_free(path); - return FALSE; - } - - device->priv->device_name = ipod_device_read_device_info_string(fd); - if(device->priv->device_name == NULL) - device->priv->device_name = g_strdup("iPod"); - - intres=fseek(fd, 0x200, SEEK_SET); - device->priv->user_name = ipod_device_read_device_info_string(fd); - - intres=fseek(fd, 0x400, SEEK_SET); - device->priv->host_name = ipod_device_read_device_info_string(fd); - - fclose(fd); - g_free(path); - - return TRUE; -} - -gboolean -ipod_device_detect_writeable(IpodDevice *device) -{ - FILE *fp; - gchar *itunes_dir, *music_dir, *itunesdb_path; - struct stat finfo; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE); - - device->priv->can_write = FALSE; - - itunes_dir = g_strdup_printf("%siTunes", device->priv->control_path); - - if(!g_file_test(itunes_dir, G_FILE_TEST_IS_DIR)) { - if(g_mkdir_with_parents(itunes_dir, 0755) != 0) { - g_free(itunes_dir); - return FALSE; - } - } - - itunesdb_path = g_strdup_printf("%s/iTunesDB", itunes_dir); - - if((fp = fopen(itunesdb_path, "a+")) != NULL) { - device->priv->can_write = TRUE; - fclose(fp); - - memset(&finfo, 0, sizeof(finfo)); - if(stat(itunesdb_path, &finfo) == 0) { - if(finfo.st_size == 0) { - unlink(itunesdb_path); - } - } - } else { - g_free(itunes_dir); - g_free(itunesdb_path); - return FALSE; - } - - music_dir = g_strdup_printf("%sMusic", device->priv->control_path); - - if(!g_file_test(music_dir, G_FILE_TEST_IS_DIR)) { - device->priv->can_write = g_mkdir_with_parents(music_dir, 0755) == 0; - } - - g_free(itunes_dir); - g_free(itunesdb_path); - g_free(music_dir); - - return device->priv->can_write; -} - -static gint -ipod_device_get_model_index_from_table(const gchar *_model_num) -{ - gint i; - gchar *model_num = g_strdup(_model_num); - gchar *p = model_num; - - if(isalpha(model_num[0])) - p++; - - for(i = 2; ipod_model_table[i].model_number != NULL; i++) { - if(g_strncasecmp(p, ipod_model_table[i].model_number, 4) == 0) { - g_free(model_num); - return i; - } - } - - g_free(model_num); - return 1; -} - -guint -ipod_device_detect_model(IpodDevice *device) -{ - gint i; - guint64 adv, act; - gint cap; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), 0); - - device->priv->model_index = 0; - - /* Shuffle! */ - if(device->priv->model_number == NULL) { - for(i = 2; ipod_model_table[i].model_number != NULL; i++) { - if(ipod_model_table[i].model_type != MODEL_TYPE_SHUFFLE) - continue; - - cap = ipod_model_table[i].capacity; - adv = cap * 1048576; - act = device->priv->volume_size; - - if((adv - act) / 1048576 < 50) { - device->priv->model_index = i; - device->priv->model_number = g_strdup_printf("M%s", - ipod_model_table[i].model_number); - - device->priv->adv_capacity = g_strdup_printf("%d %s", - cap < 1024 ? cap : cap / 1024, - cap < 1024 ? "MB" : "GB"); - break; - } - } - } else { - /* Anything Else */ - device->priv->model_index = - ipod_device_get_model_index_from_table(device->priv->model_number); - - cap = ipod_model_table[device->priv->model_index].capacity; - - device->priv->adv_capacity = g_strdup_printf("%d %s", - cap < 1024 ? cap : cap / 1024, - cap < 1024 ? "MB" : "GB"); - } - - return device->priv->model_index; -} - -void -ipod_device_restore_reboot_preferences(IpodDevice *device) -{ - gchar *backup_prefs, *prefs; - - backup_prefs = g_strdup_printf("%s/.Reboot_Preferences", - device->priv->control_path); - prefs = g_strdup_printf("%s/Device/Preferences", - device->priv->control_path); - - g_return_if_fail(IS_IPOD_DEVICE(device)); - - if(g_file_test(backup_prefs, G_FILE_TEST_EXISTS)) { - unlink(prefs); - g_rename(backup_prefs, prefs); - } -} - -gboolean -ipod_device_detect_volume_info(IpodDevice *device) -{ -#ifdef HAVE_LIBHAL - LibHalContext *hal_context; - gchar **volumes; - gchar *hd_mount_point, *hd_device_path; - gchar *hd_hal_id = NULL, *maybe_hd_hal_id = NULL; - gint volume_count, i; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE); - hal_context = device->priv->hal_context; - - g_free_if_not_null(device->priv->device_path); - g_free_if_not_null(device->priv->mount_point); - device->priv->volume_size = 0; - - if(!libhal_device_exists(hal_context, device->priv->hal_volume_id, NULL)) { - /* For testing/debugging... we don't have a real device, but - the location may be a directory containing an iPod image */ - if(g_strncasecmp(device->priv->hal_volume_id, "/dev/", 5) == 0 || - device->priv->hal_volume_id[0] != '/') - return FALSE; - - g_free_if_not_null(device->priv->mount_point); - device->priv->mount_point = g_strdup(device->priv->hal_volume_id); - - g_free_if_not_null(device->priv->hal_volume_id); - g_free_if_not_null(device->priv->device_path); - - /* Let's find out about the disk drive containing our image */ - - volumes = libhal_manager_find_device_string_match(hal_context, - "info.category", "volume", &volume_count, NULL); - - for(i = 0; i < volume_count; i++) { - if(!libhal_device_property_exists(hal_context, - volumes[i], "volume.is_mounted", NULL) || - !libhal_device_get_property_bool(hal_context, - volumes[i], "volume.is_mounted", NULL)) { - continue; - } - - hd_mount_point = libhal_device_get_property_string(hal_context, - volumes[i], "volume.mount_point", NULL); - - if(g_strncasecmp(hd_mount_point, device->priv->mount_point, - strlen(hd_mount_point)) != 0) - continue; - - if(g_strcasecmp(hd_mount_point, "/") == 0) - maybe_hd_hal_id = volumes[i]; - else - hd_hal_id = volumes[i]; - } - - if(hd_hal_id == NULL && maybe_hd_hal_id != NULL) - hd_hal_id = maybe_hd_hal_id; - - if(hd_hal_id == NULL) { - libhal_free_string_array(volumes); - return FALSE; - } - - if(!libhal_device_exists(hal_context, hd_hal_id, NULL)) { - libhal_free_string_array(volumes); - return FALSE; - } - - hd_device_path = libhal_device_get_property_string(hal_context, - hd_hal_id, "block.device", NULL); - - device->priv->hal_volume_id = g_strdup(hd_hal_id); - device->priv->device_path = g_strdup(hd_device_path); - device->priv->volume_size = libhal_device_get_property_uint64( - hal_context, hd_hal_id, "volume.size", NULL); - - libhal_free_string_array(volumes); - - return TRUE; - } - - if(!libhal_device_property_exists(hal_context, - device->priv->hal_volume_id, "volume.is_mounted", NULL) - || !libhal_device_get_property_bool(hal_context, - device->priv->hal_volume_id, "volume.is_mounted", NULL)) { - return FALSE; - } - - if(libhal_device_property_exists(hal_context, device->priv->hal_volume_id, - "block.device", NULL)) - device->priv->device_path = libhal_device_get_property_string( - hal_context, device->priv->hal_volume_id, "block.device", NULL); - - if(libhal_device_property_exists(hal_context, device->priv->hal_volume_id, - "volume.mount_point", NULL)) - device->priv->mount_point = libhal_device_get_property_string( - hal_context, device->priv->hal_volume_id, - "volume.mount_point", NULL); - - if(libhal_device_property_exists(hal_context, device->priv->hal_volume_id, - "volume.size", NULL)) - device->priv->volume_size = libhal_device_get_property_uint64( - hal_context, device->priv->hal_volume_id, "volume.size", NULL); - - if(libhal_device_property_exists(hal_context, device->priv->hal_volume_id, - "volume.uuid", NULL)) { - device->priv->volume_uuid = libhal_device_get_property_string( - hal_context, device->priv->hal_volume_id, - "volume.uuid", NULL); - - if(strlen(device->priv->volume_uuid) == 0) { - g_free(device->priv->volume_uuid); - device->priv->volume_uuid = NULL; - } - } - - if(libhal_device_property_exists(hal_context, device->priv->hal_volume_id, - "volume.label", NULL)) - device->priv->volume_label = libhal_device_get_property_string( - hal_context, device->priv->hal_volume_id, - "volume.label", NULL); -#endif - return TRUE; -} - -void -ipod_device_detect_volume_used(IpodDevice *device) -{ - device->priv->volume_used = - ipod_device_dir_size(device->priv->mount_point); - device->priv->volume_available = device->priv->volume_size - - device->priv->volume_used; -} - -static void -_ipod_device_dir_size(const gchar *path, guint64 *total_size) -{ - GDir *dir; - const gchar *next_path; - gchar *fullpath; - struct stat finfo; - - if((dir = g_dir_open(path, 0, NULL)) == NULL) - return; - - while((next_path = g_dir_read_name(dir)) != NULL) { - fullpath = g_strdup_printf("%s/%s", path, next_path); - - if(g_file_test(fullpath, G_FILE_TEST_IS_DIR)) - _ipod_device_dir_size(fullpath, total_size); - else - *total_size += stat(fullpath, &finfo) == 0 ? finfo.st_size : 0; - - g_free(fullpath); - fullpath = NULL; - } - - g_dir_close(dir); -} - -guint64 -ipod_device_dir_size(const gchar *path) -{ - guint64 retsize, *size = g_new(guint64, 1); - *size = 0; - _ipod_device_dir_size(path, size); - retsize = *size; - g_free(size); - return retsize; -} - -#ifdef HAVE_LIBHAL -static gboolean -ipod_device_has_open_fd(IpodDevice *device) -{ - GDir *dir, *fddir; - gchar *fdpath, *fdidpath, *realpath; - const gchar *procpath, *fdid; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE); - - if((dir = g_dir_open("/proc", 0, NULL)) == NULL) - return FALSE; - - while((procpath = g_dir_read_name(dir)) != NULL) { - if(atoi(procpath) <= 0) - continue; - - fdpath = g_strdup_printf("/proc/%s/fd", procpath); - - if(!g_file_test(fdpath, G_FILE_TEST_IS_DIR)) { - g_free(fdpath); - continue; - } - - if((fddir = g_dir_open(fdpath, 0, NULL)) == NULL) { - g_free(fdpath); - continue; - } - - while((fdid = g_dir_read_name(fddir)) != NULL) { - fdidpath = g_strdup_printf("%s/%s", fdpath, fdid); - realpath = g_file_read_link(fdidpath, NULL); - - if(realpath == NULL) { - g_free(fdidpath); - continue; - } - - if(g_strncasecmp(realpath, device->priv->mount_point, - strlen(device->priv->mount_point)) == 0) { - g_dir_close(fddir); - g_dir_close(dir); - g_free(realpath); - g_free(fdidpath); - return TRUE; - } - - g_free(realpath); - g_free(fdidpath); - } - - g_dir_close(fddir); - } - - g_dir_close(dir); - - return FALSE; -} - -/* modded from g-v-m */ -static int -ipod_device_run_command(IpodDevice *device, const char *command, - GError **error_out) -{ - char *path; - const char *inptr, *start; - GError *error = NULL; - GString *exec; - char *argv[4]; - int status = 0; - - exec = g_string_new(NULL); - - /* perform s/%d/device/, s/%m/mount_point/ and s/%h/udi/ */ - start = inptr = command; - while((inptr = strchr (inptr, '%')) != NULL) { - g_string_append_len(exec, start, inptr - start); - inptr++; - switch (*inptr) { - case 'd': - g_string_append(exec, device->priv->device_path ? - device->priv->device_path : ""); - break; - case 'm': - if(device->priv->mount_point) { - path = g_shell_quote(device->priv->mount_point); - g_string_append(exec, path); - g_free(path); - } else { - g_string_append(exec, "\"\""); - } - break; - case 'h': - g_string_append(exec, device->priv->hal_volume_id); - break; - case '%': - g_string_append_c(exec, '%'); - break; - default: - g_string_append_c(exec, '%'); - if(*inptr) - g_string_append_c(exec, *inptr); - break; - } - - if(*inptr) - inptr++; - start = inptr; - } - - g_string_append(exec, start); - - argv[0] = "/bin/sh"; - argv[1] = "-c"; - argv[2] = exec->str; - argv[3] = NULL; - - g_spawn_sync(g_get_home_dir(), argv, NULL, 0, NULL, - NULL, NULL, NULL, &status, &error); - - if(error != NULL) - g_propagate_error(error_out, error); - - g_string_free(exec, TRUE); - - return status; -} -#endif - -/* PUBLIC METHODS */ - -IpodDevice * -ipod_device_new(const gchar *hal_volume_id) -{ - IpodDevice *device = g_object_new(TYPE_IPOD_DEVICE, - "hal-volume-id", hal_volume_id, NULL); - - if (device == NULL) { - /* This can happen if one forgot to call g_type_init before - * calling ipod_device_new - */ - return NULL; - } - - if(!device->priv->is_ipod) { - g_object_unref(device); - return NULL; - } - - return device; -} - -gboolean -ipod_device_rescan_disk(IpodDevice *device) -{ - g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE); - ipod_device_detect_volume_used(device); - return TRUE; -} - -guint -ipod_device_eject(IpodDevice *device, GError **error_out) -{ -#ifdef HAVE_LIBHAL - gint exit_status; - GError *error = NULL; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), EJECT_ERROR); - g_return_val_if_fail(device->priv->is_ipod, EJECT_ERROR); - - if(ipod_device_has_open_fd(device)) - return EJECT_BUSY; - -#ifdef ASSUME_SUBMOUNT - sync(); - - exit_status = ipod_device_run_command(device, EJECT_COMMAND, &error); - if(error) { - g_propagate_error(error_out, error); - return EJECT_ERROR; - } - - return exit_status == 0 ? EJECT_OK : EJECT_ERROR; -#endif - - exit_status = ipod_device_run_command(device, UNMOUNT_COMMAND, &error); - - if(!error && exit_status == 0) { - exit_status = ipod_device_run_command(device, EJECT_COMMAND, &error); - if(error) { - g_propagate_error(error_out, error); - return EJECT_ERROR; - } - - return exit_status == 0 ? EJECT_OK : EJECT_ERROR; - } - - if(error) - g_propagate_error(error_out, error); - - return EJECT_ERROR; -} - -guint -ipod_device_reboot(IpodDevice *device, GError **error_out) -{ - gchar *sysinfo, *prefs, *backup_prefs, *devpath; - gboolean can_eject = TRUE; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), EJECT_ERROR); - g_return_val_if_fail(device->priv->is_ipod, EJECT_ERROR); - - devpath = g_strdup_printf("%s/Device/", device->priv->control_path); - sysinfo = g_strdup_printf("%sSysInfo", devpath); - prefs = g_strdup_printf("%sPreferences", devpath); - backup_prefs = g_strdup_printf("%s/.Reboot_Preferences", - device->priv->control_path); - - if(g_file_test(sysinfo, G_FILE_TEST_EXISTS)) - can_eject = unlink(sysinfo) == 0; - - if(g_file_test(prefs, G_FILE_TEST_EXISTS) && can_eject) { - if(g_file_test(backup_prefs, G_FILE_TEST_EXISTS)) - unlink(backup_prefs); - - g_rename(prefs, backup_prefs); - unlink(prefs); - - can_eject = TRUE; - } - - if(can_eject) - can_eject = rmdir(devpath) == 0; - - g_free(devpath); - g_free(sysinfo); - g_free(prefs); - g_free(backup_prefs); - - if(can_eject) - return ipod_device_eject(device, error_out); - - g_propagate_error(error_out, g_error_new(g_quark_from_string("UNLINK"), - errno, "Could not remove file to initiate iPod reboot")); -#endif - return EJECT_ERROR; -} - -static GList * -_ipod_device_list_devices(gboolean create_device) -{ - LibHalContext *hal_context; - GList *finalDevices = NULL; - gchar **ipods, **volumes; - gint ipod_count, volume_count, i, j; - IpodDevice *ipod; - gboolean validIpod = FALSE; - - hal_context = ipod_device_hal_initialize(); - if(hal_context == NULL) - return NULL; - - ipods = libhal_manager_find_device_string_match(hal_context, - "info.product", "iPod", &ipod_count, NULL); - - for(i = 0; i < ipod_count; i++) { - volumes = libhal_manager_find_device_string_match(hal_context, - "info.parent", ipods[i], &volume_count, NULL); - - for(j = 0; j < volume_count; j++) { - if(!libhal_device_property_exists(hal_context, - volumes[j], "volume.is_mounted", NULL) - || !libhal_device_get_property_bool(hal_context, - volumes[j], "volume.is_mounted", NULL)) - continue; - - if(!create_device) { - finalDevices = g_list_append(finalDevices, - g_strdup(volumes[j])); - continue; - } - - if((ipod = ipod_device_new(volumes[j])) == NULL) - continue; - - g_object_get(ipod, "is-ipod", &validIpod, NULL); - if(validIpod) - finalDevices = g_list_append(finalDevices, ipod); - } - } - - libhal_ctx_shutdown(hal_context, NULL); - libhal_ctx_free(hal_context); - - return finalDevices; -} - -GList * -ipod_device_list_devices() -{ - return _ipod_device_list_devices(TRUE); -} - -GList * -ipod_device_list_device_udis() -{ - return _ipod_device_list_devices(FALSE); -} - -gboolean -ipod_device_save(IpodDevice *device, GError **error_out) -{ - FILE *fd; - gchar *path, *itunes_dir; - gchar bs = 0; - GError *error = NULL; - size_t res; - gint intres; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE); - - itunes_dir = g_strdup_printf("%siTunes", device->priv->control_path); - path = g_strdup_printf("%s/DeviceInfo", itunes_dir); - - if(!g_file_test(itunes_dir, G_FILE_TEST_IS_DIR)) { - if(g_mkdir_with_parents(itunes_dir, 0744) != 0) { - if(error_out != NULL) { - error = g_error_new(g_quark_from_static_string("IPOD_DEVICE"), - ERROR_SAVE, "Could not create iTunes Directory: %s", - itunes_dir); - g_propagate_error(error_out, error); - } - - g_free(path); - g_free(itunes_dir); - - return FALSE; - } - } - - fd = fopen(path, "w+"); - if(fd == NULL) { - if(error_out != NULL) { - error = g_error_new(g_quark_from_static_string("IPOD_DEVICE"), - ERROR_SAVE, "Could not save DeviceInfo file: %s", path); - g_propagate_error(error_out, error); - } - - g_free(path); - g_free(itunes_dir); - - return FALSE; - } - - ipod_device_write_device_info_string(device->priv->device_name, fd); - - fseek(fd, 0x200, SEEK_SET); - ipod_device_write_device_info_string(device->priv->user_name, fd); - - intres = fseek(fd, 0x400, SEEK_SET); - ipod_device_write_device_info_string(device->priv->host_name, fd); - - intres = fseek(fd, 0X5FF, SEEK_SET); - /* FIXME: we do not check if the write was successful */ - res = fwrite(&bs, 1, 1, fd); - - fclose(fd); - - g_free(path); - g_free(itunes_dir); - - return TRUE; -} - -void -ipod_device_debug(IpodDevice *device) -{ - static const gchar *generation_names [] = { - "Unknown", - "First", - "Second", - "Third", - "Fourth" - }; - - gchar *device_path, *mount_point, *control_path, *hal_id; - gchar *model_number, *adv_capacity, *model_string; - guint model, generation; - gboolean is_new, can_write; - gchar *serial_number, *firmware_version; - guint64 volume_size, volume_used, volume_available; - gchar *volume_uuid, *volume_label; - gchar *device_name, *user_name, *host_name; - - g_return_if_fail(IS_IPOD_DEVICE(device)); - - g_object_get(device, - "device-path", &device_path, - "mount-point", &mount_point, - "control-path", &control_path, - "hal-volume-id", &hal_id, - "model-number", &model_number, - "device-model", &model, - "device-model-string", &model_string, - "device-generation", &generation, - "advertised-capacity", &adv_capacity, - "is-new", &is_new, - "can-write", &can_write, - "serial-number", &serial_number, - "firmware-version", &firmware_version, - "volume-size", &volume_size, - "volume-used", &volume_used, - "volume-available", &volume_available, - "volume_uuid", &volume_uuid, - "volume-label", &volume_label, - "device-name", &device_name, - "user-name", &user_name, - "host-name", &host_name, - NULL); - - g_printf("Path Info\n"); - g_printf(" Device Path: %s\n", device_path); - g_printf(" Mount Point: %s\n", mount_point); - g_printf(" Control Path: %s\n", control_path); - g_printf(" HAL ID: %s\n", hal_id); - - g_printf("Device Info\n"); - g_printf(" Model Number: %s\n", model_number); - g_printf(" Device Model: %s\n", model_string); - g_printf(" iPod Generation: %s\n", generation_names[generation]); - g_printf(" Adv. Capacity: %s\n", adv_capacity); - g_printf(" Is New: %s\n", is_new ? "YES" : "NO"); - g_printf(" Writeable: %s\n", can_write ? "YES" : "NO"); - g_printf(" Serial Number: %s\n", serial_number); - g_printf(" Firmware Version: %s\n", firmware_version); - g_printf("Volume Info\n"); - g_printf(" Volume Size: %lld\n", (long long int)volume_size); - g_printf(" Volume Used: %lld\n", (long long int)volume_used); - g_printf(" Available %lld\n", (long long int)volume_available); - g_printf(" UUID: %s\n", volume_uuid); - g_printf(" Label %s\n", volume_label); - g_printf("User-Provided Info\n"); - g_printf(" Device Name: %s\n", device_name); - g_printf(" User Name: %s\n", user_name); - g_printf(" Host Name: %s\n", host_name); - - g_printf("\n"); - fflush(stdout); -} |