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