Merge commit 'ad3ad82ad2fb99c424a8482bd1908d08b990ccea'
[unleashed.git] / usr / src / cmd / fs.d / autofs / debug_alloc.c
blob6aa429b472fb2ee396f7ad44e1b0dc499a57512d
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright (c) 1998,2001 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #ifdef MALLOC_DEBUG
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <thread.h>
33 #include <synch.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <syslog.h>
37 #include <netdb.h>
38 #include <netdir.h>
39 #include <rpc/nettype.h>
42 * To use debugging facility, compile with * -DMALLOC_DEBUG.
43 * You can do this by setting the environment variable
44 * MALLOC_DEBUG to "-DMALLOC_DEBUG"
46 * To make automountd dump trace records (i.e. make it call check_leaks),
47 * run:
48 * make malloc_dump
51 struct alloc_list
53 char type[20];
54 void *addr;
55 int size;
56 char file[80];
57 int line;
58 struct alloc_list *next;
61 static struct alloc_list *halist = NULL;
62 static mutex_t alloc_list_lock = DEFAULTMUTEX;
64 int
65 add_alloc(char *type, void *addr, size_t size, const char *file, int line)
67 struct alloc_list *alist = NULL;
69 /* allocate the list item */
70 alist = (struct alloc_list *)malloc(sizeof (*alist));
71 if (alist == NULL) {
72 syslog(LOG_ERR, "add_alloc: out of memory\n");
73 return (-1);
75 strcpy(alist->type, type);
76 alist->addr = addr;
77 alist->size = size;
78 strcpy(alist->file, file);
79 alist->line = line;
81 /* add it to the head of the list */
82 if (halist == NULL)
83 alist->next = NULL;
84 else
85 alist->next = halist;
86 halist = alist;
87 return (0);
90 int
91 drop_alloc(const char *type, void *addr, const char *file, int line)
93 struct alloc_list *alist, *alist_prev;
95 alist = halist;
96 while (alist != NULL) {
97 if (addr == alist->addr) {
98 if (alist == halist)
99 halist = halist->next;
100 else
101 alist_prev->next = alist->next;
102 free(alist);
103 break;
105 alist_prev = alist;
106 alist = alist->next;
109 if (alist == NULL) {
110 syslog(LOG_ERR, "*** POSSIBLE CORRUPTION ****\n");
111 syslog(LOG_ERR, "\tduplicate free, type %s, at %p in %s/%d\n",
112 type, addr, file, line);
113 return (-1);
115 return (0);
118 void *
119 my_malloc(size_t size, const char *file, int line)
121 void *addr;
123 addr = (void *)malloc(size);
124 if (addr == NULL)
125 return (NULL);
126 mutex_lock(&alloc_list_lock);
127 add_alloc("MALLOC", addr, size, file, line);
128 mutex_unlock(&alloc_list_lock);
129 return (addr);
132 void *
133 my_realloc(void *addr, size_t size, const char *file, int line)
135 void *ptr;
137 ptr = (void *)realloc(addr, size);
138 if (ptr == NULL)
139 return (NULL);
140 mutex_lock(&alloc_list_lock);
141 drop_alloc("MALLOC", addr, file, line);
142 add_alloc("MALLOC", ptr, size, file, line);
143 mutex_unlock(&alloc_list_lock);
145 return (ptr);
148 void
149 my_free(void *addr, const char *file, int line)
151 mutex_lock(&alloc_list_lock);
152 drop_alloc("MALLOC", addr, file, line);
153 mutex_unlock(&alloc_list_lock);
154 free(addr);
157 char *
158 my_strdup(const char *straddr, const char *file, int line)
160 void *addr;
161 size_t size;
163 addr = strdup(straddr);
164 if (addr == NULL)
165 return (NULL);
166 size = strlen(straddr);
167 mutex_lock(&alloc_list_lock);
168 add_alloc("STRDUP", addr, size, file, line);
169 mutex_unlock(&alloc_list_lock);
171 return ((char *)addr);
175 my_sethostent(int stay, const char *file, int line)
177 (void) sethostent(stay);
178 mutex_lock(&alloc_list_lock);
179 add_alloc("SETHOSTENT", NULL, 0, file, line);
180 mutex_unlock(&alloc_list_lock);
181 return (0);
185 my_endhostent(const char *file, int line)
187 int ret;
189 ret = endhostent();
190 if (ret != 0)
191 return (ret);
192 mutex_lock(&alloc_list_lock);
193 drop_alloc("SETHOSTENT", NULL, file, line);
194 mutex_unlock(&alloc_list_lock);
195 return (ret);
198 void *
199 my_setnetconfig(const char *file, int line)
201 void *nconf;
203 nconf = setnetconfig();
204 if (nconf == NULL)
205 return (NULL);
206 mutex_lock(&alloc_list_lock);
207 add_alloc("SETNETCONFIG", nconf, 0, file, line);
208 mutex_unlock(&alloc_list_lock);
209 return (nconf);
213 my_endnetconfig(void *nconf, const char *file, int line)
215 int res;
217 res = endnetconfig(nconf);
218 if (res != 0)
219 return (res);
220 mutex_lock(&alloc_list_lock);
221 drop_alloc("SETNETCONFIG", nconf, file, line);
222 mutex_unlock(&alloc_list_lock);
223 return (0);
226 void *
227 my_setnetpath(const char *file, int line)
229 void *npath;
231 npath = setnetpath();
232 if (npath == NULL)
233 return (NULL);
234 mutex_lock(&alloc_list_lock);
235 add_alloc("SETNETPATH", npath, 0, file, line);
236 mutex_unlock(&alloc_list_lock);
237 return (npath);
241 my_endnetpath(void *npath, const char *file, int line)
243 int res;
245 res = endnetpath(npath);
246 if (res != 0)
247 return (res);
248 mutex_lock(&alloc_list_lock);
249 drop_alloc("SETNETPATH", npath, file, line);
250 mutex_unlock(&alloc_list_lock);
251 return (0);
255 my_netdir_getbyname(
256 struct netconfig *tp,
257 struct nd_hostserv *serv,
258 struct nd_addrlist **addrs,
259 const char *file,
260 int line)
262 int res;
264 res = netdir_getbyname(tp, serv, addrs);
265 if (res != 0)
266 return (res);
267 mutex_lock(&alloc_list_lock);
268 add_alloc("NETDIR_GETBYNAME", *addrs, 0, file, line);
269 mutex_unlock(&alloc_list_lock);
270 return (0);
273 void
274 my_netdir_free(void *ptr, int type, const char *file, int line)
276 netdir_free(ptr, type);
277 mutex_lock(&alloc_list_lock);
278 drop_alloc("NETDIR_GETBYNAME", ptr, file, line);
279 mutex_unlock(&alloc_list_lock);
282 struct hostent *
283 my_getipnodebyname(
284 const char *name,
285 int af,
286 int flags,
287 int *error_num,
288 char *file,
289 int line)
291 struct hostent *res;
293 res = getipnodebyname(name, af, flags, error_num);
294 if (res == NULL)
295 return (NULL);
296 mutex_lock(&alloc_list_lock);
297 add_alloc("GETIPNODEBYNAME", res, 0, file, line);
298 mutex_unlock(&alloc_list_lock);
299 return (res);
302 void
303 my_freehostent(struct hostent *hent, char *file, int line)
305 freehostent(hent);
306 mutex_lock(&alloc_list_lock);
307 drop_alloc("GETIPNODEBYNAME", hent, file, line);
308 mutex_unlock(&alloc_list_lock);
311 struct netconfig *
312 my_getnetconfigent(char *netid, char *file, int line)
314 struct netconfig *res;
316 res = getnetconfigent(netid);
317 if (res == NULL)
318 return (NULL);
319 mutex_lock(&alloc_list_lock);
320 add_alloc("GETNETCONFIGENT", res, 0, file, line);
321 mutex_unlock(&alloc_list_lock);
322 return (res);
325 void
326 my_freenetconfigent(struct netconfig *netp, char *file, int line)
328 freenetconfigent(netp);
329 mutex_lock(&alloc_list_lock);
330 drop_alloc("GETNETCONFIGENT", netp, file, line);
331 mutex_unlock(&alloc_list_lock);
334 void *
335 my__rpc_setconf(char *nettype, char *file, int line)
337 void *res;
339 res = __rpc_setconf(nettype);
340 if (res == NULL)
341 return (NULL);
342 mutex_lock(&alloc_list_lock);
343 add_alloc("RPC_SETCONF", res, 0, file, line);
344 mutex_unlock(&alloc_list_lock);
345 return (res);
348 void
349 my__rpc_endconf(void *vhandle, char *file, int line)
351 __rpc_endconf(vhandle);
352 mutex_lock(&alloc_list_lock);
353 drop_alloc("RPC_SETCONF", vhandle, file, line);
354 mutex_unlock(&alloc_list_lock);
357 extern void flush_caches();
358 void
359 _flush_caches()
362 #pragma weak flush_caches = _flush_caches
364 void
365 check_leaks(char *filename)
367 struct alloc_list *alist;
369 FILE *fp;
370 fp = fopen(filename, "a");
371 if (fp == NULL) {
372 syslog(LOG_ERR, "check_leaks, could not open file: %s",
373 filename);
374 return;
377 flush_caches();
378 fprintf(fp, "*** POSSIBLE LEAKS ****\n");
379 mutex_lock(&alloc_list_lock);
380 alist = halist;
381 while (alist != NULL) {
382 fprintf(fp, "\t%s: %d bytes at %p in %s/%d\n",
383 alist->type, alist->size, alist->addr,
384 alist->file, alist->line);
385 alist = alist->next;
387 mutex_unlock(&alloc_list_lock);
389 (void) fclose(fp);
391 #else
393 * To prevent a compiler warning.
395 static char filler;
396 #endif