OpenSolaris_b135/cmd/fs.d/autofs/debug_alloc.c

Compare this file to the similar file:
Show the results in this format:

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1998,2001 by Sun Microsystems, Inc.
 * All rights reserved.
 */

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#ifdef	MALLOC_DEBUG
#include <stdlib.h>
#include <stdio.h>
#include <thread.h>
#include <synch.h>
#include <string.h>
#include <stdio.h>
#include <syslog.h>
#include <netdb.h>
#include <netdir.h>
#include <rpc/nettype.h>

/*
 * To use debugging facility, compile with * -DMALLOC_DEBUG.
 * You can do this by setting the environment variable
 * MALLOC_DEBUG to "-DMALLOC_DEBUG"
 *
 * To make automountd dump trace records (i.e. make it call check_leaks),
 * run:
 * 	make malloc_dump
 */

struct alloc_list
{
	char type[20];
	void *addr;
	int size;
	char file[80];
	int line;
	struct alloc_list *next;
};

static struct alloc_list *halist = NULL;
static mutex_t alloc_list_lock = DEFAULTMUTEX;

int
add_alloc(char *type, void *addr, size_t size, const char *file, int line)
{
	struct alloc_list *alist = NULL;

	/* allocate the list item */
	alist = (struct alloc_list *)malloc(sizeof (*alist));
	if (alist == NULL) {
		syslog(LOG_ERR, "add_alloc: out of memory\n");
		return (-1);
	}
	strcpy(alist->type, type);
	alist->addr = addr;
	alist->size = size;
	strcpy(alist->file, file);
	alist->line = line;

	/* add it to the head of the list */
	if (halist == NULL)
		alist->next = NULL;
	else
		alist->next = halist;
	halist = alist;
	return (0);
}

int
drop_alloc(const char *type, void *addr, const char *file, int line)
{
	struct alloc_list *alist, *alist_prev;

	alist = halist;
	while (alist != NULL) {
		if (addr == alist->addr) {
			if (alist == halist)
				halist = halist->next;
			else
				alist_prev->next = alist->next;
			free(alist);
			break;
		}
		alist_prev = alist;
		alist = alist->next;
	}

	if (alist == NULL) {
		syslog(LOG_ERR, "*** POSSIBLE CORRUPTION ****\n");
		syslog(LOG_ERR, "\tduplicate free, type %s, at %p in %s/%d\n",
		    type, addr, file, line);
		return (-1);
	}
	return (0);
}

void *
my_malloc(size_t size, const char *file, int line)
{
	void *addr;

	addr = (void *)malloc(size);
	if (addr == NULL)
		return (NULL);
	mutex_lock(&alloc_list_lock);
	add_alloc("MALLOC", addr, size, file, line);
	mutex_unlock(&alloc_list_lock);
	return (addr);
}

void *
my_realloc(void *addr, size_t size, const char *file, int line)
{
	void *ptr;

	ptr = (void *)realloc(addr, size);
	if (ptr == NULL)
		return (NULL);
	mutex_lock(&alloc_list_lock);
	drop_alloc("MALLOC", addr, file, line);
	add_alloc("MALLOC", ptr, size, file, line);
	mutex_unlock(&alloc_list_lock);

	return (ptr);
}

void
my_free(void *addr, const char *file, int line)
{
	mutex_lock(&alloc_list_lock);
	drop_alloc("MALLOC", addr, file, line);
	mutex_unlock(&alloc_list_lock);
	free(addr);
}

char *
my_strdup(const char *straddr, const char *file, int line)
{
	void *addr;
	size_t size;

	addr = strdup(straddr);
	if (addr == NULL)
		return (NULL);
	size = strlen(straddr);
	mutex_lock(&alloc_list_lock);
	add_alloc("STRDUP", addr, size, file, line);
	mutex_unlock(&alloc_list_lock);

	return ((char *)addr);
}

int
my_sethostent(int stay, const char *file, int line)
{
	(void) sethostent(stay);
	mutex_lock(&alloc_list_lock);
	add_alloc("SETHOSTENT", NULL, 0, file, line);
	mutex_unlock(&alloc_list_lock);
	return (0);
}

int
my_endhostent(const char *file, int line)
{
	int ret;

	ret = endhostent();
	if (ret != 0)
		return (ret);
	mutex_lock(&alloc_list_lock);
	drop_alloc("SETHOSTENT", NULL, file, line);
	mutex_unlock(&alloc_list_lock);
	return (ret);
}

void *
my_setnetconfig(const char *file, int line)
{
	void *nconf;

	nconf = setnetconfig();
	if (nconf == NULL)
		return (NULL);
	mutex_lock(&alloc_list_lock);
	add_alloc("SETNETCONFIG", nconf, 0, file, line);
	mutex_unlock(&alloc_list_lock);
	return (nconf);
}

int
my_endnetconfig(void *nconf, const char *file, int line)
{
	int res;

	res = endnetconfig(nconf);
	if (res != 0)
		return (res);
	mutex_lock(&alloc_list_lock);
	drop_alloc("SETNETCONFIG", nconf, file, line);
	mutex_unlock(&alloc_list_lock);
	return (0);
}

void *
my_setnetpath(const char *file, int line)
{
	void *npath;

	npath = setnetpath();
	if (npath == NULL)
		return (NULL);
	mutex_lock(&alloc_list_lock);
	add_alloc("SETNETPATH", npath, 0, file, line);
	mutex_unlock(&alloc_list_lock);
	return (npath);
}

int
my_endnetpath(void *npath, const char *file, int line)
{
	int res;

	res = endnetpath(npath);
	if (res != 0)
		return (res);
	mutex_lock(&alloc_list_lock);
	drop_alloc("SETNETPATH", npath, file, line);
	mutex_unlock(&alloc_list_lock);
	return (0);
}

int
my_netdir_getbyname(
	struct netconfig *tp,
	struct nd_hostserv *serv,
	struct nd_addrlist **addrs,
	const char *file,
	int line)
{
	int res;

	res = netdir_getbyname(tp, serv, addrs);
	if (res != 0)
		return (res);
	mutex_lock(&alloc_list_lock);
	add_alloc("NETDIR_GETBYNAME", *addrs, 0, file, line);
	mutex_unlock(&alloc_list_lock);
	return (0);
}

void
my_netdir_free(void *ptr, int type, const char *file, int line)
{
	netdir_free(ptr, type);
	mutex_lock(&alloc_list_lock);
	drop_alloc("NETDIR_GETBYNAME", ptr, file, line);
	mutex_unlock(&alloc_list_lock);
}

struct hostent *
my_getipnodebyname(
	const char *name,
	int af,
	int flags,
	int *error_num,
	char *file,
	int line)
{
	struct hostent *res;

	res = getipnodebyname(name, af, flags, error_num);
	if (res == NULL)
		return (NULL);
	mutex_lock(&alloc_list_lock);
	add_alloc("GETIPNODEBYNAME", res, 0, file, line);
	mutex_unlock(&alloc_list_lock);
	return (res);
}

void
my_freehostent(struct hostent *hent, char *file, int line)
{
	freehostent(hent);
	mutex_lock(&alloc_list_lock);
	drop_alloc("GETIPNODEBYNAME", hent, file, line);
	mutex_unlock(&alloc_list_lock);
}

struct netconfig *
my_getnetconfigent(char *netid, char *file, int line)
{
	struct netconfig *res;

	res = getnetconfigent(netid);
	if (res == NULL)
		return (NULL);
	mutex_lock(&alloc_list_lock);
	add_alloc("GETNETCONFIGENT", res, 0, file, line);
	mutex_unlock(&alloc_list_lock);
	return (res);
}

void
my_freenetconfigent(struct netconfig *netp, char *file, int line)
{
	freenetconfigent(netp);
	mutex_lock(&alloc_list_lock);
	drop_alloc("GETNETCONFIGENT", netp, file, line);
	mutex_unlock(&alloc_list_lock);
}

void *
my__rpc_setconf(char *nettype, char *file, int line)
{
	void *res;

	res = __rpc_setconf(nettype);
	if (res == NULL)
		return (NULL);
	mutex_lock(&alloc_list_lock);
	add_alloc("RPC_SETCONF", res, 0, file, line);
	mutex_unlock(&alloc_list_lock);
	return (res);
}

void
my__rpc_endconf(void *vhandle, char *file, int line)
{
	__rpc_endconf(vhandle);
	mutex_lock(&alloc_list_lock);
	drop_alloc("RPC_SETCONF", vhandle, file, line);
	mutex_unlock(&alloc_list_lock);
}

extern void flush_caches();
void
_flush_caches()
{
}
#pragma weak    flush_caches = _flush_caches

void
check_leaks(char *filename)
{
	struct alloc_list *alist;

	FILE *fp;
	fp = fopen(filename, "a");
	if (fp == NULL) {
		syslog(LOG_ERR, "check_leaks, could not open file: %s",
			filename);
		return;
	}

	flush_caches();
	fprintf(fp, "*** POSSIBLE LEAKS ****\n");
	mutex_lock(&alloc_list_lock);
	alist = halist;
	while (alist != NULL) {
		fprintf(fp, "\t%s: %d bytes at %p in %s/%d\n",
			alist->type, alist->size, alist->addr,
			alist->file, alist->line);
		alist = alist->next;
	}
	mutex_unlock(&alloc_list_lock);

	(void) fclose(fp);
}
#else
/*
 * To prevent a compiler warning.
 */
static char filler;
#endif