Merge pull request #558 from gameblabla/cdrom_fixes_libretro_popo
[pcsx_rearmed.git] / libpcsxcore / cdriso.c
index c36c196..549b62f 100644 (file)
@@ -19,8 +19,6 @@
  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
  ***************************************************************************/
 
-#include <compat/fopen_utf8.h>
-
 #include "psxcommon.h"
 #include "plugins.h"
 #include "cdrom.h"
 #include <unistd.h>
 #endif
 
+#ifdef USE_LIBRETRO_VFS
+#include <streams/file_stream_transforms.h>
+#undef fseeko
+#undef ftello
+#define ftello rftell
+#define fseeko rfseek
+#endif
+
 #define OFF_T_MSB ((off_t)1 << (sizeof(off_t) * 8 - 1))
 
 unsigned int cdrIsoMultidiskCount;
@@ -336,16 +342,16 @@ static int parsetoc(const char *isofile) {
                return -1;
        }
 
-       if ((fi = fopen_utf8(tocname, "r")) == NULL) {
+       if ((fi = fopen(tocname, "r")) == NULL) {
                // try changing extension to .cue (to satisfy some stupid tutorials)
                strcpy(tocname + strlen(tocname) - 4, ".cue");
-               if ((fi = fopen_utf8(tocname, "r")) == NULL) {
+               if ((fi = fopen(tocname, "r")) == NULL) {
                        // if filename is image.toc.bin, try removing .bin (for Brasero)
                        strcpy(tocname, isofile);
                        t = strlen(tocname);
                        if (t >= 8 && strcmp(tocname + t - 8, ".toc.bin") == 0) {
                                tocname[t - 4] = '\0';
-                               if ((fi = fopen_utf8(tocname, "r")) == NULL) {
+                               if ((fi = fopen(tocname, "r")) == NULL) {
                                        return -1;
                                }
                        }
@@ -354,11 +360,12 @@ static int parsetoc(const char *isofile) {
                        }
                }
                // check if it's really a TOC named as a .cue
-               fgets(linebuf, sizeof(linebuf), fi);
-               token = strtok(linebuf, " ");
-               if (token && strncmp(token, "CD", 2) != 0 && strcmp(token, "CATALOG") != 0) {
-                       fclose(fi);
-                       return -1;
+               if (fgets(linebuf, sizeof(linebuf), fi) != NULL) {
+                       token = strtok(linebuf, " ");
+                       if (token && strncmp(token, "CD", 2) != 0 && strcmp(token, "CATALOG") != 0) {
+                               fclose(fi);
+                               return -1;
+                       }
                }
                fseek(fi, 0, SEEK_SET);
        }
@@ -488,7 +495,7 @@ static int parsecue(const char *isofile) {
                return -1;
        }
 
-       if ((fi = fopen_utf8(cuename, "r")) == NULL) {
+       if ((fi = fopen(cuename, "r")) == NULL) {
                return -1;
        }
 
@@ -592,7 +599,7 @@ static int parsecue(const char *isofile) {
                        else
                                tmp = tmpb;
                        strncpy(incue_fname, tmp, incue_max_len);
-                       ti[numtracks + 1].handle = fopen_utf8(filepath, "rb");
+                       ti[numtracks + 1].handle = fopen(filepath, "rb");
 
                        // update global offset if this is not first file in this .cue
                        if (numtracks + 1 > 1) {
@@ -613,7 +620,7 @@ static int parsecue(const char *isofile) {
                                strncasecmp(isofile + strlen(isofile) - 4, ".cd", 3) == 0)) {
                                // user selected .cue/.cdX as image file, use it's data track instead
                                fclose(cdHandle);
-                               cdHandle = fopen_utf8(filepath, "rb");
+                               cdHandle = fopen(filepath, "rb");
                        }
                }
        }
@@ -647,7 +654,7 @@ static int parseccd(const char *isofile) {
                return -1;
        }
 
-       if ((fi = fopen_utf8(ccdname, "r")) == NULL) {
+       if ((fi = fopen(ccdname, "r")) == NULL) {
                return -1;
        }
 
@@ -706,14 +713,15 @@ static int parsemds(const char *isofile) {
                return -1;
        }
 
-       if ((fi = fopen_utf8(mdsname, "rb")) == NULL) {
+       if ((fi = fopen(mdsname, "rb")) == NULL) {
                return -1;
        }
 
        memset(&ti, 0, sizeof(ti));
 
        // check if it's a valid mds file
-       fread(&i, 1, sizeof(unsigned int), fi);
+       if (fread(&i, 1, sizeof(i), fi) != sizeof(i))
+               goto fail_io;
        i = SWAP32(i);
        if (i != 0x4944454D) {
                // not an valid mds file
@@ -723,19 +731,22 @@ static int parsemds(const char *isofile) {
 
        // get offset to session block
        fseek(fi, 0x50, SEEK_SET);
-       fread(&offset, 1, sizeof(unsigned int), fi);
+       if (fread(&offset, 1, sizeof(offset), fi) != sizeof(offset))
+               goto fail_io;
        offset = SWAP32(offset);
 
        // get total number of tracks
        offset += 14;
        fseek(fi, offset, SEEK_SET);
-       fread(&s, 1, sizeof(unsigned short), fi);
+       if (fread(&s, 1, sizeof(s), fi) != sizeof(s))
+               goto fail_io;
        s = SWAP16(s);
        numtracks = s;
 
        // get offset to track blocks
        fseek(fi, 4, SEEK_CUR);
-       fread(&offset, 1, sizeof(unsigned int), fi);
+       if (fread(&offset, 1, sizeof(offset), fi) != sizeof(offset))
+               goto fail_io;
        offset = SWAP32(offset);
 
        // skip lead-in data
@@ -764,32 +775,41 @@ static int parsemds(const char *isofile) {
                ti[i].start[1] = fgetc(fi);
                ti[i].start[2] = fgetc(fi);
 
-               fread(&extra_offset, 1, sizeof(unsigned int), fi);
+               if (fread(&extra_offset, 1, sizeof(extra_offset), fi) != sizeof(extra_offset))
+                       goto fail_io;
                extra_offset = SWAP32(extra_offset);
 
                // get track start offset (in .mdf)
                fseek(fi, offset + 0x28, SEEK_SET);
-               fread(&l, 1, sizeof(unsigned int), fi);
+               if (fread(&l, 1, sizeof(l), fi) != sizeof(l))
+                       goto fail_io;
                l = SWAP32(l);
                ti[i].start_offset = l;
 
                // get pregap
                fseek(fi, extra_offset, SEEK_SET);
-               fread(&l, 1, sizeof(unsigned int), fi);
+               if (fread(&l, 1, sizeof(l), fi) != sizeof(l))
+                       goto fail_io;
                l = SWAP32(l);
                if (l != 0 && i > 1)
                        pregapOffset = msf2sec(ti[i].start);
 
                // get the track length
-               fread(&l, 1, sizeof(unsigned int), fi);
+               if (fread(&l, 1, sizeof(l), fi) != sizeof(l))
+                       goto fail_io;
                l = SWAP32(l);
                sec2msf(l, ti[i].length);
 
                offset += 0x50;
        }
-
        fclose(fi);
        return 0;
+fail_io:
+#ifndef NDEBUG
+       SysPrintf(_("File IO error in <%s:%s>.\n"), __FILE__, __func__);
+#endif
+       fclose(fi);
+       return -1;
 }
 
 static int handlepbp(const char *isofile) {
@@ -840,7 +860,8 @@ static int handlepbp(const char *isofile) {
        }
 
        psisoimg_offs = pbp_hdr.psar_offs;
-       fread(psar_sig, 1, sizeof(psar_sig), cdHandle);
+       if (fread(psar_sig, 1, sizeof(psar_sig), cdHandle) != sizeof(psar_sig))
+               goto fail_io;
        psar_sig[10] = 0;
        if (strcmp(psar_sig, "PSTITLEIMG") == 0) {
                // multidisk image?
@@ -876,7 +897,8 @@ static int handlepbp(const char *isofile) {
                        goto fail_io;
                }
 
-               fread(psar_sig, 1, sizeof(psar_sig), cdHandle);
+               if (fread(psar_sig, 1, sizeof(psar_sig), cdHandle) != sizeof(psar_sig))
+                       goto fail_io;
                psar_sig[10] = 0;
        }
 
@@ -894,15 +916,18 @@ static int handlepbp(const char *isofile) {
 
        // first 3 entries are special
        fseek(cdHandle, sizeof(toc_entry), SEEK_CUR);
-       fread(&toc_entry, 1, sizeof(toc_entry), cdHandle);
+       if (fread(&toc_entry, 1, sizeof(toc_entry), cdHandle) != sizeof(toc_entry))
+               goto fail_io;
        numtracks = btoi(toc_entry.index1[0]);
 
-       fread(&toc_entry, 1, sizeof(toc_entry), cdHandle);
+       if (fread(&toc_entry, 1, sizeof(toc_entry), cdHandle) != sizeof(toc_entry))
+               goto fail_io;
        cd_length = btoi(toc_entry.index1[0]) * 60 * 75 +
                btoi(toc_entry.index1[1]) * 75 + btoi(toc_entry.index1[2]);
 
        for (i = 1; i <= numtracks; i++) {
-               fread(&toc_entry, 1, sizeof(toc_entry), cdHandle);
+               if (fread(&toc_entry, 1, sizeof(toc_entry), cdHandle) != sizeof(toc_entry))
+                       goto fail_io;
 
                ti[i].type = (toc_entry.type == 1) ? CDDA : DATA;
 
@@ -960,7 +985,14 @@ static int handlepbp(const char *isofile) {
 fail_index:
        free(compr_img->index_table);
        compr_img->index_table = NULL;
+       goto done;
+
 fail_io:
+#ifndef NDEBUG
+       SysPrintf(_("File IO error in <%s:%s>.\n"), __FILE__, __func__);
+#endif
+
+done:
        if (compr_img != NULL) {
                free(compr_img);
                compr_img = NULL;
@@ -1146,7 +1178,7 @@ static int opensubfile(const char *isoname) {
                return -1;
        }
 
-       subHandle = fopen_utf8(subname, "rb");
+       subHandle = fopen(subname, "rb");
        if (subHandle == NULL) {
                return -1;
        }
@@ -1383,10 +1415,18 @@ static int cdread_sub_mixed(FILE *f, unsigned int base, void *dest, int sector)
 
        fseek(f, base + sector * (CD_FRAMESIZE_RAW + SUB_FRAMESIZE), SEEK_SET);
        ret = fread(dest, 1, CD_FRAMESIZE_RAW, f);
-       fread(subbuffer, 1, SUB_FRAMESIZE, f);
+       if (fread(subbuffer, 1, SUB_FRAMESIZE, f) != SUB_FRAMESIZE)
+               goto fail_io;
 
        if (subChanRaw) DecodeRawSubData();
+       goto done;
+
+fail_io:
+#ifndef NDEBUG
+       SysPrintf(_("File IO error in <%s:%s>.\n"), __FILE__, __func__);
+#endif
 
+done:
        return ret;
 }
 
@@ -1625,7 +1665,7 @@ static long CALLBACK ISOopen(void) {
                return 0; // it's already open
        }
 
-       cdHandle = fopen_utf8(GetIsoFile(), "rb");
+       cdHandle = fopen(GetIsoFile(), "rb");
        if (cdHandle == NULL) {
                SysPrintf(_("Could't open '%s' for reading: %s\n"),
                        GetIsoFile(), strerror(errno));
@@ -1697,7 +1737,7 @@ static long CALLBACK ISOopen(void) {
                        p = alt_bin_filename + strlen(alt_bin_filename) - 4;
                        for (i = 0; i < sizeof(exts) / sizeof(exts[0]); i++) {
                                strcpy(p, exts[i]);
-                               tmpf = fopen_utf8(alt_bin_filename, "rb");
+                               tmpf = fopen(alt_bin_filename, "rb");
                                if (tmpf != NULL)
                                        break;
                        }
@@ -1714,7 +1754,12 @@ static long CALLBACK ISOopen(void) {
        if (ftello(cdHandle) % 2048 == 0) {
                unsigned int modeTest = 0;
                fseek(cdHandle, 0, SEEK_SET);
-               fread(&modeTest, 4, 1, cdHandle);
+               if (!fread(&modeTest, sizeof(modeTest), 1, cdHandle)) {
+#ifndef NDEBUG
+                       SysPrintf(_("File IO error in <%s:%s>.\n"), __FILE__, __func__);
+#endif
+                       return -1;
+               }
                if (SWAP32(modeTest) != 0xffffff00) {
                        strcat(image_str, "[2048]");
                        isMode1ISO = TRUE;
@@ -1733,7 +1778,7 @@ static long CALLBACK ISOopen(void) {
 
        // make sure we have another handle open for cdda
        if (numtracks > 1 && ti[1].handle == NULL) {
-               ti[1].handle = fopen_utf8(bin_filename, "rb");
+               ti[1].handle = fopen(bin_filename, "rb");
        }
        cdda_cur_sector = 0;
        cdda_file_offset = 0;
@@ -1870,12 +1915,12 @@ static void DecodeRawSubData(void) {
 // read track
 // time: byte 0 - minute; byte 1 - second; byte 2 - frame
 // uses bcd format
-static long CALLBACK ISOreadTrack(unsigned char *time) {
+static boolean CALLBACK ISOreadTrack(unsigned char *time) {
        int sector = MSF2SECT(btoi(time[0]), btoi(time[1]), btoi(time[2]));
        long ret;
 
        if (cdHandle == NULL) {
-               return -1;
+               return 0;
        }
 
        if (pregapOffset) {
@@ -1889,16 +1934,18 @@ static long CALLBACK ISOreadTrack(unsigned char *time) {
 
        ret = cdimg_read_func(cdHandle, 0, cdbuffer, sector);
        if (ret < 0)
-               return -1;
+               return 0;
 
        if (subHandle != NULL) {
                fseek(subHandle, sector * SUB_FRAMESIZE, SEEK_SET);
-               fread(subbuffer, 1, SUB_FRAMESIZE, subHandle);
+               if (fread(subbuffer, 1, SUB_FRAMESIZE, subHandle) != SUB_FRAMESIZE)
+                       /* Faulty subchannel data shouldn't cause a read failure */
+                       return 0;
 
                if (subChanRaw) DecodeRawSubData();
        }
 
-       return 0;
+       return 1;
 }
 
 // plays cdda audio