This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
gfree_case_tables();
gfree_debugsyms();
gfree_charcnv();
- gfree_messages();
+ gfree_interfaces();
/* release the talloc null_context memory last */
talloc_disable_null_tracking();
Add a gid to an array of gids if it's not already there.
****************************************************************************/
-void add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid,
+BOOL add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid,
gid_t **gids, size_t *num_gids)
{
int i;
- for (i=0; i<*num_gids; i++) {
- if ((*gids)[i] == gid)
- return;
+ if ((*num_gids != 0) && (*gids == NULL)) {
+ /*
+ * A former call to this routine has failed to allocate memory
+ */
+ return False;
}
- if (mem_ctx != NULL) {
- *gids = TALLOC_REALLOC_ARRAY(mem_ctx, *gids, gid_t, *num_gids+1);
- } else {
- *gids = SMB_REALLOC_ARRAY(*gids, gid_t, *num_gids+1);
+ for (i=0; i<*num_gids; i++) {
+ if ((*gids)[i] == gid) {
+ return True;
+ }
}
+ *gids = TALLOC_REALLOC_ARRAY(mem_ctx, *gids, gid_t, *num_gids+1);
if (*gids == NULL) {
- return;
+ *num_gids = 0;
+ return False;
}
(*gids)[*num_gids] = gid;
*num_gids += 1;
+ return True;
}
/****************************************************************************
char *attrib_string(uint16 mode)
{
- static fstring attrstr;
+ fstring attrstr;
attrstr[0] = 0;
if (mode & aSYSTEM) fstrcat(attrstr,"S");
if (mode & aRONLY) fstrcat(attrstr,"R");
- return(attrstr);
+ return talloc_strdup(talloc_tos(), attrstr);
}
/*******************************************************************
if (DEBUGLEVEL < 50)
bcc = MIN(bcc, 512);
- dump_data(10, smb_buf(buf), bcc);
+ dump_data(10, (uint8 *)smb_buf(buf), bcc);
}
/*******************************************************************
return set_message_bcc((char *)outbuf,PTR_DIFF(end_ptr,smb_buf((char *)outbuf)));
}
+/*******************************************************************
+ Add a data blob to the end of a smb_buf, adjusting bcc and smb_len.
+ Return the bytes added
+********************************************************************/
+
+ssize_t message_push_blob(uint8 **outbuf, DATA_BLOB blob)
+{
+ size_t newlen = smb_len(*outbuf) + 4 + blob.length;
+ uint8 *tmp;
+
+ if (!(tmp = TALLOC_REALLOC_ARRAY(NULL, *outbuf, uint8, newlen))) {
+ DEBUG(0, ("talloc failed\n"));
+ return -1;
+ }
+ *outbuf = tmp;
+
+ memcpy(tmp + smb_len(tmp) + 4, blob.data, blob.length);
+ set_message_bcc((char *)tmp, smb_buflen(tmp) + blob.length);
+ return blob.length;
+}
+
/*******************************************************************
Reduce a file name, removing .. elements.
********************************************************************/
/* remove any double slashes */
all_string_sub(s, "\\\\", "\\", 0);
+ /* Remove leading .\\ characters */
+ if(strncmp(s, ".\\", 2) == 0) {
+ trim_string(s, ".\\", NULL);
+ if(*s == 0)
+ pstrcpy(s,".\\");
+ }
+
while ((p = strstr_m(s,"\\..\\")) != NULL) {
pstring s1;
}
trim_string(s,NULL,"\\..");
-
all_string_sub(s, "\\.\\", "\\", 0);
}
}
trim_string(s,NULL,"/..");
+ all_string_sub(s, "/./", "/", 0);
+}
+
+void clean_name(char *s)
+{
+ dos_clean_name(s);
+ unix_clean_name(s);
}
/*******************************************************************
void *malloc_(size_t size)
{
+ if (size == 0) {
+ return NULL;
+ }
#undef malloc
return malloc(size);
#define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY
static void *calloc_(size_t count, size_t size)
{
+ if (size == 0 || count == 0) {
+ return NULL;
+ }
#undef calloc
return calloc(count, size);
#define calloc(n,s) __ERROR_DONT_USE_CALLOC_DIRECTLY
return NULL;
}
+ if (el_size == 0 || count == 0) {
+ return NULL;
+ }
#if defined(PARANOID_MALLOC_CHECKER)
return malloc_(el_size*count);
#else
#endif
}
+/****************************************************************************
+ Type-safe memalign
+****************************************************************************/
+
+void *memalign_array(size_t el_size, size_t align, unsigned int count)
+{
+ if (count >= MAX_ALLOC_SIZE/el_size) {
+ return NULL;
+ }
+
+ return sys_memalign(align, el_size*count);
+}
+
/****************************************************************************
Type-safe calloc.
****************************************************************************/
if (nmemb >= MAX_ALLOC_SIZE/size) {
return NULL;
}
+ if (size == 0 || nmemb == 0) {
+ return NULL;
+ }
#if defined(PARANOID_MALLOC_CHECKER)
return calloc_(nmemb, size);
#else
goto error;
}
- if (mem_ctx != NULL) {
- *array = TALLOC(mem_ctx, element_size * (*array_size));
- } else {
- *array = SMB_MALLOC(element_size * (*array_size));
- }
-
+ *array = TALLOC(mem_ctx, element_size * (*array_size));
if (*array == NULL) {
goto error;
}
goto error;
}
- if (mem_ctx != NULL) {
- *array = TALLOC_REALLOC(mem_ctx, *array,
- element_size * (*array_size));
- } else {
- *array = SMB_REALLOC(*array,
- element_size * (*array_size));
- }
+ *array = TALLOC_REALLOC(mem_ctx, *array,
+ element_size * (*array_size));
if (*array == NULL) {
goto error;
BOOL get_myname(char *my_name)
{
- pstring hostname;
+ fstring hostname;
*hostname = 0;
if (gethostname(hostname, sizeof(hostname)) == -1) {
DEBUG(0,("gethostname failed\n"));
return False;
- }
+ }
/* Ensure null termination. */
hostname[sizeof(hostname)-1] = '\0';
if (p)
*p = 0;
-
+
fstrcpy(my_name,hostname);
}
-
+
return(True);
}
if (p) {
p++;
fstrcpy(my_domname, p);
+ return True;
}
return False;
Check if a process exists. Does this work on all unixes?
****************************************************************************/
-BOOL process_exists(const struct process_id pid)
+BOOL process_exists(const struct server_id pid)
{
if (procid_is_me(&pid)) {
return True;
}
- if (!procid_is_local(&pid)) {
- /* This *SEVERELY* needs fixing. */
- return True;
+ if (procid_is_local(&pid)) {
+ return (kill(pid.pid,0) == 0 || errno != ESRCH);
}
- /* Doing kill with a non-positive pid causes messages to be
- * sent to places we don't want. */
- SMB_ASSERT(pid.pid > 0);
- return(kill(pid.pid,0) == 0 || errno != ESRCH);
+#ifdef CLUSTER_SUPPORT
+ return ctdbd_process_exists(messaging_ctdbd_connection(), pid.vnn,
+ pid.pid);
+#else
+ return False;
+#endif
}
BOOL process_exists_by_pid(pid_t pid)
{
- return process_exists(pid_to_procid(pid));
+ /* Doing kill with a non-positive pid causes messages to be
+ * sent to places we don't want. */
+ SMB_ASSERT(pid > 0);
+ return(kill(pid,0) == 0 || errno != ESRCH);
}
/*******************************************************************
const char *uidtoname(uid_t uid)
{
- static fstring name;
- struct passwd *pass;
+ TALLOC_CTX *ctx = talloc_tos();
+ char *name = NULL;
+ struct passwd *pass = NULL;
- pass = getpwuid_alloc(NULL, uid);
+ pass = getpwuid_alloc(ctx,uid);
if (pass) {
- fstrcpy(name, pass->pw_name);
+ name = talloc_strdup(ctx,pass->pw_name);
TALLOC_FREE(pass);
} else {
- slprintf(name, sizeof(name) - 1, "%ld",(long int)uid);
+ name = talloc_asprintf(ctx,
+ "%ld",
+ (long int)uid);
}
return name;
}
-
/*******************************************************************
Convert a gid into a group name.
********************************************************************/
char *gidtoname(gid_t gid)
{
- static fstring name;
+ fstring name;
struct group *grp;
grp = getgrgid(gid);
- if (grp)
- return(grp->gr_name);
- slprintf(name,sizeof(name) - 1, "%d",(int)gid);
- return(name);
+ if (grp) {
+ fstrcpy(name, grp->gr_name);
+ }
+ else {
+ slprintf(name,sizeof(name) - 1, "%d",(int)gid);
+ }
+ return talloc_strdup(talloc_tos(), name);
}
/*******************************************************************
dname = dname - 2;
#endif
- {
- static pstring buf;
- int len = NAMLEN(ptr);
- memcpy(buf, dname, len);
- buf[len] = 0;
- dname = buf;
- }
-
- return(dname);
+ return talloc_strdup(talloc_tos(), dname);
}
/*******************************************************************
BOOL is_in_path(const char *name, name_compare_entry *namelist, BOOL case_sensitive)
{
- pstring last_component;
- char *p;
+ const char *last_component;
/* if we have no list it's obviously not in the path */
if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
DEBUG(8, ("is_in_path: %s\n", name));
/* Get the last component of the unix name. */
- p = strrchr_m(name, '/');
- pstrcpy(last_component, p ? ++p : name);
+ last_component = strrchr_m(name, '/');
+ if (!last_component) {
+ last_component = name;
+ } else {
+ last_component++; /* Go past '/' */
+ }
for(; namelist->name != NULL; namelist++) {
if(namelist->is_wild) {
}
}
DEBUG(8,("is_in_path: match not found\n"));
-
return False;
}
/* optimize for the common case */
- if (strequal(servername, global_myname()))
+ if (strequal(servername, global_myname()))
return True;
/* check for an alias */
/* check for loopback */
- if (strequal(servername, "localhost"))
+ if (strequal(servername, "127.0.0.1"))
+ return True;
+
+ if (strequal(servername, "localhost"))
return True;
/* maybe it's my dns name */
if ( get_mydnsfullname( dnsname ) )
if ( strequal( servername, dnsname ) )
return True;
-
+
/* handle possible CNAME records */
if ( !is_ipaddress( servername ) ) {
putip( (char*)&return_ip, (char*)hp->h_addr );
fstrcpy( name, inet_ntoa( return_ip ) );
servername = name;
- }
+ }
}
-
+
/* maybe its an IP address? */
if (is_ipaddress(servername)) {
struct iface_struct nics[MAX_INTERFACES];
int i, n;
uint32 ip;
-
+
ip = interpret_addr(servername);
if ((ip==0) || (ip==0xffffffff))
return False;
-
+
n = get_interfaces(nics, MAX_INTERFACES);
for (i=0; i<n; i++) {
- if (ip == nics[i].ip.s_addr)
+ if (ip == nics[i].iface_addr.ip.s_addr)
return True;
}
- }
+ }
/* no match */
return False;
/*******************************************************************
we distinguish between 2K and XP by the "Native Lan Manager" string
WinXP => "Windows 2002 5.1"
+ WinXP 64bit => "Windows XP 5.2"
Win2k => "Windows 2000 5.0"
- NT4 => "Windows NT 4.0"
+ NT4 => "Windows NT 4.0"
Win9x => "Windows 4.0"
- Windows 2003 doesn't set the native lan manager string but
+ Windows 2003 doesn't set the native lan manager string but
they do set the domain to "Windows 2003 5.2" (probably a bug).
********************************************************************/
void ra_lanman_string( const char *native_lanman )
-{
+{
if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
set_remote_arch( RA_WINXP );
+ else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
+ set_remote_arch( RA_WINXP );
else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
set_remote_arch( RA_WIN2K3 );
}
case RA_WIN2K3:
fstrcpy(remote_arch, "Win2K3");
break;
+ case RA_VISTA:
+ fstrcpy(remote_arch, "Vista");
+ break;
case RA_SAMBA:
fstrcpy(remote_arch,"Samba");
break;
DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
}
-void dump_data(int level, const char *buf1,int len)
+void dump_data(int level, const unsigned char *buf1,int len)
{
const unsigned char *buf = (const unsigned char *)buf1;
int i=0;
DEBUG(11, ("%s", msg));
if (data != NULL && len > 0)
{
- dump_data(11, (const char *)data, len);
+ dump_data(11, data, len);
}
#endif
}
void *smb_xmalloc_array(size_t size, unsigned int count)
{
void *p;
- if (size == 0)
- smb_panic("smb_xmalloc_array: called with zero size.\n");
+ if (size == 0) {
+ smb_panic("smb_xmalloc_array: called with zero size");
+ }
if (count >= MAX_ALLOC_SIZE/size) {
- smb_panic("smb_xmalloc: alloc size too large.\n");
+ smb_panic("smb_xmalloc_array: alloc size too large");
}
if ((p = SMB_MALLOC(size*count)) == NULL) {
DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
(unsigned long)size, (unsigned long)count));
- smb_panic("smb_xmalloc_array: malloc fail.\n");
+ smb_panic("smb_xmalloc_array: malloc failed");
}
return p;
}
#undef strdup
#endif
#endif
+
+#ifndef HAVE_STRDUP
+#define strdup rep_strdup
+#endif
+
char *s1 = strdup(s);
#if defined(PARANOID_MALLOC_CHECKER)
+#ifdef strdup
+#undef strdup
+#endif
#define strdup(s) __ERROR_DONT_USE_STRDUP_DIRECTLY
#endif
- if (!s1)
- smb_panic("smb_xstrdup: malloc fail\n");
+ if (!s1) {
+ smb_panic("smb_xstrdup: malloc failed");
+ }
return s1;
}
#undef strndup
#endif
#endif
+
+#if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP))
+#undef HAVE_STRNDUP
+#define strndup rep_strndup
+#endif
+
char *s1 = strndup(s, n);
#if defined(PARANOID_MALLOC_CHECKER)
+#ifdef strndup
+#undef strndup
+#endif
#define strndup(s,n) __ERROR_DONT_USE_STRNDUP_DIRECTLY
#endif
- if (!s1)
- smb_panic("smb_xstrndup: malloc fail\n");
+ if (!s1) {
+ smb_panic("smb_xstrndup: malloc failed");
+ }
return s1;
}
VA_COPY(ap2, ap);
n = vasprintf(ptr, format, ap2);
- if (n == -1 || ! *ptr)
+ if (n == -1 || ! *ptr) {
smb_panic("smb_xvasprintf: out of memory");
+ }
return n;
}
char *lock_path(const char *name)
{
- static pstring fname;
+ pstring fname;
pstrcpy(fname,lp_lockdir());
trim_char(fname,'\0','/');
pstrcat(fname,"/");
pstrcat(fname,name);
- return fname;
+ return talloc_strdup(talloc_tos(), fname);
}
/*****************************************************************
char *pid_path(const char *name)
{
- static pstring fname;
+ pstring fname;
pstrcpy(fname,lp_piddir());
trim_char(fname,'\0','/');
pstrcat(fname,"/");
pstrcat(fname,name);
- return fname;
+ return talloc_strdup(talloc_tos(), fname);
}
/**
char *lib_path(const char *name)
{
- static pstring fname;
- fstr_sprintf(fname, "%s/%s", dyn_LIBDIR, name);
- return fname;
+ return talloc_asprintf(talloc_tos(), "%s/%s", dyn_LIBDIR, name);
}
/**
/*******************************************************************
Given a filename - get its directory name
NB: Returned in static storage. Caveats:
- o Not safe in thread environment.
- o Caller must not free.
o If caller wishes to preserve, they should copy.
********************************************************************/
char *parent_dirname(const char *path)
{
- static pstring dirpath;
+ char *parent;
+
+ if (!parent_dirname_talloc(talloc_tos(), path, &parent, NULL)) {
+ return NULL;
+ }
+
+ return parent;
+}
+
+BOOL parent_dirname_talloc(TALLOC_CTX *mem_ctx, const char *dir,
+ char **parent, const char **name)
+{
char *p;
+ ptrdiff_t len;
+
+ p = strrchr_m(dir, '/'); /* Find final '/', if any */
- if (!path)
- return(NULL);
+ if (p == NULL) {
+ if (!(*parent = talloc_strdup(mem_ctx, "."))) {
+ return False;
+ }
+ if (name) {
+ *name = "";
+ }
+ return True;
+ }
- pstrcpy(dirpath, path);
- p = strrchr_m(dirpath, '/'); /* Find final '/', if any */
- if (!p) {
- pstrcpy(dirpath, "."); /* No final "/", so dir is "." */
- } else {
- if (p == dirpath)
- ++p; /* For root "/", leave "/" in place */
- *p = '\0';
+ len = p-dir;
+
+ if (!(*parent = TALLOC_ARRAY(mem_ctx, char, len+1))) {
+ return False;
}
- return dirpath;
-}
+ memcpy(*parent, dir, len);
+ (*parent)[len] = '\0';
+ if (name) {
+ *name = p+1;
+ }
+ return True;
+}
/*******************************************************************
Determine if a pattern contains any Microsoft wildcard characters.
of the ".." name.
*******************************************************************/
-BOOL mask_match(const char *string, char *pattern, BOOL is_case_sensitive)
+BOOL mask_match(const char *string, const char *pattern, BOOL is_case_sensitive)
{
if (strcmp(string,"..") == 0)
string = ".";
pattern translation.
*******************************************************************/
-BOOL mask_match_search(const char *string, char *pattern, BOOL is_case_sensitive)
+BOOL mask_match_search(const char *string, const char *pattern, BOOL is_case_sensitive)
{
if (strcmp(string,"..") == 0)
string = ".";
}
/**********************************************************************
- Converts a name to a fully qalified domain name.
+ Converts a name to a fully qualified domain name.
+ Returns True if lookup succeeded, False if not (then fqdn is set to name)
***********************************************************************/
-void name_to_fqdn(fstring fqdn, const char *name)
+BOOL name_to_fqdn(fstring fqdn, const char *name)
{
struct hostent *hp = sys_gethostbyname(name);
if ( hp && hp->h_name && *hp->h_name ) {
char *full = NULL;
- /* find out i fthe fqdn is returned as an alias
+ /* find out if the fqdn is returned as an alias
* to cope with /etc/hosts files where the first
* name is not the fqdn but the short name */
if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
}
if (full && (StrCaseCmp(full, "localhost.localdomain") == 0)) {
DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
- DEBUGADD(1, (" specifing the machine hostname for address 127.0.0.1 may lead\n"));
- DEBUGADD(1, (" to Kerberos authentication probelms as localhost.localdomain\n"));
- DEBUGADD(1, (" may end up to be used instead of the real machine FQDN.\n"));
+ DEBUGADD(1, (" Specifing the machine hostname for address 127.0.0.1 may lead\n"));
+ DEBUGADD(1, (" to Kerberos authentication problems as localhost.localdomain\n"));
+ DEBUGADD(1, (" may end up being used instead of the real machine FQDN.\n"));
full = hp->h_name;
}
DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
fstrcpy(fqdn, full);
+ return True;
} else {
DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
fstrcpy(fqdn, name);
+ return False;
}
}
DEBUG(0, ("Talloc type mismatch, expected %s, got %s\n",
name, talloc_get_name(ptr)));
- smb_panic("aborting");
+ smb_panic("talloc type mismatch");
/* Keep the compiler happy */
return NULL;
}
return (uint32)-1;
}
-pid_t procid_to_pid(const struct process_id *proc)
+pid_t procid_to_pid(const struct server_id *proc)
{
return proc->pid;
}
-struct process_id pid_to_procid(pid_t pid)
+static uint32 my_vnn = NONCLUSTER_VNN;
+
+void set_my_vnn(uint32 vnn)
+{
+ DEBUG(10, ("vnn pid %d = %u\n", (int)sys_getpid(), (unsigned int)vnn));
+ my_vnn = vnn;
+}
+
+uint32 get_my_vnn(void)
{
- struct process_id result;
+ return my_vnn;
+}
+
+struct server_id pid_to_procid(pid_t pid)
+{
+ struct server_id result;
result.pid = pid;
+#ifdef CLUSTER_SUPPORT
+ result.vnn = my_vnn;
+#endif
return result;
}
-struct process_id procid_self(void)
+struct server_id procid_self(void)
{
return pid_to_procid(sys_getpid());
}
-BOOL procid_equal(const struct process_id *p1, const struct process_id *p2)
+struct server_id server_id_self(void)
{
- return (p1->pid == p2->pid);
+ return procid_self();
}
-BOOL procid_is_me(const struct process_id *pid)
+BOOL procid_equal(const struct server_id *p1, const struct server_id *p2)
{
- return (pid->pid == sys_getpid());
+ if (p1->pid != p2->pid)
+ return False;
+#ifdef CLUSTER_SUPPORT
+ if (p1->vnn != p2->vnn)
+ return False;
+#endif
+ return True;
+}
+
+BOOL cluster_id_equal(const struct server_id *id1,
+ const struct server_id *id2)
+{
+ return procid_equal(id1, id2);
+}
+
+BOOL procid_is_me(const struct server_id *pid)
+{
+ if (pid->pid != sys_getpid())
+ return False;
+#ifdef CLUSTER_SUPPORT
+ if (pid->vnn != my_vnn)
+ return False;
+#endif
+ return True;
}
-struct process_id interpret_pid(const char *pid_string)
+struct server_id interpret_pid(const char *pid_string)
{
+#ifdef CLUSTER_SUPPORT
+ unsigned int vnn, pid;
+ struct server_id result;
+ if (sscanf(pid_string, "%u:%u", &vnn, &pid) == 2) {
+ result.vnn = vnn;
+ result.pid = pid;
+ }
+ else if (sscanf(pid_string, "%u", &pid) == 1) {
+ result.vnn = NONCLUSTER_VNN;
+ result.pid = pid;
+ }
+ else {
+ result.vnn = NONCLUSTER_VNN;
+ result.pid = -1;
+ }
+ return result;
+#else
return pid_to_procid(atoi(pid_string));
+#endif
}
-char *procid_str_static(const struct process_id *pid)
+char *procid_str(TALLOC_CTX *mem_ctx, const struct server_id *pid)
{
- static fstring str;
- fstr_sprintf(str, "%d", pid->pid);
- return str;
+ fstring str;
+#ifdef CLUSTER_SUPPORT
+ if (pid->vnn == NONCLUSTER_VNN) {
+ fstr_sprintf(str, "%d", (int)pid->pid);
+ }
+ else {
+ fstr_sprintf(str, "%u:%d", (unsigned)pid->vnn, (int)pid->pid);
+ }
+#else
+ fstr_sprintf(str, "%d", (int)pid->pid);
+#endif
+ return talloc_strdup(mem_ctx, str);
}
-char *procid_str(TALLOC_CTX *mem_ctx, const struct process_id *pid)
+char *procid_str_static(const struct server_id *pid)
{
- return talloc_strdup(mem_ctx, procid_str_static(pid));
+ return procid_str(talloc_tos(), pid);
}
-BOOL procid_valid(const struct process_id *pid)
+BOOL procid_valid(const struct server_id *pid)
{
return (pid->pid != -1);
}
-BOOL procid_is_local(const struct process_id *pid)
+BOOL procid_is_local(const struct server_id *pid)
{
+#ifdef CLUSTER_SUPPORT
+ return pid->vnn == my_vnn;
+#else
return True;
+#endif
}
int this_is_smp(void)
return 0;
#endif
}
+
+/****************************************************************
+ Check if an offset into a buffer is safe.
+ If this returns True it's safe to indirect into the byte at
+ pointer ptr+off.
+****************************************************************/
+
+BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
+{
+ const char *end_base = buf_base + buf_len;
+ char *end_ptr = ptr + off;
+
+ if (!buf_base || !ptr) {
+ return False;
+ }
+
+ if (end_base < buf_base || end_ptr < ptr) {
+ return False; /* wrap. */
+ }
+
+ if (end_ptr < end_base) {
+ return True;
+ }
+ return False;
+}
+
+/****************************************************************
+ Return a safe pointer into a buffer, or NULL.
+****************************************************************/
+
+char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
+{
+ return is_offset_safe(buf_base, buf_len, ptr, off) ?
+ ptr + off : NULL;
+}
+
+/****************************************************************
+ Return a safe pointer into a string within a buffer, or NULL.
+****************************************************************/
+
+char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
+{
+ if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
+ return NULL;
+ }
+ /* Check if a valid string exists at this offset. */
+ if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
+ return NULL;
+ }
+ return ptr + off;
+}
+
+/****************************************************************
+ Return an SVAL at a pointer, or failval if beyond the end.
+****************************************************************/
+
+int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
+{
+ /*
+ * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
+ * NOT ptr[2].
+ */
+ if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
+ return failval;
+ }
+ return SVAL(ptr,off);
+}
+
+/****************************************************************
+ Return an IVAL at a pointer, or failval if beyond the end.
+****************************************************************/
+
+int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
+{
+ /*
+ * Note we use off+3 here, not off+4 as IVAL accesses
+ * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
+ */
+ if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
+ return failval;
+ }
+ return IVAL(ptr,off);
+}
+
+#if 0
+
+Disable these now we have checked all code paths and ensured
+NULL returns on zero request. JRA.
+
+/****************************************************************
+ talloc wrapper functions that guarentee a null pointer return
+ if size == 0.
+****************************************************************/
+
+#ifndef MAX_TALLOC_SIZE
+#define MAX_TALLOC_SIZE 0x10000000
+#endif
+
+/*
+ * talloc and zero memory.
+ * - returns NULL if size is zero.
+ */
+
+void *_talloc_zero_zeronull(const void *ctx, size_t size, const char *name)
+{
+ void *p;
+
+ if (size == 0) {
+ return NULL;
+ }
+
+ p = talloc_named_const(ctx, size, name);
+
+ if (p) {
+ memset(p, '\0', size);
+ }
+
+ return p;
+}
+
+/*
+ * memdup with a talloc.
+ * - returns NULL if size is zero.
+ */
+
+void *_talloc_memdup_zeronull(const void *t, const void *p, size_t size, const char *name)
+{
+ void *newp;
+
+ if (size == 0) {
+ return NULL;
+ }
+
+ newp = talloc_named_const(t, size, name);
+ if (newp) {
+ memcpy(newp, p, size);
+ }
+
+ return newp;
+}
+
+/*
+ * alloc an array, checking for integer overflow in the array size.
+ * - returns NULL if count or el_size are zero.
+ */
+
+void *_talloc_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name)
+{
+ if (count >= MAX_TALLOC_SIZE/el_size) {
+ return NULL;
+ }
+
+ if (el_size == 0 || count == 0) {
+ return NULL;
+ }
+
+ return talloc_named_const(ctx, el_size * count, name);
+}
+
+/*
+ * alloc an zero array, checking for integer overflow in the array size
+ * - returns NULL if count or el_size are zero.
+ */
+
+void *_talloc_zero_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name)
+{
+ if (count >= MAX_TALLOC_SIZE/el_size) {
+ return NULL;
+ }
+
+ if (el_size == 0 || count == 0) {
+ return NULL;
+ }
+
+ return _talloc_zero(ctx, el_size * count, name);
+}
+
+/*
+ * Talloc wrapper that returns NULL if size == 0.
+ */
+void *talloc_zeronull(const void *context, size_t size, const char *name)
+{
+ if (size == 0) {
+ return NULL;
+ }
+ return talloc_named_const(context, size, name);
+}
+#endif