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