changeset 955:3c2efa18c422

Change semantics of xs_fread_be{32,16}() functions to match xs_fread_str() and xs_fread_byte() and change the PSID/RSID file parsing for SLDB MD5 calculation to use them. Also, fix the parser so that PSID/RSID v3 files are supported correctly.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 20 Nov 2012 21:28:39 +0200
parents a5b118c853f5
children fbcd069663e5
files src/xs_length.c src/xs_support.c src/xs_support.h
diffstat 3 files changed, 60 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/src/xs_length.c	Tue Nov 20 21:27:26 2012 +0200
+++ b/src/xs_length.c	Tue Nov 20 21:28:39 2012 +0200
@@ -370,67 +370,71 @@
 
 static gint xs_get_sid_hash(const gchar *filename, xs_md5hash_t hash)
 {
-    XSFile *inFile;
+    XSFile *inFile = NULL;
     xs_md5state_t inState;
     psidv1_header_t psidH;
     psidv2_header_t psidH2;
-    guint8 *songData;
+    guint8 *songData = NULL;
     guint8 ib8[2], i8;
     gint index, result;
 
     /* Try to open the file */
     if ((inFile = xs_fopen(filename, "rb")) == NULL)
-        return -1;
+        goto error;
 
     /* Read PSID header in */
-    xs_fread(psidH.magicID, sizeof(psidH.magicID), 1, inFile);
-    if (strncmp(psidH.magicID, "PSID", 4) &&
-        strncmp(psidH.magicID, "RSID", 4))
+    if (!xs_fread_str(inFile, psidH.magicID, sizeof(psidH.magicID)) ||
+        !xs_fread_be16(inFile, &psidH.version) ||
+        !xs_fread_be16(inFile, &psidH.dataOffset) ||
+        !xs_fread_be16(inFile, &psidH.loadAddress) ||
+        !xs_fread_be16(inFile, &psidH.initAddress) ||
+        !xs_fread_be16(inFile, &psidH.playAddress) ||
+        !xs_fread_be16(inFile, &psidH.nSongs) ||
+        !xs_fread_be16(inFile, &psidH.startSong) ||
+        !xs_fread_be32(inFile, &psidH.speed))
     {
-        xs_fclose(inFile);
-        xs_error("Not a PSID or RSID file '%s'\n", filename);
-        return -2;
+        xs_error("Could not read PSID/RSID header from '%s'\n", filename);
+        goto error;
     }
 
-    psidH.version = xs_fread_be16(inFile);
-    psidH.dataOffset = xs_fread_be16(inFile);
-    psidH.loadAddress = xs_fread_be16(inFile);
-    psidH.initAddress = xs_fread_be16(inFile);
-    psidH.playAddress = xs_fread_be16(inFile);
-    psidH.nSongs = xs_fread_be16(inFile);
-    psidH.startSong = xs_fread_be16(inFile);
-    psidH.speed = xs_fread_be32(inFile);
-
-    xs_fread(psidH.sidName, sizeof(gchar), sizeof(psidH.sidName), inFile);
-    xs_fread(psidH.sidAuthor, sizeof(gchar), sizeof(psidH.sidAuthor), inFile);
-    xs_fread(psidH.sidCopyright, sizeof(gchar), sizeof(psidH.sidCopyright), inFile);
-    
-    if (xs_feof(inFile) || xs_ferror(inFile))
+    if ((strncmp(psidH.magicID, "PSID", 4) &&
+        strncmp(psidH.magicID, "RSID", 4)) ||
+        psidH.version < 1 || psidH.version > 3)
     {
-        xs_fclose(inFile);
+        xs_error("Not a supported PSID or RSID file '%s'\n", filename);
+        goto error;
+    }
+        
+    if (!xs_fread_str(inFile, psidH.sidName, sizeof(psidH.sidName)) ||
+        !xs_fread_str(inFile, psidH.sidAuthor, sizeof(psidH.sidAuthor)) ||
+        !xs_fread_str(inFile, psidH.sidCopyright, sizeof(psidH.sidCopyright)))
+    {
         xs_error("Error reading SID file header from '%s'\n", filename);
-        return -4;
+        goto error;
     }
     
     /* Check if we need to load PSIDv2NG header ... */
     psidH2.flags = 0;    /* Just silence a stupid gcc warning */
     
-    if (psidH.version == 2)
+    if (psidH.version == 2 || psidH.version == 3)
     {
         /* Yes, we need to */
-        psidH2.flags = xs_fread_be16(inFile);
-        psidH2.startPage = xs_fgetc(inFile);
-        psidH2.pageLength = xs_fgetc(inFile);
-        psidH2.reserved = xs_fread_be16(inFile);
+        if (!xs_fread_be16(inFile, &psidH2.flags) ||
+            !xs_fread_byte(inFile, &psidH2.startPage) ||
+            !xs_fread_byte(inFile, &psidH2.startPage) ||
+            !xs_fread_be16(inFile, &psidH2.reserved))
+        {
+            xs_error("Error reading PSID/RSID v2+ extra header data from '%s'\n",
+                filename);
+            goto error;
+        }
     }
 
     /* Allocate buffer */
-    songData = (guint8 *) g_malloc(XS_SIDBUF_SIZE * sizeof(guint8));
-    if (!songData)
+    if ((songData = (guint8 *) g_malloc(XS_SIDBUF_SIZE)) == NULL)
     {
-        xs_fclose(inFile);
         xs_error("Error allocating temp data buffer for file '%s'\n", filename);
-        return -3;
+        goto error;
     }
 
     /* Read data to buffer */
@@ -479,7 +483,7 @@
         xs_md5_append(&inState, &i8, sizeof(i8));
 
     /* PSIDv2NG specific */
-    if (psidH.version == 2)
+    if (psidH.version == 2 || psidH.version == 3)
     {
         /* SEE SIDPLAY HEADERS FOR INFO */
         i8 = (psidH2.flags >> 2) & 3;
@@ -491,6 +495,12 @@
     xs_md5_finish(&inState, hash);
 
     return 0;
+
+error:
+    if (inFile != NULL)
+        xs_fclose(inFile);
+    g_free(songData);
+    return -1;
 }
 
 
--- a/src/xs_support.c	Tue Nov 20 21:27:26 2012 +0200
+++ b/src/xs_support.c	Tue Nov 20 21:28:39 2012 +0200
@@ -116,19 +116,23 @@
 }
 
 
-guint16 xs_fread_be16(XSFile *f)
+gboolean xs_fread_be16(XSFile *f, guint16 *val)
 {
-    return (((guint16) xs_fgetc(f)) << 8) | ((guint16) xs_fgetc(f));
+    guint16 result;
+    if (xs_fread(&result, sizeof(result), 1, f) != 1)
+        return FALSE;
+    *val = GUINT16_FROM_BE(result);
+    return TRUE;
 }
 
 
-guint32 xs_fread_be32(XSFile *f)
+gboolean xs_fread_be32(XSFile *f, guint32 *val)
 {
-    return
-        (((guint32) xs_fgetc(f)) << 24) |
-        (((guint32) xs_fgetc(f)) << 16) |
-        (((guint32) xs_fgetc(f)) << 8) |
-         ((guint32) xs_fgetc(f));
+    guint32 result;
+    if (xs_fread(&result, sizeof(result), 1, f) != 1)
+        return FALSE;
+    *val = GUINT32_FROM_BE(result);
+    return TRUE;
 }
 
 
--- a/src/xs_support.h	Tue Nov 20 21:27:26 2012 +0200
+++ b/src/xs_support.h	Tue Nov 20 21:28:39 2012 +0200
@@ -126,10 +126,11 @@
 off_t   xs_fsize(XSFile *f);
 #endif
 
-guint16 xs_fread_be16(XSFile *);
-guint32 xs_fread_be32(XSFile *);
 gboolean xs_fread_str(XSFile *, void *, const size_t);
 gboolean xs_fread_byte(XSFile *, guint8 *);
+gboolean xs_fread_be16(XSFile *, guint16 *);
+gboolean xs_fread_be32(XSFile *, guint32 *);
+
 gboolean xs_fload_buffer(const gchar *filename,
     guint8 **pbuf, size_t *bufSize, const size_t maxSize, gboolean failMaxSize);
 gboolean xs_fload_buffer_path(const gchar *ppath, const gchar *pfilename,