| File: | src/usr.bin/ctfconv/generate.c |
| Warning: | line 220, column 22 Access to field 'it_idx' results in a dereference of a null pointer (loaded from field 'it_refp') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* $OpenBSD: generate.c,v 1.4 2017/09/26 08:16:18 mpi Exp $ */ | |||
| 2 | ||||
| 3 | /* | |||
| 4 | * Copyright (c) 2017 Martin Pieuchot | |||
| 5 | * | |||
| 6 | * Permission to use, copy, modify, and distribute this software for any | |||
| 7 | * purpose with or without fee is hereby granted, provided that the above | |||
| 8 | * copyright notice and this permission notice appear in all copies. | |||
| 9 | * | |||
| 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
| 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
| 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||
| 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
| 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||
| 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||
| 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
| 17 | */ | |||
| 18 | ||||
| 19 | #include <sys/types.h> | |||
| 20 | #include <sys/queue.h> | |||
| 21 | #include <sys/tree.h> | |||
| 22 | #include <sys/ctf.h> | |||
| 23 | ||||
| 24 | #include <assert.h> | |||
| 25 | #include <err.h> | |||
| 26 | #include <fcntl.h> | |||
| 27 | #include <string.h> | |||
| 28 | #include <stdlib.h> | |||
| 29 | #include <stddef.h> | |||
| 30 | #include <stdint.h> | |||
| 31 | #include <unistd.h> | |||
| 32 | ||||
| 33 | #ifdef ZLIB1 | |||
| 34 | #include <zlib.h> | |||
| 35 | #endif /* ZLIB */ | |||
| 36 | ||||
| 37 | #include "itype.h" | |||
| 38 | #include "xmalloc.h" | |||
| 39 | #include "hash.h" | |||
| 40 | ||||
| 41 | #define ROUNDUP(x, y)((((x) + (y) - 1) / (y)) * (y)) ((((x) + (y) - 1) / (y)) * (y)) | |||
| 42 | ||||
| 43 | /* | |||
| 44 | * Dynamic buffer, used for content & string table. | |||
| 45 | */ | |||
| 46 | struct dbuf { | |||
| 47 | char *data; /* start data buffer */ | |||
| 48 | size_t size; /* size of the buffer */ | |||
| 49 | ||||
| 50 | char *cptr; /* position in [data, data + size] */ | |||
| 51 | size_t coff; /* number of written bytes */ | |||
| 52 | }; | |||
| 53 | ||||
| 54 | #define DBUF_CHUNKSZ(64 * 1024) (64 * 1024) | |||
| 55 | ||||
| 56 | /* In-memory representation of a CTF section. */ | |||
| 57 | struct imcs { | |||
| 58 | struct dbuf body; | |||
| 59 | struct dbuf stab; /* corresponding string table */ | |||
| 60 | struct hash *htab; /* hash table of known strings */ | |||
| 61 | }; | |||
| 62 | ||||
| 63 | struct strentry { | |||
| 64 | struct hash_entry se_key; /* Must be first */ | |||
| 65 | #define se_strse_key.hkey se_key.hkey | |||
| 66 | size_t se_off; | |||
| 67 | }; | |||
| 68 | ||||
| 69 | #ifdef ZLIB1 | |||
| 70 | char *data_compress(const char *, size_t, off_t, size_t *); | |||
| 71 | #endif /* ZLIB */ | |||
| 72 | ||||
| 73 | void | |||
| 74 | dbuf_realloc(struct dbuf *dbuf, size_t len) | |||
| 75 | { | |||
| 76 | assert(dbuf != NULL)((dbuf != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.bin/ctfconv/generate.c" , 76, __func__, "dbuf != NULL")); | |||
| 77 | assert(len != 0)((len != 0) ? (void)0 : __assert2("/usr/src/usr.bin/ctfconv/generate.c" , 77, __func__, "len != 0")); | |||
| 78 | ||||
| 79 | dbuf->data = xrealloc(dbuf->data, dbuf->size + len); | |||
| 80 | dbuf->size += len; | |||
| 81 | dbuf->cptr = dbuf->data + dbuf->coff; | |||
| 82 | } | |||
| 83 | ||||
| 84 | void | |||
| 85 | dbuf_copy(struct dbuf *dbuf, void const *data, size_t len) | |||
| 86 | { | |||
| 87 | off_t left; | |||
| 88 | ||||
| 89 | assert(dbuf->cptr != NULL)((dbuf->cptr != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.bin/ctfconv/generate.c" , 89, __func__, "dbuf->cptr != NULL")); | |||
| 90 | assert(dbuf->data != NULL)((dbuf->data != ((void*)0)) ? (void)0 : __assert2("/usr/src/usr.bin/ctfconv/generate.c" , 90, __func__, "dbuf->data != NULL")); | |||
| 91 | assert(dbuf->size != 0)((dbuf->size != 0) ? (void)0 : __assert2("/usr/src/usr.bin/ctfconv/generate.c" , 91, __func__, "dbuf->size != 0")); | |||
| 92 | ||||
| 93 | if (len == 0) | |||
| 94 | return; | |||
| 95 | ||||
| 96 | left = dbuf->size - dbuf->coff; | |||
| 97 | if (left < (off_t)len) | |||
| 98 | dbuf_realloc(dbuf, ROUNDUP((len - left), DBUF_CHUNKSZ)(((((len - left)) + ((64 * 1024)) - 1) / ((64 * 1024))) * ((64 * 1024)))); | |||
| 99 | ||||
| 100 | memcpy(dbuf->cptr, data, len); | |||
| 101 | dbuf->cptr += len; | |||
| 102 | dbuf->coff += len; | |||
| 103 | } | |||
| 104 | ||||
| 105 | size_t | |||
| 106 | dbuf_pad(struct dbuf *dbuf, int align) | |||
| 107 | { | |||
| 108 | int i = (align - (dbuf->coff % align)) % align; | |||
| 109 | ||||
| 110 | while (i-- > 0) | |||
| 111 | dbuf_copy(dbuf, "", 1); | |||
| 112 | ||||
| 113 | return dbuf->coff; | |||
| 114 | } | |||
| 115 | ||||
| 116 | size_t | |||
| 117 | imcs_add_string(struct imcs *imcs, const char *str) | |||
| 118 | { | |||
| 119 | struct strentry *se; | |||
| 120 | unsigned int slot; | |||
| 121 | ||||
| 122 | if (str == NULL((void*)0) || *str == '\0') | |||
| 123 | return 0; | |||
| 124 | ||||
| 125 | se = (struct strentry *)hash_find(imcs->htab, str, &slot); | |||
| 126 | if (se == NULL((void*)0)) { | |||
| 127 | se = xmalloc(sizeof(*se)); | |||
| 128 | hash_insert(imcs->htab, slot, &se->se_key, str); | |||
| 129 | se->se_off = imcs->stab.coff; | |||
| 130 | ||||
| 131 | dbuf_copy(&imcs->stab, str, strlen(str) + 1); | |||
| 132 | } | |||
| 133 | ||||
| 134 | return se->se_off; | |||
| 135 | } | |||
| 136 | ||||
| 137 | void | |||
| 138 | imcs_add_func(struct imcs *imcs, struct itype *it) | |||
| 139 | { | |||
| 140 | uint16_t func, arg; | |||
| 141 | struct imember *im; | |||
| 142 | int kind, root, vlen; | |||
| 143 | ||||
| 144 | vlen = it->it_nelems; | |||
| 145 | kind = it->it_type; | |||
| 146 | root = 0; | |||
| 147 | ||||
| 148 | func = (kind << 11) | (root << 10) | (vlen & CTF_MAX_VLEN0x03ff); | |||
| 149 | dbuf_copy(&imcs->body, &func, sizeof(func)); | |||
| 150 | ||||
| 151 | if (kind == CTF_K_UNKNOWN0) | |||
| 152 | return; | |||
| 153 | ||||
| 154 | func = it->it_refp->it_idx; | |||
| 155 | dbuf_copy(&imcs->body, &func, sizeof(func)); | |||
| 156 | ||||
| 157 | TAILQ_FOREACH(im, &it->it_members, im_next)for((im) = ((&it->it_members)->tqh_first); (im) != ( (void*)0); (im) = ((im)->im_next.tqe_next)) { | |||
| 158 | arg = im->im_refp->it_idx; | |||
| 159 | dbuf_copy(&imcs->body, &arg, sizeof(arg)); | |||
| 160 | } | |||
| 161 | } | |||
| 162 | ||||
| 163 | void | |||
| 164 | imcs_add_obj(struct imcs *imcs, struct itype *it) | |||
| 165 | { | |||
| 166 | uint16_t type; | |||
| 167 | ||||
| 168 | type = it->it_refp->it_idx; | |||
| 169 | dbuf_copy(&imcs->body, &type, sizeof(type)); | |||
| 170 | } | |||
| 171 | ||||
| 172 | void | |||
| 173 | imcs_add_type(struct imcs *imcs, struct itype *it) | |||
| 174 | { | |||
| 175 | struct imember *im; | |||
| 176 | struct ctf_type ctt; | |||
| 177 | struct ctf_array cta; | |||
| 178 | unsigned int eob; | |||
| 179 | uint32_t size; | |||
| 180 | uint16_t arg; | |||
| 181 | size_t ctsz; | |||
| 182 | int kind, root, vlen; | |||
| 183 | ||||
| 184 | assert(it->it_type != CTF_K_UNKNOWN && it->it_type != CTF_K_FORWARD)((it->it_type != 0 && it->it_type != 9) ? (void )0 : __assert2("/usr/src/usr.bin/ctfconv/generate.c", 184, __func__ , "it->it_type != CTF_K_UNKNOWN && it->it_type != CTF_K_FORWARD" )); | |||
| 185 | ||||
| 186 | vlen = it->it_nelems; | |||
| 187 | size = it->it_size; | |||
| 188 | kind = it->it_type; | |||
| 189 | root = 0; | |||
| 190 | ||||
| 191 | ctt.ctt_name_ctt_stype.cts_name = imcs_add_string(imcs, it_name(it)); | |||
| 192 | ctt.ctt_info_ctt_stype.cts_info = (kind << 11) | (root << 10) | (vlen & CTF_MAX_VLEN0x03ff); | |||
| 193 | ||||
| 194 | /* Base types don't have reference, typedef & pointer don't have size */ | |||
| 195 | if (it->it_refp != NULL((void*)0) && kind != CTF_K_ARRAY4) { | |||
| 196 | ctt.ctt_type_ctt_stype._ST._type = it->it_refp->it_idx; | |||
| 197 | ctsz = sizeof(struct ctf_stype); | |||
| 198 | } else if (size <= CTF_MAX_SIZE0xfffe) { | |||
| 199 | ctt.ctt_size_ctt_stype._ST._size = size; | |||
| 200 | ctsz = sizeof(struct ctf_stype); | |||
| 201 | } else { | |||
| 202 | ctt.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size)((uint32_t)((uint64_t)(size) >> 32)); | |||
| 203 | ctt.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size)((uint32_t)(size)); | |||
| 204 | ctt.ctt_size_ctt_stype._ST._size = CTF_LSIZE_SENT0xfffe +1; | |||
| 205 | ctsz = sizeof(struct ctf_type); | |||
| 206 | } | |||
| 207 | ||||
| 208 | dbuf_copy(&imcs->body, &ctt, ctsz); | |||
| 209 | ||||
| 210 | switch (kind) { | |||
| 211 | assert(1 == 0)((1 == 0) ? (void)0 : __assert2("/usr/src/usr.bin/ctfconv/generate.c" , 211, __func__, "1 == 0")); | |||
| 212 | break; | |||
| 213 | case CTF_K_INTEGER1: | |||
| 214 | case CTF_K_FLOAT2: | |||
| 215 | eob = CTF_INT_DATA(it->it_enc, 0, size)(((it->it_enc) << 24) | ((0) << 16) | (size)); | |||
| 216 | dbuf_copy(&imcs->body, &eob, sizeof(eob)); | |||
| 217 | break; | |||
| 218 | case CTF_K_ARRAY4: | |||
| 219 | memset(&cta, 0, sizeof(cta)); | |||
| 220 | cta.cta_contents = it->it_refp->it_idx; | |||
| ||||
| 221 | cta.cta_index = long_tidx; | |||
| 222 | cta.cta_nelems = it->it_nelems; | |||
| 223 | dbuf_copy(&imcs->body, &cta, sizeof(cta)); | |||
| 224 | break; | |||
| 225 | case CTF_K_STRUCT6: | |||
| 226 | case CTF_K_UNION7: | |||
| 227 | if (size < CTF_LSTRUCT_THRESH8192) { | |||
| 228 | struct ctf_member ctm; | |||
| 229 | ||||
| 230 | memset(&ctm, 0, sizeof(ctm)); | |||
| 231 | TAILQ_FOREACH(im, &it->it_members, im_next)for((im) = ((&it->it_members)->tqh_first); (im) != ( (void*)0); (im) = ((im)->im_next.tqe_next)) { | |||
| 232 | ctm.ctm_name = | |||
| 233 | imcs_add_string(imcs, im_name(im)); | |||
| 234 | ctm.ctm_type = im->im_refp->it_idx; | |||
| 235 | ctm.ctm_offset = im->im_off; | |||
| 236 | ||||
| 237 | dbuf_copy(&imcs->body, &ctm, sizeof(ctm)); | |||
| 238 | } | |||
| 239 | } else { | |||
| 240 | struct ctf_lmember ctlm; | |||
| 241 | ||||
| 242 | memset(&ctlm, 0, sizeof(ctlm)); | |||
| 243 | TAILQ_FOREACH(im, &it->it_members, im_next)for((im) = ((&it->it_members)->tqh_first); (im) != ( (void*)0); (im) = ((im)->im_next.tqe_next)) { | |||
| 244 | ctlm.ctlm_name_ctlm_member.ctm_name = | |||
| 245 | imcs_add_string(imcs, im_name(im)); | |||
| 246 | ctlm.ctlm_type_ctlm_member.ctm_type = im->im_refp->it_idx; | |||
| 247 | ctlm.ctlm_offsethi = | |||
| 248 | CTF_OFFSET_TO_LMEMHI(im->im_off)((uint32_t)((uint64_t)(im->im_off) >> 32)); | |||
| 249 | ctlm.ctlm_offsetlo = | |||
| 250 | CTF_OFFSET_TO_LMEMLO(im->im_off)((uint32_t)(im->im_off)); | |||
| 251 | ||||
| 252 | ||||
| 253 | dbuf_copy(&imcs->body, &ctlm, sizeof(ctlm)); | |||
| 254 | } | |||
| 255 | } | |||
| 256 | break; | |||
| 257 | case CTF_K_FUNCTION5: | |||
| 258 | TAILQ_FOREACH(im, &it->it_members, im_next)for((im) = ((&it->it_members)->tqh_first); (im) != ( (void*)0); (im) = ((im)->im_next.tqe_next)) { | |||
| 259 | arg = im->im_refp->it_idx; | |||
| 260 | dbuf_copy(&imcs->body, &arg, sizeof(arg)); | |||
| 261 | } | |||
| 262 | if (vlen & 1) { | |||
| 263 | arg = 0; | |||
| 264 | dbuf_copy(&imcs->body, &arg, sizeof(arg)); | |||
| 265 | } | |||
| 266 | break; | |||
| 267 | case CTF_K_ENUM8: | |||
| 268 | TAILQ_FOREACH(im, &it->it_members, im_next)for((im) = ((&it->it_members)->tqh_first); (im) != ( (void*)0); (im) = ((im)->im_next.tqe_next)) { | |||
| 269 | struct ctf_enum cte; | |||
| 270 | ||||
| 271 | cte.cte_name = imcs_add_string(imcs, im_name(im)); | |||
| 272 | cte.cte_value = im->im_ref; | |||
| 273 | ||||
| 274 | dbuf_copy(&imcs->body, &cte, sizeof(cte)); | |||
| 275 | } | |||
| 276 | break; | |||
| 277 | case CTF_K_POINTER3: | |||
| 278 | case CTF_K_TYPEDEF10: | |||
| 279 | case CTF_K_VOLATILE11: | |||
| 280 | case CTF_K_CONST12: | |||
| 281 | case CTF_K_RESTRICT13: | |||
| 282 | default: | |||
| 283 | break; | |||
| 284 | } | |||
| 285 | } | |||
| 286 | ||||
| 287 | void | |||
| 288 | imcs_generate(struct imcs *imcs, struct ctf_header *cth, const char *label) | |||
| 289 | { | |||
| 290 | struct itype *it; | |||
| 291 | struct ctf_lblent lbl; | |||
| 292 | ||||
| 293 | memset(imcs, 0, sizeof(*imcs)); | |||
| 294 | ||||
| 295 | dbuf_realloc(&imcs->body, DBUF_CHUNKSZ(64 * 1024)); | |||
| 296 | dbuf_realloc(&imcs->stab, DBUF_CHUNKSZ(64 * 1024)); | |||
| 297 | ||||
| 298 | imcs->htab = hash_init(10); | |||
| 299 | if (imcs->htab == NULL((void*)0)) | |||
| 300 | err(1, "hash_init"); | |||
| 301 | ||||
| 302 | /* Add empty string */ | |||
| 303 | dbuf_copy(&imcs->stab, "", 1); | |||
| 304 | ||||
| 305 | /* We don't use parent label */ | |||
| 306 | cth->cth_parlabel = 0; | |||
| 307 | cth->cth_parname = 0; | |||
| 308 | ||||
| 309 | /* Insert a single label for all types. */ | |||
| 310 | cth->cth_lbloff = 0; | |||
| 311 | lbl.ctl_label = imcs_add_string(imcs, label); | |||
| 312 | lbl.ctl_typeidx = tidx; | |||
| 313 | dbuf_copy(&imcs->body, &lbl, sizeof(lbl)); | |||
| 314 | ||||
| 315 | /* Insert objects */ | |||
| 316 | cth->cth_objtoff = dbuf_pad(&imcs->body, 2); | |||
| 317 | TAILQ_FOREACH(it, &iobjq, it_symb)for((it) = ((&iobjq)->tqh_first); (it) != ((void*)0); ( it) = ((it)->it_symb.tqe_next)) | |||
| 318 | imcs_add_obj(imcs, it); | |||
| 319 | ||||
| 320 | /* Insert functions */ | |||
| 321 | cth->cth_funcoff = dbuf_pad(&imcs->body, 2); | |||
| 322 | TAILQ_FOREACH(it, &ifuncq, it_symb)for((it) = ((&ifuncq)->tqh_first); (it) != ((void*)0); (it) = ((it)->it_symb.tqe_next)) | |||
| 323 | imcs_add_func(imcs, it); | |||
| 324 | ||||
| 325 | /* Insert types */ | |||
| 326 | cth->cth_typeoff = dbuf_pad(&imcs->body, 4); | |||
| 327 | TAILQ_FOREACH(it, &itypeq, it_next)for((it) = ((&itypeq)->tqh_first); (it) != ((void*)0); (it) = ((it)->it_next.tqe_next)) { | |||
| 328 | if (it->it_flags & (ITF_FUNC0x04|ITF_OBJ0x08)) | |||
| 329 | continue; | |||
| 330 | ||||
| 331 | imcs_add_type(imcs, it); | |||
| 332 | } | |||
| 333 | ||||
| 334 | /* String table is written from its own buffer. */ | |||
| 335 | cth->cth_stroff = imcs->body.coff; | |||
| 336 | cth->cth_strlen = imcs->stab.coff; | |||
| 337 | } | |||
| 338 | ||||
| 339 | /* | |||
| 340 | * Generate a CTF buffer from the internal type representation. | |||
| 341 | */ | |||
| 342 | int | |||
| 343 | generate(const char *path, const char *label, int compress) | |||
| 344 | { | |||
| 345 | char *p, *ctfdata = NULL((void*)0); | |||
| 346 | ssize_t ctflen; | |||
| 347 | struct ctf_header cth; | |||
| 348 | struct imcs imcs; | |||
| 349 | int error = 0, fd; | |||
| 350 | ||||
| 351 | memset(&cth, 0, sizeof(cth)); | |||
| 352 | ||||
| 353 | cth.cth_magic = CTF_MAGIC0xcff1; | |||
| 354 | cth.cth_version = CTF_VERSION2; | |||
| 355 | ||||
| 356 | #ifdef ZLIB1 | |||
| 357 | if (compress) | |||
| ||||
| 358 | cth.cth_flags = CTF_F_COMPRESS(1 << 0); | |||
| 359 | #endif /* ZLIB */ | |||
| 360 | ||||
| 361 | imcs_generate(&imcs, &cth, label); | |||
| 362 | ||||
| 363 | ctflen = sizeof(cth) + imcs.body.coff + imcs.stab.coff; | |||
| 364 | p = ctfdata = xmalloc(ctflen); | |||
| 365 | ||||
| 366 | memcpy(p, &cth, sizeof(cth)); | |||
| 367 | p += sizeof(cth); | |||
| 368 | ||||
| 369 | memcpy(p, imcs.body.data, imcs.body.coff); | |||
| 370 | p += imcs.body.coff; | |||
| 371 | ||||
| 372 | memcpy(p, imcs.stab.data, imcs.stab.coff); | |||
| 373 | p += imcs.stab.coff; | |||
| 374 | ||||
| 375 | assert((p - ctfdata) == ctflen)(((p - ctfdata) == ctflen) ? (void)0 : __assert2("/usr/src/usr.bin/ctfconv/generate.c" , 375, __func__, "(p - ctfdata) == ctflen")); | |||
| 376 | ||||
| 377 | #ifdef ZLIB1 | |||
| 378 | if (compress) { | |||
| 379 | char *cdata; | |||
| 380 | size_t clen; | |||
| 381 | ||||
| 382 | cdata = data_compress(ctfdata + sizeof(cth), | |||
| 383 | ctflen - sizeof(cth), ctflen - sizeof(cth), &clen); | |||
| 384 | if (cdata == NULL((void*)0)) { | |||
| 385 | warnx("compressing CTF data"); | |||
| 386 | free(ctfdata); | |||
| 387 | return -1; | |||
| 388 | } | |||
| 389 | ||||
| 390 | memcpy(ctfdata + sizeof(cth), cdata, clen); | |||
| 391 | ctflen = clen + sizeof(cth); | |||
| 392 | ||||
| 393 | free(cdata); | |||
| 394 | } | |||
| 395 | #endif /* ZLIB */ | |||
| 396 | ||||
| 397 | fd = open(path, O_WRONLY0x0001 | O_CREAT0x0200 | O_TRUNC0x0400, 0644); | |||
| 398 | if (fd == -1) { | |||
| 399 | warn("open %s", path); | |||
| 400 | free(ctfdata); | |||
| 401 | return -1; | |||
| 402 | } | |||
| 403 | ||||
| 404 | if (write(fd, ctfdata, ctflen) != ctflen) { | |||
| 405 | warn("unable to write %zd bytes for %s", ctflen, path); | |||
| 406 | error = -1; | |||
| 407 | } | |||
| 408 | ||||
| 409 | close(fd); | |||
| 410 | free(ctfdata); | |||
| 411 | return error; | |||
| 412 | } | |||
| 413 | ||||
| 414 | #ifdef ZLIB1 | |||
| 415 | char * | |||
| 416 | data_compress(const char *buf, size_t size, off_t len, size_t *pclen) | |||
| 417 | { | |||
| 418 | z_stream stream; | |||
| 419 | char *data; | |||
| 420 | int error; | |||
| 421 | ||||
| 422 | data = malloc(len); | |||
| 423 | if (data == NULL((void*)0)) { | |||
| 424 | warn(NULL((void*)0)); | |||
| 425 | return NULL((void*)0); | |||
| 426 | } | |||
| 427 | ||||
| 428 | memset(&stream, 0, sizeof(stream)); | |||
| 429 | stream.zalloc = Z_NULL0; | |||
| 430 | stream.zfree = Z_NULL0; | |||
| 431 | stream.opaque = Z_NULL0; | |||
| 432 | ||||
| 433 | if ((error = deflateInit(&stream, Z_BEST_COMPRESSION)deflateInit_((&stream), (9), "1.2.11", (int)sizeof(z_stream ))) != Z_OK0) { | |||
| 434 | warnx("zlib deflateInit failed: %s", zError(error)); | |||
| 435 | goto exit; | |||
| 436 | } | |||
| 437 | ||||
| 438 | stream.next_in = (void *)buf; | |||
| 439 | stream.avail_in = size; | |||
| 440 | stream.next_out = (unsigned char *)data; | |||
| 441 | stream.avail_out = len; | |||
| 442 | ||||
| 443 | if ((error = deflate(&stream, Z_FINISH4)) != Z_STREAM_END1) { | |||
| 444 | warnx("zlib deflate failed: %s", zError(error)); | |||
| 445 | deflateEnd(&stream); | |||
| 446 | goto exit; | |||
| 447 | } | |||
| 448 | ||||
| 449 | if ((error = deflateEnd(&stream)) != Z_OK0) { | |||
| 450 | warnx("zlib deflateEnd failed: %s", zError(error)); | |||
| 451 | goto exit; | |||
| 452 | } | |||
| 453 | ||||
| 454 | if (pclen != NULL((void*)0)) | |||
| 455 | *pclen = stream.total_out; | |||
| 456 | ||||
| 457 | return data; | |||
| 458 | ||||
| 459 | exit: | |||
| 460 | free(data); | |||
| 461 | return NULL((void*)0); | |||
| 462 | } | |||
| 463 | #endif /* ZLIB */ |