1 /* 2 * libInstPatch 3 * Copyright (C) 1999-2014 Element Green <element@elementsofsound.org> 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public License 7 * as published by the Free Software Foundation; version 2.1 8 * of the License only. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 * 02110-1301, USA or on the web at http://www.gnu.org. 19 */ 20 #ifndef __IPATCH_FILE_H__ 21 #define __IPATCH_FILE_H__ 22 23 #include <glib.h> 24 #include <glib-object.h> 25 #include <libinstpatch/compat.h> 26 27 /* forward type declarations */ 28 29 typedef struct _IpatchFile IpatchFile; 30 typedef struct _IpatchFileClass IpatchFileClass; 31 typedef struct _IpatchFileIOFuncs IpatchFileIOFuncs; 32 typedef struct _IpatchFileHandle IpatchFileHandle; 33 34 #include <libinstpatch/IpatchItem.h> 35 36 #define IPATCH_TYPE_FILE (ipatch_file_get_type ()) 37 #define IPATCH_FILE(obj) \ 38 (G_TYPE_CHECK_INSTANCE_CAST ((obj), IPATCH_TYPE_FILE, IpatchFile)) 39 #define IPATCH_FILE_CLASS(klass) \ 40 (G_TYPE_CHECK_CLASS_CAST ((klass), IPATCH_TYPE_FILE, IpatchFileClass)) 41 #define IPATCH_IS_FILE(obj) \ 42 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IPATCH_TYPE_FILE)) 43 #define IPATCH_IS_FILE_CLASS(klass) \ 44 (G_TYPE_CHECK_CLASS_TYPE ((klass), IPATCH_TYPE_FILE)) 45 #define IPATCH_FILE_GET_CLASS(obj) \ 46 (G_TYPE_INSTANCE_GET_CLASS ((obj), IPATCH_TYPE_FILE, IpatchFileClass)) 47 48 /* IO function table for IpatchFile instances */ 49 struct _IpatchFileIOFuncs 50 { 51 gboolean(*open)(IpatchFileHandle *handle, const char *mode, GError **err); 52 void (*close)(IpatchFileHandle *handle); 53 GIOStatus(*read)(IpatchFileHandle *handle, gpointer buf, guint size, 54 guint *bytes_read, GError **err); 55 GIOStatus(*write)(IpatchFileHandle *handle, gconstpointer buf, guint size, 56 GError **err); 57 GIOStatus(*seek)(IpatchFileHandle *handle, int offset, GSeekType type, GError **err); 58 int (*getfd)(IpatchFileHandle *handle); /* optional get file descriptor method */ 59 int (*get_size)(IpatchFile *file, GError **err); /* optional get size method */ 60 }; 61 62 /* File object */ 63 struct _IpatchFile 64 { 65 IpatchItem parent_instance; 66 67 /*< private >*/ 68 69 IpatchFileIOFuncs *iofuncs; /* per instance I/O methods */ 70 char *file_name; /* not always set */ 71 GIOChannel *iochan; /* assigned directly with ipatch_file_set_(fd/iochan) */ 72 GHashTable *ref_hash; /* registered objects referencing this file: objectPtr -> GWeakRef */ 73 guint open_count; /* count of open file handles */ 74 }; 75 76 /* File object class */ 77 struct _IpatchFileClass 78 { 79 IpatchItemClass parent_class; 80 81 /* File identify method */ 82 gboolean(*identify)(IpatchFile *file, IpatchFileHandle *handle, GError **err); 83 int identify_order; /* Identify execution order (see #IpatchFileIdentifyOrder, 0 = default) */ 84 }; 85 86 /** 87 * IpatchFileFlags: 88 * @IPATCH_FILE_FLAG_SWAP: Swap multi-byte numbers? 89 * @IPATCH_FILE_FLAG_BIG_ENDIAN: Big endian file? 90 * @IPATCH_FILE_FLAG_FREE_IOFUNCS: Should ->iofuncs be freed? 91 */ 92 typedef enum 93 { 94 IPATCH_FILE_FLAG_SWAP = 1 << (IPATCH_ITEM_UNUSED_FLAG_SHIFT), 95 IPATCH_FILE_FLAG_BIG_ENDIAN = 1 << (IPATCH_ITEM_UNUSED_FLAG_SHIFT + 1), 96 IPATCH_FILE_FLAG_FREE_IOFUNCS = 1 << (IPATCH_ITEM_UNUSED_FLAG_SHIFT + 2) 97 } IpatchFileFlags; 98 99 /** 100 * IpatchFileIdentifyOrder: 101 * @IPATCH_FILE_IDENTIFY_ORDER_LAST: Execute last (toward the end of the list) 102 * @IPATCH_FILE_IDENTIFY_ORDER_DEFAULT: Default execution order (no preference) 103 * @IPATCH_FILE_IDENTIFY_ORDER_FIRST: Execute first (toward the start of the list) 104 * 105 * Some helpful constants for the identify_order #IpatchFileClass field. Note 106 * that any value can be used and this enum just provides some helpful values. 107 * This value determines in what order file identification methods are called. 108 * Higher values are executed first. 109 */ 110 typedef enum 111 { 112 IPATCH_FILE_IDENTIFY_ORDER_LAST = -10, 113 IPATCH_FILE_IDENTIFY_ORDER_DEFAULT = 0, 114 IPATCH_FILE_IDENTIFY_ORDER_FIRST = 10 115 } IpatchFileIdentifyOrder; 116 117 /** 118 * IPATCH_FILE_UNUSED_FLAG_SHIFT: (skip) 119 */ 120 /* reserve 6 flags (3 for expansion) */ 121 #define IPATCH_FILE_UNUSED_FLAG_SHIFT (IPATCH_ITEM_UNUSED_FLAG_SHIFT + 6) 122 123 /* macro to check if multi-byte numbers in file require swapping */ 124 #define IPATCH_FILE_NEED_SWAP(file) \ 125 (ipatch_item_get_flags(file) & IPATCH_FILE_FLAG_SWAP) 126 /* macro to check if file is big endian */ 127 #define IPATCH_FILE_BIG_ENDIAN(file) \ 128 (ipatch_item_get_flags(file) & IPATCH_FILE_FLAG_BIG_ENDIAN) 129 130 /* runtime byte swapping macros for convenient loading of cross endian 131 files, takes a pointer to the value to swap (like in a buffer) */ 132 #define IPATCH_FILE_SWAP16(file, p16) \ 133 (IPATCH_FILE_NEED_SWAP (file) ? \ 134 GUINT16_SWAP_LE_BE (*(guint16 *)(p16)) : *(guint16 *)(p16)) 135 #define IPATCH_FILE_SWAP32(file, p32) \ 136 (IPATCH_FILE_NEED_SWAP (file) ? \ 137 GUINT32_SWAP_LE_BE (*(guint32 *)(p32)) : *(guint32 *)(p32)) 138 #define IPATCH_FILE_SWAP64(file, p64) \ 139 (IPATCH_FILE_NEED_SWAP (file) ? \ 140 GUINT64_SWAP_LE_BE (*(guint64 *)(p64)) : *(guint64 *)(p64)) 141 142 #define IPATCH_IS_FILE_HANDLE(handle) \ 143 ((handle) && IPATCH_IS_FILE ((handle)->file)) 144 145 /** 146 * IpatchFileHandle: 147 * 148 * #IpatchFile handle for opening a file and reading/writing from/to it. 149 */ 150 struct _IpatchFileHandle 151 { 152 IpatchFile *file; /* Parent file object */ 153 guint position; /* Current file position */ 154 GByteArray *buf; /* For buffered reads/writes */ 155 guint buf_position; /* Current position in buffer */ 156 GIOChannel *iochan; /* glib IO channel (default methods) */ 157 gpointer data; /* iofuncs defined data */ 158 }; 159 160 161 GType ipatch_file_get_type(void); 162 GType ipatch_file_handle_get_type(void); 163 IpatchFile *ipatch_file_new(void); 164 IpatchFile *ipatch_file_pool_new(const char *file_name, gboolean *created); 165 IpatchFile *ipatch_file_pool_lookup(const char *file_name); 166 167 void ipatch_file_ref_from_object(IpatchFile *file, GObject *object); 168 void ipatch_file_unref_from_object(IpatchFile *file, GObject *object); 169 gboolean ipatch_file_test_ref_object(IpatchFile *file, GObject *object); 170 IpatchList *ipatch_file_get_refs(IpatchFile *file); 171 IpatchList *ipatch_file_get_refs_by_type(IpatchFile *file, GType type); 172 173 void ipatch_file_set_name(IpatchFile *file, const char *file_name); 174 char *ipatch_file_get_name(IpatchFile *file); 175 gboolean ipatch_file_rename(IpatchFile *file, const char *new_name, GError **err); 176 gboolean ipatch_file_unlink(IpatchFile *file, GError **err); 177 gboolean ipatch_file_replace(IpatchFile *newfile, IpatchFile *oldfile, GError **err); 178 IpatchFileHandle *ipatch_file_open(IpatchFile *file, const char *file_name, 179 const char *mode, GError **err); 180 void ipatch_file_assign_fd(IpatchFile *file, int fd, gboolean close_on_finalize); 181 void ipatch_file_assign_io_channel(IpatchFile *file, GIOChannel *iochan); 182 GIOChannel *ipatch_file_get_io_channel(IpatchFileHandle *handle); 183 int ipatch_file_get_fd(IpatchFileHandle *handle); 184 void ipatch_file_close(IpatchFileHandle *handle); 185 186 guint ipatch_file_get_position(IpatchFileHandle *handle); 187 void ipatch_file_update_position(IpatchFileHandle *handle, guint offset); 188 189 gboolean ipatch_file_read(IpatchFileHandle *handle, gpointer buf, guint size, 190 GError **err); 191 GIOStatus ipatch_file_read_eof(IpatchFileHandle *handle, gpointer buf, guint size, 192 guint *bytes_read, GError **err); 193 gboolean ipatch_file_write(IpatchFileHandle *handle, gconstpointer buf, 194 guint size, GError **err); 195 #define ipatch_file_skip(handle, offset, err) \ 196 ipatch_file_seek (handle, offset, G_SEEK_CUR, err) 197 gboolean ipatch_file_seek(IpatchFileHandle *handle, int offset, GSeekType type, 198 GError **err); 199 GIOStatus ipatch_file_seek_eof(IpatchFileHandle *handle, int offset, 200 GSeekType type, GError **err); 201 int ipatch_file_get_size(IpatchFile *file, GError **err); 202 GType ipatch_file_identify(IpatchFile *file, GError **err); 203 GType ipatch_file_identify_name(const char *filename, GError **err); 204 GType ipatch_file_identify_by_ext(IpatchFile *file); 205 IpatchFileHandle *ipatch_file_identify_open(const char *file_name, GError **err); 206 IpatchFile *ipatch_file_identify_new(const char *file_name, GError **err); 207 208 void ipatch_file_set_little_endian(IpatchFile *file); 209 void ipatch_file_set_big_endian(IpatchFile *file); 210 211 gboolean ipatch_file_read_u8(IpatchFileHandle *handle, guint8 *val, GError **err); 212 gboolean ipatch_file_read_u16(IpatchFileHandle *handle, guint16 *val, GError **err); 213 gboolean ipatch_file_read_u32(IpatchFileHandle *handle, guint32 *val, GError **err); 214 gboolean ipatch_file_read_u64(IpatchFileHandle *handle, guint64 *val, GError **err); 215 gboolean ipatch_file_read_s8(IpatchFileHandle *handle, gint8 *val, GError **err); 216 gboolean ipatch_file_read_s16(IpatchFileHandle *handle, gint16 *val, GError **err); 217 gboolean ipatch_file_read_s32(IpatchFileHandle *handle, gint32 *val, GError **err); 218 gboolean ipatch_file_read_s64(IpatchFileHandle *handle, gint64 *val, GError **err); 219 220 gboolean ipatch_file_write_u8(IpatchFileHandle *handle, guint8 val, GError **err); 221 gboolean ipatch_file_write_u16(IpatchFileHandle *handle, guint16 val, GError **err); 222 gboolean ipatch_file_write_u32(IpatchFileHandle *handle, guint32 val, GError **err); 223 gboolean ipatch_file_write_u64(IpatchFileHandle *handle, guint64 val, GError **err); 224 gboolean ipatch_file_write_s8(IpatchFileHandle *handle, gint8 val, GError **err); 225 gboolean ipatch_file_write_s16(IpatchFileHandle *handle, gint16 val, GError **err); 226 gboolean ipatch_file_write_s32(IpatchFileHandle *handle, gint32 val, GError **err); 227 gboolean ipatch_file_write_s64(IpatchFileHandle *handle, gint64 val, GError **err); 228 229 gboolean ipatch_file_buf_load(IpatchFileHandle *handle, guint size, GError **err); 230 void ipatch_file_buf_read(IpatchFileHandle *handle, gpointer buf, guint size); 231 void ipatch_file_buf_write(IpatchFileHandle *handle, gconstpointer buf, 232 guint size); 233 #define ipatch_file_buf_zero(filebuf, size) \ 234 ipatch_file_buf_memset(filebuf, 0, size) 235 void ipatch_file_buf_memset(IpatchFileHandle *handle, unsigned char c, guint size); 236 void ipatch_file_buf_set_size(IpatchFileHandle *handle, guint size); 237 gboolean ipatch_file_buf_commit(IpatchFileHandle *handle, GError **err); 238 #define ipatch_file_buf_skip(filebuf, offset) \ 239 ipatch_file_buf_seek (filebuf, offset, G_SEEK_CUR) 240 void ipatch_file_buf_seek(IpatchFileHandle *handle, int offset, GSeekType type); 241 242 guint8 ipatch_file_buf_read_u8(IpatchFileHandle *handle); 243 guint16 ipatch_file_buf_read_u16(IpatchFileHandle *handle); 244 guint32 ipatch_file_buf_read_u32(IpatchFileHandle *handle); 245 guint64 ipatch_file_buf_read_u64(IpatchFileHandle *handle); 246 gint8 ipatch_file_buf_read_s8(IpatchFileHandle *handle); 247 gint16 ipatch_file_buf_read_s16(IpatchFileHandle *handle); 248 gint32 ipatch_file_buf_read_s32(IpatchFileHandle *handle); 249 gint64 ipatch_file_buf_read_s64(IpatchFileHandle *handle); 250 251 void ipatch_file_buf_write_u8(IpatchFileHandle *handle, guint8 val); 252 void ipatch_file_buf_write_u16(IpatchFileHandle *handle, guint16 val); 253 void ipatch_file_buf_write_u32(IpatchFileHandle *handle, guint32 val); 254 void ipatch_file_buf_write_u64(IpatchFileHandle *handle, guint64 val); 255 void ipatch_file_buf_write_s8(IpatchFileHandle *handle, gint8 val); 256 void ipatch_file_buf_write_s16(IpatchFileHandle *handle, gint16 val); 257 void ipatch_file_buf_write_s32(IpatchFileHandle *handle, gint32 val); 258 void ipatch_file_buf_write_s64(IpatchFileHandle *handle, gint64 val); 259 260 void ipatch_file_set_iofuncs_static(IpatchFile *file, 261 IpatchFileIOFuncs *funcs); 262 void ipatch_file_set_iofuncs(IpatchFile *file, 263 const IpatchFileIOFuncs *funcs); 264 void ipatch_file_get_iofuncs(IpatchFile *file, IpatchFileIOFuncs *out_funcs); 265 void ipatch_file_set_iofuncs_null(IpatchFile *file); 266 267 gboolean ipatch_file_default_open_method(IpatchFileHandle *handle, const char *mode, 268 GError **err); 269 void ipatch_file_default_close_method(IpatchFileHandle *handle); 270 GIOStatus ipatch_file_default_read_method(IpatchFileHandle *handle, gpointer buf, 271 guint size, guint *bytes_read, 272 GError **err); 273 GIOStatus ipatch_file_default_write_method(IpatchFileHandle *handle, 274 gconstpointer buf, 275 guint size, GError **err); 276 GIOStatus ipatch_file_default_seek_method(IpatchFileHandle *handle, int offset, 277 GSeekType type, GError **err); 278 int ipatch_file_default_getfd_method(IpatchFileHandle *handle); 279 int ipatch_file_default_get_size_method(IpatchFile *file, GError **err); 280 281 #endif 282