summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJorg Schuler <jcsjcs@users.sourceforge.net>2007-10-01 15:52:05 +0000
committerJorg Schuler <jcsjcs@users.sourceforge.net>2007-10-01 15:52:05 +0000
commitcc47fb7ff1a7f5fea4b1e16282bc1c387ad40d04 (patch)
tree66ffc4a4dda2e73b255e4e6ec90765e2ab900284 /src
parent08584ae5069fdd4609424db99b7a0537112935ff (diff)
downloadlibgpod-cc47fb7ff1a7f5fea4b1e16282bc1c387ad40d04.tar.gz
libgpod-cc47fb7ff1a7f5fea4b1e16282bc1c387ad40d04.tar.xz
libgpod-cc47fb7ff1a7f5fea4b1e16282bc1c387ad40d04.zip
* src/itdb_itunesdb.c: integrate checksum writing into the
creation of the iTunesDB instead of modifying the iTunesDB file in place (Christophe) * src/itdb_device.c: re-use artwork definition for iPod classic also for iPod Nanos 3G. git-svn-id: https://gtkpod.svn.sf.net/svnroot/gtkpod/libgpod/trunk@1712 f01d2545-417e-4e96-918e-98f8d0dbbcb6
Diffstat (limited to 'src')
-rw-r--r--src/itdb_device.c11
-rw-r--r--src/itdb_itunesdb.c163
2 files changed, 51 insertions, 123 deletions
diff --git a/src/itdb_device.c b/src/itdb_device.c
index 9da57ad..0c5fe49 100644
--- a/src/itdb_device.c
+++ b/src/itdb_device.c
@@ -307,14 +307,6 @@ static const Itdb_ArtworkFormat ipod_iphone_1_artwork_info[] = {
{-1, -1, -1, -1, -1}
};
-static const Itdb_ArtworkFormat ipod_nano3_artwork_info[] = {
- {ITDB_THUMB_COVER_SMALL, 56, 55, 1061, THUMB_FORMAT_RGB565_LE, 0x1810}, /*pad data to 0x1810 bytes*/
- {ITDB_THUMB_COVER_LARGE, 320, 320, 1062, THUMB_FORMAT_RGB565_LE},
- {ITDB_THUMB_COVER_MEDIUM, 128, 128, 1055, THUMB_FORMAT_RGB565_LE},
- {-1, -1, -1, -1, -1}
-};
-
-
static const Itdb_ArtworkFormat ipod_classic_1_artwork_info[] = {
/* officially 55x55 -- verify! */
{ITDB_THUMB_COVER_XSMALL, 56, 56, 1061, THUMB_FORMAT_RGB565_LE},
@@ -334,6 +326,9 @@ static const Itdb_ArtworkFormat ipod_classic_1_artwork_info[] = {
{-1, -1, -1, -1, -1}
};
+/* these seem to be identical... */
+#define ipod_nano3_artwork_info ipod_classic_1_artwork_info
+
static void itdb_device_set_timezone_info (Itdb_Device *device);
diff --git a/src/itdb_itunesdb.c b/src/itdb_itunesdb.c
index 0375177..81606d5 100644
--- a/src/itdb_itunesdb.c
+++ b/src/itdb_itunesdb.c
@@ -4861,6 +4861,49 @@ static void prepare_itdb_for_write (FExport *fexp)
}
+static gboolean write_db_checksum (FExport *fexp, GError **error)
+{
+ guint64 fwid;
+ guchar backup18[8];
+ guchar backup32[20];
+ unsigned char *itdb_data;
+ unsigned char *checksum;
+ gsize len;
+
+ fwid = itdb_device_get_firewire_id (fexp->itdb->device);
+ if (fwid == 0) {
+ g_set_error (error, 0, -1, "Couldn't find the iPod firewire ID");
+ return FALSE;
+ }
+
+ if (fexp->wcontents->pos < 0x6c) {
+ g_set_error (error, 0, -1, "iTunesDB file too small to write checksum");
+ return FALSE;
+ }
+ itdb_data = (unsigned char *)fexp->wcontents->contents;
+
+ memcpy (backup18, itdb_data+0x18, sizeof (backup18));
+ memcpy (backup32, itdb_data+0x32, sizeof (backup32));
+
+ /* Those fields must be zero'ed out for the sha1 calculation */
+ memset(itdb_data+0x18, 0, 8);
+ memset(itdb_data+0x32, 0, 20);
+ memset(itdb_data+0x58, 0, 20);
+
+ checksum = itdb_compute_hash (fwid, itdb_data, fexp->wcontents->pos, &len);
+ if (checksum == NULL) {
+ g_set_error (error, 0, -1, "Failed to compute checksum");
+ return FALSE;
+ }
+ memcpy (itdb_data+0x58, checksum, len);
+ g_free (checksum);
+
+ memcpy (itdb_data+0x18, backup18, sizeof (backup18));
+ memcpy (itdb_data+0x32, backup32, sizeof (backup32));
+
+ return TRUE;
+}
+
/**
* itdb_write_file:
* @itdb: the #Itdb_iTunesDB to save
@@ -4918,6 +4961,11 @@ gboolean itdb_write_file (Itdb_iTunesDB *itdb, const gchar *filename,
if (write_mhsd_playlists (fexp, 2))
{
fix_header (cts, mhbd_seek);
+
+ /* Set checksum (ipods require it starting from iPod Classic
+ * and fat Nanos)
+ */
+ write_db_checksum (fexp, &fexp->error);
}
}
}
@@ -4947,113 +4995,6 @@ gboolean itdb_write_file (Itdb_iTunesDB *itdb, const gchar *filename,
return result;
}
-static unsigned char *
-calculate_db_checksum (const char *itdb_path, guint64 fwid, gsize *len)
-{
- int fd;
- struct stat stat_buf;
- int result;
- unsigned char *itdb_data;
- unsigned char *checksum;
-
- fd = open (itdb_path, O_RDONLY);
- if (fd < 0) {
- g_warning ("Couldn't open %s", itdb_path);
- return NULL;
- }
-
- result = fstat (fd, &stat_buf);
- if (result != 0) {
- g_warning ("Couldn't stat %s", itdb_path);
- close (fd);
- return NULL;
- }
-
- if (stat_buf.st_size < 0x80) {
- g_warning ("%s is too small", itdb_path);
- close (fd);
- return NULL;
- }
-
- itdb_data = mmap (NULL, stat_buf.st_size,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE, fd, 0);
- if (itdb_data == MAP_FAILED) {
- g_warning ("Couldn't mmap %s", itdb_path);
- close (fd);
- return NULL;
- }
-
- /* Those fields must be zero'ed out for the sha1 calculation */
- memset(itdb_data+0x18, 0, 8);
- memset(itdb_data+0x32, 0, 20);
- memset(itdb_data+0x58, 0, 20);
-
- checksum = itdb_compute_hash (fwid, itdb_data, stat_buf.st_size, len);
-
- munmap (itdb_data, stat_buf.st_size);
- close (fd);
-
- return checksum;
-}
-
-static gboolean itdb_write_checksum_to_file (const char *path,
- const unsigned char *checksum,
- size_t size)
-{
- FILE *f;
- int result;
- size_t count;
-
- f = fopen (path, "rb+");
- if (f == NULL) {
- return FALSE;
- }
-
- result = fseek (f, 0x58, SEEK_SET);
- if (result != 0) {
- fclose (f);
- return FALSE;
- }
-
- count = fwrite (checksum, size, 1, f);
- fclose (f);
-
- return (count == 1);
-}
-
-static gboolean itdb_write_checksum (Itdb_iTunesDB *db)
-{
- guint64 fwid;
- char *itdb_path;
- unsigned char *checksum;
- gsize len;
- gboolean result;
-
- if (db->device == NULL) {
- return FALSE;
- }
-
- fwid = itdb_device_get_firewire_id (db->device);
- if (fwid == 0) {
- return FALSE;
- }
-
- itdb_path = itdb_get_itunesdb_path (itdb_get_mountpoint (db));
- checksum = calculate_db_checksum (itdb_path, fwid, &len);
-
- if (checksum == NULL) {
- g_free (itdb_path);
- return FALSE;
- }
-
- result = itdb_write_checksum_to_file (itdb_path, checksum, len);
- g_free (itdb_path);
- g_free (checksum);
-
- return result;
-}
-
/**
* itdb_write:
* @itdb: the #Itdb_iTunesDB to write to disk
@@ -5101,14 +5042,6 @@ gboolean itdb_write (Itdb_iTunesDB *itdb, GError **error)
if (result != FALSE)
{
- /* Set checksum (ipods require it starting from iPod Classic
- * and fat Nanos)
- */
- result = itdb_write_checksum (itdb);
- if (!result) {
- g_warning ("Couldn't set checksum");
- }
-
/* Write SysInfo file if it has changed */
if (itdb->device->sysinfo_changed)
{
ass="hl opt">); #endif #ifdef CONFIG_SMP show_ipi_list(p); show_local_irqs(p); #endif seq_printf(p, "Err: %10lu\n", irq_err_count); } return 0; } /* Handle bad interrupts */ static struct irq_desc bad_irq_desc = { .handle_irq = handle_bad_irq, .lock = SPIN_LOCK_UNLOCKED }; /* * do_IRQ handles all hardware IRQ's. Decoded IRQs should not * come via this function. Instead, they should provide their * own 'handler' */ asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); irq_enter(); /* * Some hardware gives randomly wrong interrupts. Rather * than crashing, do something sensible. */ if (irq >= NR_IRQS) handle_bad_irq(irq, &bad_irq_desc); else generic_handle_irq(irq); /* AT91 specific workaround */ irq_finish(irq); irq_exit(); set_irq_regs(old_regs); } void set_irq_flags(unsigned int irq, unsigned int iflags) { struct irq_desc *desc; unsigned long flags; if (irq >= NR_IRQS) { printk(KERN_ERR "Trying to set irq flags for IRQ%d\n", irq); return; } desc = irq_desc + irq; spin_lock_irqsave(&desc->lock, flags); desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; if (iflags & IRQF_VALID) desc->status &= ~IRQ_NOREQUEST; if (iflags & IRQF_PROBE) desc->status &= ~IRQ_NOPROBE; if (!(iflags & IRQF_NOAUTOEN)) desc->status &= ~IRQ_NOAUTOEN; spin_unlock_irqrestore(&desc->lock, flags); } void __init init_IRQ(void) { int irq; for (irq = 0; irq < NR_IRQS; irq++) irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE; #ifdef CONFIG_SMP bad_irq_desc.affinity = CPU_MASK_ALL; bad_irq_desc.cpu = smp_processor_id(); #endif init_arch_irq(); } #ifdef CONFIG_HOTPLUG_CPU static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu) { pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->cpu, cpu); spin_lock_irq(&desc->lock); desc->chip->set_affinity(irq, cpumask_of(cpu)); spin_unlock_irq(&desc->lock); } /* * The CPU has been marked offline. Migrate IRQs off this CPU. If * the affinity settings do not allow other CPUs, force them onto any * available CPU. */ void migrate_irqs(void) { unsigned int i, cpu = smp_processor_id(); for (i = 0; i < NR_IRQS; i++) { struct irq_desc *desc = irq_desc + i; if (desc->cpu == cpu) { unsigned int newcpu = any_online_cpu(desc->affinity); if (newcpu == NR_CPUS) { if (printk_ratelimit()) printk(KERN_INFO "IRQ%u no longer affine to CPU%u\n", i, cpu); cpus_setall(desc->affinity); newcpu = any_online_cpu(desc->affinity); } route_irq(desc, i, newcpu); } } } #endif /* CONFIG_HOTPLUG_CPU */