Samba utility functions
Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) Jeremy Allison 2001
+ Copyright (C) Simo Sorce 2001
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
/****************************************************************************
find a suitable temporary directory. The result should be copied immediately
- as it may be overwritten by a subsequent call
+ as it may be overwritten by a subsequent call.
****************************************************************************/
char *tmpdir(void)
{
char *p;
- if ((p = getenv("TMPDIR"))) {
+ if ((p = getenv("TMPDIR")))
return p;
- }
return "/tmp";
}
/****************************************************************************
-determine whether we are in the specified group
+ Determine whether we are in the specified group.
****************************************************************************/
BOOL in_group(gid_t group, gid_t current_gid, int ngroups, gid_t *groups)
{
int i;
- if (group == current_gid) return(True);
+ if (group == current_gid)
+ return(True);
for (i=0;i<ngroups;i++)
if (group == groups[i])
return(False);
}
-
/****************************************************************************
-like atoi but gets the value up to the separater character
+ Like atoi but gets the value up to the separater character.
****************************************************************************/
+
char *Atoic(char *p, int *n, char *c)
{
- if (!isdigit((int)*p))
- {
+ if (!isdigit((int)*p)) {
DEBUG(5, ("Atoic: malformed number\n"));
return NULL;
}
(*n) = atoi(p);
while ((*p) && isdigit((int)*p))
- {
p++;
- }
if (strchr_m(c, *p) == NULL)
{
}
/*************************************************************************
- reads a list of numbers
+ Reads a list of numbers.
*************************************************************************/
+
char *get_numlist(char *p, uint32 **num, int *count)
{
int val;
if (num == NULL || count == NULL)
- {
return NULL;
- }
(*count) = 0;
(*num ) = NULL;
- while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':')
- {
+ while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':') {
uint32 *tn;
tn = Realloc((*num), ((*count)+1) * sizeof(uint32));
{
SAFE_FREE(*num);
return NULL;
- }
- else (*num) = tn;
+ } else
+ (*num) = tn;
(*num)[(*count)] = val;
(*count)++;
p++;
return p;
}
-
/*******************************************************************
- check if a file exists - call vfs_file_exist for samba files
+ Check if a file exists - call vfs_file_exist for samba files.
********************************************************************/
+
BOOL file_exist(char *fname,SMB_STRUCT_STAT *sbuf)
{
SMB_STRUCT_STAT st;
- if (!sbuf) sbuf = &st;
+ if (!sbuf)
+ sbuf = &st;
if (sys_stat(fname,sbuf) != 0)
return(False);
}
/*******************************************************************
-check a files mod time
+ Check a files mod time.
********************************************************************/
+
time_t file_modtime(char *fname)
{
SMB_STRUCT_STAT st;
}
/*******************************************************************
- check if a directory exists
+ Check if a directory exists.
********************************************************************/
+
BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st)
{
SMB_STRUCT_STAT st2;
trim_string(s,NULL,"/..");
}
+/*******************************************************************
+convert '\' to '/'
+reduce a file name, removing or reducing /../ , /./ , // elements.
+remove also any trailing . and /
+return a new allocated string.
+********************************************************************/
+smb_ucs2_t *unix_clean_path(const smb_ucs2_t *s)
+{
+ smb_ucs2_t *ns;
+ smb_ucs2_t *p, *r, *t;
+
+ DEBUG(3, ("unix_clean_path\n")); /* [%unicode]\n")); */
+
+ /* convert '\' to '/' */
+ ns = strdup_w(s);
+ if (!ns) return NULL;
+ unix_format_w(ns);
+
+ /* remove all double slashes */
+ p = ns;
+ ns = all_string_sub_wa(p, "//", "/");
+ SAFE_FREE(p);
+ if (!ns) return NULL;
+
+ /* remove any /./ */
+ p = ns;
+ ns = all_string_sub_wa(p, "/./", "/");
+ SAFE_FREE(p);
+ if (!ns) return NULL;
+
+ /* reduce any /../ */
+ t = ns;
+ while ((r = strstr_wa(t, "/.."))) {
+ t = &(r[3]);
+ if (*t == UCS2_CHAR('/') || *t == 0) {
+ *r = 0;
+ p = strrchr_w(ns, UCS2_CHAR('/'));
+ if (!p) p = ns;
+ memmove(p, t, (strlen_w(t) + 1) * sizeof(smb_ucs2_t));
+ t = p;
+ }
+ }
+
+ /* remove any trailing /. */
+ trim_string_wa(ns, NULL, "/.");
+
+ /* remove any leading and trailing / */
+ trim_string_wa(ns, "/", "/");
+
+ return ns;
+}
+
/****************************************************************************
make a dir struct
****************************************************************************/
Transfer some data between two fd's.
****************************************************************************/
+#ifndef TRANSFER_BUF_SIZE
+#define TRANSFER_BUF_SIZE 65536
+#endif
+
ssize_t transfer_file_internal(int infd, int outfd, size_t n, ssize_t (*read_fn)(int, void *, size_t),
ssize_t (*write_fn)(int, const void *, size_t))
{
- static char buf[16384];
+ char *buf;
size_t total = 0;
ssize_t read_ret;
- size_t write_total = 0;
- ssize_t write_ret;
+ ssize_t write_ret;
+ size_t num_to_read_thistime;
+ size_t num_written = 0;
+
+ if ((buf = malloc(TRANSFER_BUF_SIZE)) == NULL)
+ return -1;
while (total < n) {
- size_t num_to_read_thistime = MIN((n - total), sizeof(buf));
+ num_to_read_thistime = MIN((n - total), TRANSFER_BUF_SIZE);
- read_ret = (*read_fn)(infd, buf + total, num_to_read_thistime);
+ read_ret = (*read_fn)(infd, buf, num_to_read_thistime);
if (read_ret == -1) {
DEBUG(0,("transfer_file_internal: read failure. Error = %s\n", strerror(errno) ));
+ SAFE_FREE(buf);
return -1;
}
if (read_ret == 0)
break;
- write_total = 0;
+ num_written = 0;
- while (write_total < read_ret) {
- write_ret = (*write_fn)(outfd,buf + total, read_ret);
+ while (num_written < read_ret) {
+ write_ret = (*write_fn)(outfd,buf + num_written, read_ret - num_written);
if (write_ret == -1) {
DEBUG(0,("transfer_file_internal: write failure. Error = %s\n", strerror(errno) ));
+ SAFE_FREE(buf);
return -1;
}
if (write_ret == 0)
return (ssize_t)total;
- write_total += (size_t)write_ret;
+ num_written += (size_t)write_ret;
}
total += (size_t)read_ret;
}
+ SAFE_FREE(buf);
return (ssize_t)total;
}
}
/*******************************************************************
-sleep for a specified number of milliseconds
+ Sleep for a specified number of milliseconds.
********************************************************************/
+
void msleep(int t)
{
int tdiff=0;
}
}
-
/****************************************************************************
-become a daemon, discarding the controlling terminal
+ Become a daemon, discarding the controlling terminal.
****************************************************************************/
+
void become_daemon(void)
{
if (sys_fork()) {
}
/****************************************************************************
-expand a pointer to be a particular size
+ Expand a pointer to be a particular size.
****************************************************************************/
+
void *Realloc(void *p,size_t size)
{
void *ret=NULL;
return(ret);
}
-
/****************************************************************************
-free memory, checks for NULL and set to NULL
+ Free memory, checks for NULL.
use directly SAFE_FREE()
exist only because we need to pass a function pointer somewhere --SSS
****************************************************************************/
+
void safe_free(void *p)
{
SAFE_FREE(p);
}
/****************************************************************************
-get my own name and IP
+ Get my own name and IP.
****************************************************************************/
+
BOOL get_myname(char *my_name)
{
pstring hostname;
if (my_name) {
/* split off any parts after an initial . */
char *p = strchr_m(hostname,'.');
- if (p) *p = 0;
+
+ if (p)
+ *p = 0;
fstrcpy(my_name,hostname);
}
}
/****************************************************************************
-interpret a protocol description string, with a default
+ Interpret a protocol description string, with a default.
****************************************************************************/
+
int interpret_protocol(char *str,int def)
{
if (strequal(str,"NT1"))
/*******************************************************************
check if an IP is the 0.0.0.0
******************************************************************/
-BOOL zero_ip(struct in_addr ip)
+BOOL is_zero_ip(struct in_addr ip)
{
uint32 a;
putip((char *)&a,(char *)&ip);
return(a == 0);
}
+/* Set an IP to 0.0.0.0 */
+
+void zero_ip(struct in_addr *ip)
+{
+ static BOOL init;
+ static struct in_addr ipzero;
+
+ if (!init) {
+ ipzero = *interpret_addr2("0.0.0.0");
+ init = True;
+ }
+
+ *ip = ipzero;
+}
#if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
/******************************************************************
return(ret);
}
+BOOL is_myname_or_ipaddr(char *s)
+{
+ char **ptr;
+
+ /* optimize for the common case */
+ if (strequal(s, global_myname))
+ return True;
+
+ /* maybe its an IP address? */
+ if (is_ipaddress(s))
+ {
+ struct iface_struct nics[MAX_INTERFACES];
+ int i, n;
+ uint32 ip;
+
+ ip = interpret_addr(s);
+ 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)
+ return True;
+ }
+ }
+
+ /* check for an alias */
+ ptr = lp_netbios_aliases();
+ for ( ; *ptr; ptr++ )
+ {
+ if (StrCaseCmp(s, *ptr) == 0)
+ return True;
+ }
+
+
+ /* no match */
+ return False;
+
+}
+
+
/*******************************************************************
set the horrid remote_arch string based on an enum.
********************************************************************/
#endif
}
-/*****************************************************************
- malloc that aborts with smb_panic on fail or zero size.
- *****************************************************************/
-void *xmalloc(size_t size)
+/**
+ malloc that aborts with smb_panic on fail or zero size.
+**/
+void *smb_xmalloc(size_t size)
{
void *p;
if (size == 0)
- smb_panic("xmalloc: called with zero size.\n");
+ smb_panic("smb_xmalloc: called with zero size.\n");
if ((p = malloc(size)) == NULL)
- smb_panic("xmalloc: malloc fail.\n");
+ smb_panic("smb_xmalloc: malloc fail.\n");
return p;
}
-/*****************************************************************
+/**
Memdup with smb_panic on fail.
- *****************************************************************/
-
-void *xmemdup(void *p, size_t size)
+**/
+void *smb_xmemdup(const void *p, size_t size)
{
void *p2;
- p2 = xmalloc(size);
+ p2 = smb_xmalloc(size);
memcpy(p2, p, size);
return p2;
}
-/*****************************************************************
+/**
strdup that aborts on malloc fail.
- *****************************************************************/
-
-char *xstrdup(const char *s)
+**/
+char *smb_xstrdup(const char *s)
{
char *s1 = strdup(s);
if (!s1)
- smb_panic("xstrdup: malloc fail\n");
+ smb_panic("smb_xstrdup: malloc fail\n");
return s1;
}
+/*
+ vasprintf that aborts on malloc fail
+*/
+int smb_xvasprintf(char **ptr, const char *format, va_list ap)
+{
+ int n;
+ n = vasprintf(ptr, format, ap);
+ if (n == -1 || ! *ptr) {
+ smb_panic("smb_xvasprintf: out of memory");
+ }
+ return n;
+}
+
/*****************************************************************
like strdup but for memory
*****************************************************************/
-void *memdup(void *p, size_t size)
+void *memdup(const void *p, size_t size)
{
void *p2;
if (size == 0) return NULL;
return fname;
}
-/*****************************************************************
-a useful function for returning a path in the Samba lib directory
- *****************************************************************/
+
+/**
+ * @brief Returns an absolute path to a file in the Samba lib directory.
+ *
+ * @param name File to find, relative to LIBDIR.
+ *
+ * @retval Pointer to a static #pstring containing the full path.
+ **/
char *lib_path(char *name)
{
static pstring fname;
- snprintf(fname, sizeof(fname), "%s/%s", LIBDIR, name);
+ snprintf(fname, sizeof(fname), "%s/%s", dyn_LIBDIR, name);
return fname;
}
return False;
}
+BOOL ms_has_wild_w(const smb_ucs2_t *s)
+{
+ smb_ucs2_t c;
+ while ((c = *s++)) {
+ switch (c) {
+ case UCS2_CHAR('*'):
+ case UCS2_CHAR('?'):
+ case UCS2_CHAR('<'):
+ case UCS2_CHAR('>'):
+ case UCS2_CHAR('"'):
+ return True;
+ }
+ }
+ return False;
+}
+
/*******************************************************************
a wrapper that handles case sensitivity and the special handling
of the ".." name
return unix_do_match(p2, s2) == 0;
}
+/*******************************************************************
+ free() a data blob
+*******************************************************************/
+static void free_data_blob(DATA_BLOB *d)
+{
+ if ((d) && (d->free)) {
+ SAFE_FREE(d->data);
+ }
+}
+
/*******************************************************************
construct a data blob, must be freed with data_blob_free()
+ you can pass NULL for p and get a blank data blob
*******************************************************************/
-DATA_BLOB data_blob(void *p, size_t length)
+DATA_BLOB data_blob(const void *p, size_t length)
+{
+ DATA_BLOB ret;
+
+ if (!length) {
+ ZERO_STRUCT(ret);
+ return ret;
+ }
+
+ if (p) {
+ ret.data = smb_xmemdup(p, length);
+ } else {
+ ret.data = smb_xmalloc(length);
+ }
+ ret.length = length;
+ ret.free = free_data_blob;
+ return ret;
+}
+
+/*******************************************************************
+ construct a data blob, using supplied TALLOC_CTX
+*******************************************************************/
+DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length)
{
DATA_BLOB ret;
return ret;
}
- ret.data = xmemdup(p, length);
+ ret.data = talloc_memdup(mem_ctx, p, length);
+ if (ret.data == NULL)
+ smb_panic("data_blob_talloc: talloc_memdup failed.\n");
+
ret.length = length;
+ ret.free = NULL;
return ret;
}
*******************************************************************/
void data_blob_free(DATA_BLOB *d)
{
- SAFE_FREE(d->data);
+ if (d) {
+ if (d->free) {
+ (d->free)(d);
+ }
+ ZERO_STRUCTP(d);
+ }
+}
+
+/*******************************************************************
+clear a DATA_BLOB's contents
+*******************************************************************/
+void data_blob_clear(DATA_BLOB *d)
+{
+ if (d->data) {
+ memset(d->data, 0, d->length);
+ }
}
+/*******************************************************************
+free a data blob and clear its contents
+*******************************************************************/
+void data_blob_clear_free(DATA_BLOB *d)
+{
+ data_blob_clear(d);
+ data_blob_free(d);
+}
#ifdef __INSURE__
static int (*fn)();
int ret;
char pidstr[10];
- pstring cmd = "/usr/X11R6/bin/xterm -display :0 -T Panic -n Panic -e /bin/sh -c 'cat /tmp/ierrs.*.%d ; gdb /proc/%d/exe %d'";
+ /* you can get /usr/bin/backtrace from
+ http://samba.org/ftp/unpacked/junkcode/backtrace */
+ pstring cmd = "/usr/bin/backtrace %d";
slprintf(pidstr, sizeof(pidstr)-1, "%d", sys_getpid());
pstring_sub(cmd, "%d", pidstr);