hb-blob.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-private.hh" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-blob.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-object-private.hh" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYS_MMAN_H 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_UNISTD_H 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h> 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* HAVE_UNISTD_H */ 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/mman.h> 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* HAVE_SYS_MMAN_H */ 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_DEBUG_BLOB 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_DEBUG_BLOB (HB_DEBUG+0) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct hb_blob_t { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_object_header_t header; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_POD (); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool immutable; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *data; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int length; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_memory_mode_t mode; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *user_data; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_destroy_func_t destroy; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool _try_writable (hb_blob_t *blob); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_hb_blob_destroy_user_data (hb_blob_t *blob) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (blob->destroy) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->destroy (blob->user_data); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->user_data = NULL; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->destroy = NULL; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_t * 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_create (const char *data, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int length, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_memory_mode_t mode, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void *user_data, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_destroy_func_t destroy) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_blob_t *blob; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!length || !(blob = hb_object_create<hb_blob_t> ())) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (destroy) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) destroy (user_data); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hb_blob_get_empty (); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->data = data; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->length = length; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->mode = mode; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->user_data = user_data; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->destroy = destroy; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (blob->mode == HB_MEMORY_MODE_DUPLICATE) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->mode = HB_MEMORY_MODE_READONLY; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!_try_writable (blob)) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_blob_destroy (blob); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hb_blob_get_empty (); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return blob; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_t * 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_create_sub_blob (hb_blob_t *parent, 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int offset, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int length) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_blob_t *blob; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!length || offset >= parent->length) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hb_blob_get_empty (); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_blob_make_immutable (parent); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob = hb_blob_create (parent->data + offset, 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MIN (length, parent->length - offset), 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent->mode, 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_blob_reference (parent), 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (hb_destroy_func_t) hb_blob_destroy); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return blob; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_t * 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_get_empty (void) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const hb_blob_t _hb_blob_nil = { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HB_OBJECT_HEADER_STATIC, 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, /* immutable */ 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, /* data */ 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, /* length */ 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HB_MEMORY_MODE_READONLY, /* mode */ 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, /* user_data */ 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL /* destroy */ 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return const_cast<hb_blob_t *> (&_hb_blob_nil); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_t * 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_reference (hb_blob_t *blob) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hb_object_reference (blob); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_destroy (hb_blob_t *blob) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!hb_object_destroy (blob)) return; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _hb_blob_destroy_user_data (blob); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) free (blob); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_set_user_data (hb_blob_t *blob, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_user_data_key_t *key, 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void * data, 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_destroy_func_t destroy, 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_bool_t replace) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hb_object_set_user_data (blob, key, data, destroy, replace); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void * 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_get_user_data (hb_blob_t *blob, 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hb_user_data_key_t *key) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hb_object_get_user_data (blob, key); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_make_immutable (hb_blob_t *blob) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (hb_object_is_inert (blob)) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->immutable = true; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_bool_t 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_is_immutable (hb_blob_t *blob) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return blob->immutable; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned int 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_get_length (hb_blob_t *blob) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return blob->length; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char * 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_get_data (hb_blob_t *blob, unsigned int *length) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (length) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *length = blob->length; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return blob->data; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char * 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)hb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!_try_writable (blob)) { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (length) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *length = 0; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (length) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *length = blob->length; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return const_cast<char *> (blob->data); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static hb_bool_t 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_try_make_writable_inplace_unix (hb_blob_t *blob) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t pagesize = -1, mask, length; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *addr; 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pagesize = (uintptr_t) sysconf (_SC_PAGE_SIZE); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pagesize = (uintptr_t) sysconf (_SC_PAGESIZE); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(HAVE_GETPAGESIZE) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pagesize = (uintptr_t) getpagesize (); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((uintptr_t) -1L == pagesize) { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, "failed to get pagesize: %s", strerror (errno)); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, "pagesize is %lu", (unsigned long) pagesize); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mask = ~(pagesize-1); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr = (const char *) (((uintptr_t) blob->data) & mask); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length = (const char *) (((uintptr_t) blob->data + blob->length + pagesize-1) & mask) - addr; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "calling mprotect on [%p..%p] (%lu bytes)", 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr, addr+length, (unsigned long) length); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (-1 == mprotect ((void *) addr, length, PROT_READ | PROT_WRITE)) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, "mprotect failed: %s", strerror (errno)); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->mode = HB_MEMORY_MODE_WRITABLE; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "successfully made [%p..%p] (%lu bytes) writable\n", 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr, addr+length, (unsigned long) length); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_try_writable_inplace (hb_blob_t *blob) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, "making writable inplace\n"); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (_try_make_writable_inplace_unix (blob)) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, "making writable -> FAILED\n"); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Failed to make writable inplace, mark that */ 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->mode = HB_MEMORY_MODE_READONLY; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_try_writable (hb_blob_t *blob) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (blob->immutable) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (blob->mode == HB_MEMORY_MODE_WRITABLE) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE && _try_writable_inplace (blob)) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (blob->mode == HB_MEMORY_MODE_WRITABLE) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, "current data is -> %p\n", blob->data); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *new_data; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_data = (char *) malloc (blob->length); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unlikely (!new_data)) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DEBUG_MSG_FUNC (BLOB, blob, "dupped successfully -> %p\n", blob->data); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy (new_data, blob->data, blob->length); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _hb_blob_destroy_user_data (blob); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->mode = HB_MEMORY_MODE_WRITABLE; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->data = new_data; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->user_data = new_data; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blob->destroy = free; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 326