[164] | 1 | /***************************************************************************
|
---|
| 2 | * _ _ ____ _
|
---|
| 3 | * Project ___| | | | _ \| |
|
---|
| 4 | * / __| | | | |_) | |
|
---|
| 5 | * | (__| |_| | _ <| |___
|
---|
| 6 | * \___|\___/|_| \_\_____|
|
---|
| 7 | *
|
---|
| 8 | * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
|
---|
| 9 | *
|
---|
| 10 | * This software is licensed as described in the file COPYING, which
|
---|
| 11 | * you should have received as part of this distribution. The terms
|
---|
| 12 | * are also available at https://curl.haxx.se/docs/copyright.html.
|
---|
| 13 | *
|
---|
| 14 | * You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
---|
| 15 | * copies of the Software, and permit persons to whom the Software is
|
---|
| 16 | * furnished to do so, under the terms of the COPYING file.
|
---|
| 17 | *
|
---|
| 18 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
---|
| 19 | * KIND, either express or implied.
|
---|
| 20 | *
|
---|
| 21 | ***************************************************************************/
|
---|
| 22 |
|
---|
| 23 | #include "curl_setup.h"
|
---|
| 24 |
|
---|
| 25 | #ifdef CURLDEBUG
|
---|
| 26 |
|
---|
| 27 | #include <curl/curl.h>
|
---|
| 28 |
|
---|
| 29 | #include "curl_printf.h"
|
---|
| 30 | #include "urldata.h"
|
---|
| 31 |
|
---|
| 32 | #define MEMDEBUG_NODEFINES /* don't redefine the standard functions */
|
---|
| 33 | #include "curl_memory.h"
|
---|
| 34 | #include "memdebug.h"
|
---|
| 35 |
|
---|
| 36 | #ifndef HAVE_ASSERT_H
|
---|
| 37 | # define assert(x) Curl_nop_stmt
|
---|
| 38 | #endif
|
---|
| 39 |
|
---|
| 40 | /*
|
---|
| 41 | * Until 2011-08-17 libcurl's Memory Tracking feature also performed
|
---|
| 42 | * automatic malloc and free filling operations using 0xA5 and 0x13
|
---|
| 43 | * values. Our own preinitialization of dynamically allocated memory
|
---|
| 44 | * might be useful when not using third party memory debuggers, but
|
---|
| 45 | * on the other hand this would fool memory debuggers into thinking
|
---|
| 46 | * that all dynamically allocated memory is properly initialized.
|
---|
| 47 | *
|
---|
| 48 | * As a default setting, libcurl's Memory Tracking feature no longer
|
---|
| 49 | * performs preinitialization of dynamically allocated memory on its
|
---|
| 50 | * own. If you know what you are doing, and really want to retain old
|
---|
| 51 | * behavior, you can achieve this compiling with preprocessor symbols
|
---|
| 52 | * CURL_MT_MALLOC_FILL and CURL_MT_FREE_FILL defined with appropriate
|
---|
| 53 | * values.
|
---|
| 54 | */
|
---|
| 55 |
|
---|
| 56 | #ifdef CURL_MT_MALLOC_FILL
|
---|
| 57 | # if (CURL_MT_MALLOC_FILL < 0) || (CURL_MT_MALLOC_FILL > 0xff)
|
---|
| 58 | # error "invalid CURL_MT_MALLOC_FILL or out of range"
|
---|
| 59 | # endif
|
---|
| 60 | #endif
|
---|
| 61 |
|
---|
| 62 | #ifdef CURL_MT_FREE_FILL
|
---|
| 63 | # if (CURL_MT_FREE_FILL < 0) || (CURL_MT_FREE_FILL > 0xff)
|
---|
| 64 | # error "invalid CURL_MT_FREE_FILL or out of range"
|
---|
| 65 | # endif
|
---|
| 66 | #endif
|
---|
| 67 |
|
---|
| 68 | #if defined(CURL_MT_MALLOC_FILL) && defined(CURL_MT_FREE_FILL)
|
---|
| 69 | # if (CURL_MT_MALLOC_FILL == CURL_MT_FREE_FILL)
|
---|
| 70 | # error "CURL_MT_MALLOC_FILL same as CURL_MT_FREE_FILL"
|
---|
| 71 | # endif
|
---|
| 72 | #endif
|
---|
| 73 |
|
---|
| 74 | #ifdef CURL_MT_MALLOC_FILL
|
---|
| 75 | # define mt_malloc_fill(buf,len) memset((buf), CURL_MT_MALLOC_FILL, (len))
|
---|
| 76 | #else
|
---|
| 77 | # define mt_malloc_fill(buf,len) Curl_nop_stmt
|
---|
| 78 | #endif
|
---|
| 79 |
|
---|
| 80 | #ifdef CURL_MT_FREE_FILL
|
---|
| 81 | # define mt_free_fill(buf,len) memset((buf), CURL_MT_FREE_FILL, (len))
|
---|
| 82 | #else
|
---|
| 83 | # define mt_free_fill(buf,len) Curl_nop_stmt
|
---|
| 84 | #endif
|
---|
| 85 |
|
---|
| 86 | struct memdebug {
|
---|
| 87 | size_t size;
|
---|
| 88 | union {
|
---|
| 89 | curl_off_t o;
|
---|
| 90 | double d;
|
---|
| 91 | void * p;
|
---|
| 92 | } mem[1];
|
---|
| 93 | /* I'm hoping this is the thing with the strictest alignment
|
---|
| 94 | * requirements. That also means we waste some space :-( */
|
---|
| 95 | };
|
---|
| 96 |
|
---|
| 97 | /*
|
---|
| 98 | * Note that these debug functions are very simple and they are meant to
|
---|
| 99 | * remain so. For advanced analysis, record a log file and write perl scripts
|
---|
| 100 | * to analyze them!
|
---|
| 101 | *
|
---|
| 102 | * Don't use these with multithreaded test programs!
|
---|
| 103 | */
|
---|
| 104 |
|
---|
| 105 | #define logfile curl_debuglogfile
|
---|
| 106 | FILE *curl_debuglogfile = NULL;
|
---|
| 107 | static bool memlimit = FALSE; /* enable memory limit */
|
---|
| 108 | static long memsize = 0; /* set number of mallocs allowed */
|
---|
| 109 |
|
---|
| 110 | /* this sets the log file name */
|
---|
| 111 | void curl_memdebug(const char *logname)
|
---|
| 112 | {
|
---|
| 113 | if(!logfile) {
|
---|
| 114 | if(logname && *logname)
|
---|
| 115 | logfile = fopen(logname, FOPEN_WRITETEXT);
|
---|
| 116 | else
|
---|
| 117 | logfile = stderr;
|
---|
| 118 | #ifdef MEMDEBUG_LOG_SYNC
|
---|
| 119 | /* Flush the log file after every line so the log isn't lost in a crash */
|
---|
| 120 | setvbuf(logfile, (char *)NULL, _IOLBF, 0);
|
---|
| 121 | #endif
|
---|
| 122 | }
|
---|
| 123 | }
|
---|
| 124 |
|
---|
| 125 | /* This function sets the number of malloc() calls that should return
|
---|
| 126 | successfully! */
|
---|
| 127 | void curl_memlimit(long limit)
|
---|
| 128 | {
|
---|
| 129 | if(!memlimit) {
|
---|
| 130 | memlimit = TRUE;
|
---|
| 131 | memsize = limit;
|
---|
| 132 | }
|
---|
| 133 | }
|
---|
| 134 |
|
---|
| 135 | /* returns TRUE if this isn't allowed! */
|
---|
| 136 | static bool countcheck(const char *func, int line, const char *source)
|
---|
| 137 | {
|
---|
| 138 | /* if source is NULL, then the call is made internally and this check
|
---|
| 139 | should not be made */
|
---|
| 140 | if(memlimit && source) {
|
---|
| 141 | if(!memsize) {
|
---|
| 142 | if(source) {
|
---|
| 143 | /* log to file */
|
---|
| 144 | curl_memlog("LIMIT %s:%d %s reached memlimit\n",
|
---|
| 145 | source, line, func);
|
---|
| 146 | /* log to stderr also */
|
---|
| 147 | fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
|
---|
| 148 | source, line, func);
|
---|
| 149 | }
|
---|
| 150 | SET_ERRNO(ENOMEM);
|
---|
| 151 | return TRUE; /* RETURN ERROR! */
|
---|
| 152 | }
|
---|
| 153 | else
|
---|
| 154 | memsize--; /* countdown */
|
---|
| 155 |
|
---|
| 156 | /* log the countdown */
|
---|
| 157 | if(source)
|
---|
| 158 | curl_memlog("LIMIT %s:%d %ld ALLOCS left\n",
|
---|
| 159 | source, line, memsize);
|
---|
| 160 |
|
---|
| 161 | }
|
---|
| 162 |
|
---|
| 163 | return FALSE; /* allow this */
|
---|
| 164 | }
|
---|
| 165 |
|
---|
| 166 | void *curl_domalloc(size_t wantedsize, int line, const char *source)
|
---|
| 167 | {
|
---|
| 168 | struct memdebug *mem;
|
---|
| 169 | size_t size;
|
---|
| 170 |
|
---|
| 171 | assert(wantedsize != 0);
|
---|
| 172 |
|
---|
| 173 | if(countcheck("malloc", line, source))
|
---|
| 174 | return NULL;
|
---|
| 175 |
|
---|
| 176 | /* alloc at least 64 bytes */
|
---|
| 177 | size = sizeof(struct memdebug)+wantedsize;
|
---|
| 178 |
|
---|
| 179 | mem = (Curl_cmalloc)(size);
|
---|
| 180 | if(mem) {
|
---|
| 181 | /* fill memory with junk */
|
---|
| 182 | mt_malloc_fill(mem->mem, wantedsize);
|
---|
| 183 | mem->size = wantedsize;
|
---|
| 184 | }
|
---|
| 185 |
|
---|
| 186 | if(source)
|
---|
| 187 | curl_memlog("MEM %s:%d malloc(%zu) = %p\n",
|
---|
| 188 | source, line, wantedsize,
|
---|
| 189 | mem ? (void *)mem->mem : (void *)0);
|
---|
| 190 |
|
---|
| 191 | return (mem ? mem->mem : NULL);
|
---|
| 192 | }
|
---|
| 193 |
|
---|
| 194 | void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
|
---|
| 195 | int line, const char *source)
|
---|
| 196 | {
|
---|
| 197 | struct memdebug *mem;
|
---|
| 198 | size_t size, user_size;
|
---|
| 199 |
|
---|
| 200 | assert(wanted_elements != 0);
|
---|
| 201 | assert(wanted_size != 0);
|
---|
| 202 |
|
---|
| 203 | if(countcheck("calloc", line, source))
|
---|
| 204 | return NULL;
|
---|
| 205 |
|
---|
| 206 | /* alloc at least 64 bytes */
|
---|
| 207 | user_size = wanted_size * wanted_elements;
|
---|
| 208 | size = sizeof(struct memdebug) + user_size;
|
---|
| 209 |
|
---|
| 210 | mem = (Curl_ccalloc)(1, size);
|
---|
| 211 | if(mem)
|
---|
| 212 | mem->size = user_size;
|
---|
| 213 |
|
---|
| 214 | if(source)
|
---|
| 215 | curl_memlog("MEM %s:%d calloc(%zu,%zu) = %p\n",
|
---|
| 216 | source, line, wanted_elements, wanted_size,
|
---|
| 217 | mem ? (void *)mem->mem : (void *)0);
|
---|
| 218 |
|
---|
| 219 | return (mem ? mem->mem : NULL);
|
---|
| 220 | }
|
---|
| 221 |
|
---|
| 222 | char *curl_dostrdup(const char *str, int line, const char *source)
|
---|
| 223 | {
|
---|
| 224 | char *mem;
|
---|
| 225 | size_t len;
|
---|
| 226 |
|
---|
| 227 | assert(str != NULL);
|
---|
| 228 |
|
---|
| 229 | if(countcheck("strdup", line, source))
|
---|
| 230 | return NULL;
|
---|
| 231 |
|
---|
| 232 | len=strlen(str)+1;
|
---|
| 233 |
|
---|
| 234 | mem=curl_domalloc(len, 0, NULL); /* NULL prevents logging */
|
---|
| 235 | if(mem)
|
---|
| 236 | memcpy(mem, str, len);
|
---|
| 237 |
|
---|
| 238 | if(source)
|
---|
| 239 | curl_memlog("MEM %s:%d strdup(%p) (%zu) = %p\n",
|
---|
| 240 | source, line, (void *)str, len, (void *)mem);
|
---|
| 241 |
|
---|
| 242 | return mem;
|
---|
| 243 | }
|
---|
| 244 |
|
---|
| 245 | #if defined(WIN32) && defined(UNICODE)
|
---|
| 246 | wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
|
---|
| 247 | {
|
---|
| 248 | wchar_t *mem;
|
---|
| 249 | size_t wsiz, bsiz;
|
---|
| 250 |
|
---|
| 251 | assert(str != NULL);
|
---|
| 252 |
|
---|
| 253 | if(countcheck("wcsdup", line, source))
|
---|
| 254 | return NULL;
|
---|
| 255 |
|
---|
| 256 | wsiz = wcslen(str) + 1;
|
---|
| 257 | bsiz = wsiz * sizeof(wchar_t);
|
---|
| 258 |
|
---|
| 259 | mem = curl_domalloc(bsiz, 0, NULL); /* NULL prevents logging */
|
---|
| 260 | if(mem)
|
---|
| 261 | memcpy(mem, str, bsiz);
|
---|
| 262 |
|
---|
| 263 | if(source)
|
---|
| 264 | curl_memlog("MEM %s:%d wcsdup(%p) (%zu) = %p\n",
|
---|
| 265 | source, line, (void *)str, bsiz, (void *)mem);
|
---|
| 266 |
|
---|
| 267 | return mem;
|
---|
| 268 | }
|
---|
| 269 | #endif
|
---|
| 270 |
|
---|
| 271 | /* We provide a realloc() that accepts a NULL as pointer, which then
|
---|
| 272 | performs a malloc(). In order to work with ares. */
|
---|
| 273 | void *curl_dorealloc(void *ptr, size_t wantedsize,
|
---|
| 274 | int line, const char *source)
|
---|
| 275 | {
|
---|
| 276 | struct memdebug *mem=NULL;
|
---|
| 277 |
|
---|
| 278 | size_t size = sizeof(struct memdebug)+wantedsize;
|
---|
| 279 |
|
---|
| 280 | assert(wantedsize != 0);
|
---|
| 281 |
|
---|
| 282 | if(countcheck("realloc", line, source))
|
---|
| 283 | return NULL;
|
---|
| 284 |
|
---|
| 285 | #ifdef __INTEL_COMPILER
|
---|
| 286 | # pragma warning(push)
|
---|
| 287 | # pragma warning(disable:1684)
|
---|
| 288 | /* 1684: conversion from pointer to same-sized integral type */
|
---|
| 289 | #endif
|
---|
| 290 |
|
---|
| 291 | if(ptr)
|
---|
| 292 | mem = (void *)((char *)ptr - offsetof(struct memdebug, mem));
|
---|
| 293 |
|
---|
| 294 | #ifdef __INTEL_COMPILER
|
---|
| 295 | # pragma warning(pop)
|
---|
| 296 | #endif
|
---|
| 297 |
|
---|
| 298 | mem = (Curl_crealloc)(mem, size);
|
---|
| 299 | if(source)
|
---|
| 300 | curl_memlog("MEM %s:%d realloc(%p, %zu) = %p\n",
|
---|
| 301 | source, line, (void *)ptr, wantedsize,
|
---|
| 302 | mem ? (void *)mem->mem : (void *)0);
|
---|
| 303 |
|
---|
| 304 | if(mem) {
|
---|
| 305 | mem->size = wantedsize;
|
---|
| 306 | return mem->mem;
|
---|
| 307 | }
|
---|
| 308 |
|
---|
| 309 | return NULL;
|
---|
| 310 | }
|
---|
| 311 |
|
---|
| 312 | void curl_dofree(void *ptr, int line, const char *source)
|
---|
| 313 | {
|
---|
| 314 | struct memdebug *mem;
|
---|
| 315 |
|
---|
| 316 | if(ptr) {
|
---|
| 317 |
|
---|
| 318 | #ifdef __INTEL_COMPILER
|
---|
| 319 | # pragma warning(push)
|
---|
| 320 | # pragma warning(disable:1684)
|
---|
| 321 | /* 1684: conversion from pointer to same-sized integral type */
|
---|
| 322 | #endif
|
---|
| 323 |
|
---|
| 324 | mem = (void *)((char *)ptr - offsetof(struct memdebug, mem));
|
---|
| 325 |
|
---|
| 326 | #ifdef __INTEL_COMPILER
|
---|
| 327 | # pragma warning(pop)
|
---|
| 328 | #endif
|
---|
| 329 |
|
---|
| 330 | /* destroy */
|
---|
| 331 | mt_free_fill(mem->mem, mem->size);
|
---|
| 332 |
|
---|
| 333 | /* free for real */
|
---|
| 334 | (Curl_cfree)(mem);
|
---|
| 335 | }
|
---|
| 336 |
|
---|
| 337 | if(source)
|
---|
| 338 | curl_memlog("MEM %s:%d free(%p)\n", source, line, (void *)ptr);
|
---|
| 339 | }
|
---|
| 340 |
|
---|
| 341 | curl_socket_t curl_socket(int domain, int type, int protocol,
|
---|
| 342 | int line, const char *source)
|
---|
| 343 | {
|
---|
| 344 | const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
|
---|
| 345 | "FD %s:%d socket() = %d\n" :
|
---|
| 346 | (sizeof(curl_socket_t) == sizeof(long)) ?
|
---|
| 347 | "FD %s:%d socket() = %ld\n" :
|
---|
| 348 | "FD %s:%d socket() = %zd\n";
|
---|
| 349 |
|
---|
| 350 | curl_socket_t sockfd = socket(domain, type, protocol);
|
---|
| 351 |
|
---|
| 352 | if(source && (sockfd != CURL_SOCKET_BAD))
|
---|
| 353 | curl_memlog(fmt, source, line, sockfd);
|
---|
| 354 |
|
---|
| 355 | return sockfd;
|
---|
| 356 | }
|
---|
| 357 |
|
---|
| 358 | #ifdef HAVE_SOCKETPAIR
|
---|
| 359 | int curl_socketpair(int domain, int type, int protocol,
|
---|
| 360 | curl_socket_t socket_vector[2],
|
---|
| 361 | int line, const char *source)
|
---|
| 362 | {
|
---|
| 363 | const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
|
---|
| 364 | "FD %s:%d socketpair() = %d %d\n" :
|
---|
| 365 | (sizeof(curl_socket_t) == sizeof(long)) ?
|
---|
| 366 | "FD %s:%d socketpair() = %ld %ld\n" :
|
---|
| 367 | "FD %s:%d socketpair() = %zd %zd\n";
|
---|
| 368 |
|
---|
| 369 | int res = socketpair(domain, type, protocol, socket_vector);
|
---|
| 370 |
|
---|
| 371 | if(source && (0 == res))
|
---|
| 372 | curl_memlog(fmt, source, line, socket_vector[0], socket_vector[1]);
|
---|
| 373 |
|
---|
| 374 | return res;
|
---|
| 375 | }
|
---|
| 376 | #endif
|
---|
| 377 |
|
---|
| 378 | curl_socket_t curl_accept(curl_socket_t s, void *saddr, void *saddrlen,
|
---|
| 379 | int line, const char *source)
|
---|
| 380 | {
|
---|
| 381 | const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
|
---|
| 382 | "FD %s:%d accept() = %d\n" :
|
---|
| 383 | (sizeof(curl_socket_t) == sizeof(long)) ?
|
---|
| 384 | "FD %s:%d accept() = %ld\n" :
|
---|
| 385 | "FD %s:%d accept() = %zd\n";
|
---|
| 386 |
|
---|
| 387 | struct sockaddr *addr = (struct sockaddr *)saddr;
|
---|
| 388 | curl_socklen_t *addrlen = (curl_socklen_t *)saddrlen;
|
---|
| 389 |
|
---|
| 390 | curl_socket_t sockfd = accept(s, addr, addrlen);
|
---|
| 391 |
|
---|
| 392 | if(source && (sockfd != CURL_SOCKET_BAD))
|
---|
| 393 | curl_memlog(fmt, source, line, sockfd);
|
---|
| 394 |
|
---|
| 395 | return sockfd;
|
---|
| 396 | }
|
---|
| 397 |
|
---|
| 398 | /* separate function to allow libcurl to mark a "faked" close */
|
---|
| 399 | void curl_mark_sclose(curl_socket_t sockfd, int line, const char *source)
|
---|
| 400 | {
|
---|
| 401 | const char *fmt = (sizeof(curl_socket_t) == sizeof(int)) ?
|
---|
| 402 | "FD %s:%d sclose(%d)\n":
|
---|
| 403 | (sizeof(curl_socket_t) == sizeof(long)) ?
|
---|
| 404 | "FD %s:%d sclose(%ld)\n":
|
---|
| 405 | "FD %s:%d sclose(%zd)\n";
|
---|
| 406 |
|
---|
| 407 | if(source)
|
---|
| 408 | curl_memlog(fmt, source, line, sockfd);
|
---|
| 409 | }
|
---|
| 410 |
|
---|
| 411 | /* this is our own defined way to close sockets on *ALL* platforms */
|
---|
| 412 | int curl_sclose(curl_socket_t sockfd, int line, const char *source)
|
---|
| 413 | {
|
---|
| 414 | int res=sclose(sockfd);
|
---|
| 415 | curl_mark_sclose(sockfd, line, source);
|
---|
| 416 | return res;
|
---|
| 417 | }
|
---|
| 418 |
|
---|
| 419 | FILE *curl_fopen(const char *file, const char *mode,
|
---|
| 420 | int line, const char *source)
|
---|
| 421 | {
|
---|
| 422 | FILE *res=fopen(file, mode);
|
---|
| 423 |
|
---|
| 424 | if(source)
|
---|
| 425 | curl_memlog("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
|
---|
| 426 | source, line, file, mode, (void *)res);
|
---|
| 427 |
|
---|
| 428 | return res;
|
---|
| 429 | }
|
---|
| 430 |
|
---|
| 431 | #ifdef HAVE_FDOPEN
|
---|
| 432 | FILE *curl_fdopen(int filedes, const char *mode,
|
---|
| 433 | int line, const char *source)
|
---|
| 434 | {
|
---|
| 435 | FILE *res=fdopen(filedes, mode);
|
---|
| 436 |
|
---|
| 437 | if(source)
|
---|
| 438 | curl_memlog("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n",
|
---|
| 439 | source, line, filedes, mode, (void *)res);
|
---|
| 440 |
|
---|
| 441 | return res;
|
---|
| 442 | }
|
---|
| 443 | #endif
|
---|
| 444 |
|
---|
| 445 | int curl_fclose(FILE *file, int line, const char *source)
|
---|
| 446 | {
|
---|
| 447 | int res;
|
---|
| 448 |
|
---|
| 449 | assert(file != NULL);
|
---|
| 450 |
|
---|
| 451 | res=fclose(file);
|
---|
| 452 |
|
---|
| 453 | if(source)
|
---|
| 454 | curl_memlog("FILE %s:%d fclose(%p)\n",
|
---|
| 455 | source, line, (void *)file);
|
---|
| 456 |
|
---|
| 457 | return res;
|
---|
| 458 | }
|
---|
| 459 |
|
---|
| 460 | #define LOGLINE_BUFSIZE 1024
|
---|
| 461 |
|
---|
| 462 | /* this does the writting to the memory tracking log file */
|
---|
| 463 | void curl_memlog(const char *format, ...)
|
---|
| 464 | {
|
---|
| 465 | char *buf;
|
---|
| 466 | int nchars;
|
---|
| 467 | va_list ap;
|
---|
| 468 |
|
---|
| 469 | if(!logfile)
|
---|
| 470 | return;
|
---|
| 471 |
|
---|
| 472 | buf = (Curl_cmalloc)(LOGLINE_BUFSIZE);
|
---|
| 473 | if(!buf)
|
---|
| 474 | return;
|
---|
| 475 |
|
---|
| 476 | va_start(ap, format);
|
---|
| 477 | nchars = vsnprintf(buf, LOGLINE_BUFSIZE, format, ap);
|
---|
| 478 | va_end(ap);
|
---|
| 479 |
|
---|
| 480 | if(nchars > LOGLINE_BUFSIZE - 1)
|
---|
| 481 | nchars = LOGLINE_BUFSIZE - 1;
|
---|
| 482 |
|
---|
| 483 | if(nchars > 0)
|
---|
| 484 | fwrite(buf, 1, nchars, logfile);
|
---|
| 485 |
|
---|
| 486 | (Curl_cfree)(buf);
|
---|
| 487 | }
|
---|
| 488 |
|
---|
| 489 | #endif /* CURLDEBUG */
|
---|