hb-blob.cc revision f88d3bd7e407d332bb04688344c54756d24128c9
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 27f88d3bd7e407d332bb04688344c54756d24128c9Behdad Esfahbod/* http://www.oracle.com/technetwork/articles/servers-storage-dev/standardheaderfiles-453865.html */ 28f88d3bd7e407d332bb04688344c54756d24128c9Behdad Esfahbod#define _POSIX_C_SOURCE 3 29f88d3bd7e407d332bb04688344c54756d24128c9Behdad Esfahbod 30c57d454accff66e5f2c58006e8fb40bc020b6182Behdad Esfahbod#include "hb-private.hh" 31f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 3256eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod#include "hb-blob.h" 3356eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod#include "hb-object-private.hh" 34f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 35ec90ee23b29aab187c3fa209970aa97434c84b1bBehdad Esfahbod#ifdef HAVE_SYS_MMAN_H 36c486ea9c3582710474c1085c21c1dc5e2700adc3Behdad Esfahbod#ifdef HAVE_UNISTD_H 37a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod#include <unistd.h> 38c486ea9c3582710474c1085c21c1dc5e2700adc3Behdad Esfahbod#endif /* HAVE_UNISTD_H */ 39a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod#include <sys/mman.h> 40ec90ee23b29aab187c3fa209970aa97434c84b1bBehdad Esfahbod#endif /* HAVE_SYS_MMAN_H */ 41a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 42acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod#include <stdio.h> 43acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod#include <errno.h> 44acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 45acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 46acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 4795e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#ifndef HB_DEBUG_BLOB 4811e3ec444a85fc72541823c2e98cc92c4ceb19afBehdad Esfahbod#define HB_DEBUG_BLOB (HB_DEBUG+0) 4995e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod#endif 5095e202403ffa543c817f45cca21fbc116eb8e807Behdad Esfahbod 5156eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod 521bc1cb3603167f5da309336f7018c8b0608ac104Behdad Esfahbodstruct hb_blob_t { 5356eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod hb_object_header_t header; 546220e5fc0dad728e67a92e838d3ac275d032f2c7Behdad Esfahbod ASSERT_POD (); 5556eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod 561c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod bool immutable; 5756eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod 5856eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod const char *data; 591c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod unsigned int length; 601c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod hb_memory_mode_t mode; 6156eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod 6256eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod void *user_data; 6356eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod hb_destroy_func_t destroy; 6456eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod}; 6556eb5ad6f94c32189ad219438db9a18683ca6846Behdad Esfahbod 661c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 671c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodstatic bool _try_writable (hb_blob_t *blob); 681c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 69f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodstatic void 70f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod_hb_blob_destroy_user_data (hb_blob_t *blob) 71f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 72f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod if (blob->destroy) { 73f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->destroy (blob->user_data); 74f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->user_data = NULL; 75e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod blob->destroy = NULL; 76f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod } 77f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 78f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 79f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_t * 80f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_create (const char *data, 81a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod unsigned int length, 82f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod hb_memory_mode_t mode, 83e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod void *user_data, 84e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod hb_destroy_func_t destroy) 85f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 86f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod hb_blob_t *blob; 87f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 8847e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod if (!length || !(blob = hb_object_create<hb_blob_t> ())) { 89f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod if (destroy) 90f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod destroy (user_data); 91f06ab8a4262c759b4723614fd28f55ee77aa8466Behdad Esfahbod return hb_blob_get_empty (); 92f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod } 93f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 94f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->data = data; 95a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod blob->length = length; 96f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->mode = mode; 97f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 98f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->user_data = user_data; 99e5847f75fb7bd25c5db6061d8e20d61fa469f9feBehdad Esfahbod blob->destroy = destroy; 100f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 101f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod if (blob->mode == HB_MEMORY_MODE_DUPLICATE) { 102f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod blob->mode = HB_MEMORY_MODE_READONLY; 1031c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (!_try_writable (blob)) { 104fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod hb_blob_destroy (blob); 105f06ab8a4262c759b4723614fd28f55ee77aa8466Behdad Esfahbod return hb_blob_get_empty (); 106fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod } 107f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod } 108f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 109f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod return blob; 110f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 111f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 112f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_t * 113a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbodhb_blob_create_sub_blob (hb_blob_t *parent, 114a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod unsigned int offset, 115a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod unsigned int length) 116a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod{ 117a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod hb_blob_t *blob; 118a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 1194101ca7dbbdf1438fa116fb8cad935501ac7cca8Behdad Esfahbod if (!length || offset >= parent->length) 120f06ab8a4262c759b4723614fd28f55ee77aa8466Behdad Esfahbod return hb_blob_get_empty (); 121a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 1221c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod hb_blob_make_immutable (parent); 123a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 1241c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob = hb_blob_create (parent->data + offset, 125d4141a44b97377a65e6d2a3e03b3709307af38c1Behdad Esfahbod MIN (length, parent->length - offset), 126d4141a44b97377a65e6d2a3e03b3709307af38c1Behdad Esfahbod parent->mode, 127d4141a44b97377a65e6d2a3e03b3709307af38c1Behdad Esfahbod hb_blob_reference (parent), 1281c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod (hb_destroy_func_t) hb_blob_destroy); 129a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 130a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod return blob; 131a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod} 132a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 133a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbodhb_blob_t * 1344911062d5be0d937ee8f1a70cc93e05d162f45b3Behdad Esfahbodhb_blob_get_empty (void) 135a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod{ 136f06ab8a4262c759b4723614fd28f55ee77aa8466Behdad Esfahbod static const hb_blob_t _hb_blob_nil = { 137f06ab8a4262c759b4723614fd28f55ee77aa8466Behdad Esfahbod HB_OBJECT_HEADER_STATIC, 138f06ab8a4262c759b4723614fd28f55ee77aa8466Behdad Esfahbod 1390594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod true, /* immutable */ 140f06ab8a4262c759b4723614fd28f55ee77aa8466Behdad Esfahbod 141f06ab8a4262c759b4723614fd28f55ee77aa8466Behdad Esfahbod NULL, /* data */ 142f06ab8a4262c759b4723614fd28f55ee77aa8466Behdad Esfahbod 0, /* length */ 143f06ab8a4262c759b4723614fd28f55ee77aa8466Behdad Esfahbod HB_MEMORY_MODE_READONLY, /* mode */ 144f06ab8a4262c759b4723614fd28f55ee77aa8466Behdad Esfahbod 145f06ab8a4262c759b4723614fd28f55ee77aa8466Behdad Esfahbod NULL, /* user_data */ 146f06ab8a4262c759b4723614fd28f55ee77aa8466Behdad Esfahbod NULL /* destroy */ 147f06ab8a4262c759b4723614fd28f55ee77aa8466Behdad Esfahbod }; 148f06ab8a4262c759b4723614fd28f55ee77aa8466Behdad Esfahbod 149f06ab8a4262c759b4723614fd28f55ee77aa8466Behdad Esfahbod return const_cast<hb_blob_t *> (&_hb_blob_nil); 150a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod} 151a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbod 152a26442437ae9f11674e0d68cd5cbf395ade7695dBehdad Esfahbodhb_blob_t * 153f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_reference (hb_blob_t *blob) 154f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 15547e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod return hb_object_reference (blob); 156f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 157f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 158f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodvoid 159f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbodhb_blob_destroy (hb_blob_t *blob) 160f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 16147e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod if (!hb_object_destroy (blob)) return; 162f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 163f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod _hb_blob_destroy_user_data (blob); 164f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 165f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod free (blob); 166f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 167f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 1685fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodhb_bool_t 1695fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodhb_blob_set_user_data (hb_blob_t *blob, 1705fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod hb_user_data_key_t *key, 1715fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod void * data, 17233ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod hb_destroy_func_t destroy, 17333ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod hb_bool_t replace) 1745fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod{ 17533ccc77902660ed4b49184e5ec99f4fd0ef63175Behdad Esfahbod return hb_object_set_user_data (blob, key, data, destroy, replace); 1765fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod} 1775fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod 1785fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodvoid * 1795fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbodhb_blob_get_user_data (hb_blob_t *blob, 1805fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod hb_user_data_key_t *key) 1815fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod{ 1825fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod return hb_object_get_user_data (blob, key); 1835fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod} 1845fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod 1855fa849b77d49da2212825ebb1bea9145713b8449Behdad Esfahbod 186fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbodvoid 1871c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodhb_blob_make_immutable (hb_blob_t *blob) 188fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod{ 18947e71d9661946a4ffb96026bf1d697d788414ab5Behdad Esfahbod if (hb_object_is_inert (blob)) 1907f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod return; 1917f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 1920594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod blob->immutable = true; 1931c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod} 1947acb389569cf99c6bae9db31a8ed7c7007fbb566Behdad Esfahbod 1951c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodhb_bool_t 1961c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodhb_blob_is_immutable (hb_blob_t *blob) 1971c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod{ 1981c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return blob->immutable; 1991c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod} 2007f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 2015a11c875d8c95d480e6f32b57e969ee34ca1940dBehdad Esfahbod 2021c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodunsigned int 2031c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodhb_blob_get_length (hb_blob_t *blob) 2041c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod{ 2051c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return blob->length; 206f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 207f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 2081c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodconst char * 2091c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodhb_blob_get_data (hb_blob_t *blob, unsigned int *length) 210f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 2111c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (length) 2121c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod *length = blob->length; 2137f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 2141c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return blob->data; 2151c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod} 2167f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 2171c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodchar * 2181c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodhb_blob_get_data_writable (hb_blob_t *blob, unsigned int *length) 2191c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod{ 2201c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (!_try_writable (blob)) { 2211c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (length) 2221c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod *length = 0; 2237f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 2241c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return NULL; 2251c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod } 2267f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 2271c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (length) 2281c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod *length = blob->length; 2297f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 2301c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod return const_cast<char *> (blob->data); 231f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 232f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 2334ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2344ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbodstatic hb_bool_t 2351c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod_try_make_writable_inplace_unix (hb_blob_t *blob) 2364ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod{ 2374ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#if defined(HAVE_SYS_MMAN_H) && defined(HAVE_MPROTECT) 238917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod uintptr_t pagesize = -1, mask, length; 2394ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod const char *addr; 2404ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2414ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE) 242917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod pagesize = (uintptr_t) sysconf (_SC_PAGE_SIZE); 2434ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#elif defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE) 244917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod pagesize = (uintptr_t) sysconf (_SC_PAGESIZE); 2454ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#elif defined(HAVE_GETPAGESIZE) 246917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod pagesize = (uintptr_t) getpagesize (); 2474ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#endif 2484ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 249917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod if ((uintptr_t) -1L == pagesize) { 250cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, "failed to get pagesize: %s", strerror (errno)); 2510594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod return false; 2524ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod } 253cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, "pagesize is %lu", (unsigned long) pagesize); 2544ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2554ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod mask = ~(pagesize-1); 256917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod addr = (const char *) (((uintptr_t) blob->data) & mask); 257917c227500305aee543981ad24a39f868c5ca0b7Behdad Esfahbod length = (const char *) (((uintptr_t) blob->data + blob->length + pagesize-1) & mask) - addr; 258cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, 259cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod "calling mprotect on [%p..%p] (%lu bytes)", 260cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod addr, addr+length, (unsigned long) length); 2614ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod if (-1 == mprotect ((void *) addr, length, PROT_READ | PROT_WRITE)) { 262cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, "mprotect failed: %s", strerror (errno)); 2630594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod return false; 2644ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod } 2654ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2661c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->mode = HB_MEMORY_MODE_WRITABLE; 2671c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 268cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, 269cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod "successfully made [%p..%p] (%lu bytes) writable\n", 270cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod addr, addr+length, (unsigned long) length); 2710594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod return true; 2724ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#else 2730594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod return false; 2744ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod#endif 2754ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod} 2764ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2771c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodstatic bool 2781c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod_try_writable_inplace (hb_blob_t *blob) 279388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod{ 280cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, "making writable inplace\n"); 281388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod 2821c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (_try_make_writable_inplace_unix (blob)) 2830594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod return true; 2841c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 285cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, "making writable -> FAILED\n"); 2861c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 2871c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod /* Failed to make writable inplace, mark that */ 2881c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->mode = HB_MEMORY_MODE_READONLY; 2890594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod return false; 290388ad037ff399c23c5e24bbcede27e0e35bed07eBehdad Esfahbod} 2914ff2a58952f010c6252f06e5f404d6840d257250Behdad Esfahbod 2921c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbodstatic bool 2931c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod_try_writable (hb_blob_t *blob) 294f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod{ 2951c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (blob->immutable) 2960594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod return false; 297fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod 2981c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (blob->mode == HB_MEMORY_MODE_WRITABLE) 2990594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod return true; 3007f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 3011c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (blob->mode == HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE && _try_writable_inplace (blob)) 3020594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod return true; 30371e735e915c85536ee4d3035576f7426e8cd19ddBehdad Esfahbod 3041c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (blob->mode == HB_MEMORY_MODE_WRITABLE) 3050594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod return true; 306f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod 307fc6c94002dd5478cf9fbdaff12d8374a786c85e1Behdad Esfahbod 308bc71ad4973842f25216b48842a46d6c9cbce6aa3Behdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, "current data is -> %p\n", blob->data); 3091c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 3101c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod char *new_data; 3111c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 3121c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod new_data = (char *) malloc (blob->length); 3131c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod if (unlikely (!new_data)) 3140594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod return false; 3157f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 316cc06c243d8be3ebb1190281653d2dba504c16c0fBehdad Esfahbod DEBUG_MSG_FUNC (BLOB, blob, "dupped successfully -> %p\n", blob->data); 3177f3d5c8166e5205e9d9bf8b4b2f31d44387a8006Behdad Esfahbod 3181c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod memcpy (new_data, blob->data, blob->length); 3191c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod _hb_blob_destroy_user_data (blob); 3201c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->mode = HB_MEMORY_MODE_WRITABLE; 3211c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->data = new_data; 3221c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->user_data = new_data; 3231c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod blob->destroy = free; 3241c9f8717eb12c37c219333cbb0d123e1d2da4896Behdad Esfahbod 3250594a2448440208efa0acac9a5d8d52d43108289Behdad Esfahbod return true; 326f0954d1e08ae288eda9904e17108fc73f48c0b98Behdad Esfahbod} 327acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 328acdba3f90b232fc12fcb200dca2584481b339118Behdad Esfahbod 329