hb-blob.cc revision 4101ca7dbbdf1438fa116fb8cad935501ac7cca8
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 EsfahbodHB_BEGIN_DECLS 43acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 44acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 4595e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#ifndef HB_DEBUG_BLOB 4611e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod#define HB_DEBUG_BLOB (HB_DEBUG+0) 4795e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#endif 4895e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod 4956eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod 5056eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbodstruct _hb_blob_t { 5156eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod hb_object_header_t header; 5256eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod 531c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod bool immutable; 5456eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod 5556eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod const char *data; 561c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod unsigned int length; 571c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod hb_memory_mode_t mode; 5856eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod 5956eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod void *user_data; 6056eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod hb_destroy_func_t destroy; 6156eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod}; 6256eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod 6356eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbodstatic hb_blob_t _hb_blob_nil = { 64fca368c4682624346a0aaee690e1ad6ed4c0b337Behdad Esfahbod HB_OBJECT_HEADER_STATIC, 65e97a95f2ea2770689bbf076d3c3ac404f273271eBehdad Esfahbod 661c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod TRUE, /* immutable */ 67f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 681c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 0, /* length */ 697f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod NULL, /* data */ 701c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod HB_MEMORY_MODE_READONLY, /* mode */ 717f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 72e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod NULL, /* user_data */ 73e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod NULL /* destroy */ 74f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod}; 75f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 761c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 771c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodstatic bool _try_writable (hb_blob_t *blob); 781c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 79f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodstatic void 80f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod_hb_blob_destroy_user_data (hb_blob_t *blob) 81f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 82f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod if (blob->destroy) { 83f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->destroy (blob->user_data); 84f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->user_data = NULL; 85e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod blob->destroy = NULL; 86f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod } 87f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 88f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 89f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_t * 90f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_create (const char *data, 91a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod unsigned int length, 92f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod hb_memory_mode_t mode, 93e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod void *user_data, 94e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod hb_destroy_func_t destroy) 95f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 96f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod hb_blob_t *blob; 97f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 9847e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod if (!length || !(blob = hb_object_create<hb_blob_t> ())) { 99f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod if (destroy) 100f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod destroy (user_data); 101f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod return &_hb_blob_nil; 102f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod } 103f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 104f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->data = data; 105a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod blob->length = length; 106f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->mode = mode; 107f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 108f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->user_data = user_data; 109e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod blob->destroy = destroy; 110f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 111f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod if (blob->mode == HB_MEMORY_MODE_DUPLICATE) { 112f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->mode = HB_MEMORY_MODE_READONLY; 1131c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (!_try_writable (blob)) { 114fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod hb_blob_destroy (blob); 115fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod return &_hb_blob_nil; 116fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod } 117f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod } 118f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 119f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod return blob; 120f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 121f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 122f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_t * 123a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbodhb_blob_create_sub_blob (hb_blob_t *parent, 124a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod unsigned int offset, 125a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod unsigned int length) 126a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod{ 127a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod hb_blob_t *blob; 128a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 1294101ca7dbbdf1438fa116fb8cad935501ac7cca8Behdad Esfahbod if (!length || offset >= parent->length) 130a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod return &_hb_blob_nil; 131a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 1321c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod hb_blob_make_immutable (parent); 133a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 1341c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob = hb_blob_create (parent->data + offset, 135d4141a44b97377a65e6d2a3e03b3709307af38c1Behdad Esfahbod MIN (length, parent->length - offset), 136d4141a44b97377a65e6d2a3e03b3709307af38c1Behdad Esfahbod parent->mode, 137d4141a44b97377a65e6d2a3e03b3709307af38c1Behdad Esfahbod hb_blob_reference (parent), 1381c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod (hb_destroy_func_t) hb_blob_destroy); 139a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 140a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod return blob; 141a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod} 142a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 143a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbodhb_blob_t * 1444911062d5be0d937ee8f1a70cc93e05d162f45b3Behdad Esfahbodhb_blob_get_empty (void) 145a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod{ 146a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod return &_hb_blob_nil; 147a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod} 148a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 149a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbodhb_blob_t * 150f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_reference (hb_blob_t *blob) 151f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 15247e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod return hb_object_reference (blob); 153f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 154f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 155f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodvoid 156f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_destroy (hb_blob_t *blob) 157f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 15847e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod if (!hb_object_destroy (blob)) return; 159f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 160f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod _hb_blob_destroy_user_data (blob); 161f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 162f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod free (blob); 163f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 164f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 1655fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodhb_bool_t 1665fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodhb_blob_set_user_data (hb_blob_t *blob, 1675fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod hb_user_data_key_t *key, 1685fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod void * data, 1695fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod hb_destroy_func_t destroy) 1705fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod{ 1715fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod return hb_object_set_user_data (blob, key, data, destroy); 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) { 246a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 2478be1420f8fd0e5c53282245d6830efbee5c7409dBehdad Esfahbod fprintf (stderr, "%p %s: failed to get pagesize: %s\n", blob, HB_FUNC, strerror (errno))); 2484ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod return FALSE; 2494ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod } 250a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 2518be1420f8fd0e5c53282245d6830efbee5c7409dBehdad Esfahbod fprintf (stderr, "%p %s: pagesize is %lu\n", blob, HB_FUNC, (unsigned long) pagesize)); 2524ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2534ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod mask = ~(pagesize-1); 254917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod addr = (const char *) (((uintptr_t) blob->data) & mask); 255917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod length = (const char *) (((uintptr_t) blob->data + blob->length + pagesize-1) & mask) - addr; 256a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 25717e9ff938b638fd1cb80c990ba13bd47562116b8Behdad Esfahbod fprintf (stderr, "%p %s: calling mprotect on [%p..%p] (%lu bytes)\n", 2588be1420f8fd0e5c53282245d6830efbee5c7409dBehdad Esfahbod blob, HB_FUNC, 259a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod addr, addr+length, (unsigned long) length)); 2604ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod if (-1 == mprotect ((void *) addr, length, PROT_READ | PROT_WRITE)) { 261a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 2628be1420f8fd0e5c53282245d6830efbee5c7409dBehdad Esfahbod fprintf (stderr, "%p %s: %s\n", blob, HB_FUNC, strerror (errno))); 2634ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod return FALSE; 2644ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod } 2654ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2661c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->mode = HB_MEMORY_MODE_WRITABLE; 2671c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 268a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 26917e9ff938b638fd1cb80c990ba13bd47562116b8Behdad Esfahbod fprintf (stderr, "%p %s: successfully made [%p..%p] (%lu bytes) writable\n", 2708be1420f8fd0e5c53282245d6830efbee5c7409dBehdad Esfahbod blob, HB_FUNC, 271a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod addr, addr+length, (unsigned long) length)); 2724ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod return TRUE; 2734ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#else 2744ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod return FALSE; 2754ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#endif 2764ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod} 2774ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2781c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodstatic bool 2791c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod_try_writable_inplace (hb_blob_t *blob) 280388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod{ 281a5ab682b9ba8224fc132624f93e6fef9973a68caBehdad Esfahbod (void) (HB_DEBUG_BLOB && 2821c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod fprintf (stderr, "%p %s: making writable inplace\n", blob, HB_FUNC)); 283388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod 2841c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (_try_make_writable_inplace_unix (blob)) 2851c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return TRUE; 2861c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 2871c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod (void) (HB_DEBUG_BLOB && 2881c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod fprintf (stderr, "%p %s: making writable -> FAILED\n", blob, HB_FUNC)); 2891c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 2901c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod /* Failed to make writable inplace, mark that */ 2911c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->mode = HB_MEMORY_MODE_READONLY; 2921c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return FALSE; 293388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod} 2944ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2951c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodstatic bool 2961c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod_try_writable (hb_blob_t *blob) 297f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 2981c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (blob->immutable) 299fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod return FALSE; 300fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod 3011c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (blob->mode == HB_MEMORY_MODE_WRITABLE) 3021c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return TRUE; 3037f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 3041c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE && _try_writable_inplace (blob)) 3051c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return TRUE; 30671e735e915c85536ee4d3035576f7426e8cd19ddBehdad Esfahbod 3071c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (blob->mode == HB_MEMORY_MODE_WRITABLE) 3081c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return TRUE; 309f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 310fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod 3111c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod (void) (HB_DEBUG_BLOB && 3121c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod fprintf (stderr, "%p %s -> %p\n", blob, HB_FUNC, blob->data)); 3131c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 3141c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod char *new_data; 3151c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 3161c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod new_data = (char *) malloc (blob->length); 3171c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (unlikely (!new_data)) 3181c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return FALSE; 3197f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 3201c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod (void) (HB_DEBUG_BLOB && 3211c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod fprintf (stderr, "%p %s: dupped successfully -> %p\n", blob, HB_FUNC, blob->data)); 3227f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 3231c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod memcpy (new_data, blob->data, blob->length); 3241c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod _hb_blob_destroy_user_data (blob); 3251c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->mode = HB_MEMORY_MODE_WRITABLE; 3261c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->data = new_data; 3271c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->user_data = new_data; 3281c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->destroy = free; 3291c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 3301c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return TRUE; 331f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 332acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 333acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 334acdba3f90b232fc12fcb200dca2584481b339118Behdad EsfahbodHB_END_DECLS 335