hb-blob.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2009 Red Hat, Inc. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This is part of HarfBuzz, a text shaping library. 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, without written agreement and without 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * license or royalty fees, to use, copy, modify, and distribute this 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * software and its documentation for any purpose, provided that the 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * above copyright notice and the following two paragraphs appear in 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * all copies of this software. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DAMAGE. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Red Hat Author(s): Behdad Esfahbod 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* http://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html */ 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(_POSIX_C_SOURCE) 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#undef _POSIX_C_SOURCE 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define _POSIX_C_SOURCE 199309L 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-private.hh" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-blob.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-object-private.hh" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYS_MMAN_H 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_UNISTD_H 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h> 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* HAVE_UNISTD_H */ 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/mman.h> 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* HAVE_SYS_MMAN_H */ 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_DEBUG_BLOB 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_DEBUG_BLOB (HB_DEBUG+0) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_blob_t { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_object_header_t header; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_POD (); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool immutable; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *data; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int length; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_memory_mode_t mode; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *user_data; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_destroy_func_t destroy; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool _try_writable (hb_blob_t *blob); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_blob_destroy_user_data (hb_blob_t *blob) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (blob->destroy) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->destroy (blob->user_data); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->user_data = NULL; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->destroy = NULL; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_t * 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_create (const char *data, 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int length, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_memory_mode_t mode, 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *user_data, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_destroy_func_t destroy) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_blob_t *blob; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!length || !(blob = hb_object_create<hb_blob_t> ())) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (destroy) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) destroy (user_data); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hb_blob_get_empty (); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->data = data; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->length = length; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->mode = mode; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->user_data = user_data; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->destroy = destroy; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (blob->mode == HB_MEMORY_MODE_DUPLICATE) { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->mode = HB_MEMORY_MODE_READONLY; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!_try_writable (blob)) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_blob_destroy (blob); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hb_blob_get_empty (); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return blob; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_t * 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_create_sub_blob (hb_blob_t *parent, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int offset, 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int length) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_blob_t *blob; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!length || offset >= parent->length) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hb_blob_get_empty (); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_blob_make_immutable (parent); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob = hb_blob_create (parent->data + offset, 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MIN (length, parent->length - offset), 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) HB_MEMORY_MODE_READONLY, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_blob_reference (parent), 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (hb_destroy_func_t) hb_blob_destroy); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return blob; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_t * 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_get_empty (void) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const hb_blob_t _hb_blob_nil = { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HB_OBJECT_HEADER_STATIC, 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, /* immutable */ 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, /* data */ 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, /* length */ 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HB_MEMORY_MODE_READONLY, /* mode */ 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, /* user_data */ 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL /* destroy */ 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return const_cast<hb_blob_t *> (&_hb_blob_nil); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_t * 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_reference (hb_blob_t *blob) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hb_object_reference (blob); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_destroy (hb_blob_t *blob) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!hb_object_destroy (blob)) return; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _hb_blob_destroy_user_data (blob); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free (blob); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_set_user_data (hb_blob_t *blob, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_user_data_key_t *key, 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void * data, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_destroy_func_t destroy, 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_bool_t replace) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hb_object_set_user_data (blob, key, data, destroy, replace); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void * 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_get_user_data (hb_blob_t *blob, 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_user_data_key_t *key) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hb_object_get_user_data (blob, key); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_make_immutable (hb_blob_t *blob) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hb_object_is_inert (blob)) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->immutable = true; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_is_immutable (hb_blob_t *blob) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return blob->immutable; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned int 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_get_length (hb_blob_t *blob) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return blob->length; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char * 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_get_data (hb_blob_t *blob, unsigned int *length) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (length) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *length = blob->length; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return blob->data; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char * 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!_try_writable (blob)) { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (length) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *length = 0; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (length) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *length = blob->length; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return const_cast<char *> (blob->data); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static hb_bool_t 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_try_make_writable_inplace_unix (hb_blob_t *blob) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t pagesize = -1, mask, length; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *addr; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pagesize = (uintptr_t) sysconf (_SC_PAGE_SIZE); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pagesize = (uintptr_t) sysconf (_SC_PAGESIZE); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(HAVE_GETPAGESIZE) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pagesize = (uintptr_t) getpagesize (); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((uintptr_t) -1L == pagesize) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, "failed to get pagesize: %s", strerror (errno)); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, "pagesize is %lu", (unsigned long) pagesize); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mask = ~(pagesize-1); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr = (const char *) (((uintptr_t) blob->data) & mask); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length = (const char *) (((uintptr_t) blob->data + blob->length + pagesize-1) & mask) - addr; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "calling mprotect on [%p..%p] (%lu bytes)", 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr, addr+length, (unsigned long) length); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (-1 == mprotect ((void *) addr, length, PROT_READ | PROT_WRITE)) { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, "mprotect failed: %s", strerror (errno)); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->mode = HB_MEMORY_MODE_WRITABLE; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "successfully made [%p..%p] (%lu bytes) writable\n", 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr, addr+length, (unsigned long) length); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_try_writable_inplace (hb_blob_t *blob) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, "making writable inplace\n"); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (_try_make_writable_inplace_unix (blob)) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, "making writable -> FAILED\n"); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Failed to make writable inplace, mark that */ 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->mode = HB_MEMORY_MODE_READONLY; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_try_writable (hb_blob_t *blob) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (blob->immutable) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (blob->mode == HB_MEMORY_MODE_WRITABLE) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE && _try_writable_inplace (blob)) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (blob->mode == HB_MEMORY_MODE_WRITABLE) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, "current data is -> %p\n", blob->data); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *new_data; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_data = (char *) malloc (blob->length); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unlikely (!new_data)) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, "dupped successfully -> %p\n", blob->data); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy (new_data, blob->data, blob->length); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _hb_blob_destroy_user_data (blob); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->mode = HB_MEMORY_MODE_WRITABLE; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->data = new_data; 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->user_data = new_data; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->destroy = free; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 332