xref: /third_party/curl/lib/memdebug.c (revision 13498266)
113498266Sopenharmony_ci/***************************************************************************
213498266Sopenharmony_ci *                                  _   _ ____  _
313498266Sopenharmony_ci *  Project                     ___| | | |  _ \| |
413498266Sopenharmony_ci *                             / __| | | | |_) | |
513498266Sopenharmony_ci *                            | (__| |_| |  _ <| |___
613498266Sopenharmony_ci *                             \___|\___/|_| \_\_____|
713498266Sopenharmony_ci *
813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
913498266Sopenharmony_ci *
1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which
1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms
1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html.
1313498266Sopenharmony_ci *
1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell
1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is
1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file.
1713498266Sopenharmony_ci *
1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
1913498266Sopenharmony_ci * KIND, either express or implied.
2013498266Sopenharmony_ci *
2113498266Sopenharmony_ci * SPDX-License-Identifier: curl
2213498266Sopenharmony_ci *
2313498266Sopenharmony_ci ***************************************************************************/
2413498266Sopenharmony_ci
2513498266Sopenharmony_ci#include "curl_setup.h"
2613498266Sopenharmony_ci
2713498266Sopenharmony_ci#ifdef CURLDEBUG
2813498266Sopenharmony_ci
2913498266Sopenharmony_ci#include <curl/curl.h>
3013498266Sopenharmony_ci
3113498266Sopenharmony_ci#include "urldata.h"
3213498266Sopenharmony_ci
3313498266Sopenharmony_ci#define MEMDEBUG_NODEFINES /* don't redefine the standard functions */
3413498266Sopenharmony_ci
3513498266Sopenharmony_ci/* The last 3 #include files should be in this order */
3613498266Sopenharmony_ci#include "curl_printf.h"
3713498266Sopenharmony_ci#include "curl_memory.h"
3813498266Sopenharmony_ci#include "memdebug.h"
3913498266Sopenharmony_ci
4013498266Sopenharmony_cistruct memdebug {
4113498266Sopenharmony_ci  size_t size;
4213498266Sopenharmony_ci  union {
4313498266Sopenharmony_ci    curl_off_t o;
4413498266Sopenharmony_ci    double d;
4513498266Sopenharmony_ci    void *p;
4613498266Sopenharmony_ci  } mem[1];
4713498266Sopenharmony_ci  /* I'm hoping this is the thing with the strictest alignment
4813498266Sopenharmony_ci   * requirements.  That also means we waste some space :-( */
4913498266Sopenharmony_ci};
5013498266Sopenharmony_ci
5113498266Sopenharmony_ci/*
5213498266Sopenharmony_ci * Note that these debug functions are very simple and they are meant to
5313498266Sopenharmony_ci * remain so. For advanced analysis, record a log file and write perl scripts
5413498266Sopenharmony_ci * to analyze them!
5513498266Sopenharmony_ci *
5613498266Sopenharmony_ci * Don't use these with multithreaded test programs!
5713498266Sopenharmony_ci */
5813498266Sopenharmony_ci
5913498266Sopenharmony_ciFILE *curl_dbg_logfile = NULL;
6013498266Sopenharmony_cistatic bool registered_cleanup = FALSE; /* atexit registered cleanup */
6113498266Sopenharmony_cistatic bool memlimit = FALSE; /* enable memory limit */
6213498266Sopenharmony_cistatic long memsize = 0;  /* set number of mallocs allowed */
6313498266Sopenharmony_ci
6413498266Sopenharmony_ci/* LeakSantizier (LSAN) calls _exit() instead of exit() when a leak is detected
6513498266Sopenharmony_ci   on exit so the logfile must be closed explicitly or data could be lost.
6613498266Sopenharmony_ci   Though _exit() does not call atexit handlers such as this, LSAN's call to
6713498266Sopenharmony_ci   _exit() comes after the atexit handlers are called. curl/curl#6620 */
6813498266Sopenharmony_cistatic void curl_dbg_cleanup(void)
6913498266Sopenharmony_ci{
7013498266Sopenharmony_ci  if(curl_dbg_logfile &&
7113498266Sopenharmony_ci     curl_dbg_logfile != stderr &&
7213498266Sopenharmony_ci     curl_dbg_logfile != stdout) {
7313498266Sopenharmony_ci    fclose(curl_dbg_logfile);
7413498266Sopenharmony_ci  }
7513498266Sopenharmony_ci  curl_dbg_logfile = NULL;
7613498266Sopenharmony_ci}
7713498266Sopenharmony_ci
7813498266Sopenharmony_ci/* this sets the log file name */
7913498266Sopenharmony_civoid curl_dbg_memdebug(const char *logname)
8013498266Sopenharmony_ci{
8113498266Sopenharmony_ci  if(!curl_dbg_logfile) {
8213498266Sopenharmony_ci    if(logname && *logname)
8313498266Sopenharmony_ci      curl_dbg_logfile = fopen(logname, FOPEN_WRITETEXT);
8413498266Sopenharmony_ci    else
8513498266Sopenharmony_ci      curl_dbg_logfile = stderr;
8613498266Sopenharmony_ci#ifdef MEMDEBUG_LOG_SYNC
8713498266Sopenharmony_ci    /* Flush the log file after every line so the log isn't lost in a crash */
8813498266Sopenharmony_ci    if(curl_dbg_logfile)
8913498266Sopenharmony_ci      setbuf(curl_dbg_logfile, (char *)NULL);
9013498266Sopenharmony_ci#endif
9113498266Sopenharmony_ci  }
9213498266Sopenharmony_ci  if(!registered_cleanup)
9313498266Sopenharmony_ci    registered_cleanup = !atexit(curl_dbg_cleanup);
9413498266Sopenharmony_ci}
9513498266Sopenharmony_ci
9613498266Sopenharmony_ci/* This function sets the number of malloc() calls that should return
9713498266Sopenharmony_ci   successfully! */
9813498266Sopenharmony_civoid curl_dbg_memlimit(long limit)
9913498266Sopenharmony_ci{
10013498266Sopenharmony_ci  if(!memlimit) {
10113498266Sopenharmony_ci    memlimit = TRUE;
10213498266Sopenharmony_ci    memsize = limit;
10313498266Sopenharmony_ci  }
10413498266Sopenharmony_ci}
10513498266Sopenharmony_ci
10613498266Sopenharmony_ci/* returns TRUE if this isn't allowed! */
10713498266Sopenharmony_cistatic bool countcheck(const char *func, int line, const char *source)
10813498266Sopenharmony_ci{
10913498266Sopenharmony_ci  /* if source is NULL, then the call is made internally and this check
11013498266Sopenharmony_ci     should not be made */
11113498266Sopenharmony_ci  if(memlimit && source) {
11213498266Sopenharmony_ci    if(!memsize) {
11313498266Sopenharmony_ci      /* log to file */
11413498266Sopenharmony_ci      curl_dbg_log("LIMIT %s:%d %s reached memlimit\n",
11513498266Sopenharmony_ci                   source, line, func);
11613498266Sopenharmony_ci      /* log to stderr also */
11713498266Sopenharmony_ci      fprintf(stderr, "LIMIT %s:%d %s reached memlimit\n",
11813498266Sopenharmony_ci              source, line, func);
11913498266Sopenharmony_ci      fflush(curl_dbg_logfile); /* because it might crash now */
12013498266Sopenharmony_ci      errno = ENOMEM;
12113498266Sopenharmony_ci      return TRUE; /* RETURN ERROR! */
12213498266Sopenharmony_ci    }
12313498266Sopenharmony_ci    else
12413498266Sopenharmony_ci      memsize--; /* countdown */
12513498266Sopenharmony_ci
12613498266Sopenharmony_ci
12713498266Sopenharmony_ci  }
12813498266Sopenharmony_ci
12913498266Sopenharmony_ci  return FALSE; /* allow this */
13013498266Sopenharmony_ci}
13113498266Sopenharmony_ci
13213498266Sopenharmony_ciALLOC_FUNC void *curl_dbg_malloc(size_t wantedsize,
13313498266Sopenharmony_ci                                 int line, const char *source)
13413498266Sopenharmony_ci{
13513498266Sopenharmony_ci  struct memdebug *mem;
13613498266Sopenharmony_ci  size_t size;
13713498266Sopenharmony_ci
13813498266Sopenharmony_ci  DEBUGASSERT(wantedsize != 0);
13913498266Sopenharmony_ci
14013498266Sopenharmony_ci  if(countcheck("malloc", line, source))
14113498266Sopenharmony_ci    return NULL;
14213498266Sopenharmony_ci
14313498266Sopenharmony_ci  /* alloc at least 64 bytes */
14413498266Sopenharmony_ci  size = sizeof(struct memdebug) + wantedsize;
14513498266Sopenharmony_ci
14613498266Sopenharmony_ci  mem = (Curl_cmalloc)(size);
14713498266Sopenharmony_ci  if(mem) {
14813498266Sopenharmony_ci    mem->size = wantedsize;
14913498266Sopenharmony_ci  }
15013498266Sopenharmony_ci
15113498266Sopenharmony_ci  if(source)
15213498266Sopenharmony_ci    curl_dbg_log("MEM %s:%d malloc(%zu) = %p\n",
15313498266Sopenharmony_ci                 source, line, wantedsize,
15413498266Sopenharmony_ci                 mem ? (void *)mem->mem : (void *)0);
15513498266Sopenharmony_ci
15613498266Sopenharmony_ci  return (mem ? mem->mem : NULL);
15713498266Sopenharmony_ci}
15813498266Sopenharmony_ci
15913498266Sopenharmony_ciALLOC_FUNC void *curl_dbg_calloc(size_t wanted_elements, size_t wanted_size,
16013498266Sopenharmony_ci                                 int line, const char *source)
16113498266Sopenharmony_ci{
16213498266Sopenharmony_ci  struct memdebug *mem;
16313498266Sopenharmony_ci  size_t size, user_size;
16413498266Sopenharmony_ci
16513498266Sopenharmony_ci  DEBUGASSERT(wanted_elements != 0);
16613498266Sopenharmony_ci  DEBUGASSERT(wanted_size != 0);
16713498266Sopenharmony_ci
16813498266Sopenharmony_ci  if(countcheck("calloc", line, source))
16913498266Sopenharmony_ci    return NULL;
17013498266Sopenharmony_ci
17113498266Sopenharmony_ci  /* alloc at least 64 bytes */
17213498266Sopenharmony_ci  user_size = wanted_size * wanted_elements;
17313498266Sopenharmony_ci  size = sizeof(struct memdebug) + user_size;
17413498266Sopenharmony_ci
17513498266Sopenharmony_ci  mem = (Curl_ccalloc)(1, size);
17613498266Sopenharmony_ci  if(mem)
17713498266Sopenharmony_ci    mem->size = user_size;
17813498266Sopenharmony_ci
17913498266Sopenharmony_ci  if(source)
18013498266Sopenharmony_ci    curl_dbg_log("MEM %s:%d calloc(%zu,%zu) = %p\n",
18113498266Sopenharmony_ci                 source, line, wanted_elements, wanted_size,
18213498266Sopenharmony_ci                 mem ? (void *)mem->mem : (void *)0);
18313498266Sopenharmony_ci
18413498266Sopenharmony_ci  return (mem ? mem->mem : NULL);
18513498266Sopenharmony_ci}
18613498266Sopenharmony_ci
18713498266Sopenharmony_ciALLOC_FUNC char *curl_dbg_strdup(const char *str,
18813498266Sopenharmony_ci                                 int line, const char *source)
18913498266Sopenharmony_ci{
19013498266Sopenharmony_ci  char *mem;
19113498266Sopenharmony_ci  size_t len;
19213498266Sopenharmony_ci
19313498266Sopenharmony_ci  DEBUGASSERT(str != NULL);
19413498266Sopenharmony_ci
19513498266Sopenharmony_ci  if(countcheck("strdup", line, source))
19613498266Sopenharmony_ci    return NULL;
19713498266Sopenharmony_ci
19813498266Sopenharmony_ci  len = strlen(str) + 1;
19913498266Sopenharmony_ci
20013498266Sopenharmony_ci  mem = curl_dbg_malloc(len, 0, NULL); /* NULL prevents logging */
20113498266Sopenharmony_ci  if(mem)
20213498266Sopenharmony_ci    memcpy(mem, str, len);
20313498266Sopenharmony_ci
20413498266Sopenharmony_ci  if(source)
20513498266Sopenharmony_ci    curl_dbg_log("MEM %s:%d strdup(%p) (%zu) = %p\n",
20613498266Sopenharmony_ci                 source, line, (const void *)str, len, (const void *)mem);
20713498266Sopenharmony_ci
20813498266Sopenharmony_ci  return mem;
20913498266Sopenharmony_ci}
21013498266Sopenharmony_ci
21113498266Sopenharmony_ci#if defined(_WIN32) && defined(UNICODE)
21213498266Sopenharmony_ciALLOC_FUNC wchar_t *curl_dbg_wcsdup(const wchar_t *str,
21313498266Sopenharmony_ci                                    int line, const char *source)
21413498266Sopenharmony_ci{
21513498266Sopenharmony_ci  wchar_t *mem;
21613498266Sopenharmony_ci  size_t wsiz, bsiz;
21713498266Sopenharmony_ci
21813498266Sopenharmony_ci  DEBUGASSERT(str != NULL);
21913498266Sopenharmony_ci
22013498266Sopenharmony_ci  if(countcheck("wcsdup", line, source))
22113498266Sopenharmony_ci    return NULL;
22213498266Sopenharmony_ci
22313498266Sopenharmony_ci  wsiz = wcslen(str) + 1;
22413498266Sopenharmony_ci  bsiz = wsiz * sizeof(wchar_t);
22513498266Sopenharmony_ci
22613498266Sopenharmony_ci  mem = curl_dbg_malloc(bsiz, 0, NULL); /* NULL prevents logging */
22713498266Sopenharmony_ci  if(mem)
22813498266Sopenharmony_ci    memcpy(mem, str, bsiz);
22913498266Sopenharmony_ci
23013498266Sopenharmony_ci  if(source)
23113498266Sopenharmony_ci    curl_dbg_log("MEM %s:%d wcsdup(%p) (%zu) = %p\n",
23213498266Sopenharmony_ci                source, line, (void *)str, bsiz, (void *)mem);
23313498266Sopenharmony_ci
23413498266Sopenharmony_ci  return mem;
23513498266Sopenharmony_ci}
23613498266Sopenharmony_ci#endif
23713498266Sopenharmony_ci
23813498266Sopenharmony_ci/* We provide a realloc() that accepts a NULL as pointer, which then
23913498266Sopenharmony_ci   performs a malloc(). In order to work with ares. */
24013498266Sopenharmony_civoid *curl_dbg_realloc(void *ptr, size_t wantedsize,
24113498266Sopenharmony_ci                      int line, const char *source)
24213498266Sopenharmony_ci{
24313498266Sopenharmony_ci  struct memdebug *mem = NULL;
24413498266Sopenharmony_ci
24513498266Sopenharmony_ci  size_t size = sizeof(struct memdebug) + wantedsize;
24613498266Sopenharmony_ci
24713498266Sopenharmony_ci  DEBUGASSERT(wantedsize != 0);
24813498266Sopenharmony_ci
24913498266Sopenharmony_ci  if(countcheck("realloc", line, source))
25013498266Sopenharmony_ci    return NULL;
25113498266Sopenharmony_ci
25213498266Sopenharmony_ci#ifdef __INTEL_COMPILER
25313498266Sopenharmony_ci#  pragma warning(push)
25413498266Sopenharmony_ci#  pragma warning(disable:1684)
25513498266Sopenharmony_ci   /* 1684: conversion from pointer to same-sized integral type */
25613498266Sopenharmony_ci#endif
25713498266Sopenharmony_ci
25813498266Sopenharmony_ci  if(ptr)
25913498266Sopenharmony_ci    mem = (void *)((char *)ptr - offsetof(struct memdebug, mem));
26013498266Sopenharmony_ci
26113498266Sopenharmony_ci#ifdef __INTEL_COMPILER
26213498266Sopenharmony_ci#  pragma warning(pop)
26313498266Sopenharmony_ci#endif
26413498266Sopenharmony_ci
26513498266Sopenharmony_ci  mem = (Curl_crealloc)(mem, size);
26613498266Sopenharmony_ci  if(source)
26713498266Sopenharmony_ci    curl_dbg_log("MEM %s:%d realloc(%p, %zu) = %p\n",
26813498266Sopenharmony_ci                source, line, (void *)ptr, wantedsize,
26913498266Sopenharmony_ci                mem ? (void *)mem->mem : (void *)0);
27013498266Sopenharmony_ci
27113498266Sopenharmony_ci  if(mem) {
27213498266Sopenharmony_ci    mem->size = wantedsize;
27313498266Sopenharmony_ci    return mem->mem;
27413498266Sopenharmony_ci  }
27513498266Sopenharmony_ci
27613498266Sopenharmony_ci  return NULL;
27713498266Sopenharmony_ci}
27813498266Sopenharmony_ci
27913498266Sopenharmony_civoid curl_dbg_free(void *ptr, int line, const char *source)
28013498266Sopenharmony_ci{
28113498266Sopenharmony_ci  if(ptr) {
28213498266Sopenharmony_ci    struct memdebug *mem;
28313498266Sopenharmony_ci
28413498266Sopenharmony_ci#ifdef __INTEL_COMPILER
28513498266Sopenharmony_ci#  pragma warning(push)
28613498266Sopenharmony_ci#  pragma warning(disable:1684)
28713498266Sopenharmony_ci   /* 1684: conversion from pointer to same-sized integral type */
28813498266Sopenharmony_ci#endif
28913498266Sopenharmony_ci
29013498266Sopenharmony_ci    mem = (void *)((char *)ptr - offsetof(struct memdebug, mem));
29113498266Sopenharmony_ci
29213498266Sopenharmony_ci#ifdef __INTEL_COMPILER
29313498266Sopenharmony_ci#  pragma warning(pop)
29413498266Sopenharmony_ci#endif
29513498266Sopenharmony_ci
29613498266Sopenharmony_ci    /* free for real */
29713498266Sopenharmony_ci    (Curl_cfree)(mem);
29813498266Sopenharmony_ci  }
29913498266Sopenharmony_ci
30013498266Sopenharmony_ci  if(source && ptr)
30113498266Sopenharmony_ci    curl_dbg_log("MEM %s:%d free(%p)\n", source, line, (void *)ptr);
30213498266Sopenharmony_ci}
30313498266Sopenharmony_ci
30413498266Sopenharmony_cicurl_socket_t curl_dbg_socket(int domain, int type, int protocol,
30513498266Sopenharmony_ci                             int line, const char *source)
30613498266Sopenharmony_ci{
30713498266Sopenharmony_ci  curl_socket_t sockfd;
30813498266Sopenharmony_ci
30913498266Sopenharmony_ci  if(countcheck("socket", line, source))
31013498266Sopenharmony_ci    return CURL_SOCKET_BAD;
31113498266Sopenharmony_ci
31213498266Sopenharmony_ci  sockfd = socket(domain, type, protocol);
31313498266Sopenharmony_ci
31413498266Sopenharmony_ci  if(source && (sockfd != CURL_SOCKET_BAD))
31513498266Sopenharmony_ci    curl_dbg_log("FD %s:%d socket() = %" CURL_FORMAT_SOCKET_T "\n",
31613498266Sopenharmony_ci                 source, line, sockfd);
31713498266Sopenharmony_ci
31813498266Sopenharmony_ci  return sockfd;
31913498266Sopenharmony_ci}
32013498266Sopenharmony_ci
32113498266Sopenharmony_ciSEND_TYPE_RETV curl_dbg_send(SEND_TYPE_ARG1 sockfd,
32213498266Sopenharmony_ci                            SEND_QUAL_ARG2 SEND_TYPE_ARG2 buf,
32313498266Sopenharmony_ci                            SEND_TYPE_ARG3 len, SEND_TYPE_ARG4 flags, int line,
32413498266Sopenharmony_ci                            const char *source)
32513498266Sopenharmony_ci{
32613498266Sopenharmony_ci  SEND_TYPE_RETV rc;
32713498266Sopenharmony_ci  if(countcheck("send", line, source))
32813498266Sopenharmony_ci    return -1;
32913498266Sopenharmony_ci  rc = send(sockfd, buf, len, flags);
33013498266Sopenharmony_ci  if(source)
33113498266Sopenharmony_ci    curl_dbg_log("SEND %s:%d send(%lu) = %ld\n",
33213498266Sopenharmony_ci                source, line, (unsigned long)len, (long)rc);
33313498266Sopenharmony_ci  return rc;
33413498266Sopenharmony_ci}
33513498266Sopenharmony_ci
33613498266Sopenharmony_ciRECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd, RECV_TYPE_ARG2 buf,
33713498266Sopenharmony_ci                            RECV_TYPE_ARG3 len, RECV_TYPE_ARG4 flags, int line,
33813498266Sopenharmony_ci                            const char *source)
33913498266Sopenharmony_ci{
34013498266Sopenharmony_ci  RECV_TYPE_RETV rc;
34113498266Sopenharmony_ci  if(countcheck("recv", line, source))
34213498266Sopenharmony_ci    return -1;
34313498266Sopenharmony_ci  rc = recv(sockfd, buf, len, flags);
34413498266Sopenharmony_ci  if(source)
34513498266Sopenharmony_ci    curl_dbg_log("RECV %s:%d recv(%lu) = %ld\n",
34613498266Sopenharmony_ci                source, line, (unsigned long)len, (long)rc);
34713498266Sopenharmony_ci  return rc;
34813498266Sopenharmony_ci}
34913498266Sopenharmony_ci
35013498266Sopenharmony_ci#ifdef HAVE_SOCKETPAIR
35113498266Sopenharmony_ciint curl_dbg_socketpair(int domain, int type, int protocol,
35213498266Sopenharmony_ci                       curl_socket_t socket_vector[2],
35313498266Sopenharmony_ci                       int line, const char *source)
35413498266Sopenharmony_ci{
35513498266Sopenharmony_ci  int res = socketpair(domain, type, protocol, socket_vector);
35613498266Sopenharmony_ci
35713498266Sopenharmony_ci  if(source && (0 == res))
35813498266Sopenharmony_ci    curl_dbg_log("FD %s:%d socketpair() = "
35913498266Sopenharmony_ci      "%" CURL_FORMAT_SOCKET_T " %" CURL_FORMAT_SOCKET_T "\n",
36013498266Sopenharmony_ci      source, line, socket_vector[0], socket_vector[1]);
36113498266Sopenharmony_ci
36213498266Sopenharmony_ci  return res;
36313498266Sopenharmony_ci}
36413498266Sopenharmony_ci#endif
36513498266Sopenharmony_ci
36613498266Sopenharmony_cicurl_socket_t curl_dbg_accept(curl_socket_t s, void *saddr, void *saddrlen,
36713498266Sopenharmony_ci                             int line, const char *source)
36813498266Sopenharmony_ci{
36913498266Sopenharmony_ci  struct sockaddr *addr = (struct sockaddr *)saddr;
37013498266Sopenharmony_ci  curl_socklen_t *addrlen = (curl_socklen_t *)saddrlen;
37113498266Sopenharmony_ci
37213498266Sopenharmony_ci  curl_socket_t sockfd = accept(s, addr, addrlen);
37313498266Sopenharmony_ci
37413498266Sopenharmony_ci  if(source && (sockfd != CURL_SOCKET_BAD))
37513498266Sopenharmony_ci    curl_dbg_log("FD %s:%d accept() = %" CURL_FORMAT_SOCKET_T "\n",
37613498266Sopenharmony_ci                 source, line, sockfd);
37713498266Sopenharmony_ci
37813498266Sopenharmony_ci  return sockfd;
37913498266Sopenharmony_ci}
38013498266Sopenharmony_ci
38113498266Sopenharmony_ci/* separate function to allow libcurl to mark a "faked" close */
38213498266Sopenharmony_civoid curl_dbg_mark_sclose(curl_socket_t sockfd, int line, const char *source)
38313498266Sopenharmony_ci{
38413498266Sopenharmony_ci  if(source)
38513498266Sopenharmony_ci    curl_dbg_log("FD %s:%d sclose(%" CURL_FORMAT_SOCKET_T ")\n",
38613498266Sopenharmony_ci                 source, line, sockfd);
38713498266Sopenharmony_ci}
38813498266Sopenharmony_ci
38913498266Sopenharmony_ci/* this is our own defined way to close sockets on *ALL* platforms */
39013498266Sopenharmony_ciint curl_dbg_sclose(curl_socket_t sockfd, int line, const char *source)
39113498266Sopenharmony_ci{
39213498266Sopenharmony_ci  int res = sclose(sockfd);
39313498266Sopenharmony_ci  curl_dbg_mark_sclose(sockfd, line, source);
39413498266Sopenharmony_ci  return res;
39513498266Sopenharmony_ci}
39613498266Sopenharmony_ci
39713498266Sopenharmony_ciALLOC_FUNC FILE *curl_dbg_fopen(const char *file, const char *mode,
39813498266Sopenharmony_ci                                int line, const char *source)
39913498266Sopenharmony_ci{
40013498266Sopenharmony_ci  FILE *res = fopen(file, mode);
40113498266Sopenharmony_ci
40213498266Sopenharmony_ci  if(source)
40313498266Sopenharmony_ci    curl_dbg_log("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n",
40413498266Sopenharmony_ci                source, line, file, mode, (void *)res);
40513498266Sopenharmony_ci
40613498266Sopenharmony_ci  return res;
40713498266Sopenharmony_ci}
40813498266Sopenharmony_ci
40913498266Sopenharmony_ciALLOC_FUNC FILE *curl_dbg_fdopen(int filedes, const char *mode,
41013498266Sopenharmony_ci                                 int line, const char *source)
41113498266Sopenharmony_ci{
41213498266Sopenharmony_ci  FILE *res = fdopen(filedes, mode);
41313498266Sopenharmony_ci  if(source)
41413498266Sopenharmony_ci    curl_dbg_log("FILE %s:%d fdopen(\"%d\",\"%s\") = %p\n",
41513498266Sopenharmony_ci                 source, line, filedes, mode, (void *)res);
41613498266Sopenharmony_ci  return res;
41713498266Sopenharmony_ci}
41813498266Sopenharmony_ci
41913498266Sopenharmony_ciint curl_dbg_fclose(FILE *file, int line, const char *source)
42013498266Sopenharmony_ci{
42113498266Sopenharmony_ci  int res;
42213498266Sopenharmony_ci
42313498266Sopenharmony_ci  DEBUGASSERT(file != NULL);
42413498266Sopenharmony_ci
42513498266Sopenharmony_ci  if(source)
42613498266Sopenharmony_ci    curl_dbg_log("FILE %s:%d fclose(%p)\n",
42713498266Sopenharmony_ci                 source, line, (void *)file);
42813498266Sopenharmony_ci
42913498266Sopenharmony_ci  res = fclose(file);
43013498266Sopenharmony_ci
43113498266Sopenharmony_ci  return res;
43213498266Sopenharmony_ci}
43313498266Sopenharmony_ci
43413498266Sopenharmony_ci#define LOGLINE_BUFSIZE  1024
43513498266Sopenharmony_ci
43613498266Sopenharmony_ci/* this does the writing to the memory tracking log file */
43713498266Sopenharmony_civoid curl_dbg_log(const char *format, ...)
43813498266Sopenharmony_ci{
43913498266Sopenharmony_ci  char *buf;
44013498266Sopenharmony_ci  int nchars;
44113498266Sopenharmony_ci  va_list ap;
44213498266Sopenharmony_ci
44313498266Sopenharmony_ci  if(!curl_dbg_logfile)
44413498266Sopenharmony_ci    return;
44513498266Sopenharmony_ci
44613498266Sopenharmony_ci  buf = (Curl_cmalloc)(LOGLINE_BUFSIZE);
44713498266Sopenharmony_ci  if(!buf)
44813498266Sopenharmony_ci    return;
44913498266Sopenharmony_ci
45013498266Sopenharmony_ci  va_start(ap, format);
45113498266Sopenharmony_ci  nchars = mvsnprintf(buf, LOGLINE_BUFSIZE, format, ap);
45213498266Sopenharmony_ci  va_end(ap);
45313498266Sopenharmony_ci
45413498266Sopenharmony_ci  if(nchars > LOGLINE_BUFSIZE - 1)
45513498266Sopenharmony_ci    nchars = LOGLINE_BUFSIZE - 1;
45613498266Sopenharmony_ci
45713498266Sopenharmony_ci  if(nchars > 0)
45813498266Sopenharmony_ci    fwrite(buf, 1, (size_t)nchars, curl_dbg_logfile);
45913498266Sopenharmony_ci
46013498266Sopenharmony_ci  (Curl_cfree)(buf);
46113498266Sopenharmony_ci}
46213498266Sopenharmony_ci
46313498266Sopenharmony_ci#endif /* CURLDEBUG */
464