int wiiso_get_file_id(wiiso_t disc, unsigned int partition_number, const char *full_path, unsigned int *file_id) { struct partition_data *p = &disc->partitions[partition_number]; unsigned int i, fullname_len; char *ref_name; fail_if_closed(); if(partition_number >= disc->num_partitions) { log_error(disc->log_level, "wiiso_get_file_id: bad partition number\n"); return 1; } fullname_len = strlen(full_path); ref_name = strrchr(full_path, '/'); if(!ref_name || *full_path!='/' || fullname_len < 1) { log_error(disc->log_level, "wiiso_get_file_id: not invoked with a full path name\n"); return 1; } ref_name++; for(i=0; i<p->fst_files; i++) { unsigned int file_parent; char *file_name, *curpath; if(get_file_by_id(disc, partition_number, i, &file_name, NULL, NULL, &file_parent)) { log_error(disc->log_level, "wiiso_get_file_id: bad FST tree\n"); return 1; } /* if(!file_offset) continue; */ if(strcmp(file_name, ref_name)) continue; curpath = ref_name; do { unsigned int parent_len; if(!file_parent && curpath == full_path + 1) { *file_id = i; return 0; } get_file_by_id(disc, partition_number, file_parent, &file_name, NULL, NULL, &file_parent); parent_len = strlen(file_name); curpath -= 2 + parent_len; if(curpath < full_path || *curpath != '/') break; curpath++; if(memcmp(curpath, file_name, parent_len)) break; } while(1); } log_debug(disc->log_level, "wiiso_get_file_id: file '%s' not found in partition %u\n", full_path, partition_number); return 1; }
char* get_path_by_id(int id) { const char *path = global_path_get(RESOURCE_PATH); const char *filename = get_file_by_id(id); if(filename != NULL && path != NULL) { int len = strlen(path) + strlen(filename) + 1; char *out = malloc(len); sprintf(out, "%s%s", path, filename); return out; } return NULL; }
int wiiso_extract_file(wiiso_t disc, unsigned int partition_number, unsigned int file_id, const char *output_file) { unsigned int file_size; off_t file_offset; char buf[4096]; FILE *of; fail_if_closed(); if(partition_number >= disc->num_partitions) { log_error(disc->log_level, "wiiso_extract_file: bad partition number\n"); return 1; } if(get_file_by_id(disc, partition_number, file_id, NULL, &file_offset, &file_size, NULL)) { log_error(disc->log_level, "wiiso_extract_file: bad file id\n"); return 1; } if(!file_offset) { log_error(disc->log_level, "wiiso_extract_file: file %u is a directory\n", file_id); return 1; } of = fopen(output_file, "w"); if(!of) { strerror_r(errno, buf, sizeof(buf)); log_error(disc->log_level, "wiiso_extract_file: failed to open file %s for writing: %s\n", output_file, buf); return 1; } while(file_size) { unsigned int todo = MIN(file_size, sizeof(buf)); if(read_data(disc, partition_number, file_offset, todo, buf, NULL)) { log_error(disc->log_level, "wiiso_extract_file: read failed\n"); fclose(of); unlink(output_file); return 1; } if(fwrite(buf, todo, 1, of) != 1) { strerror_r(errno, buf, sizeof(buf)); log_error(disc->log_level, "wiiso_extract_file: write failed: %s\n", buf); fclose(of); unlink(output_file); return 1; } file_size -= todo; file_offset += todo; } fclose(of); return 0; }
int wiiso_get_file_name(wiiso_t disc, unsigned int partition_number, unsigned int file_id, char *buf, unsigned int buf_len) { unsigned int file_len, file_parent, avail_len = buf_len; off_t file_offset; char *file_name; int len; fail_if_closed(); if(partition_number >= disc->num_partitions) { log_error(disc->log_level, "wiiso_get_file_name: bad partition number\n"); return 1; } if(get_file_by_id(disc, partition_number, file_id, &file_name, &file_offset, &file_len, &file_parent)) { log_error(disc->log_level, "wiiso_get_file_name: bad file id\n"); return 1; } do { len = strlen(file_name); if(len + 1 >= avail_len) { log_error(disc->log_level, "wiiso_get_file_name: buffer too small\n"); return 1; } memcpy(buf + avail_len - len, file_name, len); buf[avail_len - len - 1] = '/'; avail_len -= len + 1; file_id = file_parent; if(get_file_by_id(disc, partition_number, file_id, &file_name, NULL, NULL, &file_parent)) { log_error(disc->log_level, "wiiso_get_file_name: bad FST tree\n"); return 1; } } while(file_id); memmove(buf, &buf[avail_len], buf_len - avail_len); buf[buf_len - avail_len] = '\0'; return 0; }
int wiiso_get_file_size(wiiso_t disc, unsigned int partition_number, unsigned int file_id, unsigned int *file_size) { fail_if_closed(); if(partition_number >= disc->num_partitions) { log_error(disc->log_level, "wiiso_get_file_size: bad partition number\n"); return 1; } if(get_file_by_id(disc, partition_number, file_id, NULL, NULL, file_size, NULL)) { log_error(disc->log_level, "wiiso_get_file_size: bad file id\n"); return 1; } return 0; }