diff --git a/tasks/task_database.c b/tasks/task_database.c index 6c831dbbff..b1de616503 100644 --- a/tasks/task_database.c +++ b/tasks/task_database.c @@ -71,8 +71,12 @@ typedef struct db_handle int cue_find_track(const char *cue_path, bool first, size_t *offset, size_t *size, char *track_path, size_t max_len); +bool cue_next_file(intfstream_t *fd, const char *cue_path, char *path, size_t max_len); + int gdi_find_track(const char *gdi_path, bool first, char *track_path, size_t max_len); +bool gdi_next_file(intfstream_t *fd, const char *gdi_path, char *path, size_t max_len); + int detect_system(intfstream_t *fd, const char** system_name); int detect_ps1_game(intfstream_t *fd, char *game_id); @@ -180,6 +184,12 @@ static const char *database_info_get_current_element_name( { if (!handle || !handle->list) return NULL; + /* Skip pruned entries */ + while (handle->list->elems[handle->list_ptr].data == NULL) + { + if (++handle->list_ptr >= handle->list->size) + return NULL; + } return handle->list->elems[handle->list_ptr].data; } @@ -514,6 +524,58 @@ static bool chd_get_crc(const char *name, uint32_t *crc) return rv; } +static void cue_prune(database_info_handle_t *db, const char *name) +{ + char *path = (char *)malloc(PATH_MAX_LENGTH + 1); + intfstream_t *fd = open_file(name); + size_t i; + + if (!fd) + { + free(path); + return; + } + + while (cue_next_file(fd, name, path, PATH_MAX_LENGTH)) + { + for (i = db->list_ptr; i < db->list->size; ++i) + { + if (db->list->elems[i].data && !strcmp(path, db->list->elems[i].data)) + { + RARCH_LOG("Pruning file referenced by cue: %s\n", path); + free(db->list->elems[i].data); + db->list->elems[i].data = NULL; + } + } + } +} + +static void gdi_prune(database_info_handle_t *db, const char *name) +{ + char *path = (char *)malloc(PATH_MAX_LENGTH + 1); + intfstream_t *fd = open_file(name); + size_t i; + + if (!fd) + { + free(path); + return; + } + + while (gdi_next_file(fd, name, path, PATH_MAX_LENGTH)) + { + for (i = db->list_ptr; i < db->list->size; ++i) + { + if (db->list->elems[i].data && !strcmp(path, db->list->elems[i].data)) + { + RARCH_LOG("Pruning file referenced by gdi: %s\n", path); + free(db->list->elems[i].data); + db->list->elems[i].data = NULL; + } + } + } +} + static int task_database_iterate_playlist( database_state_handle_t *db_state, database_info_handle_t *db, const char *name) @@ -529,6 +591,7 @@ static int task_database_iterate_playlist( break; #endif case FILE_TYPE_CUE: + cue_prune(db, name); db_state->serial[0] = '\0'; if (cue_get_serial(name, db_state->serial)) { @@ -541,6 +604,7 @@ static int task_database_iterate_playlist( } break; case FILE_TYPE_GDI: + gdi_prune(db, name); db_state->serial[0] = '\0'; if (gdi_get_serial(name, db_state->serial)) { diff --git a/tasks/task_database_cue.c b/tasks/task_database_cue.c index 027066996b..8a9c7fc8b7 100644 --- a/tasks/task_database_cue.c +++ b/tasks/task_database_cue.c @@ -541,6 +541,34 @@ error: return -errno; } +bool cue_next_file(intfstream_t *fd, const char *cue_path, char *path, size_t max_len) +{ + bool rv = false; + char *tmp_token = malloc(MAX_TOKEN_LEN); + ssize_t volatile file_size = -1; + char *cue_dir = (char*)malloc(PATH_MAX_LENGTH); + cue_dir[0] = '\0'; + + fill_pathname_basedir(cue_dir, cue_path, PATH_MAX_LENGTH); + + tmp_token[0] = '\0'; + + while (get_token(fd, tmp_token, MAX_TOKEN_LEN) > 0) + { + if (string_is_equal(tmp_token, "FILE")) + { + get_token(fd, tmp_token, MAX_TOKEN_LEN); + fill_pathname_join(path, cue_dir, tmp_token, max_len); + rv = true; + break; + } + } + + free(cue_dir); + free(tmp_token); + return rv; +} + int gdi_find_track(const char *gdi_path, bool first, char *track_path, size_t max_len) { int rv; @@ -659,3 +687,44 @@ error: intfstream_close(fd); return -errno; } + +bool gdi_next_file(intfstream_t *fd, const char *gdi_path, char *path, size_t max_len) +{ + bool rv = false; + char *tmp_token = malloc(MAX_TOKEN_LEN); + ssize_t offset = -1; + char *gdi_dir = (char*)malloc(PATH_MAX_LENGTH); + + gdi_dir[0] = '\0'; + tmp_token[0] = '\0'; + + fill_pathname_basedir(gdi_dir, gdi_path, PATH_MAX_LENGTH); + + /* Skip initial track count */ + offset = intfstream_tell(fd); + if (offset == 0) + { + get_token(fd, tmp_token, MAX_TOKEN_LEN); + } + + /* Track number */ + get_token(fd, tmp_token, MAX_TOKEN_LEN); + /* Offset */ + get_token(fd, tmp_token, MAX_TOKEN_LEN); + /* Mode */ + get_token(fd, tmp_token, MAX_TOKEN_LEN); + /* Sector size */ + get_token(fd, tmp_token, MAX_TOKEN_LEN); + /* File name */ + if (get_token(fd, tmp_token, MAX_TOKEN_LEN) > 0) + { + fill_pathname_join(path, gdi_dir, tmp_token, max_len); + rv = true; + /* Disc offset */ + get_token(fd, tmp_token, MAX_TOKEN_LEN); + } + + free(gdi_dir); + free(tmp_token); + return rv; +}