1 /* Copyright (C) 2010-2020 The RetroArch team 2 * 3 * --------------------------------------------------------------------------------------- 4 * The following license statement only applies to this file (archive_file.h). 5 * --------------------------------------------------------------------------------------- 6 * 7 * Permission is hereby granted, free of charge, 8 * to any person obtaining a copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation the rights to 10 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 11 * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 16 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23 #ifndef LIBRETRO_SDK_ARCHIVE_FILE_H__ 24 #define LIBRETRO_SDK_ARCHIVE_FILE_H__ 25 26 #include <stdint.h> 27 #include <stddef.h> 28 #include <boolean.h> 29 30 #ifdef _WIN32 31 #include <direct.h> 32 #else 33 #include <unistd.h> 34 #endif 35 36 #include <retro_miscellaneous.h> 37 38 #include <retro_common_api.h> 39 40 #if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H) 41 #include "../../../config.h" /* for HAVE_MMAP */ 42 #endif 43 44 RETRO_BEGIN_DECLS 45 46 enum file_archive_transfer_type 47 { 48 ARCHIVE_TRANSFER_NONE = 0, 49 ARCHIVE_TRANSFER_INIT, 50 ARCHIVE_TRANSFER_ITERATE, 51 ARCHIVE_TRANSFER_DEINIT, 52 ARCHIVE_TRANSFER_DEINIT_ERROR 53 }; 54 55 typedef struct file_archive_handle 56 { 57 uint8_t *data; 58 uint32_t real_checksum; 59 } file_archive_file_handle_t; 60 61 typedef struct file_archive_transfer 62 { 63 int64_t archive_size; 64 void *context; 65 struct RFILE *archive_file; 66 const struct file_archive_file_backend *backend; 67 #ifdef HAVE_MMAP 68 uint8_t *archive_mmap_data; 69 int archive_mmap_fd; 70 #endif 71 unsigned step_total; 72 unsigned step_current; 73 enum file_archive_transfer_type type; 74 } file_archive_transfer_t; 75 76 typedef struct 77 { 78 file_archive_transfer_t archive; /* int64_t alignment */ 79 char *source_file; 80 char *subdir; 81 char *target_dir; 82 char *target_file; 83 char *valid_ext; 84 char *callback_error; 85 struct archive_extract_userdata *userdata; 86 } decompress_state_t; 87 88 struct archive_extract_userdata 89 { 90 /* These are set or read by the archive processing */ 91 char *first_extracted_file_path; 92 const char *extraction_directory; 93 struct string_list *ext; 94 struct string_list *list; 95 file_archive_transfer_t *transfer; 96 /* Not used by the processing, free to use outside or in iterate callback */ 97 decompress_state_t *dec; 98 void* cb_data; 99 size_t archive_path_size; 100 uint32_t crc; 101 char archive_path[PATH_MAX_LENGTH]; 102 char current_file_path[PATH_MAX_LENGTH]; 103 bool found_file; 104 bool list_only; 105 }; 106 107 /* Returns true when parsing should continue. False to stop. */ 108 typedef int (*file_archive_file_cb)(const char *name, const char *valid_exts, 109 const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, 110 uint32_t crc32, struct archive_extract_userdata *userdata); 111 112 struct file_archive_file_backend 113 { 114 int (*archive_parse_file_init)( 115 file_archive_transfer_t *state, 116 const char *file); 117 int (*archive_parse_file_iterate_step)( 118 void *context, 119 const char *valid_exts, 120 struct archive_extract_userdata *userdata, 121 file_archive_file_cb file_cb); 122 void (*archive_parse_file_free)( 123 void *context); 124 125 bool (*stream_decompress_data_to_file_init)( 126 void *context, file_archive_file_handle_t *handle, 127 const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size); 128 int (*stream_decompress_data_to_file_iterate)( 129 void *context, 130 file_archive_file_handle_t *handle); 131 132 uint32_t (*stream_crc_calculate)(uint32_t, const uint8_t *, size_t); 133 int64_t (*compressed_file_read)(const char *path, const char *needle, void **buf, 134 const char *optional_outfile); 135 const char *ident; 136 }; 137 138 int file_archive_parse_file_iterate( 139 file_archive_transfer_t *state, 140 bool *returnerr, 141 const char *file, 142 const char *valid_exts, 143 file_archive_file_cb file_cb, 144 struct archive_extract_userdata *userdata); 145 146 void file_archive_parse_file_iterate_stop(file_archive_transfer_t *state); 147 148 int file_archive_parse_file_progress(file_archive_transfer_t *state); 149 150 /** 151 * file_archive_extract_file: 152 * @archive_path : filename path to ZIP archive. 153 * @archive_path_size : size of ZIP archive. 154 * @valid_exts : valid extensions for a file. 155 * @extraction_directory : the directory to extract the temporary 156 * file to. 157 * 158 * Extract file from archive. If no file inside the archive is 159 * specified, the first file found will be used. 160 * 161 * Returns : true (1) on success, otherwise false (0). 162 **/ 163 bool file_archive_extract_file(char *archive_path, size_t archive_path_size, 164 const char *valid_exts, const char *extraction_dir, 165 char *out_path, size_t len); 166 167 /* Warning: 'list' must zero initialised before 168 * calling this function, otherwise memory leaks/ 169 * undefined behaviour will occur */ 170 bool file_archive_get_file_list_noalloc(struct string_list *list, 171 const char *path, 172 const char *valid_exts); 173 174 /** 175 * file_archive_get_file_list: 176 * @path : filename path of archive 177 * @valid_exts : Valid extensions of archive to be parsed. 178 * If NULL, allow all. 179 * 180 * Returns: string listing of files from archive on success, otherwise NULL. 181 **/ 182 struct string_list* file_archive_get_file_list(const char *path, const char *valid_exts); 183 184 bool file_archive_perform_mode(const char *name, const char *valid_exts, 185 const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size, 186 uint32_t crc32, struct archive_extract_userdata *userdata); 187 188 int file_archive_compressed_read( 189 const char* path, void **buf, 190 const char* optional_filename, int64_t *length); 191 192 const struct file_archive_file_backend* file_archive_get_zlib_file_backend(void); 193 const struct file_archive_file_backend* file_archive_get_7z_file_backend(void); 194 195 const struct file_archive_file_backend* file_archive_get_file_backend(const char *path); 196 197 /** 198 * file_archive_get_file_crc32: 199 * @path : filename path of archive 200 * 201 * Returns: CRC32 of the specified file in the archive, otherwise 0. 202 * If no path within the archive is specified, the first 203 * file found inside is used. 204 **/ 205 uint32_t file_archive_get_file_crc32(const char *path); 206 207 extern const struct file_archive_file_backend zlib_backend; 208 extern const struct file_archive_file_backend sevenzip_backend; 209 210 RETRO_END_DECLS 211 212 #endif 213