Hello community,
here is the log from the commit of package libipoddevice
checked in at Mon Apr 24 21:09:18 CEST 2006.
--------
--- GNOME/libipoddevice/libipoddevice.changes 2006-02-13 17:19:35.000000000 +0100
+++ STABLE/libipoddevice/libipoddevice.changes 2006-04-23 21:13:33.000000000 +0200
@@ -1,0 +2,17 @@
+Sun Apr 23 21:07:34 CEST 2006 - jpr@suse.de
+
+- Update to 0.4.5
+- Fixes:
+ * Fix critical segfault found on Shuffle iPods (#157382)
+ * Handle proper return from fread;
+ * Add "Fifth" string to generation string table
+ * Use buildID instead of visibleBuildID from SysInfo to report
+ firmware version
+ * Guess the model number based on iPod generation and volume
+ size for 1G/2G iPods (BGO #338006)
+ * Remove broken reboot support
+ * gcc 4.1 fixes
+ * Handle overwritten play counts in sysinfo files
+ * Don't support, but safely new dhdp binary headers
+
+-------------------------------------------------------------------
Old:
----
libipoddevice-0.4.1.tar.gz
New:
----
libipoddevice-0.4.5.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ libipoddevice.spec ++++++
--- /var/tmp/diff_new_pack.oqSRI7/_old 2006-04-24 21:08:52.000000000 +0200
+++ /var/tmp/diff_new_pack.oqSRI7/_new 2006-04-24 21:08:52.000000000 +0200
@@ -1,5 +1,5 @@
#
-# spec file for package libipoddevice (Version 0.4.1)
+# spec file for package libipoddevice (Version 0.4.5)
#
# Copyright (c) 2006 SUSE LINUX Products GmbH, Nuernberg, Germany.
# This file and all modifications and additions to the pristine
@@ -16,7 +16,7 @@
License: LGPL
Group: Development/Libraries/GNOME
Autoreqprov: on
-Version: 0.4.1
+Version: 0.4.5
Release: 1
Summary: GObject Library That Provides iPod Device Transparency through HAL
Source: %{name}-%{version}.tar.gz
@@ -91,6 +91,20 @@
%{_libdir}/pkgconfig/ipoddevice.pc
%changelog -n libipoddevice
+* Sun Apr 23 2006 - jpr@suse.de
+- Update to 0.4.5
+- Fixes:
+ * Fix critical segfault found on Shuffle iPods (#157382)
+ * Handle proper return from fread;
+ * Add "Fifth" string to generation string table
+ * Use buildID instead of visibleBuildID from SysInfo to report
+ firmware version
+ * Guess the model number based on iPod generation and volume
+ size for 1G/2G iPods (BGO #338006)
+ * Remove broken reboot support
+ * gcc 4.1 fixes
+ * Handle overwritten play counts in sysinfo files
+ * Don't support, but safely new dhdp binary headers
* Mon Feb 13 2006 - gekker@suse.de
- Update to version 0.4.1
- Handle ejecting of devices properly
++++++ libipoddevice-0.4.1.tar.gz -> libipoddevice-0.4.5.tar.gz ++++++
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/libipoddevice-0.4.1/ChangeLog new/libipoddevice-0.4.5/ChangeLog
--- old/libipoddevice-0.4.1/ChangeLog 2006-02-13 08:37:47.000000000 +0100
+++ new/libipoddevice-0.4.5/ChangeLog 2006-04-14 01:34:54.000000000 +0200
@@ -1,3 +1,67 @@
+2006-04-13 Aaron Bockover
+
+ 0.4.5 Released
+
+ * configure.ac: Bump to 0.4.5
+
+ * src/ipod-device.c: Fix critical segfault found on Shuffle iPods due
+ to strtol not handling NULL input; use the safer g_ascii_strtoull
+ instead of strtol and explicitly check for NULL
+
+2006-04-11 Aaron Bockover
+
+ 0.4.4 Released
+
+ * configure.ac: Bump to 0.4.4
+
+ * src/ipod-device.c: Handle proper return from fread; Add "Fifth" string
+ to generation string table
+
+2006-04-11 Aaron Bockover
+
+ 0.4.3 Released
+
+ * configure.ac: Bump to 0.4.3
+
+2006-04-11 Aaron Bockover
+
+ * src/ipod-device.c: Use buildID instead of visibleBuildID from SysInfo
+ to report firmware version; added a hex version parser to construct
+ a pretty version string
+
+2006-04-10 Aaron Bockover
+
+ * src/ipod-device.c: Guess the model number based on iPod generation
+ and volume size for 1G/2G iPods (BGO #338006)
+
+2006-04-10 Aaron Bockover
+
+ 0.4.2 Released
+
+ * cconfigure.ac: Bump to 0.4.2; do not show unmount/eject summary if
+ using HAL for ejecting
+
+2006-04-10 Aaron Bockover
+
+ * src/ipod-device-test.c: Removed reboot support
+
+ * src/ipod-device.c: Lots of clean up, reorganized some things; make
+ gcc 4.1 happy by handling return values on some previously ignored
+ functions (fread/fwrite); removed reboot support (never worked properly)
+
+2006-04-10 Aaron Bockover
+
+ * src/ipod-device.c: Use a GData structure to hold full SysInfo table
+ in memory for the lifetime of the instance; ipod_device_read_sysinfo
+ now has a faster and safer SysInfo parser and warns if SysInfo looks
+ overwritten by Play Counts (apparently this is happening on some iPods)
+
+2006-04-07 Aaron Bockover
+
+ * src/ipod-device.c: Check for an mhdp binary header in the SysInfo file;
+ do not attempt to parse it if found... new format needs reverse
+ engineering now :/
+
2006-02-13 Aaron Bockover
0.4.1 Released
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/libipoddevice-0.4.1/configure new/libipoddevice-0.4.5/configure
--- old/libipoddevice-0.4.1/configure 2006-02-13 08:04:08.000000000 +0100
+++ new/libipoddevice-0.4.5/configure 2006-04-14 01:30:12.000000000 +0200
@@ -1839,7 +1839,7 @@
# Define the identity of the package.
PACKAGE=libipoddevice
- VERSION=0.4.1
+ VERSION=0.4.5
cat >>confdefs.h <<_ACEOF
@@ -21220,8 +21220,16 @@
echo "
libipoddevice has been configured as follows:
- Install Prefix: ${prefix}
+ Install Prefix: ${prefix}"
+
+if test "x$hal_eject" = "xyes"; then
+echo "
+ Using HAL for ejecting
+"
+else
+echo "
Unmount command: $unmount_command
Eject command: $eject_command
"
+fi
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/libipoddevice-0.4.1/configure.ac new/libipoddevice-0.4.5/configure.ac
--- old/libipoddevice-0.4.1/configure.ac 2006-02-13 08:03:57.000000000 +0100
+++ new/libipoddevice-0.4.5/configure.ac 2006-04-14 01:30:02.000000000 +0200
@@ -3,7 +3,7 @@
AC_INIT(src/ipod-device.c)
AM_CONFIG_HEADER(config.h)
AC_CONFIG_SRCDIR(src)
-AM_INIT_AUTOMAKE(libipoddevice, 0.4.1)
+AM_INIT_AUTOMAKE(libipoddevice, 0.4.5)
AM_MAINTAINER_MODE
AC_PROG_CC
@@ -58,8 +58,16 @@
echo "
libipoddevice has been configured as follows:
- Install Prefix: ${prefix}
+ Install Prefix: ${prefix}"
+
+if test "x$hal_eject" = "xyes"; then
+echo "
+ Using HAL for ejecting
+"
+else
+echo "
Unmount command: $unmount_command
Eject command: $eject_command
"
+fi
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/libipoddevice-0.4.1/src/ipod-device-test.c new/libipoddevice-0.4.5/src/ipod-device-test.c
--- old/libipoddevice-0.4.1/src/ipod-device-test.c 2005-11-08 23:04:53.000000000 +0100
+++ new/libipoddevice-0.4.5/src/ipod-device-test.c 2006-04-11 04:24:57.000000000 +0200
@@ -55,7 +55,7 @@
g_message("Device Removed: %s", udi);
}
-void list_devices()
+static void list_devices()
{
IpodDevice *device;
GList *devices;
@@ -78,7 +78,7 @@
g_list_free(devices);
}
-void list_device_udis()
+static void list_device_udis()
{
gchar *udi;
GList *devices;
@@ -101,7 +101,7 @@
g_list_free(devices);
}
-gint eject_device(gchar *id)
+static gint eject_device(gchar *id)
{
IpodDevice *device = ipod_device_new(id);
gint ret = 1;
@@ -131,38 +131,7 @@
return ret;
}
-gint reboot_device(gchar *id)
-{
- IpodDevice *device = ipod_device_new(id);
- gint ret = 1;
- GError *error = NULL;
-
- if(device == NULL) {
- g_printf("Could not get device for '%s'\n", id);
- return 1;
- }
-
- switch(ipod_device_reboot(device, &error)) {
- case EJECT_OK:
- g_printf("Rebooted `%s' OK\n", id);
- ret = 0;
- break;
- case EJECT_ERROR:
- g_printf("Could not Reboot `%s':%s \n", id, error->message);
- ret = 1;
- break;
- case EJECT_BUSY:
- g_printf("Could not Reboot `%s', Device Busy\n", id);
- ret = 1;
- break;
- }
-
- g_object_unref(device);
-
- return ret;
-}
-
-gint eject_all_devices()
+static gint eject_all_devices()
{
gchar *udi;
GList *devices;
@@ -189,7 +158,7 @@
return failure ? 1 : 0;
}
-int debug_image(gchar *path)
+static int debug_image(gchar *path)
{
IpodDevice *device = ipod_device_new(path);
if(device == NULL) {
@@ -202,7 +171,7 @@
return 0;
}
-int set_settings(gchar *id, gchar *name, gchar *user, gchar *host)
+static int set_settings(gchar *id, gchar *name, gchar *user, gchar *host)
{
IpodDevice *device = ipod_device_new(id);
int ret = 0;
@@ -231,7 +200,7 @@
return !ret;
}
-void help()
+static void help()
{
g_printf(
"ipod: Test control program for the IpodDevice and IpodDeviceEventListener\n"
@@ -272,8 +241,6 @@
exit(0);
} else if(argc > 2 && strcmp(argv[1], "--eject") == 0) {
exit(eject_device(argv[2]));
- } else if(argc > 2 && strcmp(argv[1], "--reboot") == 0) {
- exit(reboot_device(argv[2]));
} else if(argc > 1 && strcmp(argv[1], "--eject") == 0) {
exit(eject_all_devices());
} else if(argc > 2 && strcmp(argv[1], "--image") == 0) {
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/libipoddevice-0.4.1/src/ipod-device.c new/libipoddevice-0.4.5/src/ipod-device.c
--- old/libipoddevice-0.4.1/src/ipod-device.c 2006-02-13 08:41:05.000000000 +0100
+++ new/libipoddevice-0.4.5/src/ipod-device.c 2006-04-14 01:33:36.000000000 +0200
@@ -1,8 +1,8 @@
/* ex: set ts=4: */
/***************************************************************************
* ipod-device.c
-* Copyright (C) 2005 Novell
-* Written by Aaron Bockover
+* Copyright (C) 2005-2006 Novell, Inc.
+* Written by Aaron Bockover
****************************************************************************/
/*
@@ -50,7 +50,6 @@
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*/
@@ -205,24 +204,10 @@
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;
-}
+#define CAPACITY_DISPLAY_STRING(cap) \
+ g_strdup_printf("%d %s", \
+ cap < 1024 ? cap : cap / 1024, \
+ cap < 1024 ? "MB" : "GB")
static void ipod_device_class_init(IpodDeviceClass *klass);
static void ipod_device_init(IpodDevice *sp);
@@ -238,11 +223,8 @@
static gboolean ipod_device_detect_volume_info(IpodDevice *device);
static LibHalContext *ipod_device_hal_initialize();
static void ipod_device_detect_volume_used(IpodDevice *device);
-static gboolean ipod_device_has_open_fd(IpodDevice *device);
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);
-static gboolean ipod_device_udi_is_subfs_mount(IpodDevice *device);
struct IpodDevicePrivate {
LibHalContext *hal_context;
@@ -267,9 +249,7 @@
guint64 volume_used;
/* System Info */
- gchar *serial_number;
- gchar *model_number;
- gchar *firmware_version;
+ GData *sys_info_table;
gchar *volume_uuid;
gchar *volume_label;
@@ -311,6 +291,31 @@
return type;
}
+static gchar *
+ipod_version_string_from_hex(glong version)
+{
+ gint major, minor, micro;
+
+ version >>= 16;
+ major = (version & 0x0f00) >> 8;
+ minor = (version & 0x00f0) >> 4;
+ micro = version & 0x000f;
+
+ return micro == 0 ?
+ g_strdup_printf("%d.%d", major, minor) :
+ g_strdup_printf("%d.%d.%d", major, minor, micro);
+}
+
+static gchar *
+ipod_version_string_from_hex_string(gchar *hex_version)
+{
+ if(hex_version == NULL) {
+ return NULL;
+ }
+
+ return ipod_version_string_from_hex(g_ascii_strtoull(hex_version, NULL, 16));
+}
+
static void
ipod_device_get_property(GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
@@ -374,15 +379,22 @@
g_value_set_boolean(value, device->priv->is_new);
break;
case PROP_SERIAL_NUMBER:
- g_value_set_string(value, device->priv->serial_number);
+ g_value_set_string(value, g_datalist_get_data(
+ &device->priv->sys_info_table, "pszSerialNumber"));
break;
case PROP_MODEL_NUMBER:
- g_value_set_string(value, device->priv->model_number);
+ g_value_set_string(value, g_datalist_get_data(
+ &device->priv->sys_info_table, "ModelNumStr"));
break;
- case PROP_FIRMWARE_VERSION:
- g_value_set_string(value, device->priv->firmware_version);
+ case PROP_FIRMWARE_VERSION: {
+ gchar *firmware = g_datalist_get_data(&device->priv->sys_info_table, "buildID");
+ gchar *firmware_formatted = ipod_version_string_from_hex_string(firmware);
+ g_value_set_string(value, firmware_formatted);
+ if(firmware_formatted != NULL) {
+ g_free(firmware_formatted);
+ }
break;
- case PROP_VOLUME_UUID:
+ } case PROP_VOLUME_UUID:
g_value_set_string(value, device->priv->volume_uuid);
break;
case PROP_VOLUME_LABEL:
@@ -675,9 +687,7 @@
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->sys_info_table = NULL;
device->priv->volume_uuid = NULL;
device->priv->volume_label = NULL;
@@ -703,12 +713,14 @@
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->sys_info_table != NULL) {
+ g_datalist_clear(&device->priv->sys_info_table);
+ device->priv->sys_info_table = NULL;
+ }
+
if(device->priv->hal_context != NULL) {
libhal_ctx_shutdown(device->priv->hal_context, NULL);
libhal_ctx_free(device->priv->hal_context);
@@ -718,9 +730,9 @@
G_OBJECT_CLASS(parent_class)->finalize(object);
}
-/* PRIVATE METHODS */
+/* Private Methods */
-LibHalContext *
+static LibHalContext *
ipod_device_hal_initialize()
{
LibHalContext *hal_context;
@@ -730,8 +742,9 @@
gint device_count;
hal_context = libhal_ctx_new();
- if(hal_context == NULL)
+ if(hal_context == NULL) {
return NULL;
+ }
dbus_error_init(&error);
dbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
@@ -761,15 +774,16 @@
return hal_context;
}
-gboolean
+static 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))
+ if(!ipod_device_detect_volume_info(device)) {
return FALSE;
+ }
ipod_device_construct_paths(device);
@@ -779,12 +793,11 @@
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
+static void
ipod_device_construct_paths(IpodDevice *device)
{
int len;
@@ -793,33 +806,37 @@
g_return_if_fail(device->priv->mount_point != NULL);
len = strlen(device->priv->mount_point);
- if(device->priv->mount_point[len - 1] == '/')
+ if(device->priv->mount_point[len - 1] == '/') {
device->priv->mount_point[len - 1] = '\0';
-
- if(strlen(device->priv->mount_point) == 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 *
+static gchar *
ipod_device_read_device_info_string(FILE *fd)
{
gshort length;
gunichar2 *utf16;
gchar *utf8;
- fread(&length, 1, sizeof(gshort), fd);
-
- if(length <= 0)
+ if(fread(&length, 1, sizeof(gshort), fd) <= 0) {
return NULL;
+ } else if(length <= 0) {
+ return NULL;
+ }
utf16 = (gunichar2 *)g_malloc(length * sizeof(gunichar2));
- fread(utf16, sizeof(gunichar2), length, fd);
-
- if(utf16 == NULL)
+ if(utf16 == NULL) {
return NULL;
+ } else if(fread(utf16, sizeof(gunichar2), length, fd) <= 0) {
+ return NULL;
+ }
utf8 = g_utf16_to_utf8(utf16, length, NULL, NULL, NULL);
@@ -829,38 +846,39 @@
return utf8;
}
-void
+static void
ipod_device_write_device_info_string(gchar *str, FILE *fd)
{
gunichar2 *unistr;
gshort length;
- if(str == NULL)
+ if(str == NULL) {
return;
+ }
length = strlen(str);
unistr = g_utf8_to_utf16(str, length, NULL, NULL, NULL);
length = length > 0x198 ? 0x198 : length;
- fwrite(&length, 2, 1, fd);
- fwrite(unistr, 2, length, fd);
+ if(fwrite(&length, 2, 1, fd) <= 0
+ || fwrite(unistr, 2, length, fd) <= 0) {
+ g_warning("Could not write to DeviceInfo file");
+ }
g_free(unistr);
}
-gboolean
+static gboolean
ipod_device_read_sysinfo(IpodDevice *device)
{
- gchar *field_values[sizeof(sysinfo_field_names) + 1];
- gchar *tmp, *path, buf[512];
- gint i, name_len;
+ gchar *path, buf[512];
+ gboolean corrupt_check = FALSE;
FILE *fd;
g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE);
- path = g_strdup_printf("%sDevice/SysInfo",
- device->priv->control_path);
+ path = g_strdup_printf("%sDevice/SysInfo", device->priv->control_path);
fd = fopen(path, "r");
if(fd == NULL) {
@@ -868,40 +886,72 @@
return FALSE;
}
+ if(device->priv->sys_info_table != NULL) {
+ g_datalist_clear(&device->priv->sys_info_table);
+ device->priv->sys_info_table = NULL;
+ }
+
+ g_datalist_init(&device->priv->sys_info_table);
+
while(fgets(buf, sizeof(buf), fd)) {
- buf[strlen(buf) - 1] = '\0';
+ gint key_length, value_length;
+ gchar *key, *value, *p;
- 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]);
- }
+ // there have been reports that SysInfo can become "corrupt";
+ // the iPod writes the Play Counts file in place of SysInfo
+ if(!corrupt_check && strncasecmp(buf, "mhdp", 4) == 0) {
+ g_fprintf(stderr,
+ "*******************************************************************\n"
+ "Your iPod's SysInfo file is corrupt! To fix it, run the\n"
+ "following command and eject your iPod:\n\n"
+ " rm -rf %sDevice/\n\n"
+ "This will cause the iPod to reboot and restore its SysInfo file\n"
+ "after you eject it. You WILL lose your iPod preferences (language\n"
+ "setting, clicker setting, etc.), but not the database, music, \n"
+ "or other data. Perform at your own risk!\n"
+ "*******************************************************************\n\n",
+ device->priv->control_path);
+ break;
+ }
+
+ corrupt_check = TRUE;
+
+ if((value = strchr(buf, ':')) == NULL) {
+ continue;
+ }
+
+ value += 2;
+ value_length = strlen(value);
+ key_length = value - buf - 2;
+
+ if(value_length <= 4 || key_length <= 0) {
+ continue;
+ }
+
+ value[value_length - 1] = '\0';
+
+ key = g_strndup(buf, key_length);
+ if(key == NULL) {
+ continue;
+ }
+
+ // if it's a hex value, be sure to strip out the version string if it exists
+ if(value[0] == '0' && value[1] == 'x' && (p = strchr(value, ' ')) != NULL) {
+ *p = '\0';
}
+
+ g_datalist_set_data_full(&device->priv->sys_info_table,
+ key, g_strdup(value), g_free);
+ g_free(key);
}
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
+static gboolean
ipod_device_info_load(IpodDevice *device)
{
gchar *path;
@@ -919,8 +969,9 @@
}
device->priv->device_name = ipod_device_read_device_info_string(fd);
- if(device->priv->device_name == NULL)
+ if(device->priv->device_name == NULL) {
device->priv->device_name = g_strdup("iPod");
+ }
fseek(fd, 0x200, SEEK_SET);
device->priv->user_name = ipod_device_read_device_info_string(fd);
@@ -934,82 +985,7 @@
return TRUE;
}
-
-#ifndef HAVE_G_MKDIR_WITH_PARENTS
-/**
- * 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
- */
-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
-
-gboolean
+static gboolean
ipod_device_detect_writeable(IpodDevice *device)
{
FILE *fp;
@@ -1060,15 +1036,16 @@
return device->priv->can_write;
}
-gint
+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]))
+ 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) {
@@ -1081,22 +1058,27 @@
return 1;
}
-guint
+static guint
ipod_device_detect_model(IpodDevice *device)
{
gint i;
guint64 adv, act;
gint cap;
+ const gchar *model_number;
+ const gchar *board_rev;
g_return_val_if_fail(IS_IPOD_DEVICE(device), 0);
device->priv->model_index = 0;
+ model_number = g_datalist_get_data(&device->priv->sys_info_table, "ModelNumStr");
+ board_rev = g_datalist_get_data(&device->priv->sys_info_table, "boardHwSwInterfaceRev");
- /* Shuffle! */
- if(device->priv->model_number == NULL) {
+ if(model_number == NULL && board_rev == NULL) {
+ /* Will be an iPod Shuffle; it doesn't have a SysInfo file */
for(i = 2; ipod_model_table[i].model_number != NULL; i++) {
- if(ipod_model_table[i].model_type != MODEL_TYPE_SHUFFLE)
+ if(ipod_model_table[i].model_type != MODEL_TYPE_SHUFFLE) {
continue;
+ }
cap = ipod_model_table[i].capacity;
adv = cap * 1048576;
@@ -1104,49 +1086,55 @@
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);
+
+ g_datalist_set_data_full(&device->priv->sys_info_table, "ModelNumStr",
+ g_strdup_printf("M%s", ipod_model_table[i].model_number), g_free);
- device->priv->adv_capacity = g_strdup_printf("%d %s",
- cap < 1024 ? cap : cap / 1024,
- cap < 1024 ? "MB" : "GB");
+ device->priv->adv_capacity = CAPACITY_DISPLAY_STRING(cap);
break;
}
}
- } else {
- /* Anything Else */
- device->priv->model_index =
- ipod_device_get_model_index_from_table(device->priv->model_number);
+ } else if(model_number == NULL) {
+ /* Guess the model number based on capacity and generation;
+ 2G iPods and older do not have ModelNumStr in SysInfo */
+
+ glong raw_generation = (glong)g_ascii_strtoull(board_rev, NULL, 16);
+ gint i, generation = raw_generation >> 16;
+ const gchar *model_num = NULL;
+
+ /* we have to guess based on generation and volume size :'( */
+ if(generation == 1) {
+ model_num = device->priv->volume_size >= 9000000000ll ?
+ "8709" : "8513";
+ } else if(generation == 2) {
+ model_num = device->priv->volume_size >= 19000000000ll ?
+ "8741" : "8737";
+ }
+ if(model_num != NULL) {
+ g_datalist_set_data_full(&device->priv->sys_info_table, "ModelNumStr",
+ g_strdup_printf("M%s", model_num), g_free);
+
+ for(i = 2; ipod_model_table[i].model_number != NULL; i++) {
+ if(strcmp(ipod_model_table[i].model_number, model_num) == 0) {
+ cap = ipod_model_table[i].capacity;
+ device->priv->adv_capacity = CAPACITY_DISPLAY_STRING(cap);
+ device->priv->model_index = i;
+ break;
+ }
+ }
+ }
+ } else {
+ /* Anything else */
+ device->priv->model_index = ipod_device_get_model_index_from_table(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");
+ device->priv->adv_capacity = CAPACITY_DISPLAY_STRING(cap);
}
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
+static gboolean
ipod_device_detect_volume_info(IpodDevice *device)
{
LibHalContext *hal_context;
@@ -1166,9 +1154,10 @@
/* 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] != '/')
+ 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);
@@ -1192,17 +1181,20 @@
volumes[i], "volume.mount_point", NULL);
if(g_strncasecmp(hd_mount_point, device->priv->mount_point,
- strlen(hd_mount_point)) != 0)
+ strlen(hd_mount_point)) != 0) {
continue;
+ }
- if(g_strcasecmp(hd_mount_point, "/") == 0)
+ if(g_strcasecmp(hd_mount_point, "/") == 0) {
maybe_hd_hal_id = volumes[i];
- else
+ } else {
hd_hal_id = volumes[i];
+ }
}
- if(hd_hal_id == NULL && maybe_hd_hal_id != NULL)
+ 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);
@@ -1235,20 +1227,23 @@
}
if(libhal_device_property_exists(hal_context, device->priv->hal_volume_id,
- "block.device", NULL))
+ "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))
+ "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))
+ "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)) {
@@ -1263,15 +1258,16 @@
}
if(libhal_device_property_exists(hal_context, device->priv->hal_volume_id,
- "volume.label", NULL))
+ "volume.label", NULL)) {
device->priv->volume_label = libhal_device_get_property_string(
hal_context, device->priv->hal_volume_id,
"volume.label", NULL);
+ }
return TRUE;
}
-void
+static void
ipod_device_detect_volume_used(IpodDevice *device)
{
glibtop_fsusage fsbuf;
@@ -1281,7 +1277,68 @@
device->priv->volume_available;
}
-gboolean
+/* Private Eject/Unmount Helper Methods */
+
+#ifdef HAVE_HAL_EJECT
+
+static gboolean
+ipod_device_eject_hal(IpodDevice *device, gchar **error_out)
+{
+ DBusMessage *dmesg, *reply;
+ DBusError error;
+ GPtrArray *options;
+ DBusConnection *dbus_connection;
+
+ gchar *udi = device->priv->hal_volume_id;
+
+ *error_out = NULL;
+
+ dbus_error_init(&error);
+ dbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+ if(dbus_error_is_set(&error)) {
+ *error_out = g_strdup_printf("eject failed for %s: %s", udi, error.message);
+ dbus_error_free(&error);
+ return FALSE;
+ }
+
+ if(!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
+ "org.freedesktop.Hal.Device.Volume", "Eject"))) {
+ *error_out = g_strdup_printf("eject failed for %s: could not create dbus message", udi);
+ return FALSE;
+ }
+
+ options = g_ptr_array_new();
+
+ if(!dbus_message_append_args(dmesg,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options->pdata, options->len,
+ DBUS_TYPE_INVALID)) {
+ *error_out = g_strdup_printf("eject failed for %s: could not append args to dbus message", udi);
+ dbus_message_unref(dmesg);
+ g_ptr_array_free(options, TRUE);
+ return FALSE;
+ }
+
+ g_ptr_array_free(options, TRUE);
+
+ if(!(reply = dbus_connection_send_with_reply_and_block(
+ dbus_connection, dmesg, -1, &error))) {
+ *error_out = g_strdup_printf("eject failed for %s: %s", udi, error.message);
+ dbus_message_unref(dmesg);
+ dbus_error_free(&error);
+ return FALSE;
+ }
+
+ g_debug("eject queued for %s\n", udi);
+
+ dbus_message_unref(dmesg);
+ dbus_message_unref(reply);
+
+ return TRUE;
+}
+
+#else
+
+static gboolean
ipod_device_has_open_fd(IpodDevice *device)
{
GDir *dir, *fddir;
@@ -1290,12 +1347,14 @@
g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE);
- if((dir = g_dir_open("/proc", 0, NULL)) == NULL)
+ if((dir = g_dir_open("/proc", 0, NULL)) == NULL) {
return FALSE;
-
+ }
+
while((procpath = g_dir_read_name(dir)) != NULL) {
- if(atoi(procpath) <= 0)
+ if(atoi(procpath) <= 0) {
continue;
+ }
fdpath = g_strdup_printf("/proc/%s/fd", procpath);
@@ -1339,7 +1398,30 @@
return FALSE;
}
-// modded from g-v-m
+static gboolean
+ipod_device_udi_is_subfs_mount(IpodDevice *device)
+{
+ gint subfs = FALSE;
+ gchar **callouts;
+ gint i;
+
+ if((callouts = libhal_device_get_property_strlist(device->priv->hal_context,
+ device->priv->hal_volume_id, "info.callouts.add", NULL))) {
+ for(i = 0; callouts[i] != NULL; i++) {
+ if(!strcmp(callouts[i], "hald-subfs-mount")) {
+ subfs = TRUE;
+ g_debug("subfs handles mount for %s; skipping unmount",
+ device->priv->device_path);
+ break;
+ }
+ }
+
+ libhal_free_string_array(callouts);
+ }
+
+ return subfs;
+}
+
static int
ipod_device_run_command(IpodDevice *device, const char *command,
GError **error_out)
@@ -1380,13 +1462,16 @@
break;
default:
g_string_append_c(exec, '%');
- if(*inptr)
+ if(*inptr) {
g_string_append_c(exec, *inptr);
+ }
break;
}
- if(*inptr)
+ if(*inptr) {
inptr++;
+ }
+
start = inptr;
}
@@ -1400,15 +1485,18 @@
g_spawn_sync(g_get_home_dir(), argv, NULL, 0, NULL,
NULL, NULL, NULL, &status, &error);
- if(error != NULL)
+ if(error != NULL) {
g_propagate_error(error_out, error);
+ }
g_string_free(exec, TRUE);
return status;
}
-/* PUBLIC METHODS */
+#endif
+
+/* Public Methods */
IpodDevice *
ipod_device_new(const gchar *hal_volume_id)
@@ -1416,10 +1504,7 @@
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
- */
+ if(device == NULL) {
return NULL;
}
@@ -1439,104 +1524,20 @@
return TRUE;
}
-static gboolean
-ipod_device_udi_is_subfs_mount(IpodDevice *device)
-{
- gint subfs = FALSE;
- gchar **callouts;
- gint i;
-
- if((callouts = libhal_device_get_property_strlist(device->priv->hal_context,
- device->priv->hal_volume_id, "info.callouts.add", NULL))) {
- for(i = 0; callouts[i] != NULL; i++) {
- if(!strcmp(callouts[i], "hald-subfs-mount")) {
- subfs = TRUE;
- g_debug("subfs handles mount for %s; skipping unmount",
- device->priv->device_path);
- break;
- }
- }
-
- libhal_free_string_array(callouts);
- }
-
- return subfs;
-}
-
-#ifdef HAVE_HAL_EJECT
-
-static gboolean
-ipod_device_eject_hal(IpodDevice *device, gchar **error_out)
-{
- DBusMessage *dmesg, *reply;
- DBusError error;
- GPtrArray *options;
- DBusConnection *dbus_connection;
-
- gchar *udi = device->priv->hal_volume_id;
-
- *error_out = NULL;
-
- dbus_error_init(&error);
- dbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
- if(dbus_error_is_set(&error)) {
- *error_out = g_strdup_printf("eject failed for %s: %s", udi, error.message);
- dbus_error_free(&error);
- return FALSE;
- }
-
- if(!(dmesg = dbus_message_new_method_call("org.freedesktop.Hal", udi,
- "org.freedesktop.Hal.Device.Volume", "Eject"))) {
- *error_out = g_strdup_printf("eject failed for %s: could not create dbus message", udi);
- return FALSE;
- }
-
- options = g_ptr_array_new();
-
- if(!dbus_message_append_args(dmesg,
- DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options->pdata, options->len,
- DBUS_TYPE_INVALID)) {
- *error_out = g_strdup_printf("eject failed for %s: could not append args to dbus message", udi);
- dbus_message_unref(dmesg);
- g_ptr_array_free(options, TRUE);
- return FALSE;
- }
-
- g_ptr_array_free(options, TRUE);
-
- if(!(reply = dbus_connection_send_with_reply_and_block(
- dbus_connection, dmesg, -1, &error))) {
- *error_out = g_strdup_printf("eject failed for %s: %s", udi, error.message);
- dbus_message_unref(dmesg);
- dbus_error_free(&error);
- return FALSE;
- }
-
- g_debug("eject queued for %s\n", udi);
-
- dbus_message_unref(dmesg);
- dbus_message_unref(reply);
-
- return TRUE;
-}
-
-#endif
-
guint
ipod_device_eject(IpodDevice *device, GError **error_out)
{
- gint exit_status;
GError *error = NULL;
- gchar *alt_command;
+#ifdef HAVE_HAL_EJECT
gchar *hal_eject_error = NULL;
+#else
+ gint exit_status;
+ gchar *alt_command;
+#endif
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 HAVE_HAL_EJECT
if(ipod_device_eject_hal(device, &hal_eject_error) == TRUE) {
@@ -1552,6 +1553,10 @@
#else
if(ipod_device_udi_is_subfs_mount(device)) {
+ if(ipod_device_has_open_fd(device)) {
+ return EJECT_BUSY;
+ }
+
sync();
exit_status = ipod_device_run_command(device, EJECT_COMMAND, &error);
@@ -1562,9 +1567,7 @@
return exit_status == 0 ? EJECT_OK : EJECT_ERROR;
}
-
-
-
+
exit_status = ipod_device_run_command(device, UNMOUNT_COMMAND, &error);
if(exit_status != 0 || error != NULL) {
g_warning("Could not execute unmount command libipoddevice was "
@@ -1592,52 +1595,7 @@
#endif
}
-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"));
-
- return EJECT_ERROR;
-}
-
-GList *
+static GList *
_ipod_device_list_devices(gboolean create_device)
{
LibHalContext *hal_context;
@@ -1648,8 +1606,9 @@
gboolean validIpod = FALSE;
hal_context = ipod_device_hal_initialize();
- if(hal_context == NULL)
+ if(hal_context == NULL) {
return NULL;
+ }
ipods = libhal_manager_find_device_string_match(hal_context,
"info.product", "iPod", &ipod_count, NULL);
@@ -1662,21 +1621,24 @@
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))
+ 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)
+ if((ipod = ipod_device_new(volumes[j])) == NULL) {
continue;
+ }
g_object_get(ipod, "is-ipod", &validIpod, NULL);
- if(validIpod)
+ if(validIpod) {
finalDevices = g_list_append(finalDevices, ipod);
+ }
}
}
@@ -1750,7 +1712,9 @@
ipod_device_write_device_info_string(device->priv->host_name, fd);
fseek(fd, 0X5FF, SEEK_SET);
- fwrite(&bs, 1, 1, fd);
+ if(fwrite(&bs, 1, 1, fd) <= 0) {
+ g_warning("Could not write to DeviceInfo file");
+ }
fclose(fd);
@@ -1765,11 +1729,13 @@
{
static const gchar *generation_names [] = {
"Unknown",
- "First",
- "Second",
- "Third",
- "Fourth"
+ "First (1)",
+ "Second (2)",
+ "Third (3)",
+ "Fourth (4)",
+ "Fifth (5)"
};
+
static const gchar *artwork_names [] = {
"Small Cover: ",
"Large Cover: ",
@@ -1850,7 +1816,7 @@
g_print("Supported Artwork Formats\n");
format = artwork_formats;
while(format->type != -1) {
- printf(" %s %dx%d\n", artwork_names[format->type],
+ printf(" %s %dx%d\n", artwork_names[format->type],
format->width, format->height);
format++;
}
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/libipoddevice-0.4.1/src/ipod-device.h new/libipoddevice-0.4.5/src/ipod-device.h
--- old/libipoddevice-0.4.1/src/ipod-device.h 2006-02-13 08:32:01.000000000 +0100
+++ new/libipoddevice-0.4.5/src/ipod-device.h 2006-04-11 04:35:01.000000000 +0200
@@ -140,7 +140,6 @@
IpodDevice *ipod_device_new(const gchar *mount_point);
gboolean ipod_device_rescan_disk(IpodDevice *device);
guint ipod_device_eject(IpodDevice *device, GError **error);
-guint ipod_device_reboot(IpodDevice *device, GError **error_out);
void ipod_device_debug(IpodDevice *device);
gboolean ipod_device_save(IpodDevice *device, GError **error);
GList *ipod_device_list_devices();
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Remember to have fun...