mirror of
https://github.com/samba-team/samba.git
synced 2025-01-12 09:18:10 +03:00
74d539f557
the pre-alpha "domain group" etc parameters have disappeared.
- interactive debug detection
- re-added mem_man (andrew's memory management, detects memory corruption)
- american spellings of "initialise" replaced with english spelling of
"initialise".
- started on "lookup_name()" and "lookup_sid()" functions. proper ones.
- moved lots of functions around. created some modules of commonly used
code. e.g the password file locking code, which is used in groupfile.c
and aliasfile.c and smbpass.c
- moved RID_TYPE_MASK up another bit. this is really unfortunate, but
there is no other "fast" way to identify users from groups from aliases.
i do not believe that this code saves us anything (the multipliers)
and puts us at a disadvantage (reduces the useable rid space).
the designers of NT aren't silly: if they can get away with a user-
interface-speed LsaLookupNames / LsaLookupSids, then so can we. i
spoke with isaac at the cifs conference, the only time for example that
they do a security context check is on file create. certainly not on
individual file reads / writes, which would drastically hit their
performance and ours, too.
- renamed myworkgroup to global_sam_name, amongst other things, when used
in the rpc code. there is also a global_member_name, as we are always
responsible for a SAM database, the scope of which is limited by the role
of the machine (e.g if a member of a workgroup, your SAM is for _local_
logins only, and its name is the name of your server. you even still
have a SID. see LsaQueryInfoPolicy, levels 3 and 5).
- updated functionality of groupname.c to be able to cope with names
like DOMAIN\group and SERVER\alias. used this code to be able to
do aliases as well as groups. this code may actually be better
off being used in username mapping, too.
- created a connect to serverlist function in clientgen.c and used it
in password.c
- initialisation in server.c depends on the role of the server. well,
it does now.
- rpctorture. smbtorture. EXERCISE EXTREME CAUTION.
(This used to be commit 0d21e1e609
)
744 lines
21 KiB
C
744 lines
21 KiB
C
#if MEM_MAN
|
|
/* a simple memory manager. All allocates and frees should go through here */
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#define MEM_MAN_MAIN
|
|
|
|
#include "mem_man.h"
|
|
|
|
#ifdef MEM_SIGNAL_HANDLER
|
|
#include <signal.h>
|
|
#endif
|
|
|
|
/*
|
|
this module is stand alone. typically a define will occur in a C file
|
|
like this
|
|
|
|
#define malloc(x) smb_mem_malloc(x,__FILE__,__LINE__)
|
|
#define free(x) smb_mem_free(x,__FILE__,__LINE__)
|
|
|
|
which redirects all calls to malloc and free through this module
|
|
|
|
Various configuration options can be set in mem_man.h. This file also
|
|
includes the defines above - so the complete system can be implemented
|
|
with just one include call.
|
|
|
|
|
|
*/
|
|
|
|
extern FILE *dbf;
|
|
|
|
/*
|
|
ACCESSING the memory manager :
|
|
|
|
mem_init_memory_manager() :
|
|
initialises internal data structures of memory manager
|
|
|
|
void *malloc(size_t size) :
|
|
allocates memory as per usual. also records lots of info
|
|
|
|
int free(void *ptr) :
|
|
frees some memory as per usual. writes errors if necessary.
|
|
|
|
void *smb_mem_resize(void *ptr,size_t newsize) :
|
|
changes the memory assignment size of a pointer. note it may return a
|
|
different pointer than the one given. memory can be sized up or down.
|
|
|
|
int smb_mem_query_size(void *ptr) :
|
|
returns the size of the allocated memory.
|
|
|
|
int smb_mem_query_real_size(void *ptr) :
|
|
returns the actual amount of memory allocated to a pointer.
|
|
|
|
char *smb_mem_query_file(void *ptr) :
|
|
returns the name of the file where the pointer was allocated.
|
|
|
|
int smb_mem_query_line(void *ptr) :
|
|
returns the line of the file where the memory was allocated.
|
|
|
|
void smb_mem_write_status(FILE *outfile) :
|
|
writes short summary of memory stats on the stream.
|
|
|
|
void smb_mem_write_verbose(FILE *outfile) :
|
|
writes lots of info on current allocations to stream.
|
|
|
|
void smb_mem_write_errors(FILE *outfile) :
|
|
writes info on error blocks
|
|
|
|
void smb_mem_write_info(void *ptr,FILE *outfile)
|
|
writes info on one pointer to outfile
|
|
|
|
int smb_mem_test(void *ptr) :
|
|
returns true if the pointer is OK - false if it is not.
|
|
|
|
void smb_mem_set_multiplier(int multiplier) :
|
|
sets defaults amount of memory allocated to multiplier times
|
|
amount requested.
|
|
|
|
int smb_mem_total_errors(void) :
|
|
returns the total number of error blocks
|
|
|
|
void smb_mem_check_buffers(void) :
|
|
checks all buffers for corruption. It marks them as corrupt if they are.
|
|
|
|
kill -USR1 <pid> :
|
|
this will send a signal to the memory manager to do a mem_write_verbose
|
|
it also checks them for corruption. Note that the signal number can be
|
|
set in the header file mem_man.h. This can also be turned off.
|
|
|
|
*/
|
|
|
|
|
|
void smb_mem_write_errors(FILE *outfile);
|
|
void smb_mem_write_verbose(FILE *outfile);
|
|
void smb_mem_write_status(FILE *outfile);
|
|
static void mem_check_buffers(void);
|
|
|
|
|
|
#define FREE_FAILURE 0
|
|
#define FREE_SUCCESS 1
|
|
#define FN
|
|
#define True (0==0)
|
|
#define False (!True)
|
|
#define BUF_SIZE (MEM_CORRUPT_BUFFER * sizeof(char) * 2)
|
|
#define BUF_OFFSET (BUF_SIZE/2)
|
|
|
|
typedef struct
|
|
{
|
|
void *pointer;
|
|
size_t present_size;
|
|
size_t allocated_size;
|
|
unsigned char status;
|
|
short error_number;
|
|
char file[MEM_FILE_STR_LENGTH];
|
|
unsigned short line;
|
|
} memory_struct;
|
|
|
|
/* the order of this enum is important. everything greater than
|
|
S_ALLOCATED is considered an error */
|
|
enum status_types {S_UNALLOCATED,S_ALLOCATED,
|
|
S_ERROR_UNALLOCATED,S_ERROR_FREEING,
|
|
S_CORRUPT_FRONT,S_CORRUPT_BACK,S_CORRUPT_FRONT_BACK};
|
|
|
|
/* here is the data memory */
|
|
|
|
static memory_struct *memory_blocks=NULL; /* these hold the allocation data */
|
|
static int mem_blocks_allocated=0; /* how many mem blocks are allocated */
|
|
static int mem_multiplier; /* this is the current multiplier mor over allocation */
|
|
static int mem_manager_initialised=False; /* has it been initialised ? */
|
|
static int last_block_allocated=0; /* a speed up method - this will contain the
|
|
index of the last block allocated or freed
|
|
to cut down searching time for a new block */
|
|
|
|
|
|
typedef struct
|
|
{
|
|
int status;
|
|
char *label;
|
|
} stat_str_type;
|
|
|
|
static stat_str_type stat_str_struct[] =
|
|
{
|
|
{S_UNALLOCATED,"S_UNALLOCATED"},
|
|
{S_ALLOCATED,"S_ALLOCATED"},
|
|
{S_ERROR_UNALLOCATED,"S_ERROR_UNALLOCATED"},
|
|
{S_ERROR_FREEING,"S_ERROR_FREEING"},
|
|
{S_CORRUPT_FRONT,"S_CORRUPT_FRONT"},
|
|
{S_CORRUPT_BACK,"S_CORRUPT_BACK"},
|
|
{S_CORRUPT_FRONT_BACK,"S_CORRUPT_FRONT_BACK"},
|
|
{-1,NULL}
|
|
};
|
|
|
|
|
|
#define INIT_MANAGER() if (!mem_manager_initialised) mem_init_memory_manager()
|
|
|
|
/*******************************************************************
|
|
returns a pointer to a static string for each status
|
|
********************************************************************/
|
|
static char *status_to_str(int status)
|
|
{
|
|
int i=0;
|
|
while (stat_str_struct[i].label != NULL)
|
|
{
|
|
if (stat_str_struct[i].status == status)
|
|
return(stat_str_struct[i].label);
|
|
i++;
|
|
}
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
|
|
#ifdef MEM_SIGNAL_HANDLER
|
|
/*******************************************************************
|
|
this handles signals - causes a mem_write_verbose on stderr
|
|
********************************************************************/
|
|
static void mem_signal_handler()
|
|
{
|
|
mem_check_buffers();
|
|
smb_mem_write_verbose(dbf);
|
|
signal(MEM_SIGNAL_VECTOR,mem_signal_handler);
|
|
}
|
|
#endif
|
|
|
|
#ifdef MEM_SIGNAL_HANDLER
|
|
/*******************************************************************
|
|
this handles error signals - causes a mem_write_verbose on stderr
|
|
********************************************************************/
|
|
static void error_signal_handler()
|
|
{
|
|
fprintf(dbf,"Received error signal!\n");
|
|
mem_check_buffers();
|
|
smb_mem_write_status(dbf);
|
|
smb_mem_write_errors(dbf);
|
|
abort();
|
|
}
|
|
#endif
|
|
|
|
|
|
/*******************************************************************
|
|
initialise memory manager data structures
|
|
********************************************************************/
|
|
static void mem_init_memory_manager(void)
|
|
{
|
|
int i;
|
|
/* allocate the memory_blocks array */
|
|
mem_blocks_allocated = MEM_MAX_MEM_OBJECTS;
|
|
|
|
while (mem_blocks_allocated > 0)
|
|
{
|
|
memory_blocks = (memory_struct *)
|
|
calloc(mem_blocks_allocated,sizeof(memory_struct));
|
|
if (memory_blocks != NULL) break;
|
|
mem_blocks_allocated /= 2;
|
|
}
|
|
|
|
if (memory_blocks == NULL)
|
|
{
|
|
fprintf(dbf,"Panic ! can't allocate mem manager blocks!\n");
|
|
abort();
|
|
}
|
|
|
|
/* just loop setting status flag to unallocated */
|
|
for (i=0;i<mem_blocks_allocated;i++)
|
|
memory_blocks[i].status = S_UNALLOCATED;
|
|
|
|
/* also set default mem multiplier */
|
|
mem_multiplier = MEM_DEFAULT_MEM_MULTIPLIER;
|
|
mem_manager_initialised=True;
|
|
|
|
#ifdef MEM_SIGNAL_HANDLER
|
|
signal(MEM_SIGNAL_VECTOR,mem_signal_handler);
|
|
signal(SIGSEGV,error_signal_handler);
|
|
signal(SIGBUS,error_signal_handler);
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
finds first available slot in memory blocks
|
|
********************************************************************/
|
|
static int mem_first_avail_slot(void)
|
|
{
|
|
int i;
|
|
for (i=last_block_allocated;i<mem_blocks_allocated;i++)
|
|
if (memory_blocks[i].status == S_UNALLOCATED)
|
|
return(last_block_allocated=i);
|
|
for (i=0;i<last_block_allocated;i++)
|
|
if (memory_blocks[i].status == S_UNALLOCATED)
|
|
return(last_block_allocated=i);
|
|
return(-1);
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
find which Index a pointer refers to
|
|
********************************************************************/
|
|
static int mem_find_Index(void *ptr)
|
|
{
|
|
int i;
|
|
int start = last_block_allocated+mem_blocks_allocated/50;
|
|
if (start > mem_blocks_allocated-1) start = mem_blocks_allocated-1;
|
|
for (i=start;i>=0;i--)
|
|
if ((memory_blocks[i].status == S_ALLOCATED) &&
|
|
(memory_blocks[i].pointer == ptr))
|
|
return(i);
|
|
for (i=(start+1);i<mem_blocks_allocated;i++)
|
|
if ((memory_blocks[i].status == S_ALLOCATED) &&
|
|
(memory_blocks[i].pointer == ptr))
|
|
return(i);
|
|
/* it's not there! */
|
|
return(-1);
|
|
}
|
|
|
|
/*******************************************************************
|
|
fill the buffer areas of a mem block
|
|
********************************************************************/
|
|
static void mem_fill_bytes(void *p,int size,int Index)
|
|
{
|
|
memset(p,Index%256,size);
|
|
}
|
|
|
|
/*******************************************************************
|
|
fill the buffer areas of a mem block
|
|
********************************************************************/
|
|
static void mem_fill_buffer(int Index)
|
|
{
|
|
char *iptr,*tailptr;
|
|
int i;
|
|
int seed;
|
|
|
|
/* fill the front and back ends */
|
|
seed = MEM_CORRUPT_SEED;
|
|
iptr = (char *)((char *)memory_blocks[Index].pointer - BUF_OFFSET);
|
|
tailptr = (char *)((char *)memory_blocks[Index].pointer +
|
|
memory_blocks[Index].present_size);
|
|
|
|
for (i=0;i<MEM_CORRUPT_BUFFER;i++)
|
|
{
|
|
iptr[i] = seed;
|
|
tailptr[i] = seed;
|
|
seed += MEM_SEED_INCREMENT;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************
|
|
check if a mem block is corrupt
|
|
********************************************************************/
|
|
static int mem_buffer_ok(int Index)
|
|
{
|
|
char *iptr;
|
|
int i;
|
|
int corrupt_front = False;
|
|
int corrupt_back = False;
|
|
|
|
/* check the front end */
|
|
iptr = (char *)((char *)memory_blocks[Index].pointer - BUF_OFFSET);
|
|
for (i=0;i<MEM_CORRUPT_BUFFER;i++)
|
|
if (iptr[i] != (char)(MEM_CORRUPT_SEED + i*MEM_SEED_INCREMENT))
|
|
corrupt_front = True;
|
|
|
|
/* now check the tail end */
|
|
iptr = (char *)((char *)memory_blocks[Index].pointer +
|
|
memory_blocks[Index].present_size);
|
|
for (i=0;i<MEM_CORRUPT_BUFFER;i++)
|
|
if (iptr[i] != (char)(MEM_CORRUPT_SEED + i*MEM_SEED_INCREMENT))
|
|
corrupt_back = True;
|
|
|
|
if (corrupt_front && !corrupt_back)
|
|
memory_blocks[Index].status = S_CORRUPT_FRONT;
|
|
if (corrupt_back && !corrupt_front)
|
|
memory_blocks[Index].status = S_CORRUPT_BACK;
|
|
if (corrupt_front && corrupt_back)
|
|
memory_blocks[Index].status = S_CORRUPT_FRONT_BACK;
|
|
if (!corrupt_front && !corrupt_back)
|
|
return(True);
|
|
return(False);
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
check all buffers for corruption
|
|
********************************************************************/
|
|
static void mem_check_buffers(void)
|
|
{
|
|
int i;
|
|
for (i=0;i<mem_blocks_allocated;i++)
|
|
if (memory_blocks[i].status == S_ALLOCATED)
|
|
mem_buffer_ok(i);
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
record stats and alloc memory
|
|
********************************************************************/
|
|
void *smb_mem_malloc(size_t size,char *file,int line)
|
|
{
|
|
int Index;
|
|
INIT_MANAGER();
|
|
|
|
/* find an open spot */
|
|
|
|
Index = mem_first_avail_slot();
|
|
if (Index<0) return(NULL);
|
|
|
|
/* record some info */
|
|
memory_blocks[Index].present_size = size;
|
|
memory_blocks[Index].allocated_size = size*mem_multiplier;
|
|
memory_blocks[Index].line = line;
|
|
strncpy(memory_blocks[Index].file,file,MEM_FILE_STR_LENGTH);
|
|
memory_blocks[Index].file[MEM_FILE_STR_LENGTH-1] = 0;
|
|
memory_blocks[Index].error_number = 0;
|
|
|
|
/* now try and actually get the memory */
|
|
memory_blocks[Index].pointer = malloc(size*mem_multiplier + BUF_SIZE);
|
|
|
|
/* if that failed then try and get exactly what was actually requested */
|
|
if (memory_blocks[Index].pointer == NULL)
|
|
{
|
|
memory_blocks[Index].allocated_size = size;
|
|
memory_blocks[Index].pointer = malloc(size + BUF_SIZE);
|
|
}
|
|
|
|
/* if it failed then return NULL */
|
|
if (memory_blocks[Index].pointer == NULL) return(NULL);
|
|
|
|
|
|
/* it succeeded - set status flag and return */
|
|
memory_blocks[Index].status = S_ALLOCATED;
|
|
|
|
/* add an offset */
|
|
memory_blocks[Index].pointer =
|
|
(void *)((char *)memory_blocks[Index].pointer + BUF_OFFSET);
|
|
|
|
/* fill the buffer appropriately */
|
|
mem_fill_buffer(Index);
|
|
|
|
/* and set the fill byte */
|
|
mem_fill_bytes(memory_blocks[Index].pointer,memory_blocks[Index].present_size,Index);
|
|
|
|
/* return the allocated memory */
|
|
return(memory_blocks[Index].pointer);
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
dup a string
|
|
********************************************************************/
|
|
char *smb_mem_strdup(char *s, char *file, int line)
|
|
{
|
|
char *ret = (char *)smb_mem_malloc(strlen(s)+1, file, line);
|
|
strcpy(ret, s);
|
|
return ret;
|
|
}
|
|
|
|
/*******************************************************************
|
|
free some memory
|
|
********************************************************************/
|
|
int smb_mem_free(void *ptr,char *file,int line)
|
|
{
|
|
int Index;
|
|
int free_ret;
|
|
static int count;
|
|
INIT_MANAGER();
|
|
|
|
if (count % 100 == 0) {
|
|
smb_mem_write_errors(dbf);
|
|
}
|
|
count++;
|
|
|
|
Index = mem_find_Index(ptr);
|
|
|
|
if (Index<0) /* we are freeing a pointer that hasn't been allocated ! */
|
|
{
|
|
/* set up an error block */
|
|
Index = mem_first_avail_slot();
|
|
if (Index < 0) /* I can't even allocate an Error! */
|
|
{
|
|
fprintf(dbf,"Panic in memory manager - can't allocate error block!\n");
|
|
fprintf(dbf,"freeing un allocated pointer at %s(%d)\n",file,line);
|
|
abort();
|
|
}
|
|
/* fill in error block */
|
|
memory_blocks[Index].present_size = 0;
|
|
memory_blocks[Index].allocated_size = 0;
|
|
memory_blocks[Index].line = line;
|
|
strncpy(memory_blocks[Index].file,file,MEM_FILE_STR_LENGTH);
|
|
memory_blocks[Index].file[MEM_FILE_STR_LENGTH-1] = 0;
|
|
memory_blocks[Index].status = S_ERROR_UNALLOCATED;
|
|
memory_blocks[Index].pointer = ptr;
|
|
return(FREE_FAILURE);
|
|
}
|
|
|
|
/* it is a valid pointer - check for corruption */
|
|
if (!mem_buffer_ok(Index))
|
|
/* it's bad ! return an error */
|
|
return(FREE_FAILURE);
|
|
|
|
/* the pointer is OK - try to free it */
|
|
#ifdef MEM_FREE_RETURNS_INT
|
|
free_ret = free((char *)ptr - BUF_OFFSET);
|
|
#else
|
|
free((char *)ptr - BUF_OFFSET);
|
|
free_ret = FREE_SUCCESS;
|
|
#endif
|
|
|
|
|
|
/* if this failed then make an error block again */
|
|
if (free_ret == FREE_FAILURE)
|
|
{
|
|
memory_blocks[Index].present_size = 0;
|
|
memory_blocks[Index].allocated_size = 0;
|
|
memory_blocks[Index].line = line;
|
|
strncpy(memory_blocks[Index].file,file,MEM_FILE_STR_LENGTH);
|
|
memory_blocks[Index].file[MEM_FILE_STR_LENGTH-1] = 0;
|
|
memory_blocks[Index].status = S_ERROR_FREEING;
|
|
memory_blocks[Index].pointer = ptr;
|
|
memory_blocks[Index].error_number = errno;
|
|
return(FREE_FAILURE);
|
|
}
|
|
|
|
/* all is OK - set status and return */
|
|
memory_blocks[Index].status = S_UNALLOCATED;
|
|
|
|
/* this is a speedup - if it is freed then it can be allocated again ! */
|
|
last_block_allocated = Index;
|
|
|
|
return(FREE_SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************
|
|
writes info on just one Index
|
|
it must not be un allocated to do this
|
|
********************************************************************/
|
|
static void mem_write_Index_info(int Index,FILE *outfile)
|
|
{
|
|
if (memory_blocks[Index].status != S_UNALLOCATED)
|
|
fprintf(outfile,"block %d file %s(%d) : ptr: %p size %d, alloc size %d, status %s\n",
|
|
Index,memory_blocks[Index].file,memory_blocks[Index].line,
|
|
memory_blocks[Index].pointer,
|
|
memory_blocks[Index].present_size,
|
|
memory_blocks[Index].allocated_size,
|
|
status_to_str(memory_blocks[Index].status));
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************
|
|
writes info on one pointer
|
|
********************************************************************/
|
|
void smb_mem_write_info(void *ptr,FILE *outfile)
|
|
{
|
|
int Index;
|
|
INIT_MANAGER();
|
|
Index = mem_find_Index(ptr);
|
|
if (Index<0) return;
|
|
mem_write_Index_info(Index,outfile);
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************
|
|
return the size of the mem block
|
|
********************************************************************/
|
|
size_t smb_mem_query_size(void *ptr)
|
|
{
|
|
int Index;
|
|
INIT_MANAGER();
|
|
Index = mem_find_Index(ptr);
|
|
if (Index<0) return(0);
|
|
return(memory_blocks[Index].present_size);
|
|
}
|
|
|
|
/*******************************************************************
|
|
return the allocated size of the mem block
|
|
********************************************************************/
|
|
size_t smb_mem_query_real_size(void *ptr)
|
|
{
|
|
int Index;
|
|
INIT_MANAGER();
|
|
Index = mem_find_Index(ptr);
|
|
if (Index<0) return(0);
|
|
return(memory_blocks[Index].allocated_size);
|
|
}
|
|
|
|
|
|
|
|
|
|
/*******************************************************************
|
|
return the file of caller of the mem block
|
|
********************************************************************/
|
|
char *smb_mem_query_file(void *ptr)
|
|
{
|
|
int Index;
|
|
INIT_MANAGER();
|
|
Index = mem_find_Index(ptr);
|
|
if (Index<0) return(NULL);
|
|
return(memory_blocks[Index].file);
|
|
}
|
|
|
|
|
|
|
|
/*******************************************************************
|
|
return the line in the file of caller of the mem block
|
|
********************************************************************/
|
|
int smb_mem_query_line(void *ptr)
|
|
{
|
|
int Index;
|
|
INIT_MANAGER();
|
|
Index = mem_find_Index(ptr);
|
|
if (Index<0) return(0);
|
|
return(memory_blocks[Index].line);
|
|
}
|
|
|
|
/*******************************************************************
|
|
return True if the pointer is OK
|
|
********************************************************************/
|
|
int smb_mem_test(void *ptr)
|
|
{
|
|
int Index;
|
|
INIT_MANAGER();
|
|
Index = mem_find_Index(ptr);
|
|
if (Index<0) return(False);
|
|
|
|
return(mem_buffer_ok(Index));
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
write brief info on mem status
|
|
********************************************************************/
|
|
void smb_mem_write_status(FILE *outfile)
|
|
{
|
|
int num_allocated=0;
|
|
int total_size=0;
|
|
int total_alloc_size=0;
|
|
int num_errors=0;
|
|
int i;
|
|
INIT_MANAGER();
|
|
mem_check_buffers();
|
|
for (i=0;i<mem_blocks_allocated;i++)
|
|
switch (memory_blocks[i].status)
|
|
{
|
|
case S_UNALLOCATED :
|
|
break;
|
|
case S_ALLOCATED :
|
|
num_allocated++;
|
|
total_size += memory_blocks[i].present_size;
|
|
total_alloc_size += memory_blocks[i].allocated_size;
|
|
break;
|
|
case S_ERROR_UNALLOCATED :
|
|
case S_ERROR_FREEING :
|
|
case S_CORRUPT_BACK :
|
|
case S_CORRUPT_FRONT :
|
|
num_errors++;
|
|
break;
|
|
}
|
|
|
|
fprintf(outfile,
|
|
"Mem Manager : %d blocks, allocation %dK, real allocation %dK, %d errors\n",
|
|
num_allocated,(int)(total_size/1024),(int)(total_alloc_size/1024),
|
|
num_errors);
|
|
fflush(outfile);
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
write verbose info on allocated blocks
|
|
********************************************************************/
|
|
void smb_mem_write_verbose(FILE *outfile)
|
|
{
|
|
int Index;
|
|
/* first write a summary */
|
|
INIT_MANAGER();
|
|
smb_mem_write_status(outfile);
|
|
|
|
/* just loop writing info on relevant indices */
|
|
for (Index=0;Index<mem_blocks_allocated;Index++)
|
|
if (memory_blocks[Index].status != S_UNALLOCATED)
|
|
mem_write_Index_info(Index,outfile);
|
|
}
|
|
|
|
/*******************************************************************
|
|
write verbose info on error blocks
|
|
********************************************************************/
|
|
void smb_mem_write_errors(FILE *outfile)
|
|
{
|
|
int Index;
|
|
INIT_MANAGER();
|
|
mem_check_buffers();
|
|
/* just loop writing info on relevant indices */
|
|
for (Index=0;Index<mem_blocks_allocated;Index++)
|
|
if (((int)memory_blocks[Index].status) > ((int)S_ALLOCATED))
|
|
mem_write_Index_info(Index,outfile);
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
sets the memory multiplier
|
|
********************************************************************/
|
|
void smb_mem_set_multiplier(int multiplier)
|
|
{
|
|
/* check it is valid */
|
|
if (multiplier < 1) return;
|
|
mem_multiplier = multiplier;
|
|
}
|
|
|
|
/*******************************************************************
|
|
increases or decreases the memory assigned to a pointer
|
|
********************************************************************/
|
|
void *smb_mem_resize(void *ptr,size_t newsize)
|
|
{
|
|
int Index;
|
|
size_t allocsize;
|
|
void *temp_ptr;
|
|
INIT_MANAGER();
|
|
Index = mem_find_Index(ptr);
|
|
|
|
/* if invalid return NULL */
|
|
if (Index<0)
|
|
{
|
|
#ifdef BUG
|
|
int Error();
|
|
Error("Invalid mem_resize to size %d\n",newsize);
|
|
#endif
|
|
return(NULL);
|
|
}
|
|
|
|
/* now - will it fit in the current allocation ? */
|
|
if (newsize <= memory_blocks[Index].allocated_size)
|
|
{
|
|
memory_blocks[Index].present_size = newsize;
|
|
mem_fill_buffer(Index);
|
|
return(ptr);
|
|
}
|
|
|
|
/* can it be allocated ? */
|
|
allocsize = newsize*mem_multiplier;
|
|
temp_ptr = malloc(newsize*mem_multiplier + BUF_SIZE);
|
|
|
|
/* no? try with just the size asked for */
|
|
if (temp_ptr == NULL)
|
|
{
|
|
allocsize=newsize;
|
|
temp_ptr = malloc(newsize + BUF_SIZE);
|
|
}
|
|
|
|
/* if it's still NULL give up */
|
|
if (temp_ptr == NULL)
|
|
return(NULL);
|
|
|
|
/* copy the old data to the new memory area */
|
|
memcpy(temp_ptr,(char *)memory_blocks[Index].pointer - BUF_OFFSET,
|
|
memory_blocks[Index].allocated_size + BUF_SIZE);
|
|
|
|
/* fill the extra space */
|
|
mem_fill_bytes((char *)temp_ptr + BUF_OFFSET + memory_blocks[Index].present_size,newsize - memory_blocks[Index].present_size,Index);
|
|
|
|
|
|
/* free the old mem and set vars */
|
|
free((char *)ptr - BUF_OFFSET);
|
|
memory_blocks[Index].pointer = (void *)((char *)temp_ptr + BUF_OFFSET);
|
|
memory_blocks[Index].present_size = newsize;
|
|
memory_blocks[Index].allocated_size = allocsize;
|
|
|
|
/* fill the buffer appropriately */
|
|
mem_fill_buffer(Index);
|
|
|
|
|
|
/* now return the new pointer */
|
|
return((char *)temp_ptr + BUF_OFFSET);
|
|
}
|
|
|
|
#else
|
|
void dummy_mem_man(void) {}
|
|
#endif
|