1/* $Id$ */ 2 3/*** 4 This file is part of avahi. 5 6 avahi is free software; you can redistribute it and/or modify it 7 under the terms of the GNU Lesser General Public License as 8 published by the Free Software Foundation; either version 2.1 of the 9 License, or (at your option) any later version. 10 11 avahi is distributed in the hope that it will be useful, but WITHOUT 12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General 14 Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with avahi; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 19 USA. 20***/ 21 22#ifdef HAVE_CONFIG_H 23#include <config.h> 24#endif 25 26#include <stdlib.h> 27#include <string.h> 28#include <assert.h> 29#include <stdio.h> 30#include <unistd.h> 31 32#include "malloc.h" 33 34#ifndef va_copy 35#ifdef __va_copy 36#define va_copy(DEST,SRC) __va_copy((DEST),(SRC)) 37#else 38#define va_copy(DEST,SRC) memcpy(&(DEST), &(SRC), sizeof(va_list)) 39#endif 40#endif 41 42static const AvahiAllocator *allocator = NULL; 43 44static void oom(void) AVAHI_GCC_NORETURN; 45 46static void oom(void) { 47 48 static const char msg[] = "Out of memory, aborting ...\n"; 49 const char *n = msg; 50 51 while (strlen(n) > 0) { 52 ssize_t r; 53 54 if ((r = write(2, n, strlen(n))) < 0) 55 break; 56 57 n += r; 58 } 59 60 abort(); 61} 62 63/* Default implementation for avahi_malloc() */ 64static void* xmalloc(size_t size) { 65 void *p; 66 67 if (size == 0) 68 return NULL; 69 70 if (!(p = malloc(size))) 71 oom(); 72 73 return p; 74} 75 76/* Default implementation for avahi_realloc() */ 77static void *xrealloc(void *p, size_t size) { 78 79 if (size == 0) { 80 free(p); 81 return NULL; 82 } 83 84 if (!(p = realloc(p, size))) 85 oom(); 86 87 return p; 88} 89 90/* Default implementation for avahi_calloc() */ 91static void *xcalloc(size_t nmemb, size_t size) { 92 void *p; 93 94 if (size == 0 || nmemb == 0) 95 return NULL; 96 97 if (!(p = calloc(nmemb, size))) 98 oom(); 99 100 return p; 101} 102 103void *avahi_malloc(size_t size) { 104 105 if (size <= 0) 106 return NULL; 107 108 if (!allocator) 109 return xmalloc(size); 110 111 assert(allocator->malloc); 112 return allocator->malloc(size); 113} 114 115void *avahi_malloc0(size_t size) { 116 void *p; 117 118 if (size <= 0) 119 return NULL; 120 121 if (!allocator) 122 return xcalloc(1, size); 123 124 if (allocator->calloc) 125 return allocator->calloc(1, size); 126 127 assert(allocator->malloc); 128 if ((p = allocator->malloc(size))) 129 memset(p, 0, size); 130 131 return p; 132} 133 134void avahi_free(void *p) { 135 136 if (!p) 137 return; 138 139 if (!allocator) { 140 free(p); 141 return; 142 } 143 144 assert(allocator->free); 145 allocator->free(p); 146} 147 148void *avahi_realloc(void *p, size_t size) { 149 150 if (size == 0) { 151 avahi_free(p); 152 return NULL; 153 } 154 155 if (!allocator) 156 return xrealloc(p, size); 157 158 assert(allocator->realloc); 159 return allocator->realloc(p, size); 160} 161 162char *avahi_strdup(const char *s) { 163 char *r; 164 size_t size; 165 166 if (!s) 167 return NULL; 168 169 size = strlen(s); 170 if (!(r = avahi_malloc(size+1))) 171 return NULL; 172 173 memcpy(r, s, size+1); 174 return r; 175} 176 177char *avahi_strndup(const char *s, size_t max) { 178 char *r; 179 size_t size; 180 const char *p; 181 182 if (!s) 183 return NULL; 184 185 for (p = s, size = 0; 186 size < max && *p; 187 p++, size++); 188 189 if (!(r = avahi_new(char, size+1))) 190 return NULL; 191 192 memcpy(r, s, size); 193 r[size] = 0; 194 return r; 195} 196 197/* Change the allocator */ 198void avahi_set_allocator(const AvahiAllocator *a) { 199 allocator = a; 200} 201 202char *avahi_strdup_vprintf(const char *fmt, va_list ap) { 203 size_t len = 80; 204 char *buf; 205 206 assert(fmt); 207 208 if (!(buf = avahi_malloc(len))) 209 return NULL; 210 211 for (;;) { 212 int n; 213 char *nbuf; 214 va_list ap2; 215 216 va_copy (ap2, ap); 217 n = vsnprintf(buf, len, fmt, ap2); 218 va_end (ap2); 219 220 if (n >= 0 && n < (int) len) 221 return buf; 222 223 if (n >= 0) 224 len = n+1; 225 else 226 len *= 2; 227 228 if (!(nbuf = avahi_realloc(buf, len))) { 229 avahi_free(buf); 230 return NULL; 231 } 232 233 buf = nbuf; 234 } 235} 236 237char *avahi_strdup_printf(const char *fmt, ... ) { 238 char *s; 239 va_list ap; 240 241 assert(fmt); 242 243 va_start(ap, fmt); 244 s = avahi_strdup_vprintf(fmt, ap); 245 va_end(ap); 246 247 return s; 248} 249 250void *avahi_memdup(const void *s, size_t l) { 251 void *p; 252 assert(s); 253 254 if (!(p = avahi_malloc(l))) 255 return NULL; 256 257 memcpy(p, s, l); 258 return p; 259} 260