Version 1.9.
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
#endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
#ifdef WITH_SSL
-#include <ssl.h>
+#include <openssl/ssl.h>
#undef Realloc /* SSLeay defines this and samba has a function of this name */
extern SSL *ssl;
extern int sslFd;
#endif /* WITH_SSL */
-pstring scope = "";
-
-extern int DEBUGLEVEL;
-
int Protocol = PROTOCOL_COREPLUS;
/* a default finfo structure to ensure all fields are sensible */
-file_info def_finfo = {-1,0,0,0,0,0,0,""};
-
-/* the client file descriptor */
-extern int Client;
+file_info def_finfo = {-1,0,0,0,0,0,0,"",""};
/* this is used by the chaining code */
int chain_size = 0;
BOOL short_case_preserve;
BOOL case_mangle;
-fstring remote_machine="";
-fstring local_machine="";
-fstring remote_arch="UNKNOWN";
static enum remote_arch_types ra_type = RA_UNKNOWN;
-fstring remote_proto="UNKNOWN";
pstring user_socket_options=DEFAULT_SOCKET_OPTIONS;
-pstring sesssetup_user="";
-pstring samlogon_user="";
-
-BOOL sam_logon_in_ssb = False;
-
pstring global_myname = "";
fstring global_myworkgroup = "";
char **my_netbios_names;
-static char *filename_dos(char *path,char *buf);
-
-
/****************************************************************************
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(c, *p) == NULL)
+ if (strchr_m(c, *p) == NULL)
{
DEBUG(5, ("Atoic: no separator characters (%s) not found\n", c));
return 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) != ':')
- {
- (*num) = Realloc((*num), ((*count)+1) * sizeof(uint32));
- if ((*num) == NULL)
+ while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':') {
+ uint32 *tn;
+
+ tn = Realloc((*num), ((*count)+1) * sizeof(uint32));
+ if (tn == NULL)
{
+ SAFE_FREE(*num);
return NULL;
- }
+ } else
+ (*num) = tn;
(*num)[(*count)] = val;
(*count)++;
p++;
}
/*******************************************************************
-copy an IP address from one buffer to another
+ Check if a file exists - call vfs_file_exist for samba files.
********************************************************************/
-void putip(void *dest,void *src)
-{
- memcpy(dest,src,4);
-}
-
-
-#define TRUNCATE_NETBIOS_NAME 1
-
-/*******************************************************************
- convert, possibly using a stupid microsoft-ism which has destroyed
- the transport independence of netbios (for CIFS vendors that usually
- use the Win95-type methods, not for NT to NT communication, which uses
- DCE/RPC and therefore full-length unicode strings...) a dns name into
- a netbios name.
-
- the netbios name (NOT necessarily null-terminated) is truncated to 15
- characters.
-
- ******************************************************************/
-char *dns_to_netbios_name(char *dns_name)
-{
- static char netbios_name[16];
- int i;
- StrnCpy(netbios_name, dns_name, 15);
- netbios_name[15] = 0;
-
-#ifdef TRUNCATE_NETBIOS_NAME
- /* ok. this is because of a stupid microsoft-ism. if the called host
- name contains a '.', microsoft clients expect you to truncate the
- netbios name up to and including the '.' this even applies, by
- mistake, to workgroup (domain) names, which is _really_ daft.
- */
- for (i = 15; i >= 0; i--)
- {
- if (netbios_name[i] == '.')
- {
- netbios_name[i] = 0;
- break;
- }
- }
-#endif /* TRUNCATE_NETBIOS_NAME */
-
- return netbios_name;
-}
-
-
-/****************************************************************************
-interpret the weird netbios "name". Return the name type
-****************************************************************************/
-static int name_interpret(char *in,char *out)
-{
- int ret;
- int len = (*in++) / 2;
-
- *out=0;
-
- if (len > 30 || len<1) return(0);
-
- while (len--)
- {
- if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
- *out = 0;
- return(0);
- }
- *out = ((in[0]-'A')<<4) + (in[1]-'A');
- in += 2;
- out++;
- }
- *out = 0;
- ret = out[-1];
-
-#ifdef NETBIOS_SCOPE
- /* Handle any scope names */
- while(*in)
- {
- *out++ = '.'; /* Scope names are separated by periods */
- len = *(unsigned char *)in++;
- StrnCpy(out, in, len);
- out += len;
- *out=0;
- in += len;
- }
-#endif
- return(ret);
-}
-
-/****************************************************************************
-mangle a name into netbios format
-
- Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
-****************************************************************************/
-int name_mangle( char *In, char *Out, char name_type )
- {
- int i;
- int c;
- int len;
- char buf[20];
- char *p = Out;
-
- /* Safely copy the input string, In, into buf[]. */
- (void)memset( buf, 0, 20 );
- if (strcmp(In,"*") == 0)
- buf[0] = '*';
- else
- (void)slprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, name_type );
-
- /* Place the length of the first field into the output buffer. */
- p[0] = 32;
- p++;
-
- /* Now convert the name to the rfc1001/1002 format. */
- for( i = 0; i < 16; i++ )
- {
- c = toupper( buf[i] );
- p[i*2] = ( (c >> 4) & 0x000F ) + 'A';
- p[(i*2)+1] = (c & 0x000F) + 'A';
- }
- p += 32;
- p[0] = '\0';
-
- /* Add the scope string. */
- for( i = 0, len = 0; NULL != scope; i++, len++ )
- {
- switch( scope[i] )
- {
- case '\0':
- p[0] = len;
- if( len > 0 )
- p[len+1] = 0;
- return( name_len(Out) );
- case '.':
- p[0] = len;
- p += (len + 1);
- len = -1;
- break;
- default:
- p[len+1] = scope[i];
- break;
- }
- }
-
- return( name_len(Out) );
- } /* name_mangle */
-/*******************************************************************
- check if a file exists
-********************************************************************/
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);
}
/*******************************************************************
- rename a unix file
+ Check a files mod time.
********************************************************************/
-int file_rename(char *from, char *to)
-{
- int rcode = rename (from, to);
-
- if (errno == EXDEV)
- {
- /* Rename across filesystems needed. */
- rcode = copy_reg (from, to);
- }
- return rcode;
-}
-/*******************************************************************
-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;
return(attrstr);
}
-
-
-/****************************************************************************
- make a file into unix format
-****************************************************************************/
-void unix_format(char *fname)
-{
- string_replace(fname,'\\','/');
-}
-
-/****************************************************************************
- make a file into dos format
-****************************************************************************/
-void dos_format(char *fname)
-{
- string_replace(fname,'/','\\');
-}
-
/*******************************************************************
show a smb message structure
********************************************************************/
dump_data(10, smb_buf(buf), bcc);
}
-/*******************************************************************
- return the length of an smb packet
-********************************************************************/
-int smb_len(char *buf)
-{
- return( PVAL(buf,3) | (PVAL(buf,2)<<8) | ((PVAL(buf,1)&1)<<16) );
-}
-
-/*******************************************************************
- set the length of an smb packet
-********************************************************************/
-void _smb_setlen(char *buf,int len)
-{
- buf[0] = 0;
- buf[1] = (len&0x10000)>>16;
- buf[2] = (len&0xFF00)>>8;
- buf[3] = len&0xFF;
-}
/*******************************************************************
set the length and marker of an smb packet
********************************************************************/
int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
{
- if (zero)
- memset(buf + smb_size,'\0',num_words*2 + num_bytes);
- CVAL(buf,smb_wct) = num_words;
- SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
- smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
- return (smb_size + num_words*2 + num_bytes);
-}
-
-/*******************************************************************
-return the number of smb words
-********************************************************************/
-static int smb_numwords(char *buf)
-{
- return (CVAL(buf,smb_wct));
-}
-
-/*******************************************************************
-return the size of the smb_buf region of a message
-********************************************************************/
-int smb_buflen(char *buf)
-{
- return(SVAL(buf,smb_vwv0 + smb_numwords(buf)*2));
-}
-
-/*******************************************************************
- return a pointer to the smb_buf data area
-********************************************************************/
-static int smb_buf_ofs(char *buf)
-{
- return (smb_size + CVAL(buf,smb_wct)*2);
+ if (zero)
+ memset(buf + smb_size,'\0',num_words*2 + num_bytes);
+ CVAL(buf,smb_wct) = num_words;
+ SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
+ smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
+ return (smb_size + num_words*2 + num_bytes);
}
/*******************************************************************
- return a pointer to the smb_buf data area
+ setup only the byte count for a smb message
********************************************************************/
-char *smb_buf(char *buf)
+int set_message_bcc(char *buf,int num_bytes)
{
- return (buf + smb_buf_ofs(buf));
+ int num_words = CVAL(buf,smb_wct);
+ SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
+ smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
+ return (smb_size + num_words*2 + num_bytes);
}
/*******************************************************************
-return the SMB offset into an SMB buffer
+ setup only the byte count for a smb message, using the end of the
+ message as a marker
********************************************************************/
-int smb_offset(char *p,char *buf)
+int set_message_end(void *outbuf,void *end_ptr)
{
- return(PTR_DIFF(p,buf+4) + chain_size);
+ return set_message_bcc((char *)outbuf,PTR_DIFF(end_ptr,smb_buf((char *)outbuf)));
}
/*******************************************************************
*p = 0;
pstrcpy(s1,p+3);
- if ((p=strrchr(s,'\\')) != NULL)
+ if ((p=strrchr_m(s,'\\')) != NULL)
*p = 0;
else
*s = 0;
*p = 0;
pstrcpy(s1,p+3);
- if ((p=strrchr(s,'/')) != NULL)
+ if ((p=strrchr_m(s,'/')) != NULL)
*p = 0;
else
*s = 0;
}
/*******************************************************************
-reduce a file name, removing .. elements and checking that
-it is below dir in the heirachy. This uses dos_GetWd() and so must be run
-on the system that has the referenced file system.
-
-widelinks are allowed if widelinks is true
+convert '\' to '/'
+reduce a file name, removing or reducing /../ , /./ , // elements.
+remove also any trailing . and /
+return a new allocated string.
********************************************************************/
-
-BOOL reduce_name(char *s,char *dir,BOOL widelinks)
-{
-#ifndef REDUCE_PATHS
- return True;
-#else
- pstring dir2;
- pstring wd;
- pstring base_name;
- pstring newname;
- char *p=NULL;
- BOOL relative = (*s != '/');
-
- *dir2 = *wd = *base_name = *newname = 0;
-
- if (widelinks)
- {
- unix_clean_name(s);
- /* can't have a leading .. */
- if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
- {
- DEBUG(3,("Illegal file name? (%s)\n",s));
- return(False);
- }
-
- if (strlen(s) == 0)
- pstrcpy(s,"./");
-
- return(True);
- }
-
- DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
-
- /* remove any double slashes */
- all_string_sub(s,"//","/",0);
-
- pstrcpy(base_name,s);
- p = strrchr(base_name,'/');
-
- if (!p)
- return(True);
-
- if (!dos_GetWd(wd))
- {
- DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
- return(False);
- }
-
- if (dos_ChDir(dir) != 0)
- {
- DEBUG(0,("couldn't chdir to %s\n",dir));
- return(False);
- }
-
- if (!dos_GetWd(dir2))
- {
- DEBUG(0,("couldn't getwd for %s\n",dir));
- dos_ChDir(wd);
- return(False);
- }
-
- if (p && (p != base_name))
- {
- *p = 0;
- if (strcmp(p+1,".")==0)
- p[1]=0;
- if (strcmp(p+1,"..")==0)
- *p = '/';
- }
-
- if (dos_ChDir(base_name) != 0)
- {
- dos_ChDir(wd);
- DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name));
- return(False);
- }
-
- if (!dos_GetWd(newname))
- {
- dos_ChDir(wd);
- DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
- return(False);
- }
-
- if (p && (p != base_name))
- {
- pstrcat(newname,"/");
- pstrcat(newname,p+1);
- }
-
- {
- size_t l = strlen(dir2);
- if (dir2[l-1] == '/')
- l--;
-
- if (strncmp(newname,dir2,l) != 0)
- {
- dos_ChDir(wd);
- DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,(int)l));
- return(False);
- }
-
- if (relative)
- {
- if (newname[l] == '/')
- pstrcpy(s,newname + l + 1);
- else
- pstrcpy(s,newname+l);
- }
- else
- pstrcpy(s,newname);
- }
-
- dos_ChDir(wd);
-
- if (strlen(s) == 0)
- pstrcpy(s,"./");
-
- DEBUG(3,("reduced to %s\n",s));
- return(True);
-#endif
-}
-
-/****************************************************************************
-expand some *s
-****************************************************************************/
-static void expand_one(char *Mask,int len)
-{
- char *p1;
- while ((p1 = strchr(Mask,'*')) != NULL)
- {
- int lfill = (len+1) - strlen(Mask);
- int l1= (p1 - Mask);
- pstring tmp;
- pstrcpy(tmp,Mask);
- memset(tmp+l1,'?',lfill);
- pstrcpy(tmp + l1 + lfill,Mask + l1 + 1);
- pstrcpy(Mask,tmp);
- }
-}
-
-/****************************************************************************
-parse out a directory name from a path name. Assumes dos style filenames.
-****************************************************************************/
-static void dirname_dos(char *path,char *buf)
-{
- split_at_last_component(path, buf, '\\', NULL);
-}
-
-
-/****************************************************************************
-expand a wildcard expression, replacing *s with ?s
-****************************************************************************/
-void expand_mask(char *Mask,BOOL doext)
-{
- pstring mbeg,mext;
- pstring dirpart;
- pstring filepart;
- BOOL hasdot = False;
- char *p1;
- BOOL absolute = (*Mask == '\\');
-
- *mbeg = *mext = *dirpart = *filepart = 0;
-
- /* parse the directory and filename */
- if (strchr(Mask,'\\'))
- dirname_dos(Mask,dirpart);
-
- filename_dos(Mask,filepart);
-
- pstrcpy(mbeg,filepart);
- if ((p1 = strchr(mbeg,'.')) != NULL)
- {
- hasdot = True;
- *p1 = 0;
- p1++;
- pstrcpy(mext,p1);
- }
- else
- {
- pstrcpy(mext,"");
- if (strlen(mbeg) > 8)
- {
- pstrcpy(mext,mbeg + 8);
- mbeg[8] = 0;
+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;
+ }
}
- }
-
- if (*mbeg == 0)
- pstrcpy(mbeg,"????????");
- if ((*mext == 0) && doext && !hasdot)
- pstrcpy(mext,"???");
-
- if (strequal(mbeg,"*") && *mext==0)
- pstrcpy(mext,"*");
-
- /* expand *'s */
- expand_one(mbeg,8);
- if (*mext)
- expand_one(mext,3);
- pstrcpy(Mask,dirpart);
- if (*dirpart || absolute) pstrcat(Mask,"\\");
- pstrcat(Mask,mbeg);
- pstrcat(Mask,".");
- pstrcat(Mask,mext);
-
- DEBUG(6,("Mask expanded to [%s]\n",Mask));
-}
+ /* remove any trailing /. */
+ trim_string_wa(ns, NULL, "/.");
+ /* remove any leading and trailing / */
+ trim_string_wa(ns, "/", "/");
+ return ns;
+}
/****************************************************************************
make a dir struct
size = 0;
memset(buf+1,' ',11);
- if ((p = strchr(mask2,'.')) != NULL)
+ if ((p = strchr_m(mask2,'.')) != NULL)
{
*p = 0;
- memcpy(buf+1,mask2,MIN(strlen(mask2),8));
- memcpy(buf+9,p+1,MIN(strlen(p+1),3));
+ push_ascii(buf+1,mask2,8, 0);
+ push_ascii(buf+9,p+1,3, 0);
*p = '.';
}
else
- memcpy(buf+1,mask2,MIN(strlen(mask2),11));
+ push_ascii(buf+1,mask2,11, 0);
memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
CVAL(buf,21) = mode;
put_dos_date(buf,22,date);
SSVAL(buf,26,size & 0xFFFF);
SSVAL(buf,28,(size >> 16)&0xFFFF);
- StrnCpy(buf+30,fname,12);
+ push_ascii(buf+30,fname,12, 0);
if (!case_sensitive)
strupper(buf+30);
- DEBUG(8,("put name [%s] into dir struct\n",buf+30));
+ DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
}
{
int fd;
int i;
- close(0); close(1); close(2);
+ close(0); close(1);
+#ifndef __INSURE__
+ close(2);
+#endif
/* try and use up these file descriptors, so silly
library routines writing to stdout etc won't cause havoc */
for (i=0;i<3;i++) {
#undef FLAG_TO_SET
}
-
-/*******************************************************************
-find the difference in milliseconds between two struct timeval
-values
-********************************************************************/
-int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew)
-{
- return((tvalnew->tv_sec - tvalold->tv_sec)*1000 +
- ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000);
-}
-
-
-
/****************************************************************************
-transfer some data between two fd's
+ Transfer some data between two fd's.
****************************************************************************/
-SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n,char *header,int headlen,int align)
-{
- static char *buf=NULL;
- static int size=0;
- char *buf1,*abuf;
- SMB_OFF_T total = 0;
-
- DEBUG(4,("transfer_file n=%.0f (head=%d) called\n",(double)n,headlen));
-
- if (size == 0) {
- size = lp_readsize();
- size = MAX(size,1024);
- }
- while (!buf && size>0) {
- buf = (char *)Realloc(buf,size+8);
- if (!buf) size /= 2;
- }
-
- if (!buf) {
- DEBUG(0,("Can't allocate transfer buffer!\n"));
- exit(1);
- }
-
- abuf = buf + (align%8);
+#ifndef TRANSFER_BUF_SIZE
+#define TRANSFER_BUF_SIZE 65536
+#endif
- if (header)
- n += headlen;
+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))
+{
+ char *buf;
+ size_t total = 0;
+ ssize_t read_ret;
+ ssize_t write_ret;
+ size_t num_to_read_thistime;
+ size_t num_written = 0;
- while (n > 0)
- {
- int s = (int)MIN(n,(SMB_OFF_T)size);
- int ret,ret2=0;
+ if ((buf = malloc(TRANSFER_BUF_SIZE)) == NULL)
+ return -1;
- ret = 0;
+ while (total < n) {
+ num_to_read_thistime = MIN((n - total), TRANSFER_BUF_SIZE);
- if (header && (headlen >= MIN(s,1024))) {
- buf1 = header;
- s = headlen;
- ret = headlen;
- headlen = 0;
- header = NULL;
- } else {
- buf1 = abuf;
- }
+ 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;
- if (header && headlen > 0)
- {
- ret = MIN(headlen,size);
- memcpy(buf1,header,ret);
- headlen -= ret;
- header += ret;
- if (headlen <= 0) header = NULL;
- }
+ num_written = 0;
+
+ 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;
+
+ num_written += (size_t)write_ret;
+ }
- if (s > ret)
- ret += read(infd,buf1+ret,s-ret);
+ total += (size_t)read_ret;
+ }
- if (ret > 0)
- {
- ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret);
- if (ret2 > 0) total += ret2;
- /* if we can't write then dump excess data */
- if (ret2 != ret)
- transfer_file(infd,-1,n-(ret+headlen),NULL,0,0);
- }
- if (ret <= 0 || ret2 != ret)
- return(total);
- n -= ret;
- }
- return(total);
+ SAFE_FREE(buf);
+ return (ssize_t)total;
}
-
-
-/****************************************************************************
-find a pointer to a netbios name
-****************************************************************************/
-static char *name_ptr(char *buf,int ofs)
-{
- unsigned char c = *(unsigned char *)(buf+ofs);
-
- if ((c & 0xC0) == 0xC0)
- {
- uint16 l = RSVAL(buf, ofs) & 0x3FFF;
- DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
- return(buf + l);
- }
- else
- return(buf+ofs);
-}
-
-/****************************************************************************
-extract a netbios name from a buf
-****************************************************************************/
-int name_extract(char *buf,int ofs,char *name)
-{
- char *p = name_ptr(buf,ofs);
- int d = PTR_DIFF(p,buf+ofs);
- pstrcpy(name,"");
- if (d < -50 || d > 50) return(0);
- return(name_interpret(p,name));
-}
-
-/****************************************************************************
-return the total storage length of a mangled name
-****************************************************************************/
-int name_len(char *s1)
-{
- /* NOTE: this argument _must_ be unsigned */
- unsigned char *s = (unsigned char *)s1;
- int len;
-
- /* If the two high bits of the byte are set, return 2. */
- if (0xC0 == (*s & 0xC0))
- return(2);
-
- /* Add up the length bytes. */
- for (len = 1; (*s); s += (*s) + 1) {
- len += *s + 1;
- SMB_ASSERT(len < 80);
- }
-
- return(len);
-} /* name_len */
-
+SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n)
+{
+ return (SMB_OFF_T)transfer_file_internal(infd, outfd, (size_t)n, read, write);
+}
/*******************************************************************
-sleep for a specified number of milliseconds
+ Sleep for a specified number of milliseconds.
********************************************************************/
+
void msleep(int t)
{
int tdiff=0;
FD_ZERO(&fds);
errno = 0;
- sys_select(0,&fds,&tval);
+ sys_select_intr(0,&fds,&tval);
GetTimeOfDay(&t2);
tdiff = TvalDiff(&t1,&t2);
}
}
-
-/*********************************************************
-* Recursive routine that is called by unix_mask_match.
-* Does the actual matching. This is the 'original code'
-* used by the unix matcher.
-*********************************************************/
-
-BOOL unix_do_match(char *str, char *regexp, BOOL case_sig)
-{
- char *p;
-
- for( p = regexp; *p && *str; ) {
- switch(*p) {
- case '?':
- str++; p++;
- break;
-
- case '*':
- /*
- * Look for a character matching
- * the one after the '*'.
- */
- p++;
- if(!*p)
- return True; /* Automatic match */
- while(*str) {
- /*
- * Patch from weidel@multichart.de. In the case of the regexp
- * '*XX*' we want to ensure there are at least 2 'X' characters
- * in the filename after the '*' for a match to be made.
- */
-
- {
- int matchcount=0;
-
- /*
- * Eat all the characters that match, but count how many there were.
- */
-
- while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str)))) {
- str++;
- matchcount++;
- }
-
- /*
- * Now check that if the regexp had n identical characters that
- * matchcount had at least that many matches.
- */
-
- while (( *(p+1) && (case_sig ? (*(p+1) == *p) : (toupper(*(p+1))==toupper(*p))))) {
- p++;
- matchcount--;
- }
- if ( matchcount <= 0 ) {
- return False;
- }
- }
- str--; /* We've eaten the match char after the '*' */
- if(unix_do_match(str,p,case_sig))
- return True;
- if(!*str)
- return False;
- else
- str++;
- }
- return False;
-
- default:
- if(case_sig) {
- if(*str != *p)
- return False;
- } else {
- if(toupper(*str) != toupper(*p))
- return False;
- }
- str++, p++;
- break;
- }
- }
-
- if(!*p && !*str)
- return True;
-
- if (!*p && str[0] == '.' && str[1] == 0)
- return(True);
-
- if (!*str && *p == '?')
- {
- while (*p == '?') p++;
- return(!*p);
- }
-
- if(!*str && (*p == '*' && p[1] == '\0'))
- return True;
- return False;
-}
-
-
-/*********************************************************
-* Routine to match a given string with a regexp - uses
-* simplified regexp that takes * and ? only. Case can be
-* significant or not.
-* This is the 'original code' used by the unix matcher.
-*********************************************************/
-
-static BOOL unix_mask_match(char *str, char *regexp, BOOL case_sig, BOOL trans2)
-{
- char *p;
- pstring p1, p2;
- fstring ebase,eext,sbase,sext;
-
- BOOL matched;
-
- /* Make local copies of str and regexp */
- StrnCpy(p1,regexp,sizeof(pstring)-1);
- StrnCpy(p2,str,sizeof(pstring)-1);
-
- if (!strchr(p2,'.')) {
- pstrcat(p2,".");
- }
-
- /* Remove any *? and ** as they are meaningless */
- for(p = p1; *p; p++)
- while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
- (void)pstrcpy( &p[1], &p[2]);
-
- if (strequal(p1,"*")) return(True);
-
- DEBUG(8,("unix_mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
-
- if (trans2) {
- fstrcpy(ebase,p1);
- fstrcpy(sbase,p2);
- } else {
- if ((p=strrchr(p1,'.'))) {
- *p = 0;
- fstrcpy(ebase,p1);
- fstrcpy(eext,p+1);
- } else {
- fstrcpy(ebase,p1);
- eext[0] = 0;
- }
-
- if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
- *p = 0;
- fstrcpy(sbase,p2);
- fstrcpy(sext,p+1);
- } else {
- fstrcpy(sbase,p2);
- fstrcpy(sext,"");
- }
- }
-
- matched = unix_do_match(sbase,ebase,case_sig) &&
- (trans2 || unix_do_match(sext,eext,case_sig));
-
- DEBUG(8,("unix_mask_match returning %d\n", matched));
-
- return matched;
-}
-
-/*********************************************************
-* Recursive routine that is called by mask_match.
-* Does the actual matching. Returns True if matched,
-* False if failed. This is the 'new' NT style matcher.
-* The win9x_semantics parameter is needed as Win9x matching
-* is *actually different*. In Win9x, trailing '?' characters
-* will only match the *exact* number of characters. Under
-* DOS and NT they match any number. This makes no
-* sense.....
-*********************************************************/
-
-static BOOL do_match(char *str, char *regexp, int case_sig, BOOL win9x_semantics)
-{
- char *p;
-
- for( p = regexp; *p && *str; ) {
- switch(*p) {
- case '?':
- str++; p++;
- break;
-
- case '*':
- /* Look for a character matching
- the one after the '*' */
- p++;
- if(!*p)
- return True; /* Automatic match */
- while(*str) {
- while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
- str++;
-
- /*
- * Patch from weidel@multichart.de. In the case of the regexp
- * '*XX*' we want to ensure there are at least 2 'X' characters
- * in the filename after the '*' for a match to be made.
- */
-
- {
- int matchcount=0;
-
- /*
- * Eat all the characters that match, but count how many there were.
- */
-
- while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str)))) {
- str++;
- matchcount++;
- }
-
- /*
- * Now check that if the regexp had n identical characters that
- * matchcount had at least that many matches.
- */
-
- while (( *(p+1) && (case_sig ? (*(p+1) == *p) : (toupper(*(p+1))==toupper(*p))))) {
- p++;
- matchcount--;
- }
- if ( matchcount <= 0 ) {
- return False;
- }
- }
- str--; /* We've eaten the match char after the '*' */
- if(do_match(str,p,case_sig,win9x_semantics)) {
- return True;
- }
- if(!*str) {
- return False;
- } else {
- str++;
- }
- }
- return False;
-
- default:
- if(case_sig) {
- if(*str != *p) {
- return False;
- }
- } else {
- if(toupper(*str) != toupper(*p)) {
- return False;
- }
- }
- str++, p++;
- break;
- }
- }
-
- if(!*p && !*str)
- return True;
-
- if (!*p && str[0] == '.' && str[1] == 0) {
- return(True);
- }
-
- if (!win9x_semantics) {
- if (!*str && *p == '?') {
- while (*p == '?')
- p++;
- return(!*p);
- }
- }
-
- if(!*str && (*p == '*' && p[1] == '\0')) {
- return True;
- }
-
- return False;
-}
-
-/*********************************************************
-* Routine to check if a given string matches exactly.
-* Case can be significant or not.
-**********************************************************/
-
-BOOL exact_match(char *str, char *regexp, BOOL case_sig)
-{
- return ((case_sig?strcmp(str,regexp):strcasecmp(str,regexp)) == 0);
-}
-
-/*********************************************************
-* Routine to match a given string with a regexp - uses
-* simplified regexp that takes * and ? only. Case can be
-* significant or not.
-* The 8.3 handling was rewritten by Ums Harald <Harald.Ums@pro-sieben.de>
-* This is the new 'NT style' matcher.
-*********************************************************/
-
-BOOL mask_match(char *str, char *regexp, BOOL case_sig, BOOL trans2)
-{
- char *p;
- pstring t_pattern, t_filename, te_pattern, te_filename;
- fstring ebase,eext,sbase,sext;
- BOOL matched = False;
- BOOL win9x_semantics = (get_remote_arch() == RA_WIN95) && trans2;
-
- /* special case - if it is exactly the same then it always matches! */
- if(exact_match(str, regexp, case_sig))
- return True;
-
- /* Make local copies of str and regexp */
- pstrcpy(t_pattern,regexp);
- pstrcpy(t_filename,str);
-
- if(trans2) {
-
- /* a special case for 16 bit apps */
- if (strequal(t_pattern,"????????.???"))
- pstrcpy(t_pattern,"*");
-
-#if 0
- /*
- * Handle broken clients that send us old 8.3 format.
- */
- pstring_sub(t_pattern,"????????","*");
- pstring_sub(t_pattern,".???",".*");
-#endif
- }
-
-#if 0
- /*
- * Not sure if this is a good idea. JRA.
- */
- if(trans2 && is_8_3(t_pattern,False) && is_8_3(t_filename,False))
- trans2 = False;
-#endif
-
-#if 0
- if (!strchr(t_filename,'.')) {
- pstrcat(t_filename,".");
- }
-#endif
-
- /* Remove any *? and ** as they are meaningless */
- pstring_sub(t_pattern, "*?", "*");
- pstring_sub(t_pattern, "**", "*");
-
- if (strequal(t_pattern,"*"))
- return(True);
-
- DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", t_filename, t_pattern, case_sig));
-
- if(trans2) {
- /*
- * Match each component of the regexp, split up by '.'
- * characters.
- */
- char *fp, *rp, *cp2, *cp1;
- BOOL last_wcard_was_star = False;
- int num_path_components, num_regexp_components;
-
- pstrcpy(te_pattern,t_pattern);
- pstrcpy(te_filename,t_filename);
- /*
- * Remove multiple "*." patterns.
- */
- pstring_sub(te_pattern, "*.*.", "*.");
- num_regexp_components = count_chars(te_pattern, '.');
- num_path_components = count_chars(te_filename, '.');
-
- /*
- * Check for special 'hack' case of "DIR a*z". - needs to match a.b.c...z
- */
- if(num_regexp_components == 0)
- matched = do_match( te_filename, te_pattern, case_sig, win9x_semantics);
- else {
- for( cp1 = te_pattern, cp2 = te_filename; cp1;) {
- fp = strchr(cp2, '.');
- if(fp)
- *fp = '\0';
- rp = strchr(cp1, '.');
- if(rp)
- *rp = '\0';
-
- if(cp1[0] && cp1[strlen(cp1)-1] == '*')
- last_wcard_was_star = True;
- else
- last_wcard_was_star = False;
-
- if(!do_match(cp2, cp1, case_sig, win9x_semantics))
- break;
-
- /*
- * Ugly ! Special case for Win9x *only*. If filename is XXXX and pattern extension
- * is '*' or all '?' then disallow match.
- */
-
- if (win9x_semantics) {
- if (*cp2 == '\0' && str_is_all(cp1, '?'))
- break;
- }
-
- cp1 = rp ? rp + 1 : NULL;
- cp2 = fp ? fp + 1 : "";
-
- if(last_wcard_was_star || ((cp1 != NULL) && (*cp1 == '*'))) {
- /* Eat the extra path components. */
- int i;
-
- for(i = 0; i < num_path_components - num_regexp_components; i++) {
- fp = strchr(cp2, '.');
- if(fp)
- *fp = '\0';
-
- if((cp1 != NULL) && do_match( cp2, cp1, case_sig, win9x_semantics)) {
- cp2 = fp ? fp + 1 : "";
- break;
- }
- cp2 = fp ? fp + 1 : "";
- }
- num_path_components -= i;
- }
- }
- if(cp1 == NULL && ((*cp2 == '\0') || last_wcard_was_star))
- matched = True;
- }
- } else {
-
- /* -------------------------------------------------
- * Behaviour of Win95
- * for 8.3 filenames and 8.3 Wildcards
- * -------------------------------------------------
- */
- if (strequal (t_filename, ".")) {
- /*
- * Patterns: *.* *. ?. ? ????????.??? are valid.
- *
- */
- if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
- strequal(t_pattern, "????????.???") ||
- strequal(t_pattern, "?.") || strequal(t_pattern, "?"))
- matched = True;
- } else if (strequal (t_filename, "..")) {
- /*
- * Patterns: *.* *. ?. ? *.? ????????.??? are valid.
- *
- */
- if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
- strequal(t_pattern, "?.") || strequal(t_pattern, "?") ||
- strequal(t_pattern, "????????.???") ||
- strequal(t_pattern, "*.?") || strequal(t_pattern, "?.*"))
- matched = True;
- } else {
-
- if ((p = strrchr (t_pattern, '.'))) {
- /*
- * Wildcard has a suffix.
- */
- *p = 0;
- fstrcpy (ebase, t_pattern);
- if (p[1]) {
- fstrcpy (eext, p + 1);
- } else {
- /* pattern ends in DOT: treat as if there is no DOT */
- *eext = 0;
- if (strequal (ebase, "*"))
- return (True);
- }
- } else {
- /*
- * No suffix for wildcard.
- */
- fstrcpy (ebase, t_pattern);
- eext[0] = 0;
- }
-
- p = strrchr (t_filename, '.');
- if (p && (p[1] == 0) ) {
- /*
- * Filename has an extension of '.' only.
- */
- *p = 0; /* nuke dot at end of string */
- p = 0; /* and treat it as if there is no extension */
- }
-
- if (p) {
- /*
- * Filename has an extension.
- */
- *p = 0;
- fstrcpy (sbase, t_filename);
- fstrcpy (sext, p + 1);
- if (*eext) {
- matched = do_match(sbase, ebase, case_sig, False)
- && do_match(sext, eext, case_sig, False);
- } else {
- /* pattern has no extension */
- /* Really: match complete filename with pattern ??? means exactly 3 chars */
- matched = do_match(str, ebase, case_sig, False);
- }
- } else {
- /*
- * Filename has no extension.
- */
- fstrcpy (sbase, t_filename);
- fstrcpy (sext, "");
- if (*eext) {
- /* pattern has extension */
- matched = do_match(sbase, ebase, case_sig, False)
- && do_match(sext, eext, case_sig, False);
-
- } else {
- matched = do_match(sbase, ebase, case_sig, False);
-#ifdef EMULATE_WEIRD_W95_MATCHING
- /*
- * Even Microsoft has some problems
- * Behaviour Win95 -> local disk
- * is different from Win95 -> smb drive from Nt 4.0
- * This branch would reflect the Win95 local disk behaviour
- */
- if (!matched) {
- /* a? matches aa and a in w95 */
- fstrcat (sbase, ".");
- matched = do_match(sbase, ebase, case_sig, False);
- }
-#endif
- }
- }
- }
- }
-
- DEBUG(8,("mask_match returning %d\n", matched));
-
- return matched;
-}
-
/****************************************************************************
-become a daemon, discarding the controlling terminal
+ Become a daemon, discarding the controlling terminal.
****************************************************************************/
+
void become_daemon(void)
{
- if (fork()) {
+ if (sys_fork()) {
_exit(0);
}
}
/****************************************************************************
-set the length of a file from a filedescriptor.
-Returns 0 on success, -1 on failure.
+ Expand a pointer to be a particular size.
****************************************************************************/
-int set_filelen(int fd, SMB_OFF_T len)
-{
-/* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
- extend a file with ftruncate. Provide alternate implementation
- for this */
-
-#ifdef HAVE_FTRUNCATE_EXTEND
- return sys_ftruncate(fd, len);
-#else
- SMB_STRUCT_STAT st;
- char c = 0;
- SMB_OFF_T currpos = sys_lseek(fd, (SMB_OFF_T)0, SEEK_CUR);
-
- if(currpos == -1)
- return -1;
- /* Do an fstat to see if the file is longer than
- the requested size (call ftruncate),
- or shorter, in which case seek to len - 1 and write 1
- byte of zero */
- if(sys_fstat(fd, &st)<0)
- return -1;
-
-#ifdef S_ISFIFO
- if (S_ISFIFO(st.st_mode))
- return 0;
-#endif
-
- if(st.st_size == len)
- return 0;
- if(st.st_size > len)
- return sys_ftruncate(fd, len);
-
- if(sys_lseek(fd, len-1, SEEK_SET) != len -1)
- return -1;
- if(write(fd, &c, 1)!=1)
- return -1;
- /* Seek to where we were */
- if(sys_lseek(fd, currpos, SEEK_SET) != currpos)
- return -1;
- return 0;
-#endif
-}
-
-
-#ifdef HPUX
-/****************************************************************************
-this is a version of setbuffer() for those machines that only have setvbuf
-****************************************************************************/
- void setbuffer(FILE *f,char *buf,int bufsize)
-{
- setvbuf(f,buf,_IOFBF,bufsize);
-}
-#endif
-
-
-/****************************************************************************
-parse out a filename from a path name. Assumes dos style filenames.
-****************************************************************************/
-static char *filename_dos(char *path,char *buf)
-{
- char *p = strrchr(path,'\\');
-
- if (!p)
- pstrcpy(buf,path);
- else
- pstrcpy(buf,p+1);
-
- return(buf);
-}
-
-
-
-/****************************************************************************
-expand a pointer to be a particular size
-****************************************************************************/
void *Realloc(void *p,size_t size)
{
void *ret=NULL;
if (size == 0) {
- if (p) free(p);
+ SAFE_FREE(p);
DEBUG(5,("Realloc asked for 0 bytes\n"));
return NULL;
}
return(ret);
}
+/****************************************************************************
+ 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(hostname,'.');
- if (p) *p = 0;
+ char *p = strchr_m(hostname,'.');
+
+ if (p)
+ *p = 0;
fstrcpy(my_name,hostname);
}
return(True);
}
-
/****************************************************************************
-true if two IP addresses are equal
+ Interpret a protocol description string, with a default.
****************************************************************************/
-BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
-{
- return ip1.s_addr == ip2.s_addr;
-}
-
-/****************************************************************************
-interpret a protocol description string, with a default
-****************************************************************************/
int interpret_protocol(char *str,int def)
{
if (strequal(str,"NT1"))
pure_address = False;
/* Check that a pure number is not misinterpreted as an IP */
- pure_address = pure_address && (strchr(str, '.') != NULL);
+ pure_address = pure_address && (strchr_m(str, '.') != NULL);
return pure_address;
}
interpret an internet address or name into an IP address in 4 byte form
****************************************************************************/
-uint32 interpret_addr(char *str)
+uint32 interpret_addr(const char *str)
{
struct hostent *hp;
uint32 res;
res = inet_addr(str);
} else {
/* otherwise assume it's a network name of some sort and use
- Get_Hostbyname */
- if ((hp = Get_Hostbyname(str)) == 0) {
- DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
+ sys_gethostbyname */
+ if ((hp = sys_gethostbyname(str)) == 0) {
+ DEBUG(3,("sys_gethostbyname: Unknown host. %s\n",str));
return 0;
}
if(hp->h_addr == NULL) {
- DEBUG(3,("Get_Hostbyname: host address is invalid for host %s\n",str));
+ DEBUG(3,("sys_gethostbyname: host address is invalid for host %s\n",str));
return 0;
}
putip((char *)&res,(char *)hp->h_addr);
/*******************************************************************
a convenient addition to interpret_addr()
******************************************************************/
-struct in_addr *interpret_addr2(char *str)
+struct in_addr *interpret_addr2(const char *str)
{
static struct in_addr ret;
uint32 a = interpret_addr(str);
/*******************************************************************
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 */
-/*******************************************************************
- matchname - determine if host name matches IP address
- ******************************************************************/
-BOOL matchname(char *remotehost,struct in_addr addr)
+void zero_ip(struct in_addr *ip)
{
- struct hostent *hp;
- int i;
-
- if ((hp = Get_Hostbyname(remotehost)) == 0) {
- DEBUG(0,("Get_Hostbyname(%s): lookup failure.\n", remotehost));
- return False;
- }
-
- /*
- * Make sure that gethostbyname() returns the "correct" host name.
- * Unfortunately, gethostbyname("localhost") sometimes yields
- * "localhost.domain". Since the latter host name comes from the
- * local DNS, we just have to trust it (all bets are off if the local
- * DNS is perverted). We always check the address list, though.
- */
-
- if (strcasecmp(remotehost, hp->h_name)
- && strcasecmp(remotehost, "localhost")) {
- DEBUG(0,("host name/name mismatch: %s != %s\n",
- remotehost, hp->h_name));
- return False;
- }
-
- /* Look up the host address in the address list we just got. */
- for (i = 0; hp->h_addr_list[i]; i++) {
- if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
- return True;
- }
+ static BOOL init;
+ static struct in_addr ipzero;
- /*
- * The host name does not map to the original host address. Perhaps
- * someone has compromised a name server. More likely someone botched
- * it, but that could be dangerous, too.
- */
-
- DEBUG(0,("host name/address mismatch: %s != %s\n",
- inet_ntoa(addr), hp->h_name));
- return False;
-}
+ if (!init) {
+ ipzero = *interpret_addr2("0.0.0.0");
+ init = True;
+ }
+ *ip = ipzero;
+}
#if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
/******************************************************************
*******************************************************************/
#ifdef WITH_NISPLUS_HOME
-static char *automount_lookup(char *user_name)
+char *automount_lookup(const char *user_name)
{
static fstring last_key = "";
static pstring last_value = "";
char *nis_map = (char *)lp_nis_home_map_name();
- char nis_domain[NIS_MAXNAMELEN + 1];
char buffer[NIS_MAXATTRVAL + 1];
nis_result *result;
nis_object *object;
entry_obj *entry;
- strncpy(nis_domain, (char *)nis_local_directory(), NIS_MAXNAMELEN);
- nis_domain[NIS_MAXNAMELEN] = '\0';
-
- DEBUG(5, ("NIS+ Domain: %s\n", nis_domain));
-
if (strcmp(user_name, last_key))
{
- slprintf(buffer, sizeof(buffer)-1, "[%s=%s]%s.%s", "key", user_name, nis_map, nis_domain);
+ slprintf(buffer, sizeof(buffer)-1, "[key=%s],%s", user_name, nis_map);
DEBUG(5, ("NIS+ querystring: %s\n", buffer));
- if (result = nis_list(buffer, RETURN_RESULT, NULL, NULL))
+ if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL))
{
if (result->status != NIS_SUCCESS)
{
return last_value;
}
#else /* WITH_NISPLUS_HOME */
-static char *automount_lookup(char *user_name)
+char *automount_lookup(const char *user_name)
{
static fstring last_key = "";
static pstring last_value = "";
char *nis_domain; /* yp_get_default_domain inits this */
char *nis_map = (char *)lp_nis_home_map_name();
- if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
- {
+ if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
return last_value;
}
DEBUG(5, ("NIS Domain: %s\n", nis_domain));
- if (!strcmp(user_name, last_key))
- {
- nis_result = last_value;
+ if (!strcmp(user_name, last_key)) {
+ nis_result = last_value;
nis_result_len = strlen(last_value);
nis_error = 0;
- }
- else
- {
+
+ } else {
+
if ((nis_error = yp_match(nis_domain, nis_map,
user_name, strlen(user_name),
- &nis_result, &nis_result_len)) != 0)
- {
- DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
+ &nis_result, &nis_result_len)) == 0) {
+ if (!nis_error && nis_result_len >= sizeof(pstring)) {
+ nis_result_len = sizeof(pstring)-1;
+ }
+ fstrcpy(last_key, user_name);
+ strncpy(last_value, nis_result, nis_result_len);
+ last_value[nis_result_len] = '\0';
+ strip_mount_options(&last_value);
+
+ } else if(nis_error == YPERR_KEY) {
+
+ /* If Key lookup fails user home server is not in nis_map
+ use default information for server, and home directory */
+ last_value[0] = 0;
+ DEBUG(3, ("YP Key not found: while looking up \"%s\" in map \"%s\"\n",
+ user_name, nis_map));
+ DEBUG(3, ("using defaults for server and home directory\n"));
+ } else {
+ DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
yperr_string(nis_error), user_name, nis_map));
}
- if (!nis_error && nis_result_len >= sizeof(pstring))
- {
- nis_result_len = sizeof(pstring)-1;
- }
- fstrcpy(last_key, user_name);
- strncpy(last_value, nis_result, nis_result_len);
- last_value[nis_result_len] = '\0';
}
- strip_mount_options(&last_value);
DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
return last_value;
#endif /* WITH_NISPLUS_HOME */
#endif
-/*******************************************************************
- Patch from jkf@soton.ac.uk
- This is Luke's original function with the NIS lookup code
- moved out to a separate function.
-*******************************************************************/
-static char *automount_server(char *user_name)
-{
- static pstring server_name;
-
- /* use the local machine name as the default */
- /* this will be the default if WITH_AUTOMOUNT is not used or fails */
- pstrcpy(server_name, local_machine);
-
-#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
-
- if (lp_nis_home_map())
- {
- int home_server_len;
- char *automount_value = automount_lookup(user_name);
- home_server_len = strcspn(automount_value,":");
- DEBUG(5, ("NIS lookup succeeded. Home server length: %d\n",home_server_len));
- if (home_server_len > sizeof(pstring))
- {
- home_server_len = sizeof(pstring);
- }
- strncpy(server_name, automount_value, home_server_len);
- server_name[home_server_len] = '\0';
- }
-#endif
-
- DEBUG(4,("Home server: %s\n", server_name));
-
- return server_name;
-}
-
-/*******************************************************************
- Patch from jkf@soton.ac.uk
- Added this to implement %p (NIS auto-map version of %H)
-*******************************************************************/
-static char *automount_path(char *user_name)
-{
- static pstring server_path;
-
- /* use the passwd entry as the default */
- /* this will be the default if WITH_AUTOMOUNT is not used or fails */
- /* pstrcpy() copes with get_user_home_dir() returning NULL */
- pstrcpy(server_path, get_user_home_dir(user_name));
-
-#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
-
- if (lp_nis_home_map())
- {
- char *home_path_start;
- char *automount_value = automount_lookup(user_name);
- home_path_start = strchr(automount_value,':');
- if (home_path_start != NULL)
- {
- DEBUG(5, ("NIS lookup succeeded. Home path is: %s\n",
- home_path_start?(home_path_start+1):""));
- pstrcpy(server_path, home_path_start+1);
- }
- }
-#endif
-
- DEBUG(4,("Home server path: %s\n", server_path));
-
- return server_path;
-}
-
-/*******************************************************************
- Given a pointer to a %$(NAME) expand it as an environment variable.
- Return the number of characters by which the pointer should be advanced.
- Based on code by Branko Cibej <branko.cibej@hermes.si>
- When this is called p points at the '%' character.
-********************************************************************/
-
-static size_t expand_env_var(char *p, int len)
-{
- fstring envname;
- char *envval;
- char *q, *r;
- int copylen;
-
- if (p[1] != '$')
- return 1;
-
- if (p[2] != '(')
- return 2;
-
- /*
- * Look for the terminating ')'.
- */
-
- if ((q = strchr(p,')')) == NULL) {
- DEBUG(0,("expand_env_var: Unterminated environment variable [%s]\n", p));
- return 2;
- }
-
- /*
- * Extract the name from within the %$(NAME) string.
- */
-
- r = p+3;
- copylen = MIN((q-r),(sizeof(envname)-1));
- strncpy(envname,r,copylen);
- envname[copylen] = '\0';
-
- if ((envval = getenv(envname)) == NULL) {
- DEBUG(0,("expand_env_var: Environment variable [%s] not set\n", envname));
- return 2;
- }
-
- /*
- * Copy the full %$(NAME) into envname so it
- * can be replaced.
- */
-
- copylen = MIN((q+1-p),(sizeof(envname)-1));
- strncpy(envname,p,copylen);
- envname[copylen] = '\0';
- string_sub(p,envname,envval,len);
- return 0; /* Allow the environment contents to be parsed. */
-}
-
-/*******************************************************************
- Substitute strings with useful parameters.
- Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
- Paul Rippin <pr3245@nopc.eurostat.cec.be>.
-********************************************************************/
-
-void standard_sub_basic(char *str)
-{
- char *s, *p;
- char pidstr[10];
- struct passwd *pass;
- char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user;
-
- for (s = str ; s && *s && (p = strchr(s,'%')); s = p )
- {
- int l = sizeof(pstring) - (int)(p-str);
-
- if (l < 0) {
- DEBUG(0,("ERROR: string overflow by %d in standard_sub_basic(%.50s)\n",
- -l, str));
-
- return;
- }
-
- switch (*(p+1))
- {
- case 'G' :
- {
- if ((pass = Get_Pwnam(username,False))!=NULL) {
- string_sub(p,"%G",gidtoname(pass->pw_gid),l);
- } else {
- p += 2;
- }
- break;
- }
- case 'N' : string_sub(p,"%N", automount_server(username),l); break;
- case 'I' : string_sub(p,"%I", client_addr(Client),l); break;
- case 'L' : string_sub(p,"%L", local_machine,l); break;
- case 'M' : string_sub(p,"%M", client_name(Client),l); break;
- case 'R' : string_sub(p,"%R", remote_proto,l); break;
- case 'T' : string_sub(p,"%T", timestring(False),l); break;
- case 'U' : string_sub(p,"%U", username,l); break;
- case 'a' : string_sub(p,"%a", remote_arch,l); break;
- case 'd' :
- {
- slprintf(pidstr,sizeof(pidstr) - 1, "%d",(int)getpid());
- string_sub(p,"%d", pidstr,l);
- break;
- }
- case 'h' : string_sub(p,"%h", myhostname(),l); break;
- case 'm' : string_sub(p,"%m", remote_machine,l); break;
- case 'v' : string_sub(p,"%v", VERSION,l); break;
- case '$' : p += expand_env_var(p,l); break; /* Expand environment variables */
- case '\0': p++; break; /* don't run off end if last character is % */
- default : p+=2; break;
- }
- }
- return;
-}
-
-
-/****************************************************************************
- Do some standard substitutions in a string.
-****************************************************************************/
-
-void standard_sub(connection_struct *conn,char *str)
-{
- char *p, *s, *home;
-
- for (s=str; (p=strchr(s, '%'));s=p) {
- int l = sizeof(pstring) - (int)(p-str);
-
- switch (*(p+1)) {
- case 'H':
- if ((home = get_user_home_dir(conn->user))) {
- string_sub(p,"%H",home,l);
- } else {
- p += 2;
- }
- break;
-
- case 'P':
- string_sub(p,"%P",conn->connectpath,l);
- break;
-
- case 'S':
- string_sub(p,"%S",
- lp_servicename(SNUM(conn)),l);
- break;
-
- case 'g':
- string_sub(p,"%g",
- gidtoname(conn->gid),l);
- break;
- case 'u':
- string_sub(p,"%u",conn->user,l);
- break;
-
- /* Patch from jkf@soton.ac.uk Left the %N (NIS
- * server name) in standard_sub_basic as it is
- * a feature for logon servers, hence uses the
- * username. The %p (NIS server path) code is
- * here as it is used instead of the default
- * "path =" string in [homes] and so needs the
- * service name, not the username. */
- case 'p':
- string_sub(p,"%p",
- automount_path(lp_servicename(SNUM(conn))),l);
- break;
- case '\0':
- p++;
- break; /* don't run off the end of the string
- */
-
- default: p+=2;
- break;
- }
- }
-
- standard_sub_basic(str);
-}
-
-
/*******************************************************************
are two IPs on the same subnet?
********************************************************************/
BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
-{
- uint32 net1,net2,nmask;
-
- nmask = ntohl(mask.s_addr);
- net1 = ntohl(ip1.s_addr);
- net2 = ntohl(ip2.s_addr);
-
- return((net1 & nmask) == (net2 & nmask));
-}
-
-
-/****************************************************************************
-a wrapper for gethostbyname() that tries with all lower and all upper case
-if the initial name fails
-****************************************************************************/
-struct hostent *Get_Hostbyname(const char *name)
-{
- char *name2 = strdup(name);
- struct hostent *ret;
-
- if (!name2)
- {
- DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
- exit(0);
- }
-
-
- /*
- * This next test is redundent and causes some systems (with
- * broken isalnum() calls) problems.
- * JRA.
- */
-
-#if 0
- if (!isalnum(*name2))
- {
- free(name2);
- return(NULL);
- }
-#endif /* 0 */
-
- ret = sys_gethostbyname(name2);
- if (ret != NULL)
- {
- free(name2);
- return(ret);
- }
-
- /* try with all lowercase */
- strlower(name2);
- ret = sys_gethostbyname(name2);
- if (ret != NULL)
- {
- free(name2);
- return(ret);
- }
+{
+ uint32 net1,net2,nmask;
- /* try with all uppercase */
- strupper(name2);
- ret = sys_gethostbyname(name2);
- if (ret != NULL)
- {
- free(name2);
- return(ret);
- }
-
- /* nothing works :-( */
- free(name2);
- return(NULL);
+ nmask = ntohl(mask.s_addr);
+ net1 = ntohl(ip1.s_addr);
+ net2 = ntohl(ip2.s_addr);
+
+ return((net1 & nmask) == (net2 & nmask));
}
/*******************************************************************
-turn a uid into a user name
+ Convert a uid into a user name.
********************************************************************/
+
char *uidtoname(uid_t uid)
{
- static char name[40];
- struct passwd *pass = sys_getpwuid(uid);
- if (pass) return(pass->pw_name);
- slprintf(name, sizeof(name) - 1, "%d",(int)uid);
- return(name);
+ static fstring name;
+ struct passwd *pass;
+
+ if (winbind_uidtoname(name, uid))
+ return name;
+
+ pass = sys_getpwuid(uid);
+ if (pass) return(pass->pw_name);
+ slprintf(name, sizeof(name) - 1, "%d",(int)uid);
+ return(name);
}
/*******************************************************************
-turn a gid into a group name
+ Convert a gid into a group name.
********************************************************************/
char *gidtoname(gid_t gid)
{
- static char name[40];
- struct group *grp = getgrgid(gid);
+ static fstring name;
+ struct group *grp;
+
+ if (winbind_gidtoname(name, gid))
+ return name;
+
+ grp = getgrgid(gid);
if (grp) return(grp->gr_name);
slprintf(name,sizeof(name) - 1, "%d",(int)gid);
return(name);
}
/*******************************************************************
-turn a user name into a uid
+ Convert a user name into a uid. If winbindd is present uses this.
********************************************************************/
-uid_t nametouid(const char *name)
+
+uid_t nametouid(char *name)
{
struct passwd *pass;
char *p;
uid_t u;
- u = strtol(name, &p, 0);
- if (p != name) return u;
+ u = (uid_t)strtol(name, &p, 0);
+ if ((p != name) && (*p == '\0'))
+ return u;
+
+ if (winbind_nametouid(&u, name))
+ return u;
pass = sys_getpwnam(name);
- if (pass) return(pass->pw_uid);
+ if (pass)
+ return(pass->pw_uid);
return (uid_t)-1;
}
/*******************************************************************
-turn a group name into a gid
+ Convert a name to a gid_t if possible. Return -1 if not a group. If winbindd
+ is present does a shortcut lookup...
********************************************************************/
+
gid_t nametogid(const char *name)
{
struct group *grp;
char *p;
gid_t g;
- g = strtol(name, &p, 0);
- if (p != name) return g;
+ g = (gid_t)strtol(name, &p, 0);
+ if ((p != name) && (*p == '\0'))
+ return g;
+
+ if (winbind_nametogid(&g, name))
+ return g;
grp = getgrnam(name);
- if (grp) return(grp->gr_gid);
+ if (grp)
+ return(grp->gr_gid);
return (gid_t)-1;
}
{
static pstring buf;
- memcpy(buf, dname, NAMLEN(ptr)+1);
+ int len = NAMLEN(ptr);
+ memcpy(buf, dname, len);
+ buf[len] = 0;
dname = buf;
}
}
/* Get the last component of the unix name. */
- p = strrchr(name, '/');
+ p = strrchr_m(name, '/');
strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
last_component[sizeof(last_component)-1] = '\0';
{
if(namelist->is_wild)
{
- /*
- * Look for a wildcard match. Use the old
- * 'unix style' mask match, rather than the
- * new NT one.
- */
- if (unix_mask_match(last_component, namelist->name, case_sensitive, False))
+ if (mask_match(last_component, namelist->name, case_sensitive))
{
DEBUG(8,("is_in_path: mask match succeeded\n"));
return True;
continue;
}
/* find the next / */
- name_end = strchr(nameptr, '/');
+ name_end = strchr_m(nameptr, '/');
/* oops - the last check for a / didn't find one. */
if (name_end == NULL)
continue;
}
/* find the next / */
- if ((name_end = strchr(nameptr, '/')) != NULL)
+ if ((name_end = strchr_m(nameptr, '/')) != NULL)
{
*name_end = 0;
}
if(name_end == NULL)
break;
- (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
- (strchr( nameptr, '*')!=NULL));
+ (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
{
DEBUG(0,("set_namearray: malloc fail (1)\n"));
void free_namearray(name_compare_entry *name_array)
{
- if(name_array == 0)
+ if(name_array == NULL)
return;
- if(name_array->name != NULL)
- free(name_array->name);
-
- free((char *)name_array);
-}
-
-/****************************************************************************
- Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
-****************************************************************************/
-
-uint32 map_lock_offset(uint32 high, uint32 low)
-{
- unsigned int i;
- uint32 mask = 0;
- uint32 highcopy = high;
-
- /*
- * Try and find out how many significant bits there are in high.
- */
-
- for(i = 0; highcopy; i++)
- highcopy >>= 1;
-
- /*
- * We use 31 bits not 32 here as POSIX
- * lock offsets may not be negative.
- */
-
- mask = (~0) << (31 - i);
-
- if(low & mask)
- return 0; /* Fail. */
-
- high <<= (31 - i);
-
- return (high|low);
+ SAFE_FREE(name_array->name);
+ SAFE_FREE(name_array);
}
/****************************************************************************
-routine to do file locking
+ Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
+ is dealt with in posix.c
****************************************************************************/
BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
{
-#if HAVE_FCNTL_LOCK
SMB_STRUCT_FLOCK lock;
int ret;
-#if defined(LARGE_SMB_OFF_T)
- /*
- * In the 64 bit locking case we store the original
- * values in case we have to map to a 32 bit lock on
- * a filesystem that doesn't support 64 bit locks.
- */
- SMB_OFF_T orig_offset = offset;
- SMB_OFF_T orig_count = count;
-#endif /* LARGE_SMB_OFF_T */
-
- if(lp_ole_locking_compat()) {
- SMB_OFF_T mask2= ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4);
- SMB_OFF_T mask = (mask2<<2);
-
- /* make sure the count is reasonable, we might kill the lockd otherwise */
- count &= ~mask;
-
- /* the offset is often strange - remove 2 of its bits if either of
- the top two bits are set. Shift the top ones by two bits. This
- still allows OLE2 apps to operate, but should stop lockd from
- dieing */
- if ((offset & mask) != 0)
- offset = (offset & ~mask) | (((offset & mask) >> 2) & mask2);
- } else {
- SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
- SMB_OFF_T mask = (mask2<<1);
- SMB_OFF_T neg_mask = ~mask;
-
- /* interpret negative counts as large numbers */
- if (count < 0)
- count &= ~mask;
-
- /* no negative offsets */
- if(offset < 0)
- offset &= ~mask;
-
- /* count + offset must be in range */
- while ((offset < 0 || (offset + count < 0)) && mask)
- {
- offset &= ~mask;
- mask = ((mask >> 1) & neg_mask);
- }
- }
DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
errno = 0;
ret = fcntl(fd,op,&lock);
- if (errno == EFBIG)
- {
- if( DEBUGLVL( 0 ))
- {
- dbgtext("fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count);
- dbgtext("a 'file too large' error. This can happen when using 64 bit lock offsets\n");
- dbgtext("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n");
- }
- /* 32 bit NFS file system, retry with smaller offset */
- errno = 0;
- lock.l_len = count & 0x7fffffff;
- ret = fcntl(fd,op,&lock);
- }
if (errno != 0)
- DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
+ DEBUG(3,("fcntl_lock: fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
/* a lock query */
if (op == SMB_F_GETLK)
if ((ret != -1) &&
(lock.l_type != F_UNLCK) &&
(lock.l_pid != 0) &&
- (lock.l_pid != getpid()))
+ (lock.l_pid != sys_getpid()))
{
- DEBUG(3,("fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
+ DEBUG(3,("fcntl_lock: fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
return(True);
}
/* a lock set or unset */
if (ret == -1)
{
- DEBUG(3,("lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
+ DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
(double)offset,(double)count,op,type,strerror(errno)));
-
- /* perhaps it doesn't support this sort of locking?? */
- if (errno == EINVAL)
- {
-
-#if defined(LARGE_SMB_OFF_T)
- {
- /*
- * Ok - if we get here then we have a 64 bit lock request
- * that has returned EINVAL. Try and map to 31 bits for offset
- * and length and try again. This may happen if a filesystem
- * doesn't support 64 bit offsets (efs/ufs) although the underlying
- * OS does.
- */
- uint32 off_low = (orig_offset & 0xFFFFFFFF);
- uint32 off_high = ((orig_offset >> 32) & 0xFFFFFFFF);
-
- lock.l_len = (orig_count & 0x7FFFFFFF);
- lock.l_start = (SMB_OFF_T)map_lock_offset(off_high, off_low);
- ret = fcntl(fd,op,&lock);
- if (ret == -1)
- {
- if (errno == EINVAL)
- {
- DEBUG(3,("locking not supported? returning True\n"));
- return(True);
- }
- return False;
- }
- DEBUG(3,("64 -> 32 bit modified lock call successful\n"));
- return True;
- }
-#else /* LARGE_SMB_OFF_T */
- DEBUG(3,("locking not supported? returning True\n"));
- return(True);
-#endif /* LARGE_SMB_OFF_T */
- }
-
return(False);
}
/* everything went OK */
- DEBUG(8,("Lock call successful\n"));
+ DEBUG(8,("fcntl_lock: Lock call successful\n"));
return(True);
-#else
- return(False);
-#endif
}
/*******************************************************************
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.
********************************************************************/
void set_remote_arch(enum remote_arch_types type)
{
+ extern fstring remote_arch;
ra_type = type;
switch( type )
{
}
-/*******************************************************************
-align a pointer to a multiple of 2 bytes
-********************************************************************/
-char *align2(char *q, char *base)
-{
- if ((q - base) & 1)
- {
- q++;
- }
- return q;
-}
-
void out_ascii(FILE *f, unsigned char *buf,int len)
{
int i;
}
}
-void print_asc(int level, unsigned char *buf,int len)
+void print_asc(int level, const unsigned char *buf,int len)
{
int i;
for (i=0;i<len;i++)
DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
}
-void dump_data(int level,char *buf1,int len)
+void dump_data(int level, const char *buf1,int len)
{
- unsigned char *buf = (unsigned char *)buf1;
+ const unsigned char *buf = (const unsigned char *)buf1;
int i=0;
if (len<=0) return;
void zero_free(void *p, size_t size)
{
memset(p, 0, size);
- free(p);
+ SAFE_FREE(p);
}
* which always returns RLIM_INFINITY for rlp.rlim_max.
*/
+ /* Try raising the hard (max) limit to the requested amount. */
+
+#if defined(RLIM_INFINITY)
+ if (rlp.rlim_max != RLIM_INFINITY) {
+ int orig_max = rlp.rlim_max;
+
+ if ( rlp.rlim_max < requested_max )
+ rlp.rlim_max = requested_max;
+
+ /* This failing is not an error - many systems (Linux) don't
+ support our default request of 10,000 open files. JRA. */
+
+ if(setrlimit(RLIMIT_NOFILE, &rlp)) {
+ DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n",
+ (int)rlp.rlim_max, strerror(errno) ));
+
+ /* Set failed - restore original value from get. */
+ rlp.rlim_max = orig_max;
+ }
+ }
+#endif
+
+ /* Now try setting the soft (current) limit. */
+
saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
if(setrlimit(RLIMIT_NOFILE, &rlp)) {
#endif
}
-
-/*****************************************************************
- splits out the last subkey of a key
- *****************************************************************/
-void reg_get_subkey(char *full_keyname, char *key_name, char *subkey_name)
-{
- split_at_last_component(full_keyname, key_name, '\\', subkey_name);
-}
-
/*****************************************************************
splits out the start of the key (HKLM or HKU) and the rest of the key
*****************************************************************/
return False;
}
- if (next_token(NULL, tmp, "\n\r", sizeof(tmp)))
+ if (next_token(&full_keyname, tmp, "\n\r", sizeof(tmp)))
{
fstrcpy(key_name, tmp);
}
/*****************************************************************
-like mktemp() but make sure that no % characters are used
-% characters are bad for us because of the macro subs
- *****************************************************************/
-char *smbd_mktemp(char *template)
+possibly replace mkstemp if it is broken
+*****************************************************************/
+int smb_mkstemp(char *template)
{
+#if HAVE_SECURE_MKSTEMP
+ return mkstemp(template);
+#else
+ /* have a reasonable go at emulating it. Hope that
+ the system mktemp() isn't completly hopeless */
char *p = mktemp(template);
- char *p2;
- SMB_STRUCT_STAT st;
-
- if (!p) return NULL;
+ if (!p) return -1;
+ return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
+#endif
+}
- while ((p2=strchr(p,'%'))) {
- p2[0] = 'A';
- while (sys_stat(p,&st) == 0 && p2[0] < 'Z') {
- /* damn, it exists */
- p2[0]++;
- }
- if (p2[0] == 'Z') {
- /* oh well ... better return something */
- p2[0] = '%';
- return p;
- }
- }
+/**
+ malloc that aborts with smb_panic on fail or zero size.
+**/
+void *smb_xmalloc(size_t size)
+{
+ void *p;
+ if (size == 0)
+ smb_panic("smb_xmalloc: called with zero size.\n");
+ if ((p = malloc(size)) == NULL)
+ smb_panic("smb_xmalloc: malloc fail.\n");
return p;
}
+/**
+ Memdup with smb_panic on fail.
+**/
+void *smb_xmemdup(const void *p, size_t size)
+{
+ void *p2;
+ p2 = smb_xmalloc(size);
+ memcpy(p2, p, size);
+ return p2;
+}
+
+/**
+ strdup that aborts on malloc fail.
+**/
+char *smb_xstrdup(const char *s)
+{
+ char *s1 = strdup(s);
+ if (!s1)
+ 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;
p2 = malloc(size);
if (!p2) return NULL;
memcpy(p2, p, size);
return fname;
}
+
+
+/**
+ * @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", dyn_LIBDIR, name);
+ return fname;
+}
+
+/*******************************************************************
+ 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 *p;
+
+ if (!path)
+ return(NULL);
+
+ 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';
+ }
+ return dirpath;
+}
+
+
+/*******************************************************************
+determine if a pattern contains any Microsoft wildcard characters
+ *******************************************************************/
+BOOL ms_has_wild(char *s)
+{
+ char c;
+ while ((c = *s++)) {
+ switch (c) {
+ case '*':
+ case '?':
+ case '<':
+ case '>':
+ case '"':
+ return True;
+ }
+ }
+ 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
+ *******************************************************************/
+BOOL mask_match(char *string, char *pattern, BOOL is_case_sensitive)
+{
+ fstring p2, s2;
+
+ if (strcmp(string,"..") == 0) string = ".";
+ if (strcmp(pattern,".") == 0) return False;
+
+ if (is_case_sensitive) {
+ return ms_fnmatch(pattern, string, Protocol) == 0;
+ }
+
+ fstrcpy(p2, pattern);
+ fstrcpy(s2, string);
+ strlower(p2);
+ strlower(s2);
+ return ms_fnmatch(p2, s2, Protocol) == 0;
+}
+
+/*********************************************************
+ Recursive routine that is called by unix_wild_match.
+*********************************************************/
+
+static BOOL unix_do_match(char *regexp, char *str)
+{
+ char *p;
+
+ for( p = regexp; *p && *str; ) {
+
+ switch(*p) {
+ case '?':
+ str++;
+ p++;
+ break;
+
+ case '*':
+
+ /*
+ * Look for a character matching
+ * the one after the '*'.
+ */
+ p++;
+ if(!*p)
+ return True; /* Automatic match */
+ while(*str) {
+
+ while(*str && (*p != *str))
+ str++;
+
+ /*
+ * Patch from weidel@multichart.de. In the case of the regexp
+ * '*XX*' we want to ensure there are at least 2 'X' characters
+ * in the string after the '*' for a match to be made.
+ */
+
+ {
+ int matchcount=0;
+
+ /*
+ * Eat all the characters that match, but count how many there were.
+ */
+
+ while(*str && (*p == *str)) {
+ str++;
+ matchcount++;
+ }
+
+ /*
+ * Now check that if the regexp had n identical characters that
+ * matchcount had at least that many matches.
+ */
+
+ while ( *(p+1) && (*(p+1) == *p)) {
+ p++;
+ matchcount--;
+ }
+
+ if ( matchcount <= 0 )
+ return False;
+ }
+
+ str--; /* We've eaten the match char after the '*' */
+
+ if(unix_do_match(p, str))
+ return True;
+
+ if(!*str)
+ return False;
+ else
+ str++;
+ }
+ return False;
+
+ default:
+ if(*str != *p)
+ return False;
+ str++;
+ p++;
+ break;
+ }
+ }
+
+ if(!*p && !*str)
+ return True;
+
+ if (!*p && str[0] == '.' && str[1] == 0)
+ return(True);
+
+ if (!*str && *p == '?') {
+ while (*p == '?')
+ p++;
+ return(!*p);
+ }
+
+ if(!*str && (*p == '*' && p[1] == '\0'))
+ return True;
+
+ return False;
+}
+
+/*******************************************************************
+ Simple case insensitive interface to a UNIX wildcard matcher.
+*******************************************************************/
+
+BOOL unix_wild_match(char *pattern, char *string)
+{
+ pstring p2, s2;
+ char *p;
+
+ pstrcpy(p2, pattern);
+ pstrcpy(s2, string);
+ strlower(p2);
+ strlower(s2);
+
+ /* Remove any *? and ** from the pattern as they are meaningless */
+ for(p = p2; *p; p++)
+ while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
+ pstrcpy( &p[1], &p[2]);
+
+ if (strequal(p2,"*"))
+ return True;
+
+ 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(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;
+
+ if (!p || !length) {
+ ZERO_STRUCT(ret);
+ return ret;
+ }
+
+ 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;
+}
+
+/*******************************************************************
+free a data blob
+*******************************************************************/
+void data_blob_free(DATA_BLOB *d)
+{
+ 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__
+
+/*******************************************************************
+This routine is a trick to immediately catch errors when debugging
+with insure. A xterm with a gdb is popped up when insure catches
+a error. It is Linux specific.
+********************************************************************/
+int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
+{
+ static int (*fn)();
+ int ret;
+ char pidstr[10];
+ /* 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);
+
+ if (!fn) {
+ static void *h;
+ h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
+ fn = dlsym(h, "_Insure_trap_error");
+ }
+
+ ret = fn(a1, a2, a3, a4, a5, a6);
+
+ system(cmd);
+
+ return ret;
+}
+#endif