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 /*
21  * IpatchFile.c - File buffer and integer read/write funcs
22  */
23 #include <stdio.h>
24 #include <string.h>
25 #include <glib.h>
26 #include <glib-object.h>
27 #include "IpatchFile.h"
28 
29 /* Defined in IpatchFile.c */
30 extern gboolean
31 _ipatch_file_read_no_pos_update(IpatchFileHandle *handle, gpointer buf,
32                                 guint size, GError **err);
33 extern gboolean
34 _ipatch_file_write_no_pos_update(IpatchFileHandle *handle, gconstpointer buf,
35                                  guint size, GError **err);
36 
37 /**
38  * ipatch_file_read_u8:
39  * @handle: File handle
40  * @val: Location to store value
41  * @err: Location to store error info or %NULL
42  *
43  * Read an unsigned 8 bit integer from a file.
44  *
45  * Returns: %TRUE on success, %FALSE otherwise (in which case @err may be set).
46  */
47 gboolean
ipatch_file_read_u8(IpatchFileHandle * handle,guint8 * val,GError ** err)48 ipatch_file_read_u8(IpatchFileHandle *handle, guint8 *val, GError **err)
49 {
50     return (ipatch_file_read(handle, val, sizeof(guint8), err));
51 }
52 
53 /**
54  * ipatch_file_read_u16:
55  * @handle: File handle
56  * @val: Location to store value
57  * @err: Location to store error info or %NULL
58  *
59  * Read an unsigned 16 bit integer from a file and performs endian
60  * byte swapping if necessary.
61  *
62  * Returns: %TRUE on success, %FALSE otherwise (in which case @err may be set).
63  */
64 gboolean
ipatch_file_read_u16(IpatchFileHandle * handle,guint16 * val,GError ** err)65 ipatch_file_read_u16(IpatchFileHandle *handle, guint16 *val, GError **err)
66 {
67     if(!ipatch_file_read(handle, val, sizeof(guint16), err))
68     {
69         return (FALSE);
70     }
71 
72     *val = IPATCH_FILE_SWAP16(handle->file, val);
73     return (TRUE);
74 }
75 
76 /**
77  * ipatch_file_read_u32:
78  * @handle: File handle
79  * @val: Location to store value
80  * @err: Location to store error info or %NULL
81  *
82  * Read an unsigned 32 bit integer from a file and performs endian
83  * byte swapping if necessary.
84  *
85  * Returns: %TRUE on success, %FALSE otherwise (in which case @err may be set).
86  */
87 gboolean
ipatch_file_read_u32(IpatchFileHandle * handle,guint32 * val,GError ** err)88 ipatch_file_read_u32(IpatchFileHandle *handle, guint32 *val, GError **err)
89 {
90     if(!ipatch_file_read(handle, val, sizeof(guint32), err))
91     {
92         return (FALSE);
93     }
94 
95     *val = IPATCH_FILE_SWAP32(handle->file, val);
96     return (TRUE);
97 }
98 
99 /**
100  * ipatch_file_read_u64:
101  * @handle: File handle
102  * @val: Location to store value
103  * @err: Location to store error info or %NULL
104  *
105  * Read an unsigned 64 bit integer from a file and performs endian
106  * byte swapping if necessary.
107  *
108  * Returns: %TRUE on success, %FALSE otherwise (in which case @err may be set).
109  */
110 gboolean
ipatch_file_read_u64(IpatchFileHandle * handle,guint64 * val,GError ** err)111 ipatch_file_read_u64(IpatchFileHandle *handle, guint64 *val, GError **err)
112 {
113     if(!ipatch_file_read(handle, val, sizeof(guint64), err))
114     {
115         return (FALSE);
116     }
117 
118     *val = IPATCH_FILE_SWAP64(handle->file, val);
119     return (TRUE);
120 }
121 
122 /**
123  * ipatch_file_read_s8:
124  * @handle: File handle
125  * @val: Location to store value
126  * @err: Location to store error info or %NULL
127  *
128  * Read a signed 8 bit integer from a file.
129  *
130  * Returns: %TRUE on success, %FALSE otherwise (in which case @err may be set).
131  */
132 gboolean
ipatch_file_read_s8(IpatchFileHandle * handle,gint8 * val,GError ** err)133 ipatch_file_read_s8(IpatchFileHandle *handle, gint8 *val, GError **err)
134 {
135     return (ipatch_file_read(handle, val, sizeof(gint8), err));
136 }
137 
138 /**
139  * ipatch_file_read_s16:
140  * @handle: File handle
141  * @val: Location to store value
142  * @err: Location to store error info or %NULL
143  *
144  * Read a signed 16 bit integer from a file and performs endian
145  * byte swapping if necessary.
146  *
147  * Returns: %TRUE on success, %FALSE otherwise (in which case @err may be set).
148  */
149 gboolean
ipatch_file_read_s16(IpatchFileHandle * handle,gint16 * val,GError ** err)150 ipatch_file_read_s16(IpatchFileHandle *handle, gint16 *val, GError **err)
151 {
152     if(!ipatch_file_read(handle, val, sizeof(gint16), err))
153     {
154         return (FALSE);
155     }
156 
157     *val = IPATCH_FILE_SWAP16(handle->file, val);
158     return (TRUE);
159 }
160 
161 /**
162  * ipatch_file_read_s32:
163  * @handle: File handle
164  * @val: Location to store value
165  * @err: Location to store error info or %NULL
166  *
167  * Read a signed 32 bit integer from a file and performs endian
168  * byte swapping if necessary.
169  *
170  * Returns: %TRUE on success, %FALSE otherwise (in which case @err may be set).
171  */
172 gboolean
ipatch_file_read_s32(IpatchFileHandle * handle,gint32 * val,GError ** err)173 ipatch_file_read_s32(IpatchFileHandle *handle, gint32 *val, GError **err)
174 {
175     if(!ipatch_file_read(handle, val, sizeof(gint32), err))
176     {
177         return (FALSE);
178     }
179 
180     *val = IPATCH_FILE_SWAP32(handle->file, val);
181     return (TRUE);
182 }
183 
184 /**
185  * ipatch_file_read_s64:
186  * @handle: File handle
187  * @val: Location to store value
188  * @err: Location to store error info or %NULL
189  *
190  * Read a signed 64 bit integer from a file and performs endian
191  * byte swapping if necessary.
192  *
193  * Returns: %TRUE on success, %FALSE otherwise (in which case @err may be set).
194  */
195 gboolean
ipatch_file_read_s64(IpatchFileHandle * handle,gint64 * val,GError ** err)196 ipatch_file_read_s64(IpatchFileHandle *handle, gint64 *val, GError **err)
197 {
198     if(!ipatch_file_read(handle, val, sizeof(gint64), err))
199     {
200         return (FALSE);
201     }
202 
203     *val = IPATCH_FILE_SWAP64(handle->file, val);
204     return (TRUE);
205 }
206 
207 /**
208  * ipatch_file_write_u8:
209  * @handle: File handle
210  * @val: Value to store
211  * @err: Location to store error info or %NULL
212  *
213  * Write an unsigned 8 bit integer to a file.
214  *
215  * Returns: %TRUE on success, %FALSE otherwise (in which case @err may be set).
216  */
217 gboolean
ipatch_file_write_u8(IpatchFileHandle * handle,guint8 val,GError ** err)218 ipatch_file_write_u8(IpatchFileHandle *handle, guint8 val, GError **err)
219 {
220     return (ipatch_file_write(handle, &val, sizeof(guint8), err));
221 }
222 
223 /**
224  * ipatch_file_write_u16:
225  * @handle: File handle
226  * @val: Value to store
227  * @err: Location to store error info or %NULL
228  *
229  * Write an unsigned 16 bit integer to a file and performs endian
230  * byte swapping if necessary.
231  *
232  * Returns: %TRUE on success, %FALSE otherwise (in which case @err may be set).
233  */
234 gboolean
ipatch_file_write_u16(IpatchFileHandle * handle,guint16 val,GError ** err)235 ipatch_file_write_u16(IpatchFileHandle *handle, guint16 val, GError **err)
236 {
237     g_return_val_if_fail(handle != NULL, FALSE);
238     g_return_val_if_fail(IPATCH_IS_FILE(handle->file), FALSE);
239 
240     val = IPATCH_FILE_SWAP16(handle->file, &val);
241 
242     if(!ipatch_file_write(handle, &val, sizeof(guint16), err))
243     {
244         return (FALSE);
245     }
246 
247     return (TRUE);
248 }
249 
250 /**
251  * ipatch_file_write_u32:
252  * @handle: File handle
253  * @val: Value to store
254  * @err: Location to store error info or %NULL
255  *
256  * Write an unsigned 32 bit integer to a file and performs endian
257  * byte swapping if necessary.
258  *
259  * Returns: %TRUE on success, %FALSE otherwise (in which case @err may be set).
260  */
261 gboolean
ipatch_file_write_u32(IpatchFileHandle * handle,guint32 val,GError ** err)262 ipatch_file_write_u32(IpatchFileHandle *handle, guint32 val, GError **err)
263 {
264     g_return_val_if_fail(handle != NULL, FALSE);
265     g_return_val_if_fail(IPATCH_IS_FILE(handle->file), FALSE);
266 
267     val = IPATCH_FILE_SWAP32(handle->file, &val);
268 
269     if(!ipatch_file_write(handle, &val, sizeof(guint32), err))
270     {
271         return (FALSE);
272     }
273 
274     return (TRUE);
275 }
276 
277 /**
278  * ipatch_file_write_u64:
279  * @handle: File handle
280  * @val: Value to store
281  * @err: Location to store error info or %NULL
282  *
283  * Write an unsigned 64 bit integer to a file and performs endian
284  * byte swapping if necessary.
285  *
286  * Returns: %TRUE on success, %FALSE otherwise (in which case @err may be set).
287  */
288 gboolean
ipatch_file_write_u64(IpatchFileHandle * handle,guint64 val,GError ** err)289 ipatch_file_write_u64(IpatchFileHandle *handle, guint64 val, GError **err)
290 {
291     g_return_val_if_fail(handle != NULL, FALSE);
292     g_return_val_if_fail(IPATCH_IS_FILE(handle->file), FALSE);
293 
294     val = IPATCH_FILE_SWAP64(handle->file, &val);
295 
296     if(!ipatch_file_write(handle, &val, sizeof(guint64), err))
297     {
298         return (FALSE);
299     }
300 
301     return (TRUE);
302 }
303 
304 /**
305  * ipatch_file_write_s8:
306  * @handle: File handle
307  * @val: Value to store
308  * @err: Location to store error info or %NULL
309  *
310  * Write a signed 8 bit integer to a file.
311  *
312  * Returns: %TRUE on success, %FALSE otherwise (in which case @err may be set).
313  */
314 gboolean
ipatch_file_write_s8(IpatchFileHandle * handle,gint8 val,GError ** err)315 ipatch_file_write_s8(IpatchFileHandle *handle, gint8 val, GError **err)
316 {
317     return (ipatch_file_write(handle, &val, sizeof(gint8), err));
318 }
319 
320 /**
321  * ipatch_file_write_s16:
322  * @handle: File handle
323  * @val: Value to store
324  * @err: Location to store error info or %NULL
325  *
326  * Write a signed 16 bit integer to a file and performs endian
327  * byte swapping if necessary.
328  *
329  * Returns: %TRUE on success, %FALSE otherwise (in which case @err may be set).
330  */
331 gboolean
ipatch_file_write_s16(IpatchFileHandle * handle,gint16 val,GError ** err)332 ipatch_file_write_s16(IpatchFileHandle *handle, gint16 val, GError **err)
333 {
334     g_return_val_if_fail(handle != NULL, FALSE);
335     g_return_val_if_fail(IPATCH_IS_FILE(handle->file), FALSE);
336 
337     val = IPATCH_FILE_SWAP16(handle->file, &val);
338 
339     if(!ipatch_file_write(handle, &val, sizeof(gint16), err))
340     {
341         return (FALSE);
342     }
343 
344     return (TRUE);
345 }
346 
347 /**
348  * ipatch_file_write_s32:
349  * @handle: File handle
350  * @val: Value to store
351  * @err: Location to store error info or %NULL
352  *
353  * Write a signed 32 bit integer to a file and performs endian
354  * byte swapping if necessary.
355  *
356  * Returns: %TRUE on success, %FALSE otherwise (in which case @err may be set).
357  */
358 gboolean
ipatch_file_write_s32(IpatchFileHandle * handle,gint32 val,GError ** err)359 ipatch_file_write_s32(IpatchFileHandle *handle, gint32 val, GError **err)
360 {
361     g_return_val_if_fail(handle != NULL, FALSE);
362     g_return_val_if_fail(IPATCH_IS_FILE(handle->file), FALSE);
363 
364     val = IPATCH_FILE_SWAP32(handle->file, &val);
365 
366     if(!ipatch_file_write(handle, &val, sizeof(gint32), err))
367     {
368         return (FALSE);
369     }
370 
371     return (TRUE);
372 }
373 
374 /**
375  * ipatch_file_write_s64:
376  * @handle: File handle
377  * @val: Value to store
378  * @err: Location to store error info or %NULL
379  *
380  * Write a signed 64 bit integer to a file and performs endian
381  * byte swapping if necessary.
382  *
383  * Returns: %TRUE on success, %FALSE otherwise (in which case @err may be set).
384  */
385 gboolean
ipatch_file_write_s64(IpatchFileHandle * handle,gint64 val,GError ** err)386 ipatch_file_write_s64(IpatchFileHandle *handle, gint64 val, GError **err)
387 {
388     g_return_val_if_fail(handle != NULL, FALSE);
389     g_return_val_if_fail(IPATCH_IS_FILE(handle->file), FALSE);
390 
391     val = IPATCH_FILE_SWAP64(handle->file, &val);
392 
393     if(!ipatch_file_write(handle, &val, sizeof(gint64), err))
394     {
395         return (FALSE);
396     }
397 
398     return (TRUE);
399 }
400 
401 /**
402  * ipatch_file_buf_load:
403  * @handle: File handle
404  * @size: Size of data to load
405  * @err: Location to store error info or %NULL
406  *
407  * Load data from a file into a buffer for error checking convenience.
408  * I/O errors need only be checked on this function and not on the subsequent
409  * buffered read function calls.  It is an error if an end of file is
410  * encountered before all the requested data is read.
411  *
412  * Returns: %TRUE on success, %FALSE on error.
413  */
414 gboolean
ipatch_file_buf_load(IpatchFileHandle * handle,guint size,GError ** err)415 ipatch_file_buf_load(IpatchFileHandle *handle, guint size, GError **err)
416 {
417     g_return_val_if_fail(handle != NULL, FALSE);
418     g_return_val_if_fail(size != 0, FALSE);
419 
420     /* If there is still buffered data, flush it (add to file position) */
421     if(handle->buf_position < handle->buf->len)
422     {
423         handle->position += handle->buf->len - handle->buf_position;
424     }
425 
426     g_byte_array_set_size(handle->buf, size);
427     handle->buf_position = 0;
428 
429     if(!_ipatch_file_read_no_pos_update(handle, handle->buf->data, size, err))
430     {
431         return (FALSE);
432     }
433 
434     return (TRUE);
435 }
436 
437 /**
438  * ipatch_file_buf_read:
439  * @handle: File handle with loaded data to read from
440  * @buf: Buffer to copy data to
441  * @size: Amount of data to copy in bytes
442  *
443  * Read data from a file handle's buffer and advance the buffer's current
444  * position.  A call to ipatch_file_buf_load() must have been previously
445  * executed and there must be enough remaining data in the buffer for the read.
446  */
447 void
ipatch_file_buf_read(IpatchFileHandle * handle,gpointer buf,guint size)448 ipatch_file_buf_read(IpatchFileHandle *handle, gpointer buf, guint size)
449 {
450     g_return_if_fail(handle != NULL);
451     g_return_if_fail(handle->buf_position + size <= handle->buf->len);
452 
453     memcpy(buf, handle->buf->data + handle->buf_position, size);
454     handle->buf_position += size;
455     handle->position += size;
456 }
457 
458 /**
459  * ipatch_file_buf_write:
460  * @handle: File handle to append buffered data to
461  * @buf: Buffer to copy data from
462  * @size: Amount of data to copy in bytes
463  *
464  * Write data to a file handle's buffer and advance the buffer's current
465  * position. Buffer is expanded if necessary (since version 1.1.0).
466  * Data will not actually be written to file till ipatch_file_buf_commit() is
467  * called.
468  */
469 void
ipatch_file_buf_write(IpatchFileHandle * handle,gconstpointer buf,guint size)470 ipatch_file_buf_write(IpatchFileHandle *handle, gconstpointer buf, guint size)
471 {
472     g_return_if_fail(handle != NULL);
473 
474     if(size == 0)
475     {
476         return;
477     }
478 
479     if(handle->buf_position + size > handle->buf->len)
480     {
481         g_byte_array_set_size(handle->buf, handle->buf_position + size);
482     }
483 
484     memcpy(handle->buf->data + handle->buf_position, buf, size);
485     handle->buf_position += size;
486     handle->position += size;
487 }
488 
489 /**
490  * ipatch_file_buf_memset:
491  * @handle: File handle to set buffered data of
492  * @c: Character to write
493  * @size: Size of data to set
494  *
495  * Sets the given @size in bytes to the character @c and advances the
496  * current position.  Buffer is expanded if necessary.
497  */
498 void
ipatch_file_buf_memset(IpatchFileHandle * handle,unsigned char c,guint size)499 ipatch_file_buf_memset(IpatchFileHandle *handle, unsigned char c, guint size)
500 {
501     g_return_if_fail(handle != NULL);
502 
503     if(size == 0)
504     {
505         return;
506     }
507 
508     if(handle->buf_position + size > handle->buf->len)
509     {
510         g_byte_array_set_size(handle->buf, handle->buf_position + size);
511     }
512 
513     memset(handle->buf->data + handle->buf_position, c, size);
514     handle->buf_position += size;
515     handle->position += size;
516 }
517 
518 /**
519  * ipatch_file_buf_set_size:
520  * @handle: File handle to adjust buffer of
521  * @size: New size of buffer
522  *
523  * Sets the size of the buffer of @handle to @size bytes. The buffer is
524  * expanded without initializing the newly allocated part or truncated
525  * as necessary discarding any content over the new size. The current position
526  * is updated to point to the end of the buffer if it would point outside the
527  * new size of the buffer after truncating it.
528  *
529  * Since: 1.1.0
530  */
531 void
ipatch_file_buf_set_size(IpatchFileHandle * handle,guint size)532 ipatch_file_buf_set_size(IpatchFileHandle *handle, guint size)
533 {
534     g_return_if_fail(handle != NULL);
535 
536     if(size == handle->buf->len)
537     {
538         return;
539     }
540 
541     g_byte_array_set_size(handle->buf, size);
542 
543     if(handle->buf_position > size)
544     {
545         handle->position += size - handle->buf_position;
546         handle->buf_position = size;
547     }
548 }
549 
550 /**
551  * ipatch_file_buf_commit:
552  * @handle: File handle with buffered data to write
553  * @err: Location to store error info or %NULL
554  *
555  * Writes all data in a file handle's buffer to the file and resets the
556  * buffer to empty.
557  *
558  * Returns: %TRUE on success, %FALSE otherwise
559  */
560 gboolean
ipatch_file_buf_commit(IpatchFileHandle * handle,GError ** err)561 ipatch_file_buf_commit(IpatchFileHandle *handle, GError **err)
562 {
563     g_return_val_if_fail(handle != NULL, FALSE);
564 
565     if(handle->buf->len == 0)
566     {
567         return (TRUE);    /* no data? */
568     }
569 
570     if(!_ipatch_file_write_no_pos_update(handle, handle->buf->data, handle->buf->len, err))
571     {
572         return (FALSE);
573     }
574 
575     g_byte_array_set_size(handle->buf, 0);
576     handle->buf_position = 0;
577 
578     return (TRUE);
579 }
580 
581 /**
582  * ipatch_file_buf_seek:
583  * @handle: File handle
584  * @offset: Offset to seek
585  * @type: Seek type
586  *
587  * Seeks the current position in a file handle's buffer specified by an @offset
588  * and seek @type.  It is an error to seek outside of the current size of
589  * buffered data (loaded or written).  The @offset is relative to the buffer,
590  * not the file position.
591  */
592 void
ipatch_file_buf_seek(IpatchFileHandle * handle,int offset,GSeekType type)593 ipatch_file_buf_seek(IpatchFileHandle *handle, int offset, GSeekType type)
594 {
595     g_return_if_fail(handle != NULL);
596 
597     if(type == G_SEEK_CUR)
598     {
599         g_return_if_fail(handle->buf_position + offset >= 0);
600         g_return_if_fail(handle->buf_position + offset < handle->buf->len);
601         handle->buf_position += offset;
602         handle->position += offset;
603     }
604     else if(type == G_SEEK_SET)
605     {
606         g_return_if_fail(offset >= 0 && (guint)offset < handle->buf->len);
607         handle->position += offset - handle->buf_position;
608         handle->buf_position = offset;
609     }
610     else if(type == G_SEEK_END)
611     {
612         g_return_if_fail(handle->buf->len + offset >= 0);
613         g_return_if_fail(handle->buf->len + offset < handle->buf->len);
614         handle->position = (handle->buf->len + offset) - handle->buf_position;
615         handle->buf_position = handle->buf->len + offset;
616     }
617 }
618 
619 /**
620  * ipatch_file_buf_read_u8:
621  * @handle: File handle with loaded data
622  *
623  * Reads an unsigned byte from a file buffer and advances the buffer's
624  * current position.
625  *
626  * Returns: The value.
627  */
628 guint8
ipatch_file_buf_read_u8(IpatchFileHandle * handle)629 ipatch_file_buf_read_u8(IpatchFileHandle *handle)
630 {
631     guint8 *val;
632 
633     g_return_val_if_fail(handle != NULL, 0);
634     g_return_val_if_fail(handle->buf_position + 1 <= handle->buf->len, 0);
635 
636     val = (guint8 *)(handle->buf->data + handle->buf_position);
637     handle->buf_position++;
638     handle->position++;
639     return (*val);
640 }
641 
642 /**
643  * ipatch_file_buf_read_u16:
644  * @handle: File handle with loaded data
645  *
646  * Reads an unsigned 16 bit word from a file buffer and advances the buffer's
647  * current position. Performs endian byte swapping if necessary.
648  *
649  * Returns: The value.
650  */
651 guint16
ipatch_file_buf_read_u16(IpatchFileHandle * handle)652 ipatch_file_buf_read_u16(IpatchFileHandle *handle)
653 {
654     guint16 *val;
655 
656     g_return_val_if_fail(handle != NULL, 0);
657     g_return_val_if_fail(handle->buf_position + 2 <= handle->buf->len, 0);
658 
659     val = (guint16 *)(handle->buf->data + handle->buf_position);
660     handle->buf_position += 2;
661     handle->position += 2;
662     return (IPATCH_FILE_SWAP16(handle->file, val));
663 }
664 
665 /**
666  * ipatch_file_buf_read_u32:
667  * @handle: File handle with loaded data
668  *
669  * Reads an unsigned 32 bit word from a file buffer and advances the buffer's
670  * current position. Performs endian byte swapping if necessary.
671  *
672  * Returns: The value.
673  */
674 guint32
ipatch_file_buf_read_u32(IpatchFileHandle * handle)675 ipatch_file_buf_read_u32(IpatchFileHandle *handle)
676 {
677     guint32 *val;
678 
679     g_return_val_if_fail(handle != NULL, 0);
680     g_return_val_if_fail(handle->buf_position + 4 <= handle->buf->len, 0);
681 
682     val = (guint32 *)(handle->buf->data + handle->buf_position);
683     handle->buf_position += 4;
684     handle->position += 4;
685     return (IPATCH_FILE_SWAP32(handle->file, val));
686 }
687 
688 /**
689  * ipatch_file_buf_read_u64:
690  * @handle: File handle with loaded data
691  *
692  * Reads an unsigned 64 bit word from a file buffer and advances the buffer's
693  * current position. Performs endian byte swapping if necessary.
694  *
695  * Returns: The value.
696  */
697 guint64
ipatch_file_buf_read_u64(IpatchFileHandle * handle)698 ipatch_file_buf_read_u64(IpatchFileHandle *handle)
699 {
700     guint64 *val;
701 
702     g_return_val_if_fail(handle != NULL, 0);
703     g_return_val_if_fail(handle->buf_position + 8 <= handle->buf->len, 0);
704 
705     val = (guint64 *)(handle->buf->data + handle->buf_position);
706     handle->buf_position += 8;
707     handle->position += 8;
708     return (IPATCH_FILE_SWAP64(handle->file, val));
709 }
710 
711 /**
712  * ipatch_file_buf_read_s8:
713  * @handle: File handle with loaded data
714  *
715  * Reads a signed byte from a file buffer and advances the buffer's
716  * current position.
717  *
718  * Returns: The value.
719  */
720 gint8
ipatch_file_buf_read_s8(IpatchFileHandle * handle)721 ipatch_file_buf_read_s8(IpatchFileHandle *handle)
722 {
723     gint8 *val;
724 
725     g_return_val_if_fail(handle != NULL, 0);
726     g_return_val_if_fail(handle->buf_position + 1 <= handle->buf->len, 0);
727 
728     val = (gint8 *)(handle->buf->data + handle->buf_position);
729     handle->buf_position++;
730     handle->position++;
731     return (*val);
732 }
733 
734 /**
735  * ipatch_file_buf_read_s16:
736  * @handle: File handle with loaded data
737  *
738  * Reads a signed 16 bit word from a file buffer and advances the buffer's
739  * current position. Performs endian byte swapping if necessary.
740  *
741  * Returns: The value.
742  */
743 gint16
ipatch_file_buf_read_s16(IpatchFileHandle * handle)744 ipatch_file_buf_read_s16(IpatchFileHandle *handle)
745 {
746     gint16 *val;
747 
748     g_return_val_if_fail(handle != NULL, 0);
749     g_return_val_if_fail(handle->buf_position + 2 <= handle->buf->len, 0);
750 
751     val = (gint16 *)(handle->buf->data + handle->buf_position);
752     handle->buf_position += 2;
753     handle->position += 2;
754     return (IPATCH_FILE_SWAP16(handle->file, val));
755 }
756 
757 /**
758  * ipatch_file_buf_read_s32:
759  * @handle: File handle with loaded data
760  *
761  * Reads a signed 32 bit word from a file buffer and advances the buffer's
762  * current position. Performs endian byte swapping if necessary.
763  *
764  * Returns: The value.
765  */
766 gint32
ipatch_file_buf_read_s32(IpatchFileHandle * handle)767 ipatch_file_buf_read_s32(IpatchFileHandle *handle)
768 {
769     gint32 *val;
770 
771     g_return_val_if_fail(handle != NULL, 0);
772     g_return_val_if_fail(handle->buf_position + 4 <= handle->buf->len, 0);
773 
774     val = (gint32 *)(handle->buf->data + handle->buf_position);
775     handle->buf_position += 4;
776     handle->position += 4;
777     return (IPATCH_FILE_SWAP32(handle->file, val));
778 }
779 
780 /**
781  * ipatch_file_buf_read_s64:
782  * @handle: File handle with loaded data
783  *
784  * Reads a signed 64 bit word from a file buffer and advances the buffer's
785  * current position. Performs endian byte swapping if necessary.
786  *
787  * Returns: The value.
788  */
789 gint64
ipatch_file_buf_read_s64(IpatchFileHandle * handle)790 ipatch_file_buf_read_s64(IpatchFileHandle *handle)
791 {
792     gint64 *val;
793 
794     g_return_val_if_fail(handle != NULL, 0);
795     g_return_val_if_fail(handle->buf_position + 8 <= handle->buf->len, 0);
796 
797     val = (gint64 *)(handle->buf->data + handle->buf_position);
798     handle->buf_position += 8;
799     handle->position += 8;
800     return (IPATCH_FILE_SWAP64(handle->file, val));
801 }
802 
803 /**
804  * ipatch_file_buf_write_u8:
805  * @handle: File handle
806  * @val: Value to write into file buffer
807  *
808  * Writes an unsigned byte to a file buffer and advances the buffer's
809  * current position. The file buffer is expanded if needed.
810  */
811 void
ipatch_file_buf_write_u8(IpatchFileHandle * handle,guint8 val)812 ipatch_file_buf_write_u8(IpatchFileHandle *handle, guint8 val)
813 {
814     g_return_if_fail(handle != NULL);
815 
816     if(handle->buf_position + 1 > handle->buf->len)
817     {
818         g_byte_array_set_size(handle->buf, handle->buf_position + 1);
819     }
820 
821     *(guint8 *)(handle->buf->data + handle->buf_position) = val;
822     handle->buf_position++;
823     handle->position++;
824 }
825 
826 /**
827  * ipatch_file_buf_write_u16:
828  * @handle: File handle
829  * @val: Value to write into file buffer
830  *
831  * Writes an unsigned 16 bit word to a file buffer and advances the buffer's
832  * current position. Performs endian byte swapping if necessary.
833  * The file buffer is expanded if needed.
834  */
835 void
ipatch_file_buf_write_u16(IpatchFileHandle * handle,guint16 val)836 ipatch_file_buf_write_u16(IpatchFileHandle *handle, guint16 val)
837 {
838     g_return_if_fail(handle != NULL);
839 
840     if(handle->buf_position + 2 > handle->buf->len)
841     {
842         g_byte_array_set_size(handle->buf, handle->buf_position + 2);
843     }
844 
845     *(guint16 *)(handle->buf->data + handle->buf_position)
846         = IPATCH_FILE_SWAP16(handle->file, &val);
847     handle->buf_position += 2;
848     handle->position += 2;
849 }
850 
851 /**
852  * ipatch_file_buf_write_u32:
853  * @handle: File handle
854  * @val: Value to write into file buffer
855  *
856  * Writes an unsigned 32 bit word to a file buffer and advances the buffer's
857  * current position. Performs endian byte swapping if necessary.
858  * The file buffer is expanded if needed.
859  */
860 void
ipatch_file_buf_write_u32(IpatchFileHandle * handle,guint32 val)861 ipatch_file_buf_write_u32(IpatchFileHandle *handle, guint32 val)
862 {
863     g_return_if_fail(handle != NULL);
864 
865     if(handle->buf_position + 4 > handle->buf->len)
866     {
867         g_byte_array_set_size(handle->buf, handle->buf_position + 4);
868     }
869 
870     *(guint32 *)(handle->buf->data + handle->buf_position)
871         = IPATCH_FILE_SWAP32(handle->file, &val);
872     handle->buf_position += 4;
873     handle->position += 4;
874 }
875 
876 /**
877  * ipatch_file_buf_write_u64:
878  * @handle: File handle
879  * @val: Value to write into file buffer
880  *
881  * Writes an unsigned 64 bit word to a file buffer and advances the buffer's
882  * current position. Performs endian byte swapping if necessary.
883  * The file buffer is expanded if needed.
884  */
885 void
ipatch_file_buf_write_u64(IpatchFileHandle * handle,guint64 val)886 ipatch_file_buf_write_u64(IpatchFileHandle *handle, guint64 val)
887 {
888     g_return_if_fail(handle != NULL);
889 
890     if(handle->buf_position + 8 > handle->buf->len)
891     {
892         g_byte_array_set_size(handle->buf, handle->buf_position + 8);
893     }
894 
895     *(guint64 *)(handle->buf->data + handle->buf_position)
896         = IPATCH_FILE_SWAP64(handle->file, &val);
897     handle->buf_position += 8;
898     handle->position += 8;
899 }
900 
901 /**
902  * ipatch_file_buf_write_s8:
903  * @handle: File handle
904  * @val: Value to write into file buffer
905  *
906  * Writes a signed byte to a file buffer and advances the buffer's
907  * current position. The file buffer is expanded if needed.
908  */
909 void
ipatch_file_buf_write_s8(IpatchFileHandle * handle,gint8 val)910 ipatch_file_buf_write_s8(IpatchFileHandle *handle, gint8 val)
911 {
912     g_return_if_fail(handle != NULL);
913 
914     if(handle->buf_position + 1 > handle->buf->len)
915     {
916         g_byte_array_set_size(handle->buf, handle->buf_position + 1);
917     }
918 
919     *(gint8 *)(handle->buf->data + handle->buf_position) = val;
920     handle->buf_position++;
921     handle->position++;
922 }
923 
924 /**
925  * ipatch_file_buf_write_s16:
926  * @handle: File handle
927  * @val: Value to write into file buffer
928  *
929  * Writes a signed 16 bit word to a file buffer and advances the buffer's
930  * current position. Performs endian byte swapping if necessary.
931  * The file buffer is expanded if needed.
932  */
933 void
ipatch_file_buf_write_s16(IpatchFileHandle * handle,gint16 val)934 ipatch_file_buf_write_s16(IpatchFileHandle *handle, gint16 val)
935 {
936     g_return_if_fail(handle != NULL);
937 
938     if(handle->buf_position + 2 > handle->buf->len)
939     {
940         g_byte_array_set_size(handle->buf, handle->buf_position + 2);
941     }
942 
943     *(gint16 *)(handle->buf->data + handle->buf_position)
944         = IPATCH_FILE_SWAP16(handle->file, &val);
945     handle->buf_position += 2;
946     handle->position += 2;
947 }
948 
949 /**
950  * ipatch_file_buf_write_s32:
951  * @handle: File handle
952  * @val: Value to write into file buffer
953  *
954  * Writes a signed 32 bit word to a file buffer and advances the buffer's
955  * current position. Performs endian byte swapping if necessary.
956  * The file buffer is expanded if needed.
957  */
958 void
ipatch_file_buf_write_s32(IpatchFileHandle * handle,gint32 val)959 ipatch_file_buf_write_s32(IpatchFileHandle *handle, gint32 val)
960 {
961     g_return_if_fail(handle != NULL);
962 
963     if(handle->buf_position + 4 > handle->buf->len)
964     {
965         g_byte_array_set_size(handle->buf, handle->buf_position + 4);
966     }
967 
968     *(gint32 *)(handle->buf->data + handle->buf_position)
969         = IPATCH_FILE_SWAP32(handle->file, &val);
970     handle->buf_position += 4;
971     handle->position += 4;
972 }
973 
974 /**
975  * ipatch_file_buf_write_s64:
976  * @handle: File handle
977  * @val: Value to write into file buffer
978  *
979  * Writes a signed 64 bit word to a file buffer and advances the buffer's
980  * current position. Performs endian byte swapping if necessary.
981  * The file buffer is expanded if needed.
982  */
983 void
ipatch_file_buf_write_s64(IpatchFileHandle * handle,gint64 val)984 ipatch_file_buf_write_s64(IpatchFileHandle *handle, gint64 val)
985 {
986     g_return_if_fail(handle != NULL);
987 
988     if(handle->buf_position + 8 > handle->buf->len)
989     {
990         g_byte_array_set_size(handle->buf, handle->buf_position + 8);
991     }
992 
993     *(gint64 *)(handle->buf->data + handle->buf_position)
994         = IPATCH_FILE_SWAP64(handle->file, &val);
995     handle->buf_position += 8;
996     handle->position += 8;
997 }
998