hb-blob.cc revision bc71ad4973842f25216b48842a46d6c9cbce6aa3
1f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod/* 22409d5f8d7dd8b535ce5ea29e933f7db27d33793Behdad Esfahbod * Copyright © 2009 Red Hat, Inc. 3f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * 4c755cb3e3ac55156d0d2ec05adea7a650b97cc41Behdad Esfahbod * This is part of HarfBuzz, a text shaping library. 5f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * 6f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * Permission is hereby granted, without written agreement and without 7f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this 8f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * software and its documentation for any purpose, provided that the 9f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * above copyright notice and the following two paragraphs appear in 10f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * all copies of this software. 11f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * 12f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * DAMAGE. 17f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * 18f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * 24f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod * Red Hat Author(s): Behdad Esfahbod 25f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod */ 26f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 27c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#include "hb-private.hh" 28f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 2956eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod#include "hb-blob.h" 3056eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod#include "hb-object-private.hh" 31f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 32ec90ee23b29aab187c3fa209970aa97434c84b1bBehdad Esfahbod#ifdef HAVE_SYS_MMAN_H 33c486ea9c3582710474c1085c21c1dc5e2700adc3Behdad Esfahbod#ifdef HAVE_UNISTD_H 34a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod#include <unistd.h> 35c486ea9c3582710474c1085c21c1dc5e2700adc3Behdad Esfahbod#endif /* HAVE_UNISTD_H */ 36a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod#include <sys/mman.h> 37ec90ee23b29aab187c3fa209970aa97434c84b1bBehdad Esfahbod#endif /* HAVE_SYS_MMAN_H */ 38a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 39acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod#include <stdio.h> 40acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod#include <errno.h> 41acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 42acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 43acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 4495e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#ifndef HB_DEBUG_BLOB 4511e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod#define HB_DEBUG_BLOB (HB_DEBUG+0) 4695e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#endif 4795e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod 4856eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod 4956eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbodstruct _hb_blob_t { 5056eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod hb_object_header_t header; 5156eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod 521c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod bool immutable; 5356eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod 5456eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod const char *data; 551c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod unsigned int length; 561c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod hb_memory_mode_t mode; 5756eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod 5856eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod void *user_data; 5956eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod hb_destroy_func_t destroy; 6056eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod}; 6156eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod 6256eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbodstatic hb_blob_t _hb_blob_nil = { 63fca368c4682624346a0aaee690e1ad6ed4c0b337Behdad Esfahbod HB_OBJECT_HEADER_STATIC, 64e97a95f2ea2770689bbf076d3c3ac404f273271eBehdad Esfahbod 651c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod TRUE, /* immutable */ 66f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 677f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod NULL, /* data */ 68b95324cdd217f44c40c5fd44898e659500f19511Behdad Esfahbod 0, /* length */ 691c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod HB_MEMORY_MODE_READONLY, /* mode */ 707f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 71e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod NULL, /* user_data */ 72e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod NULL /* destroy */ 73f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod}; 74f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 751c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 761c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodstatic bool _try_writable (hb_blob_t *blob); 771c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 78f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodstatic void 79f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod_hb_blob_destroy_user_data (hb_blob_t *blob) 80f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 81f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod if (blob->destroy) { 82f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->destroy (blob->user_data); 83f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->user_data = NULL; 84e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod blob->destroy = NULL; 85f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod } 86f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 87f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 88f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_t * 89f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_create (const char *data, 90a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod unsigned int length, 91f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod hb_memory_mode_t mode, 92e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod void *user_data, 93e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod hb_destroy_func_t destroy) 94f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 95f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod hb_blob_t *blob; 96f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 9747e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod if (!length || !(blob = hb_object_create<hb_blob_t> ())) { 98f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod if (destroy) 99f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod destroy (user_data); 100f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod return &_hb_blob_nil; 101f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod } 102f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 103f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->data = data; 104a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod blob->length = length; 105f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->mode = mode; 106f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 107f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->user_data = user_data; 108e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod blob->destroy = destroy; 109f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 110f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod if (blob->mode == HB_MEMORY_MODE_DUPLICATE) { 111f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->mode = HB_MEMORY_MODE_READONLY; 1121c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (!_try_writable (blob)) { 113fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod hb_blob_destroy (blob); 114fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod return &_hb_blob_nil; 115fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod } 116f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod } 117f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 118f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod return blob; 119f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 120f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 121f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_t * 122a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbodhb_blob_create_sub_blob (hb_blob_t *parent, 123a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod unsigned int offset, 124a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod unsigned int length) 125a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod{ 126a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod hb_blob_t *blob; 127a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 1284101ca7dbbdf1438fa116fb8cad935501ac7cca8Behdad Esfahbod if (!length || offset >= parent->length) 129a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod return &_hb_blob_nil; 130a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 1311c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod hb_blob_make_immutable (parent); 132a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 1331c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob = hb_blob_create (parent->data + offset, 134d4141a44b97377a65e6d2a3e03b3709307af38c1Behdad Esfahbod MIN (length, parent->length - offset), 135d4141a44b97377a65e6d2a3e03b3709307af38c1Behdad Esfahbod parent->mode, 136d4141a44b97377a65e6d2a3e03b3709307af38c1Behdad Esfahbod hb_blob_reference (parent), 1371c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod (hb_destroy_func_t) hb_blob_destroy); 138a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 139a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod return blob; 140a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod} 141a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 142a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbodhb_blob_t * 1434911062d5be0d937ee8f1a70cc93e05d162f45b3Behdad Esfahbodhb_blob_get_empty (void) 144a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod{ 145a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod return &_hb_blob_nil; 146a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod} 147a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 148a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbodhb_blob_t * 149f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_reference (hb_blob_t *blob) 150f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 15147e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod return hb_object_reference (blob); 152f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 153f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 154f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodvoid 155f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_destroy (hb_blob_t *blob) 156f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 15747e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod if (!hb_object_destroy (blob)) return; 158f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 159f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod _hb_blob_destroy_user_data (blob); 160f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 161f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod free (blob); 162f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 163f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 1645fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodhb_bool_t 1655fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodhb_blob_set_user_data (hb_blob_t *blob, 1665fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod hb_user_data_key_t *key, 1675fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod void * data, 16833ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod hb_destroy_func_t destroy, 16933ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod hb_bool_t replace) 1705fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod{ 17133ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod return hb_object_set_user_data (blob, key, data, destroy, replace); 1725fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod} 1735fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod 1745fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodvoid * 1755fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodhb_blob_get_user_data (hb_blob_t *blob, 1765fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod hb_user_data_key_t *key) 1775fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod{ 1785fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod return hb_object_get_user_data (blob, key); 1795fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod} 1805fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod 1815fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod 182fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbodvoid 1831c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodhb_blob_make_immutable (hb_blob_t *blob) 184fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod{ 18547e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod if (hb_object_is_inert (blob)) 1867f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod return; 1877f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 1881c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->immutable = TRUE; 1891c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod} 1907acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod 1911c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodhb_bool_t 1921c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodhb_blob_is_immutable (hb_blob_t *blob) 1931c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod{ 1941c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return blob->immutable; 1951c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod} 1967f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 1975a11c875d8c95d480e6f32b57e969ee34ca1940dBehdad Esfahbod 1981c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodunsigned int 1991c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodhb_blob_get_length (hb_blob_t *blob) 2001c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod{ 2011c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return blob->length; 202f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 203f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 2041c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodconst char * 2051c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodhb_blob_get_data (hb_blob_t *blob, unsigned int *length) 206f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 2071c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (length) 2081c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod *length = blob->length; 2097f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 2101c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return blob->data; 2111c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod} 2127f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 2131c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodchar * 2141c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodhb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length) 2151c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod{ 2161c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (!_try_writable (blob)) { 2171c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (length) 2181c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod *length = 0; 2197f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 2201c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return NULL; 2211c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod } 2227f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 2231c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (length) 2241c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod *length = blob->length; 2257f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 2261c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return const_cast<char *> (blob->data); 227f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 228f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 2294ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2304ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbodstatic hb_bool_t 2311c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod_try_make_writable_inplace_unix (hb_blob_t *blob) 2324ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod{ 2334ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT) 234917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod uintptr_t pagesize = -1, mask, length; 2354ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod const char *addr; 2364ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2374ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE) 238917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod pagesize = (uintptr_t) sysconf (_SC_PAGE_SIZE); 2394ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#elif defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) 240917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod pagesize = (uintptr_t) sysconf (_SC_PAGESIZE); 2414ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#elif defined(HAVE_GETPAGESIZE) 242917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod pagesize = (uintptr_t) getpagesize (); 2434ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#endif 2444ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 245917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod if ((uintptr_t) -1L == pagesize) { 246cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, "failed to get pagesize: %s", strerror (errno)); 2474ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod return FALSE; 2484ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod } 249cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, "pagesize is %lu", (unsigned long) pagesize); 2504ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2514ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod mask = ~(pagesize-1); 252917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod addr = (const char *) (((uintptr_t) blob->data) & mask); 253917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod length = (const char *) (((uintptr_t) blob->data + blob->length + pagesize-1) & mask) - addr; 254cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, 255cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod "calling mprotect on [%p..%p] (%lu bytes)", 256cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod addr, addr+length, (unsigned long) length); 2574ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod if (-1 == mprotect ((void *) addr, length, PROT_READ | PROT_WRITE)) { 258cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, "mprotect failed: %s", strerror (errno)); 2594ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod return FALSE; 2604ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod } 2614ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2621c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->mode = HB_MEMORY_MODE_WRITABLE; 2631c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 264cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, 265cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod "successfully made [%p..%p] (%lu bytes) writable\n", 266cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod addr, addr+length, (unsigned long) length); 2674ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod return TRUE; 2684ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#else 2694ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod return FALSE; 2704ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#endif 2714ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod} 2724ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2731c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodstatic bool 2741c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod_try_writable_inplace (hb_blob_t *blob) 275388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod{ 276cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, "making writable inplace\n"); 277388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod 2781c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (_try_make_writable_inplace_unix (blob)) 2791c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return TRUE; 2801c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 281cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, "making writable -> FAILED\n"); 2821c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 2831c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod /* Failed to make writable inplace, mark that */ 2841c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->mode = HB_MEMORY_MODE_READONLY; 2851c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return FALSE; 286388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod} 2874ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2881c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodstatic bool 2891c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod_try_writable (hb_blob_t *blob) 290f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 2911c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (blob->immutable) 292fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod return FALSE; 293fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod 2941c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (blob->mode == HB_MEMORY_MODE_WRITABLE) 2951c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return TRUE; 2967f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 2971c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE && _try_writable_inplace (blob)) 2981c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return TRUE; 29971e735e915c85536ee4d3035576f7426e8cd19ddBehdad Esfahbod 3001c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (blob->mode == HB_MEMORY_MODE_WRITABLE) 3011c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return TRUE; 302f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 303fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod 304bc71ad4973842f25216b48842a46d6c9cbce6aa3Behdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, "current data is -> %p\n", blob->data); 3051c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 3061c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod char *new_data; 3071c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 3081c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod new_data = (char *) malloc (blob->length); 3091c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (unlikely (!new_data)) 3101c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return FALSE; 3117f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 312cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, "dupped successfully -> %p\n", blob->data); 3137f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 3141c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod memcpy (new_data, blob->data, blob->length); 3151c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod _hb_blob_destroy_user_data (blob); 3161c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->mode = HB_MEMORY_MODE_WRITABLE; 3171c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->data = new_data; 3181c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->user_data = new_data; 3191c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->destroy = free; 3201c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 3211c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return TRUE; 322f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 323acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 324acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 325