summaryrefslogtreecommitdiffstats
path: root/source/lib/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/lib/util.c')
-rw-r--r--source/lib/util.c5002
1 files changed, 2662 insertions, 2340 deletions
diff --git a/source/lib/util.c b/source/lib/util.c
index 7bd6298c4ca..8561c4f3f4a 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -2,7 +2,7 @@
Unix SMB/Netbios implementation.
Version 1.9.
Samba utility functions
- Copyright (C) Andrew Tridgell 1992-1995
+ Copyright (C) Andrew Tridgell 1992-1998
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
@@ -20,41 +20,44 @@
*/
#include "includes.h"
-#include "loadparm.h"
+
+#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
+#ifdef WITH_NISPLUS_HOME
+#include <rpcsvc/nis.h>
+#else
+#include "rpcsvc/ypclnt.h"
+#endif
+#endif
+
+#ifdef WITH_SSL
+#include <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 = "";
-int DEBUGLEVEL = 1;
+extern int DEBUGLEVEL;
BOOL passive = False;
int Protocol = PROTOCOL_COREPLUS;
-int serverzone=0;
-
/* a default finfo structure to ensure all fields are sensible */
file_info def_finfo = {-1,0,0,0,0,0,0,""};
-/* these are some file handles where debug info will be stored */
-FILE *dbf = NULL;
-
/* the client file descriptor */
int Client = -1;
-/* info on the client */
-struct from_host Client_info=
-{"UNKNOWN","0.0.0.0",NULL};
-
/* the last IP received from */
struct in_addr lastip;
/* the last port received from */
int lastport=0;
-/* my IP, the broadcast IP and the Netmask */
-struct in_addr myip;
-struct in_addr bcast_ip;
-struct in_addr Netmask;
+/* this is used by the chaining code */
+int chain_size = 0;
int trans_num = 0;
@@ -63,13 +66,6 @@ int trans_num = 0;
*/
int case_default = CASE_LOWER;
-
-/* size of reads during a direct file to file transfer */
-int ReadSize = 16*1024;
-
-pstring debugf = "/tmp/log.samba";
-int syslog_level;
-
/* the following control case operations - they are put here so the
client can link easily */
BOOL case_sensitive;
@@ -81,448 +77,39 @@ 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 myhostname="";
pstring user_socket_options="";
-pstring sesssetup_user="";
-
-
-static char *filename_dos(char *path,char *buf);
-
-static BOOL stdout_logging = False;
-
-
-/*******************************************************************
- get ready for syslog stuff
- ******************************************************************/
-void setup_logging(char *pname,BOOL interactive)
-{
-#ifdef SYSLOG
- if (!interactive) {
- char *p = strrchr(pname,'/');
- if (p) pname = p+1;
- openlog(pname, LOG_PID, LOG_DAEMON);
- }
-#endif
- if (interactive) {
- stdout_logging = True;
- dbf = stdout;
- }
-}
+pstring sesssetup_user="";
+pstring samlogon_user="";
-BOOL append_log=False;
+BOOL sam_logon_in_ssb = False;
+pstring global_myname = "";
+fstring global_myworkgroup = "";
+char **my_netbios_names;
-/****************************************************************************
-reopen the log files
-****************************************************************************/
-void reopen_logs(void)
-{
- extern FILE *dbf;
- pstring fname;
-
- if (DEBUGLEVEL > 0)
- {
- strcpy(fname,debugf);
- if (lp_loaded() && (*lp_logfile()))
- strcpy(fname,lp_logfile());
+int smb_read_error = 0;
- if (!strcsequal(fname,debugf) || !dbf || !file_exist(debugf,NULL))
- {
- strcpy(debugf,fname);
- if (dbf) fclose(dbf);
- if (append_log)
- dbf = fopen(debugf,"a");
- else
- dbf = fopen(debugf,"w");
- if (dbf) setbuf(dbf,NULL);
- }
- }
- else
- {
- if (dbf)
- {
- fclose(dbf);
- dbf = NULL;
- }
- }
-}
-
-
-/*******************************************************************
-write an debug message on the debugfile. This is called by the DEBUG
-macro
-********************************************************************/
-#ifdef __STDC__
-int Debug1(char *format_str, ...)
-{
-#else
-int Debug1(va_alist)
-va_dcl
-{
- char *format_str;
-#endif
- va_list ap;
-
-#ifdef __STDC__
- va_start(ap, format_str);
-#else
- va_start(ap);
- format_str = va_arg(ap,char *);
-#endif
+static char *filename_dos(char *path,char *buf);
- if (stdout_logging) {
- vfprintf(dbf,format_str,ap);
- va_end(ap);
- return(0);
- }
- {
- static int debug_count=0;
-
- debug_count++;
- if (debug_count == 100) {
- int maxlog = lp_max_log_size() * 1024;
- if (dbf && maxlog > 0)
- {
- struct stat st;
-
- if (fstat(fileno(dbf),&st) == 0 && st.st_size > maxlog) {
- fclose(dbf); dbf = NULL;
- reopen_logs();
- if (dbf && file_size(debugf) > maxlog) {
- pstring name;
- fclose(dbf); dbf = NULL;
- sprintf(name,"%s.old",debugf);
- sys_rename(debugf,name);
- reopen_logs();
- }
- }
- }
- debug_count=0;
- }
- }
-
-#ifdef SYSLOG
- if (!lp_syslog_only())
-#endif
- {
- if (!dbf)
- {
- dbf = fopen(debugf,"w");
- if (dbf)
- setbuf(dbf,NULL);
- else
- return(0);
- }
- }
-
-#ifdef SYSLOG
- if (syslog_level < lp_syslog())
- {
- /*
- * map debug levels to syslog() priorities
- * note that not all DEBUG(0, ...) calls are
- * necessarily errors
- */
- static int priority_map[] = {
- LOG_ERR, /* 0 */
- LOG_WARNING, /* 1 */
- LOG_NOTICE, /* 2 */
- LOG_INFO, /* 3 */
- };
- int priority;
- pstring msgbuf;
-
- if (syslog_level >= sizeof(priority_map) / sizeof(priority_map[0]) ||
- syslog_level < 0)
- priority = LOG_DEBUG;
- else
- priority = priority_map[syslog_level];
-
- vsprintf(msgbuf, format_str, ap);
-
- msgbuf[255] = '\0';
- syslog(priority, "%s", msgbuf);
- }
-#endif
-
-#ifdef SYSLOG
- if (!lp_syslog_only())
-#endif
- {
- vfprintf(dbf,format_str,ap);
- fflush(dbf);
- }
-
- va_end(ap);
- return(0);
-}
/****************************************************************************
-routine to do file locking
-****************************************************************************/
-BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type)
+ find a suitable temporary directory. The result should be copied immediately
+ as it may be overwritten by a subsequent call
+ ****************************************************************************/
+char *tmpdir(void)
{
-#if HAVE_FCNTL_LOCK
- struct flock lock;
- int ret;
-
-#if 1
- uint32 mask = 0xC0000000;
-
- /* 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);
-#else
- unsigned long mask = ((unsigned)1<<31);
-
- /* interpret negative counts as large numbers */
- if (count < 0)
- count &= ~mask;
-
- /* no negative offsets */
- offset &= ~mask;
-
- /* count + offset must be in range */
- while ((offset < 0 || (offset + count < 0)) && mask)
- {
- offset &= ~mask;
- mask = mask >> 1;
- }
-#endif
-
-
- DEBUG(5,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type));
-
- lock.l_type = type;
- lock.l_whence = SEEK_SET;
- lock.l_start = (int)offset;
- lock.l_len = (int)count;
- lock.l_pid = 0;
-
- errno = 0;
-
- ret = fcntl(fd,op,&lock);
-
- if (errno != 0)
- DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
-
- /* a lock query */
- if (op == F_GETLK)
- {
- if ((ret != -1) &&
- (lock.l_type != F_UNLCK) &&
- (lock.l_pid != 0) &&
- (lock.l_pid != getpid()))
- {
- DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid));
- return(True);
- }
-
- /* it must be not locked or locked by me */
- return(False);
- }
-
- /* a lock set or unset */
- if (ret == -1)
- {
- DEBUG(3,("lock failed at offset %d count %d op %d type %d (%s)\n",
- offset,count,op,type,strerror(errno)));
-
- /* perhaps it doesn't support this sort of locking?? */
- if (errno == EINVAL)
- {
- DEBUG(3,("locking not supported? returning True\n"));
- return(True);
- }
-
- return(False);
- }
-
- /* everything went OK */
- DEBUG(5,("Lock call successful\n"));
-
- return(True);
-#else
- return(False);
-#endif
-}
-
-/*******************************************************************
-lock a file - returning a open file descriptor or -1 on failure
-The timeout is in seconds. 0 means no timeout
-********************************************************************/
-int file_lock(char *name,int timeout)
-{
- int fd = open(name,O_RDWR|O_CREAT,0666);
- time_t t=0;
- if (fd < 0) return(-1);
-
-#if HAVE_FCNTL_LOCK
- if (timeout) t = time(NULL);
- while (!timeout || (time(NULL)-t < timeout)) {
- if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)) return(fd);
- msleep(LOCK_RETRY_TIMEOUT);
- }
- return(-1);
-#else
- return(fd);
-#endif
-}
-
-/*******************************************************************
-unlock a file locked by file_lock
-********************************************************************/
-void file_unlock(int fd)
-{
- if (fd<0) return;
-#if HAVE_FCNTL_LOCK
- fcntl_lock(fd,F_SETLK,0,1,F_UNLCK);
-#endif
- close(fd);
-}
-
-/*******************************************************************
-a gettimeofday wrapper
-********************************************************************/
-void GetTimeOfDay(struct timeval *tval)
-{
-#ifdef GETTIMEOFDAY1
- gettimeofday(tval);
-#else
- gettimeofday(tval,NULL);
-#endif
-}
-
-int extra_time_offset = 0;
-
-static int timediff = 0;
-
-/*******************************************************************
-init the time differences
-********************************************************************/
-void TimeInit(void)
-{
- struct tm tm_utc,tm_local;
- time_t t;
-
- t = time(NULL);
-
- tm_utc = *(gmtime(&t));
- tm_local = *(localtime(&t));
-
-#ifdef HAVE_GMTOFF
- timediff = -tm_local.tm_gmtoff;
-#else
- timediff = mktime(&tm_utc) - mktime(&tm_local);
-#endif
-
- if (serverzone == 0) {
- serverzone = timediff - DSTDiff(t);
- DEBUG(4,("Serverzone is %d\n",serverzone));
- }
-}
-
-
-/*******************************************************************
-return the DST offset for a particular time
-We keep a table of DST offsets to prevent calling localtime() on each
-call of this function. This saves a LOT of time on many unixes.
-********************************************************************/
-int DSTDiff(time_t t)
-{
- static struct dst_table {time_t start,end; BOOL is_dst;} *dst_table = NULL;
- static int table_size = 0;
- int i;
- BOOL is_dst = False;
-
- if (t == 0) t = time(NULL);
-
-#ifndef NO_ISDST
- for (i=0;i<table_size;i++)
- if (t >= dst_table[i].start && t <= dst_table[i].end) break;
-
- if (i<table_size) {
- is_dst = dst_table[i].is_dst;
- } else {
- time_t low,high;
-
- dst_table = (struct dst_table *)Realloc(dst_table,
- sizeof(dst_table[0])*(i+1));
- if (!dst_table) {
- table_size = 0;
- return(0);
- }
-
- table_size++;
-
- dst_table[i].is_dst = is_dst = (localtime(&t)->tm_isdst?True:False);;
- dst_table[i].start = dst_table[i].end = t;
-
- /* no entry will cover more than 6 months */
- low = t - 3*30*24*60*60;
- high = t + 3*30*24*60*60;
-
- /* widen the new entry using two bisection searches */
- while (low+60*60 < dst_table[i].start) {
- t = low + (dst_table[i].start-low)/2;
- if ((localtime(&t)->tm_isdst?True:False) == is_dst)
- dst_table[i].start = t;
- else
- low = t;
- }
-
- while (high-60*60 > dst_table[i].end) {
- t = high + (high-dst_table[i].end)/2;
- if ((localtime(&t)->tm_isdst?True:False) == is_dst)
- dst_table[i].end = t;
- else
- high = t;
- }
-
-/*
- DEBUG(1,("Added DST entry from %s ",
- asctime(localtime(&dst_table[i].start))));
- DEBUG(1,("to %s (%d)\n",asctime(localtime(&dst_table[i].end)),
- dst_table[i].is_dst));
-*/
+ char *p;
+ if ((p = getenv("TMPDIR"))) {
+ return p;
}
-#endif
-
- return((is_dst?60*60:0) - (extra_time_offset*60));
+ return "/tmp";
}
-/****************************************************************************
-return the difference between local and GMT time
-****************************************************************************/
-int TimeDiff(time_t t)
-{
- static BOOL initialised = False;
- if (!initialised) {initialised=True; TimeInit();}
- return(timediff - DSTDiff(t));
-}
-
-/****************************************************************************
-try to optimise the localtime call, it can be quite expenive on some machines
-timemul is normally LOCAL_TO_GMT, GMT_TO_LOCAL or 0
-****************************************************************************/
-struct tm *LocalTime(time_t *t,int timemul)
-{
- time_t t2 = *t;
-
- if (timemul)
- t2 += timemul * TimeDiff(t2);
-
- return(gmtime(&t2));
-}
/****************************************************************************
@@ -544,10 +131,11 @@ static char *last_ptr=NULL;
Based on a routine by GJC@VILLAGE.COM.
Extensively modified by Andrew.Tridgell@anu.edu.au
****************************************************************************/
-BOOL next_token(char **ptr,char *buff,char *sep)
+BOOL next_token(char **ptr,char *buff,char *sep, int bufsize)
{
char *s;
BOOL quoted;
+ int len=1;
if (!ptr) ptr = &last_ptr;
if (!ptr) return(False);
@@ -564,12 +152,14 @@ BOOL next_token(char **ptr,char *buff,char *sep)
if (! *s) return(False);
/* copy over the token */
- for (quoted = False; *s && (quoted || !strchr(sep,*s)); s++)
+ for (quoted = False; len < bufsize && *s && (quoted || !strchr(sep,*s)); s++)
{
- if (*s == '\"')
- quoted = !quoted;
- else
- *buff++ = *s;
+ if (*s == '\"') {
+ quoted = !quoted;
+ } else {
+ len++;
+ *buff++ = *s;
+ }
}
*ptr = (*s) ? s+1 : s;
@@ -616,71 +206,10 @@ char **toktocliplist(int *ctok, char *sep)
return ret;
}
-#ifndef HAVE_MEMMOVE
-/*******************************************************************
-safely copies memory, ensuring no overlap problems.
-this is only used if the machine does not have it's own memmove().
-this is not the fastest algorithm in town, but it will do for our
-needs.
-********************************************************************/
-void *MemMove(void *dest,void *src,int size)
-{
- unsigned long d,s;
- int i;
- if (dest==src || !size) return(dest);
-
- d = (unsigned long)dest;
- s = (unsigned long)src;
-
- if ((d >= (s+size)) || (s >= (d+size))) {
- /* no overlap */
- memcpy(dest,src,size);
- return(dest);
- }
-
- if (d < s)
- {
- /* we can forward copy */
- if (s-d >= sizeof(int) &&
- !(s%sizeof(int)) && !(d%sizeof(int)) && !(size%sizeof(int))) {
- /* do it all as words */
- int *idest = (int *)dest;
- int *isrc = (int *)src;
- size /= sizeof(int);
- for (i=0;i<size;i++) idest[i] = isrc[i];
- } else {
- /* simplest */
- char *cdest = (char *)dest;
- char *csrc = (char *)src;
- for (i=0;i<size;i++) cdest[i] = csrc[i];
- }
- }
- else
- {
- /* must backward copy */
- if (d-s >= sizeof(int) &&
- !(s%sizeof(int)) && !(d%sizeof(int)) && !(size%sizeof(int))) {
- /* do it all as words */
- int *idest = (int *)dest;
- int *isrc = (int *)src;
- size /= sizeof(int);
- for (i=size-1;i>=0;i--) idest[i] = isrc[i];
- } else {
- /* simplest */
- char *cdest = (char *)dest;
- char *csrc = (char *)src;
- for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
- }
- }
- return(dest);
-}
-#endif
-
-
/****************************************************************************
prompte a dptr (to make it recently used)
****************************************************************************/
-void array_promote(char *array,int elsize,int element)
+static void array_promote(char *array,int elsize,int element)
{
char *p;
if (element == 0)
@@ -733,6 +262,12 @@ struct
#ifdef SO_RCVLOWAT
{"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT},
#endif
+#ifdef SO_SNDTIMEO
+ {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT},
+#endif
+#ifdef SO_RCVTIMEO
+ {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
+#endif
{NULL,0,0,0,0}};
@@ -742,9 +277,9 @@ set user socket options
****************************************************************************/
void set_socket_options(int fd, char *options)
{
- string tok;
+ fstring tok;
- while (next_token(&options,tok," \t,"))
+ while (next_token(&options,tok," \t,", sizeof(tok)))
{
int ret=0,i;
int value = 1;
@@ -800,50 +335,28 @@ void set_socket_options(int fd, char *options)
****************************************************************************/
void close_sockets(void )
{
+#ifdef WITH_SSL
+ sslutil_disconnect(Client);
+#endif /* WITH_SSL */
+
close(Client);
Client = 0;
}
/****************************************************************************
- return the date and time as a string
-****************************************************************************/
-char *timestring(void )
-{
- static char TimeBuf[100];
- time_t t;
- t = time(NULL);
-#ifdef NO_STRFTIME
- strcpy(TimeBuf, asctime(LocalTime(&t,GMT_TO_LOCAL)));
-#elif defined(CLIX) || defined(CONVEX)
- strftime(TimeBuf,100,"%m/%d/%y %I:%M:%S %p",LocalTime(&t,GMT_TO_LOCAL));
-#elif defined(AMPM)
- strftime(TimeBuf,100,"%D %r",LocalTime(&t,GMT_TO_LOCAL));
-#elif defined(TZ_TIME)
- {
- strftime(TimeBuf,100,"%D:%T",LocalTime(&t,0));
- sprintf(TimeBuf+strlen(TimeBuf)," %+03d%02d",
- -TimeDiff(t)/(60*60),-(TimeDiff(t)/60)%60);
- }
-#else
- strftime(TimeBuf,100,"%D %T",LocalTime(&t,GMT_TO_LOCAL));
-#endif
- return(TimeBuf);
-}
-
-/****************************************************************************
determine whether we are in the specified group
****************************************************************************/
-BOOL in_group(gid_t group, int current_gid, int ngroups, int *groups)
+BOOL in_group(gid_t group, int current_gid, int ngroups, GID_T *groups)
{
- int i;
+ 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(True);
+ for (i=0;i<ngroups;i++)
+ if (group == groups[i])
+ return(True);
- return(False);
+ return(False);
}
/****************************************************************************
@@ -853,13 +366,8 @@ char *StrCpy(char *dest,char *src)
{
char *d = dest;
-#if AJT
/* I don't want to get lazy with these ... */
- if (!dest || !src) {
- DEBUG(0,("ERROR: NULL StrCpy() called!\n"));
- ajt_panic();
- }
-#endif
+ SMB_ASSERT(dest && src);
if (!dest) return(NULL);
if (!src) {
@@ -873,7 +381,7 @@ char *StrCpy(char *dest,char *src)
/****************************************************************************
line strncpy but always null terminates. Make sure there is room!
****************************************************************************/
-char *StrnCpy(char *dest,const char *src,int n)
+char *StrnCpy(char *dest,char *src,int n)
{
char *d = dest;
if (!dest) return(NULL);
@@ -896,6 +404,46 @@ void putip(void *dest,void *src)
}
+#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
****************************************************************************/
@@ -938,58 +486,71 @@ static int name_interpret(char *in,char *out)
/****************************************************************************
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)
-{
- fstring name;
- char buf[20];
- char *in = (char *)&buf[0];
- char *out = (char *)Out;
- char *p, *label;
- int i;
+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( '*' == In[0] )
+ buf[0] = '*';
+ else
+ (void)slprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, name_type );
- if (In[0] != '*') {
- StrnCpy(name,In,sizeof(name)-1);
- sprintf(buf,"%-15.15s%c",name,name_type);
- } else {
- buf[0]='*';
- memset(&buf[1],0,16);
- }
+ /* Place the length of the first field into the output buffer. */
+ p[0] = 32;
+ p++;
- *out++ = 32;
- for (i=0;i<16;i++) {
- char c = toupper(in[i]);
- out[i*2] = (c>>4) + 'A';
- out[i*2+1] = (c & 0xF) + 'A';
- }
- out[32]=0;
- out += 32;
-
- label = scope;
- while (*label)
+ /* Now convert the name to the rfc1001/1002 format. */
+ for( i = 0; i < 16; i++ )
{
- p = strchr(label, '.');
- if (p == 0)
- p = label + strlen(label);
- *out++ = p - label;
- memcpy(out, label, p - label);
- out += p - label;
- label += p - label + (*p == '.');
+ 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 = 0;
+ break;
+ default:
+ p[len+1] = scope[i];
+ break;
+ }
}
- *out = 0;
- return(name_len(Out));
-}
+ return( name_len(Out) );
+ } /* name_mangle */
/*******************************************************************
check if a file exists
********************************************************************/
-BOOL file_exist(char *fname,struct stat *sbuf)
+BOOL file_exist(char *fname,SMB_STRUCT_STAT *sbuf)
{
- struct stat st;
+ SMB_STRUCT_STAT st;
if (!sbuf) sbuf = &st;
- if (sys_stat(fname,sbuf) != 0)
+ if (dos_stat(fname,sbuf) != 0)
return(False);
return(S_ISREG(sbuf->st_mode));
@@ -1000,9 +561,9 @@ check a files mod time
********************************************************************/
time_t file_modtime(char *fname)
{
- struct stat st;
+ SMB_STRUCT_STAT st;
- if (sys_stat(fname,&st) != 0)
+ if (dos_stat(fname,&st) != 0)
return(0);
return(st.st_mtime);
@@ -1011,196 +572,48 @@ time_t file_modtime(char *fname)
/*******************************************************************
check if a directory exists
********************************************************************/
-BOOL directory_exist(char *dname,struct stat *st)
+BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st)
{
- struct stat st2;
+ SMB_STRUCT_STAT st2;
+ BOOL ret;
+
if (!st) st = &st2;
- if (sys_stat(dname,st) != 0)
+ if (dos_stat(dname,st) != 0)
return(False);
- return(S_ISDIR(st->st_mode));
+ ret = S_ISDIR(st->st_mode);
+ if(!ret)
+ errno = ENOTDIR;
+ return ret;
}
/*******************************************************************
returns the size in bytes of the named file
********************************************************************/
-uint32 file_size(char *file_name)
+SMB_OFF_T file_size(char *file_name)
{
- struct stat buf;
+ SMB_STRUCT_STAT buf;
buf.st_size = 0;
- sys_stat(file_name,&buf);
+ dos_stat(file_name,&buf);
return(buf.st_size);
}
-/****************************************************************************
-check if it's a null mtime
-****************************************************************************/
-static BOOL null_mtime(time_t mtime)
-{
- if (mtime == 0 || mtime == 0xFFFFFFFF)
- return(True);
- return(False);
-}
-
-/*******************************************************************
- create a 16 bit dos packed date
-********************************************************************/
-static uint16 make_dos_date1(time_t unixdate,struct tm *t)
-{
- uint16 ret=0;
- ret = (((unsigned)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
- ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5));
- return(ret);
-}
-
-/*******************************************************************
- create a 16 bit dos packed time
-********************************************************************/
-static uint16 make_dos_time1(time_t unixdate,struct tm *t)
-{
- uint16 ret=0;
- ret = ((((unsigned)t->tm_min >> 3)&0x7) | (((unsigned)t->tm_hour) << 3));
- ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5));
- return(ret);
-}
-
-/*******************************************************************
- create a 32 bit dos packed date/time from some parameters
- This takes a GMT time and returns a packed localtime structure
-********************************************************************/
-static uint32 make_dos_date(time_t unixdate)
-{
- struct tm *t;
- uint32 ret=0;
-
- t = LocalTime(&unixdate,GMT_TO_LOCAL);
-
- ret = make_dos_date1(unixdate,t);
- ret = ((ret&0xFFFF)<<16) | make_dos_time1(unixdate,t);
-
- return(ret);
-}
-
-/*******************************************************************
-put a dos date into a buffer (time/date format)
-This takes GMT time and puts local time in the buffer
-********************************************************************/
-void put_dos_date(char *buf,int offset,time_t unixdate)
-{
- uint32 x = make_dos_date(unixdate);
- SIVAL(buf,offset,x);
-}
-
-/*******************************************************************
-put a dos date into a buffer (date/time format)
-This takes GMT time and puts local time in the buffer
-********************************************************************/
-void put_dos_date2(char *buf,int offset,time_t unixdate)
-{
- uint32 x = make_dos_date(unixdate);
- x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
- SIVAL(buf,offset,x);
-}
-
-/*******************************************************************
-put a dos 32 bit "unix like" date into a buffer. This routine takes
-GMT and converts it to LOCAL time before putting it (most SMBs assume
-localtime for this sort of date)
-********************************************************************/
-void put_dos_date3(char *buf,int offset,time_t unixdate)
-{
- if (!null_mtime(unixdate))
- unixdate += GMT_TO_LOCAL*TimeDiff(unixdate);
- SIVAL(buf,offset,unixdate);
-}
-
-/*******************************************************************
- interpret a 32 bit dos packed date/time to some parameters
-********************************************************************/
-static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second)
-{
- uint32 p0,p1,p2,p3;
-
- p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF;
- p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF;
-
- *second = 2*(p0 & 0x1F);
- *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3);
- *hour = (p1>>3)&0xFF;
- *day = (p2&0x1F);
- *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1;
- *year = ((p3>>1)&0xFF) + 80;
-}
-
-/*******************************************************************
- create a unix date (int GMT) from a dos date (which is actually in
- localtime)
-********************************************************************/
-time_t make_unix_date(void *date_ptr)
-{
- uint32 dos_date=0;
- struct tm t;
- time_t ret;
-
- dos_date = IVAL(date_ptr,0);
-
- if (dos_date == 0) return(0);
-
- interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
- &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
- t.tm_wday = 1;
- t.tm_yday = 1;
- t.tm_isdst = -1;
-
- /* mktime() also does the local to GMT time conversion for us. XXXXX
- Do all unixes do this the same?? */
- ret = mktime(&t);
-
- return(ret);
-}
-
-/*******************************************************************
-like make_unix_date() but the words are reversed
-********************************************************************/
-time_t make_unix_date2(void *date_ptr)
-{
- uint32 x,x2;
-
- x = IVAL(date_ptr,0);
- x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
- SIVAL(&x,0,x2);
-
- return(make_unix_date((void *)&x));
-}
-
-/*******************************************************************
- create a unix GMT date from a dos date in 32 bit "unix like" format
-these generally arrive as localtimes, with corresponding DST
-********************************************************************/
-time_t make_unix_date3(void *date_ptr)
-{
- time_t t = IVAL(date_ptr,0);
- if (!null_mtime(t))
- t += LOCAL_TO_GMT*TimeDiff(t);
- return(t);
-}
-
/*******************************************************************
return a string representing an attribute for a file
********************************************************************/
char *attrib_string(int mode)
{
- static char attrstr[10];
+ static fstring attrstr;
attrstr[0] = 0;
- if (mode & aVOLID) strcat(attrstr,"V");
- if (mode & aDIR) strcat(attrstr,"D");
- if (mode & aARCH) strcat(attrstr,"A");
- if (mode & aHIDDEN) strcat(attrstr,"H");
- if (mode & aSYSTEM) strcat(attrstr,"S");
- if (mode & aRONLY) strcat(attrstr,"R");
+ if (mode & aVOLID) fstrcat(attrstr,"V");
+ if (mode & aDIR) fstrcat(attrstr,"D");
+ if (mode & aARCH) fstrcat(attrstr,"A");
+ if (mode & aHIDDEN) fstrcat(attrstr,"H");
+ if (mode & aSYSTEM) fstrcat(attrstr,"S");
+ if (mode & aRONLY) fstrcat(attrstr,"R");
return(attrstr);
}
@@ -1211,10 +624,72 @@ char *attrib_string(int mode)
********************************************************************/
int StrCaseCmp(char *s, char *t)
{
- for (; tolower(*s) == tolower(*t); ++s, ++t)
- if (!*s) return 0;
+ /* compare until we run out of string, either t or s, or find a difference */
+ /* We *must* use toupper rather than tolower here due to the
+ asynchronous upper to lower mapping.
+ */
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
+ if(lp_client_code_page() == KANJI_CODEPAGE)
+ {
+ /* Win95 treats full width ascii characters as case sensitive. */
+ int diff;
+ for (;;)
+ {
+ if (!*s || !*t)
+ return toupper (*s) - toupper (*t);
+ else if (is_sj_alph (*s) && is_sj_alph (*t))
+ {
+ diff = sj_toupper2 (*(s+1)) - sj_toupper2 (*(t+1));
+ if (diff)
+ return diff;
+ s += 2;
+ t += 2;
+ }
+ else if (is_shift_jis (*s) && is_shift_jis (*t))
+ {
+ diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t);
+ if (diff)
+ return diff;
+ diff = ((int) (unsigned char) *(s+1)) - ((int) (unsigned char) *(t+1));
+ if (diff)
+ return diff;
+ s += 2;
+ t += 2;
+ }
+ else if (is_shift_jis (*s))
+ return 1;
+ else if (is_shift_jis (*t))
+ return -1;
+ else
+ {
+ diff = toupper (*s) - toupper (*t);
+ if (diff)
+ return diff;
+ s++;
+ t++;
+ }
+ }
+ }
+ else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+ {
+ while (*s && *t && toupper(*s) == toupper(*t))
+ {
+ s++;
+ t++;
+ }
- return tolower(*s) - tolower(*t);
+ return(toupper(*s) - toupper(*t));
+ }
}
/*******************************************************************
@@ -1222,19 +697,89 @@ int StrCaseCmp(char *s, char *t)
********************************************************************/
int StrnCaseCmp(char *s, char *t, int n)
{
- while (n-- && *s && *t) {
- if (tolower(*s) != tolower(*t)) return(tolower(*s) - tolower(*t));
- s++; t++;
+ /* compare until we run out of string, either t or s, or chars */
+ /* We *must* use toupper rather than tolower here due to the
+ asynchronous upper to lower mapping.
+ */
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
+ if(lp_client_code_page() == KANJI_CODEPAGE)
+ {
+ /* Win95 treats full width ascii characters as case sensitive. */
+ int diff;
+ for (;n > 0;)
+ {
+ if (!*s || !*t)
+ return toupper (*s) - toupper (*t);
+ else if (is_sj_alph (*s) && is_sj_alph (*t))
+ {
+ diff = sj_toupper2 (*(s+1)) - sj_toupper2 (*(t+1));
+ if (diff)
+ return diff;
+ s += 2;
+ t += 2;
+ n -= 2;
+ }
+ else if (is_shift_jis (*s) && is_shift_jis (*t))
+ {
+ diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t);
+ if (diff)
+ return diff;
+ diff = ((int) (unsigned char) *(s+1)) - ((int) (unsigned char) *(t+1));
+ if (diff)
+ return diff;
+ s += 2;
+ t += 2;
+ n -= 2;
+ }
+ else if (is_shift_jis (*s))
+ return 1;
+ else if (is_shift_jis (*t))
+ return -1;
+ else
+ {
+ diff = toupper (*s) - toupper (*t);
+ if (diff)
+ return diff;
+ s++;
+ t++;
+ n--;
+ }
+ }
+ return 0;
}
- if (n) return(tolower(*s) - tolower(*t));
+ else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+ {
+ while (n && *s && *t && toupper(*s) == toupper(*t))
+ {
+ s++;
+ t++;
+ n--;
+ }
- return(0);
+ /* not run out of chars - strings are different lengths */
+ if (n)
+ return(toupper(*s) - toupper(*t));
+
+ /* identical up to where we run out of chars,
+ and strings are same length */
+ return(0);
+ }
}
/*******************************************************************
compare 2 strings
********************************************************************/
-BOOL strequal(char *s1,char *s2)
+BOOL strequal(char *s1, char *s2)
{
if (s1 == s2) return(True);
if (!s1 || !s2) return(False);
@@ -1271,23 +816,51 @@ BOOL strcsequal(char *s1,char *s2)
void strlower(char *s)
{
while (*s)
+ {
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
+ if(lp_client_code_page() == KANJI_CODEPAGE)
{
-#ifdef KANJI
- if (is_shift_jis (*s)) {
- s += 2;
- } else if (is_kana (*s)) {
- s++;
- } else {
- if (isupper(*s))
- *s = tolower(*s);
- s++;
- }
-#else
- if (isupper(*s))
- *s = tolower(*s);
- s++;
-#endif /* KANJI */
+ /* Win95 treats full width ascii characters as case sensitive. */
+ if (is_shift_jis (*s))
+ {
+ if (is_sj_upper (s[0], s[1]))
+ s[1] = sj_tolower2 (s[1]);
+ s += 2;
+ }
+ else if (is_kana (*s))
+ {
+ s++;
+ }
+ else
+ {
+ if (isupper(*s))
+ *s = tolower(*s);
+ s++;
+ }
}
+ else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+ {
+ int skip = skip_multibyte_char( *s );
+ if( skip != 0 )
+ s += skip;
+ else
+ {
+ if (isupper(*s))
+ *s = tolower(*s);
+ s++;
+ }
+ }
+ }
}
/*******************************************************************
@@ -1296,23 +869,51 @@ void strlower(char *s)
void strupper(char *s)
{
while (*s)
+ {
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
+ if(lp_client_code_page() == KANJI_CODEPAGE)
{
-#ifdef KANJI
- if (is_shift_jis (*s)) {
- s += 2;
- } else if (is_kana (*s)) {
- s++;
- } else {
- if (islower(*s))
- *s = toupper(*s);
- s++;
- }
-#else
- if (islower(*s))
- *s = toupper(*s);
- s++;
-#endif
+ /* Win95 treats full width ascii characters as case sensitive. */
+ if (is_shift_jis (*s))
+ {
+ if (is_sj_lower (s[0], s[1]))
+ s[1] = sj_toupper2 (s[1]);
+ s += 2;
+ }
+ else if (is_kana (*s))
+ {
+ s++;
+ }
+ else
+ {
+ if (islower(*s))
+ *s = toupper(*s);
+ s++;
+ }
}
+ else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+ {
+ int skip = skip_multibyte_char( *s );
+ if( skip != 0 )
+ s += skip;
+ else
+ {
+ if (islower(*s))
+ *s = toupper(*s);
+ s++;
+ }
+ }
+ }
}
/*******************************************************************
@@ -1343,24 +944,19 @@ BOOL strisnormal(char *s)
****************************************************************************/
void string_replace(char *s,char oldc,char newc)
{
+ int skip;
while (*s)
+ {
+ skip = skip_multibyte_char( *s );
+ if( skip != 0 )
+ s += skip;
+ else
{
-#ifdef KANJI
- if (is_shift_jis (*s)) {
- s += 2;
- } else if (is_kana (*s)) {
- s++;
- } else {
- if (oldc == *s)
- *s = newc;
- s++;
- }
-#else
if (oldc == *s)
- *s = newc;
+ *s = newc;
s++;
-#endif /* KANJI */
}
+ }
}
/****************************************************************************
@@ -1368,18 +964,7 @@ void string_replace(char *s,char oldc,char newc)
****************************************************************************/
void unix_format(char *fname)
{
- pstring namecopy;
string_replace(fname,'\\','/');
-#ifndef KANJI
- dos2unix_format(fname, True);
-#endif /* KANJI */
-
- if (*fname == '/')
- {
- strcpy(namecopy,fname);
- strcpy(fname,".");
- strcat(fname,namecopy);
- }
}
/****************************************************************************
@@ -1387,49 +972,53 @@ void unix_format(char *fname)
****************************************************************************/
void dos_format(char *fname)
{
-#ifndef KANJI
- unix2dos_format(fname, True);
-#endif /* KANJI */
string_replace(fname,'/','\\');
}
-
/*******************************************************************
show a smb message structure
********************************************************************/
void show_msg(char *buf)
{
- int i;
- int bcc=0;
- if (DEBUGLEVEL < 5)
- return;
+ int i;
+ int bcc=0;
+
+ if (DEBUGLEVEL < 5) return;
+
+ DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
+ smb_len(buf),
+ (int)CVAL(buf,smb_com),
+ (int)CVAL(buf,smb_rcls),
+ (int)CVAL(buf,smb_reh),
+ (int)SVAL(buf,smb_err),
+ (int)CVAL(buf,smb_flg),
+ (int)SVAL(buf,smb_flg2)));
+ DEBUG(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n",
+ (int)SVAL(buf,smb_tid),
+ (int)SVAL(buf,smb_pid),
+ (int)SVAL(buf,smb_uid),
+ (int)SVAL(buf,smb_mid),
+ (int)CVAL(buf,smb_wct)));
+
+ for (i=0;i<(int)CVAL(buf,smb_wct);i++)
+ {
+ DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i,
+ SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
+ }
- DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
- smb_len(buf),
- (int)CVAL(buf,smb_com),
- (int)CVAL(buf,smb_rcls),
- (int)CVAL(buf,smb_reh),
- (int)SVAL(buf,smb_err),
- (int)CVAL(buf,smb_flg),
- (int)SVAL(buf,smb_flg2)));
- DEBUG(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n",
- (int)SVAL(buf,smb_tid),
- (int)SVAL(buf,smb_pid),
- (int)SVAL(buf,smb_uid),
- (int)SVAL(buf,smb_mid),
- (int)CVAL(buf,smb_wct)));
- for (i=0;i<(int)CVAL(buf,smb_wct);i++)
- DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i,
- SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
- bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
- DEBUG(5,("smb_bcc=%d\n",bcc));
- if (DEBUGLEVEL < 10)
- return;
- for (i=0;i<MIN(bcc,128);i++)
- DEBUG(10,("%X ",CVAL(smb_buf(buf),i)));
- DEBUG(10,("\n"));
-}
+ bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
+ DEBUG(5,("smb_bcc=%d\n",bcc));
+
+ if (DEBUGLEVEL < 10) return;
+
+ if (DEBUGLEVEL < 50)
+ {
+ bcc = MIN(bcc, 512);
+ }
+
+ dump_data(10, smb_buf(buf), bcc);
+}
/*******************************************************************
return the length of an smb packet
********************************************************************/
@@ -1478,7 +1067,7 @@ int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
/*******************************************************************
return the number of smb words
********************************************************************/
-int smb_numwords(char *buf)
+static int smb_numwords(char *buf)
{
return (CVAL(buf,smb_wct));
}
@@ -1494,7 +1083,7 @@ int smb_buflen(char *buf)
/*******************************************************************
return a pointer to the smb_buf data area
********************************************************************/
-int smb_buf_ofs(char *buf)
+static int smb_buf_ofs(char *buf)
{
return (smb_size + CVAL(buf,smb_wct)*2);
}
@@ -1512,7 +1101,7 @@ return the SMB offset into an SMB buffer
********************************************************************/
int smb_offset(char *p,char *buf)
{
- return(PTR_DIFF(p,buf+4));
+ return(PTR_DIFF(p,buf+4) + chain_size);
}
@@ -1532,23 +1121,30 @@ trim the specified elements off the front and back of a string
BOOL trim_string(char *s,char *front,char *back)
{
BOOL ret = False;
- while (front && *front && strncmp(s,front,strlen(front)) == 0)
- {
- char *p = s;
- ret = True;
- while (1)
- {
- if (!(*p = p[strlen(front)]))
- break;
- p++;
- }
- }
- while (back && *back && strlen(s) >= strlen(back) &&
- (strncmp(s+strlen(s)-strlen(back),back,strlen(back))==0))
+ size_t front_len = (front && *front) ? strlen(front) : 0;
+ size_t back_len = (back && *back) ? strlen(back) : 0;
+ size_t s_len;
+
+ while (front_len && strncmp(s, front, front_len) == 0)
+ {
+ char *p = s;
+ ret = True;
+ while (1)
{
- ret = True;
- s[strlen(s)-strlen(back)] = 0;
+ if (!(*p = p[front_len]))
+ break;
+ p++;
}
+ }
+
+ s_len = strlen(s);
+ while (back_len && s_len >= back_len &&
+ (strncmp(s + s_len - back_len, back, back_len)==0))
+ {
+ ret = True;
+ s[s_len - back_len] = 0;
+ s_len = strlen(s);
+ }
return(ret);
}
@@ -1570,13 +1166,13 @@ void dos_clean_name(char *s)
pstring s1;
*p = 0;
- strcpy(s1,p+3);
+ pstrcpy(s1,p+3);
if ((p=strrchr(s,'\\')) != NULL)
*p = 0;
else
*s = 0;
- strcat(s,s1);
+ pstrcat(s,s1);
}
trim_string(s,NULL,"\\..");
@@ -1596,18 +1192,25 @@ void unix_clean_name(char *s)
/* remove any double slashes */
string_sub(s, "//","/");
+ /* Remove leading ./ characters */
+ if(strncmp(s, "./", 2) == 0) {
+ trim_string(s, "./", NULL);
+ if(*s == 0)
+ pstrcpy(s,"./");
+ }
+
while ((p = strstr(s,"/../")) != NULL)
{
pstring s1;
*p = 0;
- strcpy(s1,p+3);
+ pstrcpy(s1,p+3);
if ((p=strrchr(s,'/')) != NULL)
*p = 0;
else
*s = 0;
- strcat(s,s1);
+ pstrcat(s,s1);
}
trim_string(s,NULL,"/..");
@@ -1626,122 +1229,110 @@ int ChDir(char *path)
if (*path == '/' && strcsequal(LastDir,path)) return(0);
DEBUG(3,("chdir to %s\n",path));
- res = sys_chdir(path);
+ res = dos_chdir(path);
if (!res)
- strcpy(LastDir,path);
+ pstrcpy(LastDir,path);
return(res);
}
-
-/*******************************************************************
- return the absolute current directory path. A dumb version.
-********************************************************************/
-static char *Dumb_GetWd(char *s)
-{
-#ifdef USE_GETCWD
- return ((char *)getcwd(s,sizeof(pstring)));
-#else
- return ((char *)getwd(s));
-#endif
-}
-
-
/* number of list structures for a caching GetWd function. */
#define MAX_GETWDCACHE (50)
struct
{
- ino_t inode;
- dev_t dev;
- char *text;
+ SMB_DEV_T dev; /* These *must* be compatible with the types returned in a stat() call. */
+ SMB_INO_T inode; /* These *must* be compatible with the types returned in a stat() call. */
+ char *text; /* The pathname in DOS format. */
BOOL valid;
} ino_list[MAX_GETWDCACHE];
BOOL use_getwd_cache=True;
/*******************************************************************
- return the absolute current directory path
+ return the absolute current directory path - given a UNIX pathname.
+ Note that this path is returned in DOS format, not UNIX
+ format.
********************************************************************/
char *GetWd(char *str)
{
pstring s;
static BOOL getwd_cache_init = False;
- struct stat st, st2;
+ SMB_STRUCT_STAT st, st2;
int i;
*s = 0;
if (!use_getwd_cache)
- return(Dumb_GetWd(str));
+ return(dos_getwd(str));
/* init the cache */
if (!getwd_cache_init)
+ {
+ getwd_cache_init = True;
+ for (i=0;i<MAX_GETWDCACHE;i++)
{
- getwd_cache_init = True;
- for (i=0;i<MAX_GETWDCACHE;i++)
- {
- string_init(&ino_list[i].text,"");
- ino_list[i].valid = False;
- }
+ string_init(&ino_list[i].text,"");
+ ino_list[i].valid = False;
}
+ }
/* Get the inode of the current directory, if this doesn't work we're
in trouble :-) */
- if (stat(".",&st) == -1)
- {
- DEBUG(0,("Very strange, couldn't stat \".\"\n"));
- return(Dumb_GetWd(str));
- }
+ if (dos_stat(".",&st) == -1)
+ {
+ DEBUG(0,("Very strange, couldn't stat \".\"\n"));
+ return(dos_getwd(str));
+ }
for (i=0; i<MAX_GETWDCACHE; i++)
if (ino_list[i].valid)
- {
+ {
- /* If we have found an entry with a matching inode and dev number
- then find the inode number for the directory in the cached string.
- If this agrees with that returned by the stat for the current
- directory then all is o.k. (but make sure it is a directory all
- the same...) */
+ /* If we have found an entry with a matching inode and dev number
+ then find the inode number for the directory in the cached string.
+ If this agrees with that returned by the stat for the current
+ directory then all is o.k. (but make sure it is a directory all
+ the same...) */
- if (st.st_ino == ino_list[i].inode &&
- st.st_dev == ino_list[i].dev)
- {
- if (stat(ino_list[i].text,&st2) == 0)
- {
- if (st.st_ino == st2.st_ino &&
- st.st_dev == st2.st_dev &&
- (st2.st_mode & S_IFMT) == S_IFDIR)
- {
- strcpy (str, ino_list[i].text);
-
- /* promote it for future use */
- array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
- return (str);
- }
- else
- {
- /* If the inode is different then something's changed,
- scrub the entry and start from scratch. */
- ino_list[i].valid = False;
- }
- }
- }
+ if (st.st_ino == ino_list[i].inode &&
+ st.st_dev == ino_list[i].dev)
+ {
+ if (dos_stat(ino_list[i].text,&st2) == 0)
+ {
+ if (st.st_ino == st2.st_ino &&
+ st.st_dev == st2.st_dev &&
+ (st2.st_mode & S_IFMT) == S_IFDIR)
+ {
+ pstrcpy (str, ino_list[i].text);
+
+ /* promote it for future use */
+ array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
+ return (str);
+ }
+ else
+ {
+ /* If the inode is different then something's changed,
+ scrub the entry and start from scratch. */
+ ino_list[i].valid = False;
+ }
+ }
}
+ }
/* We don't have the information to hand so rely on traditional methods.
The very slow getcwd, which spawns a process on some systems, or the
not quite so bad getwd. */
- if (!Dumb_GetWd(s))
- {
- DEBUG(0,("Getwd failed, errno %d\n",errno));
- return (NULL);
- }
+ if (!dos_getwd(s))
+ {
+ DEBUG(0,("Getwd failed, errno %s\n",strerror(errno)));
+ return (NULL);
+ }
- strcpy(str,s);
+ pstrcpy(str,s);
DEBUG(5,("GetWd %s, inode %d, dev %x\n",s,(int)st.st_ino,(int)st.st_dev));
@@ -1774,12 +1365,12 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
#else
pstring dir2;
pstring wd;
- pstring basename;
+ pstring base_name;
pstring newname;
char *p=NULL;
BOOL relative = (*s != '/');
- *dir2 = *wd = *basename = *newname = 0;
+ *dir2 = *wd = *base_name = *newname = 0;
if (widelinks)
{
@@ -1790,6 +1381,10 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
DEBUG(3,("Illegal file name? (%s)\n",s));
return(False);
}
+
+ if (strlen(s) == 0)
+ pstrcpy(s,"./");
+
return(True);
}
@@ -1798,8 +1393,8 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
/* remove any double slashes */
string_sub(s,"//","/");
- strcpy(basename,s);
- p = strrchr(basename,'/');
+ pstrcpy(base_name,s);
+ p = strrchr(base_name,'/');
if (!p)
return(True);
@@ -1824,7 +1419,7 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
}
- if (p && (p != basename))
+ if (p && (p != base_name))
{
*p = 0;
if (strcmp(p+1,".")==0)
@@ -1833,10 +1428,10 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
*p = '/';
}
- if (ChDir(basename) != 0)
+ if (ChDir(base_name) != 0)
{
ChDir(wd);
- DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,basename));
+ DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name));
return(False);
}
@@ -1847,10 +1442,10 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
return(False);
}
- if (p && (p != basename))
+ if (p && (p != base_name))
{
- strcat(newname,"/");
- strcat(newname,p+1);
+ pstrcat(newname,"/");
+ pstrcat(newname,p+1);
}
{
@@ -1868,18 +1463,18 @@ BOOL reduce_name(char *s,char *dir,BOOL widelinks)
if (relative)
{
if (newname[l] == '/')
- strcpy(s,newname + l + 1);
+ pstrcpy(s,newname + l + 1);
else
- strcpy(s,newname+l);
+ pstrcpy(s,newname+l);
}
else
- strcpy(s,newname);
+ pstrcpy(s,newname);
}
ChDir(wd);
if (strlen(s) == 0)
- strcpy(s,"./");
+ pstrcpy(s,"./");
DEBUG(3,("reduced to %s\n",s));
return(True);
@@ -1897,14 +1492,34 @@ static void expand_one(char *Mask,int len)
int lfill = (len+1) - strlen(Mask);
int l1= (p1 - Mask);
pstring tmp;
- strcpy(tmp,Mask);
+ pstrcpy(tmp,Mask);
memset(tmp+l1,'?',lfill);
- strcpy(tmp + l1 + lfill,Mask + l1 + 1);
- strcpy(Mask,tmp);
+ pstrcpy(tmp + l1 + lfill,Mask + l1 + 1);
+ pstrcpy(Mask,tmp);
}
}
/****************************************************************************
+parse out a directory name from a path name. Assumes dos style filenames.
+****************************************************************************/
+static char *dirname_dos(char *path,char *buf)
+{
+ char *p = strrchr(path,'\\');
+
+ if (!p)
+ pstrcpy(buf,path);
+ else
+ {
+ *p = 0;
+ pstrcpy(buf,path);
+ *p = '\\';
+ }
+
+ return(buf);
+}
+
+
+/****************************************************************************
expand a wildcard expression, replacing *s with ?s
****************************************************************************/
void expand_mask(char *Mask,BOOL doext)
@@ -1924,42 +1539,42 @@ void expand_mask(char *Mask,BOOL doext)
filename_dos(Mask,filepart);
- strcpy(mbeg,filepart);
+ pstrcpy(mbeg,filepart);
if ((p1 = strchr(mbeg,'.')) != NULL)
{
hasdot = True;
*p1 = 0;
p1++;
- strcpy(mext,p1);
+ pstrcpy(mext,p1);
}
else
{
- strcpy(mext,"");
+ pstrcpy(mext,"");
if (strlen(mbeg) > 8)
{
- strcpy(mext,mbeg + 8);
+ pstrcpy(mext,mbeg + 8);
mbeg[8] = 0;
}
}
if (*mbeg == 0)
- strcpy(mbeg,"????????");
+ pstrcpy(mbeg,"????????");
if ((*mext == 0) && doext && !hasdot)
- strcpy(mext,"???");
+ pstrcpy(mext,"???");
if (strequal(mbeg,"*") && *mext==0)
- strcpy(mext,"*");
+ pstrcpy(mext,"*");
/* expand *'s */
expand_one(mbeg,8);
if (*mext)
expand_one(mext,3);
- strcpy(Mask,dirpart);
- if (*dirpart || absolute) strcat(Mask,"\\");
- strcat(Mask,mbeg);
- strcat(Mask,".");
- strcat(Mask,mext);
+ pstrcpy(Mask,dirpart);
+ if (*dirpart || absolute) pstrcat(Mask,"\\");
+ pstrcat(Mask,mbeg);
+ pstrcat(Mask,".");
+ pstrcat(Mask,mext);
DEBUG(6,("Mask expanded to [%s]\n",Mask));
}
@@ -1971,21 +1586,44 @@ does a string have any uppercase chars in it?
BOOL strhasupper(char *s)
{
while (*s)
+ {
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
+ if(lp_client_code_page() == KANJI_CODEPAGE)
{
-#ifdef KANJI
- if (is_shift_jis (*s)) {
- s += 2;
- } else if (is_kana (*s)) {
- s++;
- } else {
- if (isupper(*s)) return(True);
- s++;
- }
-#else
- if (isupper(*s)) return(True);
- s++;
-#endif /* KANJI */
+ /* Win95 treats full width ascii characters as case sensitive. */
+ if (is_shift_jis (*s))
+ s += 2;
+ else if (is_kana (*s))
+ s++;
+ else
+ {
+ if (isupper(*s))
+ return(True);
+ s++;
+ }
}
+ else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+ {
+ int skip = skip_multibyte_char( *s );
+ if( skip != 0 )
+ s += skip;
+ else {
+ if (isupper(*s))
+ return(True);
+ s++;
+ }
+ }
+ }
return(False);
}
@@ -1995,21 +1633,52 @@ does a string have any lowercase chars in it?
BOOL strhaslower(char *s)
{
while (*s)
+ {
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
+ if(lp_client_code_page() == KANJI_CODEPAGE)
{
-#ifdef KANJI
- if (is_shift_jis (*s)) {
- s += 2;
- } else if (is_kana (*s)) {
- s++;
- } else {
- if (islower(*s)) return(True);
- s++;
- }
-#else
- if (islower(*s)) return(True);
- s++;
-#endif /* KANJI */
+ /* Win95 treats full width ascii characters as case sensitive. */
+ if (is_shift_jis (*s))
+ {
+ if (is_sj_upper (s[0], s[1]))
+ return(True);
+ if (is_sj_lower (s[0], s[1]))
+ return (True);
+ s += 2;
+ }
+ else if (is_kana (*s))
+ {
+ s++;
+ }
+ else
+ {
+ if (islower(*s))
+ return(True);
+ s++;
+ }
+ }
+ else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+ {
+ int skip = skip_multibyte_char( *s );
+ if( skip != 0 )
+ s += skip;
+ else {
+ if (islower(*s))
+ return(True);
+ s++;
+ }
}
+ }
return(False);
}
@@ -2019,12 +1688,47 @@ find the number of chars in a string
int count_chars(char *s,char c)
{
int count=0;
- while (*s)
+
+#if !defined(KANJI_WIN95_COMPATIBILITY)
+ /*
+ * For completeness we should put in equivalent code for code pages
+ * 949 (Korean hangul) and 950 (Big5 Traditional Chinese) here - but
+ * doubt anyone wants Samba to behave differently from Win95 and WinNT
+ * here. They both treat full width ascii characters as case senstive
+ * filenames (ie. they don't do the work we do here).
+ * JRA.
+ */
+
+ if(lp_client_code_page() == KANJI_CODEPAGE)
+ {
+ /* Win95 treats full width ascii characters as case sensitive. */
+ while (*s)
{
- if (*s == c)
- count++;
- s++;
+ if (is_shift_jis (*s))
+ s += 2;
+ else
+ {
+ if (*s == c)
+ count++;
+ s++;
+ }
}
+ }
+ else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+ {
+ while (*s)
+ {
+ int skip = skip_multibyte_char( *s );
+ if( skip != 0 )
+ s += skip;
+ else {
+ if (*s == c)
+ count++;
+ s++;
+ }
+ }
+ }
return(count);
}
@@ -2032,12 +1736,12 @@ int count_chars(char *s,char c)
/****************************************************************************
make a dir struct
****************************************************************************/
-void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode,time_t date)
+void make_dir_struct(char *buf,char *mask,char *fname,SMB_OFF_T size,int mode,time_t date)
{
char *p;
pstring mask2;
- strcpy(mask2,mask);
+ pstrcpy(mask2,mask);
if ((mode & aDIR) != 0)
size = 0;
@@ -2057,7 +1761,7 @@ void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode
CVAL(buf,21) = mode;
put_dos_date(buf,22,date);
SSVAL(buf,26,size & 0xFFFF);
- SSVAL(buf,28,size >> 16);
+ SSVAL(buf,28,(size >> 16)&0xFFFF);
StrnCpy(buf+30,fname,12);
if (!case_sensitive)
strupper(buf+30);
@@ -2089,57 +1793,15 @@ void close_low_fds(void)
}
}
-
-/****************************************************************************
-write to a socket
-****************************************************************************/
-int write_socket(int fd,char *buf,int len)
-{
- int ret=0;
-
- if (passive)
- return(len);
- DEBUG(6,("write_socket(%d,%d)\n",fd,len));
- ret = write_data(fd,buf,len);
-
- DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,len,ret));
- return(ret);
-}
-
-/****************************************************************************
-read from a socket
-****************************************************************************/
-int read_udp_socket(int fd,char *buf,int len)
-{
- int ret;
- struct sockaddr sock;
- int socklen;
-
- socklen = sizeof(sock);
- bzero((char *)&sock,socklen);
- bzero((char *)&lastip,sizeof(lastip));
- ret = recvfrom(fd,buf,len,0,&sock,&socklen);
- if (ret <= 0)
- {
- DEBUG(2,("read socket failed. ERRNO=%d\n",errno));
- return(0);
- }
-
- lastip = *(struct in_addr *) &sock.sa_data[2];
- lastport = ntohs(((struct sockaddr_in *)&sock)->sin_port);
-
- return(ret);
-}
-
/****************************************************************************
Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
else
if SYSV use O_NDELAY
if BSD use FNDELAY
****************************************************************************/
-int set_blocking(int fd, BOOL set)
+static int set_blocking(int fd, BOOL set)
{
-int val;
+ int val;
#ifdef O_NONBLOCK
#define FLAG_TO_SET O_NONBLOCK
#else
@@ -2150,7 +1812,7 @@ int val;
#endif
#endif
- if((val = fcntl(fd, F_GETFL, 0))==-1)
+ if((val = fcntl(fd, F_GETFL, 0)) == -1)
return -1;
if(set) /* Turn blocking on - ie. clear nonblock flag */
val &= ~FLAG_TO_SET;
@@ -2162,178 +1824,158 @@ int val;
/****************************************************************************
-Calculate the difference in timeout values. Return 1 if val1 > val2,
-0 if val1 == val2, -1 if val1 < val2. Stores result in retval. retval
-may be == val1 or val2
+write to a socket
****************************************************************************/
-static int tval_sub( struct timeval *retval, struct timeval *val1, struct timeval *val2)
+ssize_t write_socket(int fd,char *buf,size_t len)
{
- int usecdiff = val1->tv_usec - val2->tv_usec;
- int secdiff = val1->tv_sec - val2->tv_sec;
- if(usecdiff < 0) {
- usecdiff = 1000000 + usecdiff;
- secdiff--;
+ ssize_t ret=0;
+
+ if (passive)
+ return(len);
+ DEBUG(6,("write_socket(%d,%d)\n",fd,len));
+ ret = write_data(fd,buf,len);
+
+ DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,len,ret));
+ if(ret <= 0)
+ DEBUG(0,("write_socket: Error writing %d bytes to socket %d: ERRNO = %s\n",
+ len, fd, strerror(errno) ));
+
+ return(ret);
+}
+
+/****************************************************************************
+read from a socket
+****************************************************************************/
+ssize_t read_udp_socket(int fd,char *buf,size_t len)
+{
+ ssize_t ret;
+ struct sockaddr_in sock;
+ int socklen;
+
+ socklen = sizeof(sock);
+ bzero((char *)&sock,socklen);
+ bzero((char *)&lastip,sizeof(lastip));
+ ret = (ssize_t)recvfrom(fd,buf,len,0,(struct sockaddr *)&sock,&socklen);
+ if (ret <= 0) {
+ DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno)));
+ return(0);
}
- retval->tv_sec = secdiff;
- retval->tv_usec = usecdiff;
- if(secdiff < 0)
- return -1;
- if(secdiff > 0)
- return 1;
- return (usecdiff < 0 ) ? -1 : ((usecdiff > 0 ) ? 1 : 0);
+
+ lastip = sock.sin_addr;
+ lastport = ntohs(sock.sin_port);
+
+ DEBUG(10,("read_udp_socket: lastip %s lastport %d read: %d\n",
+ inet_ntoa(lastip), lastport, ret));
+
+ return(ret);
}
/****************************************************************************
read data from a device with a timout in msec.
mincount = if timeout, minimum to read before returning
maxcount = number to be read.
+time_out = timeout in milliseconds
****************************************************************************/
-int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out,BOOL exact)
+
+ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out)
{
fd_set fds;
int selrtn;
- int readret;
- int nread = 0;
- struct timeval timeout, tval1, tval2, tvaldiff;
- int error_limit = 5;
+ ssize_t readret;
+ size_t nread = 0;
+ struct timeval timeout;
/* just checking .... */
if (maxcnt <= 0) return(0);
- if(time_out == -2)
- time_out = DEFAULT_PIPE_TIMEOUT;
+ smb_read_error = 0;
/* Blocking read */
- if(time_out < 0) {
+ if (time_out <= 0) {
if (mincnt == 0) mincnt = maxcnt;
- while (nread < mincnt)
- {
- readret = read(fd, buf + nread, maxcnt - nread);
- if (readret <= 0) return(nread);
- nread += readret;
+ while (nread < mincnt) {
+#ifdef WITH_SSL
+ if(fd == sslFd){
+ readret = SSL_read(ssl, buf + nread, maxcnt - nread);
+ }else{
+ readret = read(fd, buf + nread, maxcnt - nread);
+ }
+#else /* WITH_SSL */
+ readret = read(fd, buf + nread, maxcnt - nread);
+#endif /* WITH_SSL */
+
+ if (readret == 0) {
+ smb_read_error = READ_EOF;
+ return -1;
}
- return(nread);
+
+ if (readret == -1) {
+ smb_read_error = READ_ERROR;
+ return -1;
+ }
+ nread += readret;
+ }
+ return((ssize_t)nread);
}
- /* Non blocking read */
- if(time_out == 0) {
- set_blocking(fd, False);
- nread = read_data(fd, buf, mincnt);
- if (nread < maxcnt)
- nread += read(fd,buf+nread,maxcnt-nread);
- if(nread == -1 && errno == EWOULDBLOCK)
- nread = 0;
- set_blocking(fd,True);
- return nread;
- }
-
/* Most difficult - timeout read */
/* If this is ever called on a disk file and
- mincnt is greater then the filesize then
- system performance will suffer severely as
- select always return true on disk files */
+ mincnt is greater then the filesize then
+ system performance will suffer severely as
+ select always returns true on disk files */
/* Set initial timeout */
- timeout.tv_sec = time_out / 1000;
- timeout.tv_usec = 1000 * (time_out % 1000);
-
- /* As most UNIXes don't modify the value of timeout
- when they return from select we need to get the timeofday (in usec)
- now, and also after the select returns so we know
- how much time has elapsed */
-
- if (exact)
- GetTimeOfDay( &tval1);
- nread = 0; /* Number of bytes we have read */
-
- for(;;)
- {
- FD_ZERO(&fds);
- FD_SET(fd,&fds);
-
- selrtn = sys_select(&fds,&timeout);
-
- /* Check if error */
- if(selrtn == -1) {
- errno = EBADF;
- return -1;
- }
-
- /* Did we timeout ? */
- if (selrtn == 0) {
- if (nread < mincnt) return -1;
- break; /* Yes */
- }
-
- readret = read(fd, buf+nread, maxcnt-nread);
- if (readret == 0 && nread < mincnt) {
- /* error_limit should not really be needed, but some systems
- do strange things ... I don't want to just continue
- indefinately in case we get an infinite loop */
- if (error_limit--) continue;
- return(-1);
- }
+ timeout.tv_sec = (time_t)(time_out / 1000);
+ timeout.tv_usec = (long)(1000 * (time_out % 1000));
- if (readret < 0) {
- /* force a particular error number for
- portability */
- DEBUG(5,("read gave error %s\n",strerror(errno)));
- errno = EBADF;
- return -1;
- }
-
- nread += readret;
+ for (nread=0; nread < mincnt; )
+ {
+ FD_ZERO(&fds);
+ FD_SET(fd,&fds);
- /* If we have read more than mincnt then return */
- if (nread >= mincnt)
- break;
-
- /* We need to do another select - but first reduce the
- time_out by the amount of time already elapsed - if
- this is less than zero then return */
- if (exact) {
- GetTimeOfDay(&tval2);
- (void)tval_sub( &tvaldiff, &tval2, &tval1);
+ selrtn = sys_select(fd+1,&fds,&timeout);
+
+ /* Check if error */
+ if(selrtn == -1) {
+ /* something is wrong. Maybe the socket is dead? */
+ smb_read_error = READ_ERROR;
+ return -1;
+ }
- if (tval_sub(&timeout, &timeout, &tvaldiff) <= 0)
- break; /* We timed out */
- }
+ /* Did we timeout ? */
+ if (selrtn == 0) {
+ smb_read_error = READ_TIMEOUT;
+ return -1;
+ }
- /* Save the time of day as we need to do the select
- again (saves a system call) */
- tval1 = tval2;
+#ifdef WITH_SSL
+ if(fd == sslFd){
+ readret = SSL_read(ssl, buf + nread, maxcnt - nread);
+ }else{
+ readret = read(fd, buf + nread, maxcnt - nread);
}
+#else /* WITH_SSL */
+ readret = read(fd, buf+nread, maxcnt-nread);
+#endif /* WITH_SSL */
- /* Return the number we got */
- return(nread);
-}
-
-/****************************************************************************
-read data from the client. Maxtime is in milliseconds
-****************************************************************************/
-int read_max_udp(int fd,char *buffer,int bufsize,int maxtime)
-{
- fd_set fds;
- int selrtn;
- int nread;
- struct timeval timeout;
-
- FD_ZERO(&fds);
- FD_SET(fd,&fds);
-
- timeout.tv_sec = maxtime / 1000;
- timeout.tv_usec = (maxtime % 1000) * 1000;
-
- selrtn = sys_select(&fds,maxtime>0?&timeout:NULL);
-
- if (!FD_ISSET(fd,&fds))
- return 0;
+ if (readret == 0) {
+ /* we got EOF on the file descriptor */
+ smb_read_error = READ_EOF;
+ return -1;
+ }
- nread = read_udp_socket(fd, buffer, bufsize);
+ if (readret == -1) {
+ /* the descriptor is probably dead */
+ smb_read_error = READ_ERROR;
+ return -1;
+ }
+
+ nread += readret;
+ }
- /* return the number got */
- return(nread);
+ /* Return the number we got */
+ return((ssize_t)nread);
}
/*******************************************************************
@@ -2364,184 +2006,92 @@ BOOL send_keepalive(int client)
/****************************************************************************
read data from the client, reading exactly N bytes.
****************************************************************************/
-int read_data(int fd,char *buffer,int N)
+ssize_t read_data(int fd,char *buffer,size_t N)
{
- int ret;
- int total=0;
+ ssize_t ret;
+ size_t total=0;
+ smb_read_error = 0;
+
while (total < N)
- {
+ {
+#ifdef WITH_SSL
+ if(fd == sslFd){
+ ret = SSL_read(ssl, buffer + total, N - total);
+ }else{
ret = read(fd,buffer + total,N - total);
-
- /* this is for portability */
- if (ret < 0)
- errno = EBADF;
-
- if (ret <= 0)
- return total;
- total += ret;
}
- return total;
-}
+#else /* WITH_SSL */
+ ret = read(fd,buffer + total,N - total);
+#endif /* WITH_SSL */
-
-/****************************************************************************
- write data to a fd
-****************************************************************************/
-int write_data(int fd,char *buffer,int N)
-{
- int total=0;
- int ret;
-
- while (total < N)
+ if (ret == 0)
{
- ret = write(fd,buffer + total,N - total);
-
- if (ret <= 0)
- return total;
-
- total += ret;
+ smb_read_error = READ_EOF;
+ return 0;
}
- return total;
-}
-
-
-/* variables used by the read prediction module */
-int rp_fd = -1;
-int rp_offset = 0;
-int rp_length = 0;
-int rp_alloced = 0;
-int rp_predict_fd = -1;
-int rp_predict_offset = 0;
-int rp_predict_length = 0;
-int rp_timeout = 5;
-time_t rp_time = 0;
-char *rp_buffer = NULL;
-BOOL predict_skip=False;
-time_t smb_last_time=(time_t)0;
-
-/****************************************************************************
-handle read prediction on a file
-****************************************************************************/
-int read_predict(int fd,int offset,char *buf,char **ptr,int num)
-{
- int ret = 0;
- int possible = rp_length - (offset - rp_offset);
-
- possible = MIN(possible,num);
-
- /* give data if possible */
- if (fd == rp_fd &&
- offset >= rp_offset &&
- possible>0 &&
- smb_last_time-rp_time < rp_timeout)
+ if (ret == -1)
{
- ret = possible;
- if (buf)
- memcpy(buf,rp_buffer + (offset-rp_offset),possible);
- else
- *ptr = rp_buffer + (offset-rp_offset);
- DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num));
+ smb_read_error = READ_ERROR;
+ return -1;
}
-
- if (ret == num) {
- predict_skip = True;
- } else {
- predict_skip = False;
-
- /* prepare the next prediction */
- rp_predict_fd = fd;
- rp_predict_offset = offset + num;
- rp_predict_length = num;
+ total += ret;
}
-
- if (ret < 0) ret = 0;
-
- return(ret);
+ return (ssize_t)total;
}
+
/****************************************************************************
-pre-read some data
+ write data to a fd
****************************************************************************/
-void do_read_prediction()
+ssize_t write_data(int fd,char *buffer,size_t N)
{
- if (predict_skip) return;
-
- if (rp_predict_fd == -1)
- return;
-
- rp_fd = rp_predict_fd;
- rp_offset = rp_predict_offset;
- rp_length = 0;
-
- rp_predict_fd = -1;
-
- rp_predict_length = MIN(rp_predict_length,2*ReadSize);
- rp_predict_length = MAX(rp_predict_length,1024);
- rp_offset = (rp_offset/1024)*1024;
- rp_predict_length = (rp_predict_length/1024)*1024;
+ size_t total=0;
+ ssize_t ret;
- if (rp_predict_length > rp_alloced)
- {
- rp_buffer = Realloc(rp_buffer,rp_predict_length);
- rp_alloced = rp_predict_length;
- if (!rp_buffer)
- {
- DEBUG(0,("can't allocate read-prediction buffer\n"));
- rp_predict_fd = -1;
- rp_fd = -1;
- rp_alloced = 0;
- return;
- }
+ while (total < N)
+ {
+#ifdef WITH_SSL
+ if(fd == sslFd){
+ ret = SSL_write(ssl,buffer + total,N - total);
+ }else{
+ ret = write(fd,buffer + total,N - total);
}
+#else /* WITH_SSL */
+ ret = write(fd,buffer + total,N - total);
+#endif /* WITH_SSL */
- if (lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) {
- rp_fd = -1;
- rp_predict_fd = -1;
- return;
- }
-
- rp_length = read(rp_fd,rp_buffer,rp_predict_length);
- rp_time = time(NULL);
- if (rp_length < 0)
- rp_length = 0;
-}
+ if (ret == -1) return -1;
+ if (ret == 0) return total;
-/****************************************************************************
-invalidate read-prediction on a fd
-****************************************************************************/
-void invalidate_read_prediction(int fd)
-{
- if (rp_fd == fd)
- rp_fd = -1;
- if (rp_predict_fd == fd)
- rp_predict_fd = -1;
+ total += ret;
+ }
+ return (ssize_t)total;
}
/****************************************************************************
transfer some data between two fd's
****************************************************************************/
-int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align)
+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;
- static int size = 0;
- int total = 0;
+ SMB_OFF_T total = 0;
- DEBUG(4,("transfer_file %d (head=%d) called\n",n,headlen));
+ DEBUG(4,("transfer_file n=%.0f (head=%d) called\n",(double)n,headlen));
- if ((size < ReadSize) && buf) {
- free(buf);
- buf = NULL;
+ if (size == 0) {
+ size = lp_readsize();
+ size = MAX(size,1024);
}
- size = MAX(ReadSize,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);
@@ -2553,159 +2103,195 @@ int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align)
n += headlen;
while (n > 0)
- {
- int s = MIN(n,size);
- int ret,ret2=0;
+ {
+ int s = (int)MIN(n,(SMB_OFF_T)size);
+ int ret,ret2=0;
- ret = 0;
+ ret = 0;
- if (header && (headlen >= MIN(s,1024))) {
- buf1 = header;
- s = headlen;
- ret = headlen;
- headlen = 0;
- header = NULL;
- } else {
- buf1 = abuf;
- }
+ if (header && (headlen >= MIN(s,1024))) {
+ buf1 = header;
+ s = headlen;
+ ret = headlen;
+ headlen = 0;
+ header = NULL;
+ } else {
+ buf1 = abuf;
+ }
- if (header && headlen > 0)
- {
- ret = MIN(headlen,size);
- memcpy(buf1,header,ret);
- headlen -= ret;
- header += ret;
- if (headlen <= 0) header = NULL;
- }
+ if (header && headlen > 0)
+ {
+ ret = MIN(headlen,size);
+ memcpy(buf1,header,ret);
+ headlen -= ret;
+ header += ret;
+ if (headlen <= 0) header = NULL;
+ }
- if (s > ret)
- ret += read(infd,buf1+ret,s-ret);
+ if (s > ret)
+ ret += read(infd,buf1+ret,s-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;
+ 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);
}
/****************************************************************************
read 4 bytes of a smb packet and return the smb length of the packet
-possibly store the result in the buffer
+store the result in the buffer
+This version of the function will return a length of zero on receiving
+a keepalive packet.
+timeout is in milliseconds.
****************************************************************************/
-int read_smb_length(int fd,char *inbuf,int timeout)
+static ssize_t read_smb_length_return_keepalive(int fd,char *inbuf,unsigned int timeout)
{
- char *buffer;
- char buf[4];
- int len=0, msg_type;
- BOOL ok=False;
-
- if (inbuf)
- buffer = inbuf;
- else
- buffer = buf;
+ ssize_t len=0;
+ int msg_type;
+ BOOL ok = False;
while (!ok)
- {
- if (timeout > 0)
- ok = (read_with_timeout(fd,buffer,4,4,timeout,False) == 4);
- else
- ok = (read_data(fd,buffer,4) == 4);
+ {
+ if (timeout > 0)
+ ok = (read_with_timeout(fd,inbuf,4,4,timeout) == 4);
+ else
+ ok = (read_data(fd,inbuf,4) == 4);
- if (!ok)
- {
- if (timeout>0)
- {
- DEBUG(10,("select timeout (%d)\n", timeout));
- return(-1);
- }
- else
- {
- DEBUG(6,("couldn't read from client\n"));
- exit(1);
- }
- }
+ if (!ok)
+ return(-1);
- len = smb_len(buffer);
- msg_type = CVAL(buffer,0);
+ len = smb_len(inbuf);
+ msg_type = CVAL(inbuf,0);
- if (msg_type == 0x85)
- {
- DEBUG(5,( "Got keepalive packet\n"));
- ok = False;
- }
- }
+ if (msg_type == 0x85)
+ DEBUG(5,("Got keepalive packet\n"));
+ }
DEBUG(10,("got smb length of %d\n",len));
return(len);
}
+/****************************************************************************
+read 4 bytes of a smb packet and return the smb length of the packet
+store the result in the buffer. This version of the function will
+never return a session keepalive (length of zero).
+timeout is in milliseconds.
+****************************************************************************/
+ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout)
+{
+ ssize_t len;
+ for(;;)
+ {
+ len = read_smb_length_return_keepalive(fd, inbuf, timeout);
+
+ if(len < 0)
+ return len;
+
+ /* Ignore session keepalives. */
+ if(CVAL(inbuf,0) != 0x85)
+ break;
+ }
+
+ return len;
+}
/****************************************************************************
- read an smb from a fd and return it's length
-The timeout is in milli seconds
+ read an smb from a fd. Note that the buffer *MUST* be of size
+ BUFFER_SIZE+SAFETY_MARGIN.
+ The timeout is in milliseconds.
+ This function will return on a
+ receipt of a session keepalive packet.
****************************************************************************/
-BOOL receive_smb(int fd,char *buffer,int timeout)
+BOOL receive_smb(int fd,char *buffer, unsigned int timeout)
{
- int len;
- BOOL ok;
+ ssize_t len,ret;
+
+ smb_read_error = 0;
bzero(buffer,smb_size + 100);
- len = read_smb_length(fd,buffer,timeout);
- if (len == -1)
+ len = read_smb_length_return_keepalive(fd,buffer,timeout);
+ if (len < 0)
return(False);
- if (len > BUFFER_SIZE)
- {
- DEBUG(0,("Invalid packet length! (%d bytes)\n",len));
- if (len > BUFFER_SIZE + (SAFETY_MARGIN/2))
- exit(1);
- }
-
- ok = (read_data(fd,buffer+4,len) == len);
-
- if (!ok)
- {
- close_sockets();
+ if (len > BUFFER_SIZE) {
+ DEBUG(0,("Invalid packet length! (%d bytes).\n",len));
+ if (len > BUFFER_SIZE + (SAFETY_MARGIN/2))
exit(1);
- }
+ }
+ if(len > 0) {
+ ret = read_data(fd,buffer+4,len);
+ if (ret != len) {
+ smb_read_error = READ_ERROR;
+ return False;
+ }
+ }
return(True);
}
+/****************************************************************************
+ read an smb from a fd ignoring all keepalive packets. Note that the buffer
+ *MUST* be of size BUFFER_SIZE+SAFETY_MARGIN.
+ The timeout is in milliseconds
+
+ This is exactly the same as receive_smb except that it never returns
+ a session keepalive packet (just as receive_smb used to do).
+ receive_smb was changed to return keepalives as the oplock processing means this call
+ should never go into a blocking read.
+****************************************************************************/
+
+BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout)
+{
+ BOOL ret;
+
+ for(;;)
+ {
+ ret = receive_smb(fd, buffer, timeout);
+
+ if(ret == False)
+ return ret;
+
+ /* Ignore session keepalive packets. */
+ if(CVAL(buffer,0) != 0x85)
+ break;
+ }
+ return ret;
+}
/****************************************************************************
send an smb to a fd
****************************************************************************/
BOOL send_smb(int fd,char *buffer)
{
- int len;
- int ret,nwritten=0;
+ size_t len;
+ size_t nwritten=0;
+ ssize_t ret;
len = smb_len(buffer) + 4;
while (nwritten < len)
+ {
+ ret = write_socket(fd,buffer+nwritten,len - nwritten);
+ if (ret <= 0)
{
- ret = write_socket(fd,buffer+nwritten,len - nwritten);
- if (ret <= 0)
- {
- DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret));
- close_sockets();
- exit(1);
- }
- nwritten += ret;
+ DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret));
+ close_sockets();
+ exit(1);
}
-
+ nwritten += ret;
+ }
return True;
}
@@ -2714,7 +2300,7 @@ BOOL send_smb(int fd,char *buffer)
/****************************************************************************
find a pointer to a netbios name
****************************************************************************/
-char *name_ptr(char *buf,int ofs)
+static char *name_ptr(char *buf,int ofs)
{
unsigned char c = *(unsigned char *)(buf+ofs);
@@ -2739,24 +2325,30 @@ int name_extract(char *buf,int ofs,char *name)
{
char *p = name_ptr(buf,ofs);
int d = PTR_DIFF(p,buf+ofs);
- strcpy(name,"");
+ 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 *s)
+int name_len( char *s )
{
- char *s0=s;
- unsigned char c = *(unsigned char *)s;
- if ((c & 0xC0) == 0xC0)
+ int len;
+
+ /* If the two high bits of the byte are set, return 2. */
+ if( 0xC0 == (*(unsigned char *)s & 0xC0) )
return(2);
- while (*s) s += (*s)+1;
- return(PTR_DIFF(s,s0)+1);
-}
+
+ /* Add up the length bytes. */
+ for( len = 1; (*s); s += (*s) + 1 )
+ {
+ len += *s + 1;
+ }
+
+ return( len );
+} /* name_len */
/****************************************************************************
send a single packet to a port on another machine
@@ -2792,8 +2384,8 @@ BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
ret = (sendto(out_fd,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
if (!ret)
- DEBUG(0,("Packet send to %s(%d) failed ERRNO=%d\n",
- inet_ntoa(ip),port,errno));
+ DEBUG(0,("Packet send to %s(%d) failed ERRNO=%s\n",
+ inet_ntoa(ip),port,strerror(errno)));
close(out_fd);
return(ret);
@@ -2802,7 +2394,7 @@ BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
/*******************************************************************
sleep for a specified number of milliseconds
********************************************************************/
-void msleep(int t)
+static void msleep(int t)
{
int tdiff=0;
struct timeval tval,t1,t2;
@@ -2817,7 +2409,7 @@ void msleep(int t)
FD_ZERO(&fds);
errno = 0;
- sys_select(&fds,&tval);
+ sys_select(0,&fds,&tval);
GetTimeOfDay(&t2);
tdiff = TvalDiff(&t1,&t2);
@@ -2834,16 +2426,15 @@ BOOL in_list(char *s,char *list,BOOL casesensitive)
if (!list) return(False);
- while (next_token(&p,tok,LIST_SEP))
- {
- if (casesensitive) {
- if (strcmp(tok,s) == 0)
- return(True);
- } else {
- if (StrCaseCmp(tok,s) == 0)
- return(True);
- }
+ while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
+ if (casesensitive) {
+ if (strcmp(tok,s) == 0)
+ return(True);
+ } else {
+ if (StrCaseCmp(tok,s) == 0)
+ return(True);
}
+ }
return(False);
}
@@ -2863,16 +2454,24 @@ BOOL string_init(char **dest,char *src)
if (l == 0)
{
- if (!null_string)
- null_string = (char *)malloc(1);
-
- *null_string = 0;
+ if (!null_string) {
+ if((null_string = (char *)malloc(1)) == NULL) {
+ DEBUG(0,("string_init: malloc fail for null_string.\n"));
+ return False;
+ }
+ *null_string = 0;
+ }
*dest = null_string;
}
else
{
- *dest = (char *)malloc(l+1);
- strcpy(*dest,src);
+ (*dest) = (char *)malloc(l+1);
+ if ((*dest) == NULL) {
+ DEBUG(0,("Out of memory in string_init\n"));
+ return False;
+ }
+
+ pstrcpy(*dest,src);
}
return(True);
}
@@ -2934,13 +2533,12 @@ BOOL string_sub(char *s,char *pattern,char *insert)
return(ret);
}
-
-
/*********************************************************
-* Recursive routine that is called by mask_match.
-* Does the actual matching.
+* Recursive routine that is called by unix_mask_match.
+* Does the actual matching. This is the 'original code'
+* used by the unix matcher.
*********************************************************/
-BOOL do_match(char *str, char *regexp, int case_sig)
+static BOOL unix_do_match(char *str, char *regexp, int case_sig)
{
char *p;
@@ -2959,7 +2557,7 @@ BOOL do_match(char *str, char *regexp, int case_sig)
while(*str) {
while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
str++;
- if(do_match(str,p,case_sig))
+ if(unix_do_match(str,p,case_sig))
return True;
if(!*str)
return False;
@@ -3002,8 +2600,10 @@ BOOL do_match(char *str, char *regexp, int case_sig)
* 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.
*********************************************************/
-BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
+
+static BOOL unix_mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
{
char *p;
pstring p1, p2;
@@ -3016,301 +2616,365 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
StrnCpy(p2,str,sizeof(pstring)-1);
if (!strchr(p2,'.')) {
- strcat(p2,".");
- }
-
-/*
- if (!strchr(p1,'.')) {
- strcat(p1,".");
+ pstrcat(p2,".");
}
-*/
-
-#if 0
- if (strchr(p1,'.'))
- {
- string_sub(p1,"*.*","*");
- string_sub(p1,".*","*");
- }
-#endif
/* Remove any *? and ** as they are meaningless */
for(p = p1; *p; p++)
while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
- (void)strcpy( &p[1], &p[2]);
+ (void)pstrcpy( &p[1], &p[2]);
if (strequal(p1,"*")) return(True);
- DEBUG(5,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
+ DEBUG(8,("unix_mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
if (trans2) {
- strcpy(ebase,p1);
- strcpy(sbase,p2);
+ fstrcpy(ebase,p1);
+ fstrcpy(sbase,p2);
} else {
if ((p=strrchr(p1,'.'))) {
*p = 0;
- strcpy(ebase,p1);
- strcpy(eext,p+1);
+ fstrcpy(ebase,p1);
+ fstrcpy(eext,p+1);
} else {
- strcpy(ebase,p1);
+ fstrcpy(ebase,p1);
eext[0] = 0;
}
if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
*p = 0;
- strcpy(sbase,p2);
- strcpy(sext,p+1);
+ fstrcpy(sbase,p2);
+ fstrcpy(sext,p+1);
} else {
- strcpy(sbase,p2);
- strcpy(sext,"");
+ fstrcpy(sbase,p2);
+ fstrcpy(sext,"");
}
}
- matched = do_match(sbase,ebase,case_sig) &&
- (trans2 || do_match(sext,eext,case_sig));
+ matched = unix_do_match(sbase,ebase,case_sig) &&
+ (trans2 || unix_do_match(sext,eext,case_sig));
- DEBUG(5,("mask_match returning %d\n", matched));
+ 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.
+*********************************************************/
-
-/****************************************************************************
-become a daemon, discarding the controlling terminal
-****************************************************************************/
-void become_daemon(void)
+BOOL do_match(char *str, char *regexp, int case_sig)
{
-#ifndef NO_FORK_DEBUG
- if (fork())
- exit(0);
+ char *p;
- /* detach from the terminal */
-#ifdef USE_SETSID
- setsid();
-#else
-#ifdef TIOCNOTTY
- {
- int i = open("/dev/tty", O_RDWR);
- if (i >= 0)
- {
- ioctl(i, (int) TIOCNOTTY, (char *)0);
- close(i);
+ 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++;
+ /* Now eat all characters that match, as
+ we want the *last* character to match. */
+ while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str))))
+ str++;
+ str--; /* We've eaten the match char after the '*' */
+ if(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;
+ }
}
-#endif
-#endif
-#endif
-}
-/****************************************************************************
-calculate the default netmask for an address
-****************************************************************************/
-static void default_netmask(struct in_addr *inm, struct in_addr *iad)
-{
- unsigned long ad = ntohl(iad->s_addr);
- unsigned long nm;
- /*
- ** Guess a netmask based on the class of the IP address given.
- */
- if ( (ad & 0x80000000) == 0 ) {
- /* class A address */
- nm = 0xFF000000;
- } else if ( (ad & 0xC0000000) == 0x80000000 ) {
- /* class B address */
- nm = 0xFFFF0000;
- } else if ( (ad & 0xE0000000) == 0xC0000000 ) {
- /* class C address */
- nm = 0xFFFFFF00;
- } else {
- /* class D or E; netmask doesn't make much sense - guess 4 bits */
- nm = 0xFFFFFFF0;
+ if(!*p && !*str)
+ return True;
+
+ if (!*p && str[0] == '.' && str[1] == 0) {
+ return(True);
}
- inm->s_addr = htonl(nm);
+
+ if (!*str && *p == '?') {
+ while (*p == '?')
+ p++;
+ return(!*p);
+ }
+
+ if(!*str && (*p == '*' && p[1] == '\0')) {
+ return True;
+ }
+
+ return False;
}
-/****************************************************************************
- get the broadcast address for our address
-(troyer@saifr00.ateng.az.honeywell.com)
-****************************************************************************/
-void get_broadcast(struct in_addr *if_ipaddr,
- struct in_addr *if_bcast,
- struct in_addr *if_nmask)
-{
- BOOL found = False;
-#ifndef NO_GET_BROADCAST
- int sock = -1; /* AF_INET raw socket desc */
- char buff[1024];
- struct ifreq *ifr=NULL;
- int i;
-#if defined(EVEREST)
- int n_interfaces;
- struct ifconf ifc;
- struct ifreq *ifreqs;
-#elif defined(USE_IFREQ)
- struct ifreq ifreq;
- struct strioctl strioctl;
- struct ifconf *ifc;
-#else
- struct ifconf ifc;
-#endif
-#endif
+/*********************************************************
+* 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.
+*********************************************************/
- /* get a default netmask and broadcast */
- default_netmask(if_nmask, if_ipaddr);
+BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
+{
+ char *p;
+ pstring t_pattern, t_filename, te_pattern, te_filename;
+ fstring ebase,eext,sbase,sext;
-#ifndef NO_GET_BROADCAST
- /* Create a socket to the INET kernel. */
-#if USE_SOCKRAW
- if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0)
-#else
- if ((sock = socket(AF_INET, SOCK_DGRAM, 0 )) < 0)
+ BOOL matched = False;
+
+ /* Make local copies of str and regexp */
+ pstrcpy(t_pattern,regexp);
+ pstrcpy(t_filename,str);
+
+#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
- {
- DEBUG(0,( "Unable to open socket to get broadcast address\n"));
- return;
- }
-
- /* Get a list of the configured interfaces */
-#ifdef EVEREST
- /* This is part of SCO Openserver 5: The ioctls are no longer part
- if the lower level STREAMS interface glue. They are now real
- ioctl calls */
-
- if (ioctl(sock, SIOCGIFANUM, &n_interfaces) < 0) {
- DEBUG(0,( "SIOCGIFANUM: %s\n", strerror(errno)));
- } else {
- DEBUG(0,( "number of interfaces returned is: %d\n", n_interfaces));
- ifc.ifc_len = sizeof(struct ifreq) * n_interfaces;
- ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len);
+#if 0
+ if (!strchr(t_filename,'.')) {
+ pstrcat(t_filename,".");
+ }
+#endif
- if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
- DEBUG(0, ( "SIOCGIFCONF: %s\n", strerror(errno)));
- else {
- ifr = ifc.ifc_req;
+ /* Remove any *? and ** as they are meaningless */
+ string_sub(t_pattern, "*?", "*");
+ string_sub(t_pattern, "**", "*");
- for (i = 0; i < n_interfaces; ++i) {
- if (if_ipaddr->s_addr ==
- ((struct sockaddr_in *) &ifr[i].ifr_addr)->sin_addr.s_addr) {
- found = True;
- break;
- }
- }
+ 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.
+ */
+ string_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);
+ 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[strlen(cp1)-1] == '*')
+ last_wcard_was_star = True;
+ else
+ last_wcard_was_star = False;
+
+ if(!do_match(cp2, cp1, case_sig))
+ 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)) {
+ cp2 = fp ? fp + 1 : "";
+ break;
+ }
+ cp2 = fp ? fp + 1 : "";
+ }
+ num_path_components -= i;
+ }
+ }
+ if(cp1 == NULL && ((*cp2 == '\0') || last_wcard_was_star))
+ matched = True;
}
- }
-#elif defined(USE_IFREQ)
- ifc = (struct ifconf *)buff;
- ifc->ifc_len = BUFSIZ - sizeof(struct ifconf);
- strioctl.ic_cmd = SIOCGIFCONF;
- strioctl.ic_dp = (char *)ifc;
- strioctl.ic_len = sizeof(buff);
- if (ioctl(sock, I_STR, &strioctl) < 0) {
- DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno)));
} else {
- ifr = (struct ifreq *)ifc->ifc_req;
-
- /* Loop through interfaces, looking for given IP address */
- for (i = ifc->ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
- if (if_ipaddr->s_addr ==
- (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
- found = True;
- break;
+
+ /* -------------------------------------------------
+ * 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, "?"))
+ 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, "?.*"))
+ 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;
}
- }
- }
-#elif defined(__FreeBSD__) || defined(NETBSD)
- ifc.ifc_len = sizeof(buff);
- ifc.ifc_buf = buff;
- if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
- DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
- } else {
- ifr = ifc.ifc_req;
- /* Loop through interfaces, looking for given IP address */
- i = ifc.ifc_len;
- while (i > 0) {
- if (if_ipaddr->s_addr ==
- (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
- found = True;
- break;
+
+ 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 */
}
- i -= ifr->ifr_addr.sa_len + IFNAMSIZ;
- ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
- }
- }
-#else
- ifc.ifc_len = sizeof(buff);
- ifc.ifc_buf = buff;
- if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
- DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
- } else {
- ifr = ifc.ifc_req;
-
- /* Loop through interfaces, looking for given IP address */
- for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
-#ifdef BSDI
- if (ioctl(sock, SIOCGIFADDR, ifr) < 0) break;
+
+ 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)
+ && do_match(sext, eext, case_sig);
+ } else {
+ /* pattern has no extension */
+ /* Really: match complete filename with pattern ??? means exactly 3 chars */
+ matched = do_match(str, ebase, case_sig);
+ }
+ } else {
+ /*
+ * Filename has no extension.
+ */
+ fstrcpy (sbase, t_filename);
+ fstrcpy (sext, "");
+ if (*eext) {
+ /* pattern has extension */
+ matched = do_match(sbase, ebase, case_sig)
+ && do_match(sext, eext, case_sig);
+ } else {
+ matched = do_match(sbase, ebase, case_sig);
+#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);
+ }
#endif
- if (if_ipaddr->s_addr ==
- (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
- found = True;
- break;
+ }
}
}
}
-#endif
-
- if (!found) {
- DEBUG(0,("No interface found for address %s\n", inet_ntoa(*if_ipaddr)));
- } else {
- /* Get the netmask address from the kernel */
-#ifdef USE_IFREQ
- ifreq = *ifr;
-
- strioctl.ic_cmd = SIOCGIFNETMASK;
- strioctl.ic_dp = (char *)&ifreq;
- strioctl.ic_len = sizeof(struct ifreq);
- if (ioctl(sock, I_STR, &strioctl) < 0)
- DEBUG(0,("Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno)));
- else
- *if_nmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
-#else
- if (ioctl(sock, SIOCGIFNETMASK, ifr) < 0)
- DEBUG(0,("SIOCGIFNETMASK failed\n"));
- else
- *if_nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
-#endif
- DEBUG(2,("Netmask for %s = %s\n", ifr->ifr_name,
- inet_ntoa(*if_nmask)));
- }
+ DEBUG(8,("mask_match returning %d\n", matched));
- /* Close up shop */
- (void) close(sock);
-
-#endif
+ return matched;
+}
- /* sanity check on the netmask */
- {
- unsigned long nm = ntohl(if_nmask->s_addr);
- if ((nm >> 24) != 0xFF) {
- DEBUG(0,("Impossible netmask %s - using defaults\n",inet_ntoa(*if_nmask)));
- default_netmask(if_nmask, if_ipaddr);
- }
- }
+/****************************************************************************
+become a daemon, discarding the controlling terminal
+****************************************************************************/
+void become_daemon(void)
+{
+ if (fork()) {
+ _exit(0);
+ }
- /* derive the broadcast assuming a 1's broadcast, as this is what
- all MS operating systems do, we have to comply even if the unix
- box is setup differently */
- {
- unsigned long ad = ntohl(if_ipaddr->s_addr);
- unsigned long nm = ntohl(if_nmask->s_addr);
- unsigned long bc = (ad & nm) | (0xffffffff & ~nm);
- if_bcast->s_addr = htonl(bc);
- }
-
- DEBUG(2,("Derived broadcast address %s\n", inet_ntoa(*if_bcast)));
-} /* get_broadcast */
+ /* detach from the terminal */
+#ifdef HAVE_SETSID
+ setsid();
+#elif defined(TIOCNOTTY)
+ {
+ int i = open("/dev/tty", O_RDWR);
+ if (i != -1) {
+ ioctl(i, (int) TIOCNOTTY, (char *)0);
+ close(i);
+ }
+ }
+#endif /* HAVE_SETSID */
+
+ /* Close fd's 0,1,2. Needed if started by rsh */
+ close_low_fds();
+}
/****************************************************************************
@@ -3402,18 +3066,18 @@ char *fgets_slash(char *s2,int maxlen,FILE *f)
set the length of a file from a filedescriptor.
Returns 0 on success, -1 on failure.
****************************************************************************/
-int set_filelen(int fd, long len)
+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 */
-#if FTRUNCATE_CAN_EXTEND
- return ftruncate(fd, len);
+#ifdef HAVE_FTRUNCATE_EXTEND
+ return sys_ftruncate(fd, len);
#else
- struct stat st;
+ SMB_STRUCT_STAT st;
char c = 0;
- long currpos = lseek(fd, 0L, SEEK_CUR);
+ SMB_OFF_T currpos = sys_lseek(fd, (SMB_OFF_T)0, SEEK_CUR);
if(currpos < 0)
return -1;
@@ -3421,7 +3085,7 @@ int set_filelen(int fd, long len)
the requested size (call ftruncate),
or shorter, in which case seek to len - 1 and write 1
byte of zero */
- if(fstat(fd, &st)<0)
+ if(sys_fstat(fd, &st)<0)
return -1;
#ifdef S_ISFIFO
@@ -3431,38 +3095,24 @@ int set_filelen(int fd, long len)
if(st.st_size == len)
return 0;
if(st.st_size > len)
- return ftruncate(fd, len);
+ return sys_ftruncate(fd, len);
- if(lseek(fd, len-1, SEEK_SET) != len -1)
+ 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 */
- lseek(fd, currpos, SEEK_SET);
+ sys_lseek(fd, currpos, SEEK_SET);
return 0;
#endif
}
-/****************************************************************************
-return the byte checksum of some data
-****************************************************************************/
-int byte_checksum(char *buf,int len)
-{
- unsigned char *p = (unsigned char *)buf;
- int ret = 0;
- while (len--)
- ret += *p++;
- return(ret);
-}
-
-
-
#ifdef HPUX
/****************************************************************************
this is a version of setbuffer() for those machines that only have setvbuf
****************************************************************************/
-void setbuffer(FILE *f,char *buf,int bufsize)
+ void setbuffer(FILE *f,char *buf,int bufsize)
{
setvbuf(f,buf,_IOFBF,bufsize);
}
@@ -3470,26 +3120,6 @@ void setbuffer(FILE *f,char *buf,int bufsize)
/****************************************************************************
-parse out a directory name from a path name. Assumes dos style filenames.
-****************************************************************************/
-char *dirname_dos(char *path,char *buf)
-{
- char *p = strrchr(path,'\\');
-
- if (!p)
- strcpy(buf,path);
- else
- {
- *p = 0;
- strcpy(buf,path);
- *p = '\\';
- }
-
- return(buf);
-}
-
-
-/****************************************************************************
parse out a filename from a path name. Assumes dos style filenames.
****************************************************************************/
static char *filename_dos(char *path,char *buf)
@@ -3497,9 +3127,9 @@ static char *filename_dos(char *path,char *buf)
char *p = strrchr(path,'\\');
if (!p)
- strcpy(buf,path);
+ pstrcpy(buf,path);
else
- strcpy(buf,p+1);
+ pstrcpy(buf,p+1);
return(buf);
}
@@ -3509,9 +3139,16 @@ static char *filename_dos(char *path,char *buf)
/****************************************************************************
expand a pointer to be a particular size
****************************************************************************/
-void *Realloc(void *p,int size)
+void *Realloc(void *p,size_t size)
{
void *ret=NULL;
+
+ if (size == 0) {
+ if (p) free(p);
+ DEBUG(5,("Realloc asked for 0 bytes\n"));
+ return NULL;
+ }
+
if (!p)
ret = (void *)malloc(size);
else
@@ -3523,138 +3160,11 @@ void *Realloc(void *p,int size)
return(ret);
}
-/****************************************************************************
-set the time on a file
-****************************************************************************/
-BOOL set_filetime(char *fname,time_t mtime)
-{
- struct utimbuf times;
-
- if (null_mtime(mtime)) return(True);
-
- times.modtime = times.actime = mtime;
-
- if (sys_utime(fname,&times)) {
- DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
- }
-
- return(True);
-}
-
-
-#ifdef NOSTRDUP
-/****************************************************************************
-duplicate a string
-****************************************************************************/
-char *strdup(char *s)
-{
- char *ret = NULL;
- if (!s) return(NULL);
- ret = (char *)malloc(strlen(s)+1);
- if (!ret) return(NULL);
- strcpy(ret,s);
- return(ret);
-}
-#endif
-
-
-/****************************************************************************
- Signal handler for SIGPIPE (write on a disconnected socket)
-****************************************************************************/
-void Abort(void )
-{
- DEBUG(0,("Probably got SIGPIPE\nExiting\n"));
- exit(2);
-}
-
-
-#ifdef REPLACE_STRLEN
-/****************************************************************************
-a replacement strlen() that returns int for solaris
-****************************************************************************/
-int Strlen(char *s)
-{
- int ret=0;
- if (!s) return(0);
- while (*s++) ret++;
- return(ret);
-}
-#endif
-
-
-/****************************************************************************
-return a time at the start of the current month
-****************************************************************************/
-time_t start_of_month(void)
-{
- time_t t = time(NULL);
- struct tm *t2;
-
- t2 = gmtime(&t);
-
- t2->tm_mday = 1;
- t2->tm_hour = 0;
- t2->tm_min = 0;
- t2->tm_sec = 0;
-
- return(mktime(t2));
-}
-
-
-/*******************************************************************
- check for a sane unix date
-********************************************************************/
-BOOL sane_unix_date(time_t unixdate)
-{
- struct tm t,today;
- time_t t_today = time(NULL);
-
- t = *(LocalTime(&unixdate,LOCAL_TO_GMT));
- today = *(LocalTime(&t_today,LOCAL_TO_GMT));
-
- if (t.tm_year < 80)
- return(False);
-
- if (t.tm_year > today.tm_year)
- return(False);
-
- if (t.tm_year == today.tm_year &&
- t.tm_mon > today.tm_mon)
- return(False);
-
-
- if (t.tm_year == today.tm_year &&
- t.tm_mon == today.tm_mon &&
- t.tm_mday > (today.tm_mday+1))
- return(False);
-
- return(True);
-}
-
-
-
-#ifdef NO_FTRUNCATE
- /*******************************************************************
-ftruncate for operating systems that don't have it
-********************************************************************/
-int ftruncate(int f,long l)
-{
- struct flock fl;
-
- fl.l_whence = 0;
- fl.l_len = 0;
- fl.l_start = l;
- fl.l_type = F_WRLCK;
- return fcntl(f, F_FREESP, &fl);
-}
-#endif
-
-
/****************************************************************************
get my own name and IP
****************************************************************************/
-BOOL get_myname(char *myname,struct in_addr *ip)
+BOOL get_myname(char *my_name,struct in_addr *ip)
{
struct hostent *hp;
pstring hostname;
@@ -3671,17 +3181,17 @@ BOOL get_myname(char *myname,struct in_addr *ip)
/* get host info */
if ((hp = Get_Hostbyname(hostname)) == 0)
{
- DEBUG(0,( "Get_Hostbyname: Unknown host %s.\n",hostname));
+ DEBUG(0,( "Get_Hostbyname: Unknown host %s\n",hostname));
return False;
}
- if (myname)
+ if (my_name)
{
/* split off any parts after an initial . */
char *p = strchr(hostname,'.');
if (p) *p = 0;
- strcpy(myname,hostname);
+ fstrcpy(my_name,hostname);
}
if (ip)
@@ -3696,7 +3206,7 @@ true if two IP addresses are equal
****************************************************************************/
BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
{
- unsigned long a1,a2;
+ uint32 a1,a2;
a1 = ntohl(ip1.s_addr);
a2 = ntohl(ip2.s_addr);
return(a1 == a2);
@@ -3706,7 +3216,7 @@ BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
/****************************************************************************
open a socket of the specified type, port and address for incoming data
****************************************************************************/
-int open_socket_in(int type, int port, int dlevel)
+int open_socket_in(int type, int port, int dlevel,uint32 socket_addr)
{
struct hostent *hp;
struct sockaddr_in sock;
@@ -3714,28 +3224,25 @@ int open_socket_in(int type, int port, int dlevel)
int res;
/* get my host name */
-#ifdef MAXHOSTNAMELEN
if (gethostname(host_name, MAXHOSTNAMELEN) == -1)
-#else
- if (gethostname(host_name, sizeof(host_name)) == -1)
-#endif
{ DEBUG(0,("gethostname failed\n")); return -1; }
/* get host info */
if ((hp = Get_Hostbyname(host_name)) == 0)
{
- DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",host_name));
+ DEBUG(0,( "Get_Hostbyname: Unknown host %s\n",host_name));
return -1;
}
bzero((char *)&sock,sizeof(sock));
memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
-#if defined(__FreeBSD__) || defined(NETBSD) /* XXX not the right ifdef */
+
+#ifdef HAVE_SOCK_SIN_LEN
sock.sin_len = sizeof(sock);
#endif
sock.sin_port = htons( port );
sock.sin_family = hp->h_addrtype;
- sock.sin_addr.s_addr = INADDR_ANY;
+ sock.sin_addr.s_addr = socket_addr;
res = socket(hp->h_addrtype, type, 0);
if (res == -1)
{ DEBUG(0,("socket failed\n")); return -1; }
@@ -3749,16 +3256,16 @@ int open_socket_in(int type, int port, int dlevel)
if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0)
{
if (port) {
- if (port == 139 || port == 137)
- DEBUG(dlevel,("bind failed on port %d (%s)\n",
- port,strerror(errno)));
+ if (port == SMB_PORT || port == NMB_PORT)
+ DEBUG(dlevel,("bind failed on port %d socket_addr=%s (%s)\n",
+ port,inet_ntoa(sock.sin_addr),strerror(errno)));
close(res);
if (dlevel > 0 && port < 1000)
port = 7999;
if (port >= 1000 && port < 9000)
- return(open_socket_in(type,port+1,dlevel));
+ return(open_socket_in(type,port+1,dlevel,socket_addr));
}
return(-1);
@@ -3772,10 +3279,12 @@ int open_socket_in(int type, int port, int dlevel)
/****************************************************************************
create an outgoing socket
**************************************************************************/
-int open_socket_out(int type, struct in_addr *addr, int port )
+int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
{
struct sockaddr_in sock_out;
- int res;
+ int res,ret;
+ int connect_loop = 250; /* 250 milliseconds */
+ int loops = (timeout * 1000) / connect_loop;
/* create a socket to write to */
res = socket(PF_INET, type, 0);
@@ -3790,15 +3299,46 @@ int open_socket_out(int type, struct in_addr *addr, int port )
sock_out.sin_port = htons( port );
sock_out.sin_family = PF_INET;
+ /* set it non-blocking */
+ set_blocking(res,False);
+
DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port));
/* and connect it to the destination */
- if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))<0) {
- DEBUG(0,("connect error: %s\n",strerror(errno)));
- close(res);
- return(-1);
+connect_again:
+ ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out));
+
+ /* Some systems return EAGAIN when they mean EINPROGRESS */
+ if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
+ errno == EAGAIN) && loops--) {
+ msleep(connect_loop);
+ goto connect_again;
}
+ if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
+ errno == EAGAIN)) {
+ DEBUG(1,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port));
+ close(res);
+ return -1;
+ }
+
+#ifdef EISCONN
+ if (ret < 0 && errno == EISCONN) {
+ errno = 0;
+ ret = 0;
+ }
+#endif
+
+ if (ret < 0) {
+ DEBUG(1,("error connecting to %s:%d (%s)\n",
+ inet_ntoa(*addr),port,strerror(errno)));
+ close(res);
+ return -1;
+ }
+
+ /* set it blocking again */
+ set_blocking(res,True);
+
return res;
}
@@ -3826,48 +3366,42 @@ int interpret_protocol(char *str,int def)
return(def);
}
-/****************************************************************************
-interpret a security level
-****************************************************************************/
-int interpret_security(char *str,int def)
-{
- if (strequal(str,"SERVER"))
- return(SEC_SERVER);
- if (strequal(str,"USER"))
- return(SEC_USER);
- if (strequal(str,"SHARE"))
- return(SEC_SHARE);
-
- DEBUG(0,("Unrecognised security level %s\n",str));
-
- return(def);
-}
-
/****************************************************************************
interpret an internet address or name into an IP address in 4 byte form
****************************************************************************/
-unsigned long interpret_addr(char *str)
+uint32 interpret_addr(char *str)
{
struct hostent *hp;
- unsigned long res;
+ uint32 res;
+ int i;
+ BOOL pure_address = True;
if (strcmp(str,"0.0.0.0") == 0) return(0);
if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
+ for (i=0; pure_address && str[i]; i++)
+ if (!(isdigit((int)str[i]) || str[i] == '.'))
+ pure_address = False;
+
/* if it's in the form of an IP address then get the lib to interpret it */
- if (isdigit(str[0])) {
+ if (pure_address) {
res = inet_addr(str);
} else {
- /* otherwise assume it's a network name of some sort and use Get_Hostbyname */
+ /* 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));
return 0;
}
+ if(hp->h_addr == NULL) {
+ DEBUG(3,("Get_Hostbyname: host address is invalid for host %s\n",str));
+ return 0;
+ }
putip((char *)&res,(char *)hp->h_addr);
}
- if (res == (unsigned long)-1) return(0);
+ if (res == (uint32)-1) return(0);
return(res);
}
@@ -3878,8 +3412,8 @@ unsigned long interpret_addr(char *str)
struct in_addr *interpret_addr2(char *str)
{
static struct in_addr ret;
- unsigned long a = interpret_addr(str);
- putip((char *)&ret,(char *)&a);
+ uint32 a = interpret_addr(str);
+ ret.s_addr = a;
return(&ret);
}
@@ -3888,121 +3422,534 @@ struct in_addr *interpret_addr2(char *str)
******************************************************************/
BOOL zero_ip(struct in_addr ip)
{
- unsigned long a;
+ uint32 a;
putip((char *)&a,(char *)&ip);
return(a == 0);
}
-#define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
-
-/****************************************************************************
-interpret an 8 byte "filetime" structure to a time_t
-It's originally in "100ns units since jan 1st 1601"
-It appears to be kludge-GMT (at least for file listings). This means
-its the GMT you get by taking a localtime and adding the
-serverzone. This is NOT the same as GMT in some cases. This routine
-converts this to real GMT.
-****************************************************************************/
-time_t interpret_long_date(char *p)
+/*******************************************************************
+ matchname - determine if host name matches IP address
+ ******************************************************************/
+static BOOL matchname(char *remotehost,struct in_addr addr)
{
- double d;
- time_t ret;
- uint32 tlow,thigh;
- tlow = IVAL(p,0);
- thigh = IVAL(p,4);
+ struct hostent *hp;
+ int i;
+
+ if ((hp = Get_Hostbyname(remotehost)) == 0) {
+ DEBUG(0,("Get_Hostbyname(%s): lookup failure", 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",
+ 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;
+ }
+
+ /*
+ * 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",
+ inet_ntoa(addr), hp->h_name));
+ return False;
+}
- if (thigh == 0) return(0);
+/*******************************************************************
+ Reset the 'done' variables so after a client process is created
+ from a fork call these calls will be re-done. This should be
+ expanded if more variables need reseting.
+ ******************************************************************/
+
+static BOOL global_client_name_done = False;
+static BOOL global_client_addr_done = False;
+
+void reset_globals_after_fork(void)
+{
+ global_client_name_done = False;
+ global_client_addr_done = False;
- d = ((double)thigh)*4.0*(double)(1<<30);
- d += (tlow&0xFFF00000);
- d *= 1.0e-7;
+ /*
+ * Re-seed the random crypto generator, so all smbd's
+ * started from the same parent won't generate the same
+ * sequence.
+ */
+ {
+ unsigned char dummy;
+ generate_random_buffer( &dummy, 1, True);
+ }
+}
- /* now adjust by 369 years to make the secs since 1970 */
- d -= TIME_FIXUP_CONSTANT;
+/*******************************************************************
+ return the DNS name of the client
+ ******************************************************************/
+char *client_name(int fd)
+{
+ struct sockaddr sa;
+ struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
+ int length = sizeof(sa);
+ static pstring name_buf;
+ struct hostent *hp;
+ static int last_fd=-1;
+
+ if (global_client_name_done && last_fd == fd)
+ return name_buf;
+
+ last_fd = fd;
+ global_client_name_done = False;
+
+ pstrcpy(name_buf,"UNKNOWN");
+
+ if (fd == -1) {
+ return name_buf;
+ }
+
+ if (getpeername(fd, &sa, &length) < 0) {
+ DEBUG(0,("getpeername failed\n"));
+ return name_buf;
+ }
+
+ /* Look up the remote host name. */
+ if ((hp = gethostbyaddr((char *) &sockin->sin_addr,
+ sizeof(sockin->sin_addr),
+ AF_INET)) == 0) {
+ DEBUG(1,("Gethostbyaddr failed for %s\n",client_addr(fd)));
+ StrnCpy(name_buf,client_addr(fd),sizeof(name_buf) - 1);
+ } else {
+ StrnCpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1);
+ if (!matchname(name_buf, sockin->sin_addr)) {
+ DEBUG(0,("Matchname failed on %s %s\n",name_buf,client_addr(fd)));
+ pstrcpy(name_buf,"UNKNOWN");
+ }
+ }
+ global_client_name_done = True;
+ return name_buf;
+}
- if (d>=MAXINT)
- return(0);
+/*******************************************************************
+ return the IP addr of the client as a string
+ ******************************************************************/
+char *client_addr(int fd)
+{
+ struct sockaddr sa;
+ struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
+ int length = sizeof(sa);
+ static fstring addr_buf;
+ static int last_fd = -1;
- ret = (time_t)(d+0.5);
+ if (global_client_addr_done && fd == last_fd)
+ return addr_buf;
- /* this takes us from kludge-GMT to real GMT */
- ret += TimeDiff(ret) - serverzone;
+ last_fd = fd;
+ global_client_addr_done = False;
- return(ret);
+ fstrcpy(addr_buf,"0.0.0.0");
+
+ if (fd == -1) {
+ return addr_buf;
+ }
+
+ if (getpeername(fd, &sa, &length) < 0) {
+ DEBUG(0,("getpeername failed\n"));
+ return addr_buf;
+ }
+
+ fstrcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr));
+
+ global_client_addr_done = True;
+ return addr_buf;
}
+#if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
+/******************************************************************
+ Remove any mount options such as -rsize=2048,wsize=2048 etc.
+ Based on a fix from <Thomas.Hepper@icem.de>.
+*******************************************************************/
-/****************************************************************************
-put a 8 byte filetime from a time_t
-This takes real GMT as input and converts to kludge-GMT
-****************************************************************************/
-void put_long_date(char *p,time_t t)
+static void strip_mount_options( pstring *str)
{
- uint32 tlow,thigh;
- double d;
+ if (**str == '-')
+ {
+ char *p = *str;
+ while(*p && !isspace(*p))
+ p++;
+ while(*p && isspace(*p))
+ p++;
+ if(*p) {
+ pstring tmp_str;
- if (t==0) {
- SIVAL(p,0,0); SIVAL(p,4,0);
- return;
+ pstrcpy(tmp_str, p);
+ pstrcpy(*str, tmp_str);
+ }
}
+}
- /* this converts GMT to kludge-GMT */
- t -= TimeDiff(t) - serverzone;
+/*******************************************************************
+ Patch from jkf@soton.ac.uk
+ Split Luke's automount_server into YP lookup and string splitter
+ so can easily implement automount_path().
+ As we may end up doing both, cache the last YP result.
+*******************************************************************/
- d = (double) (t);
+#ifdef WITH_NISPLUS_HOME
+static char *automount_lookup(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);
+ DEBUG(5, ("NIS+ querystring: %s\n", buffer));
+
+ if (result = nis_list(buffer, RETURN_RESULT, NULL, NULL))
+ {
+ if (result->status != NIS_SUCCESS)
+ {
+ DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
+ fstrcpy(last_key, ""); pstrcpy(last_value, "");
+ }
+ else
+ {
+ object = result->objects.objects_val;
+ if (object->zo_data.zo_type == ENTRY_OBJ)
+ {
+ entry = &object->zo_data.objdata_u.en_data;
+ DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
+ DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
+
+ pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
+ string_sub(last_value, "&", user_name);
+ fstrcpy(last_key, user_name);
+ }
+ }
+ }
+ nis_freeresult(result);
+ }
+
+ strip_mount_options(&last_value);
- d += TIME_FIXUP_CONSTANT;
+ DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
+ return last_value;
+}
+#else /* WITH_NISPLUS_HOME */
+static char *automount_lookup(char *user_name)
+{
+ static fstring last_key = "";
+ static pstring last_value = "";
+
+ int nis_error; /* returned by yp all functions */
+ char *nis_result; /* yp_match inits this */
+ int nis_result_len; /* and set this */
+ char *nis_domain; /* yp_get_default_domain inits this */
+ char *nis_map = (char *)lp_nis_home_map_name();
- d *= 1.0e7;
+ if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
+ {
+ DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
+ return last_value;
+ }
- thigh = (uint32)(d * (1.0/(4.0*(double)(1<<30))));
- tlow = (uint32)(d - ((double)thigh)*4.0*(double)(1<<30));
+ DEBUG(5, ("NIS Domain: %s\n", nis_domain));
- SIVAL(p,0,tlow);
- SIVAL(p,4,thigh);
+ if (!strcmp(user_name, last_key))
+ {
+ nis_result = last_value;
+ nis_result_len = strlen(last_value);
+ nis_error = 0;
+ }
+ 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",
+ 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
/*******************************************************************
-sub strings with useful parameters
-********************************************************************/
-void standard_sub_basic(char *s)
+ 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)
{
- if (!strchr(s,'%')) return;
+ static pstring server_name;
- string_sub(s,"%R",remote_proto);
- string_sub(s,"%a",remote_arch);
- string_sub(s,"%m",remote_machine);
- string_sub(s,"%L",local_machine);
+ /* 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 (!strchr(s,'%')) return;
+#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
- string_sub(s,"%v",VERSION);
- string_sub(s,"%h",myhostname);
- string_sub(s,"%U",sesssetup_user);
+ 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
- if (!strchr(s,'%')) return;
+ DEBUG(4,("Home server: %s\n", server_name));
- string_sub(s,"%I",Client_info.addr);
- string_sub(s,"%M",Client_info.name);
- string_sub(s,"%T",timestring());
+ return server_name;
+}
- if (!strchr(s,'%')) return;
+/*******************************************************************
+ 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;
- {
- char pidstr[10];
- sprintf(pidstr,"%d",(int)getpid());
- string_sub(s,"%d",pidstr);
- }
+ /* use the passwd entry as the default */
+ /* this will be the default if WITH_AUTOMOUNT is not used or fails */
+ /* pstrcpy() copes with get_home_dir() returning NULL */
+ pstrcpy(server_path, get_home_dir(user_name));
- if (!strchr(s,'%')) return;
+#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
- {
- struct passwd *pass = Get_Pwnam(sesssetup_user,False);
- if (pass) {
- string_sub(s,"%G",gidtoname(pass->pw_gid));
- }
- }
+ 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;
+}
+
+
+/*******************************************************************
+sub 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 )
+ {
+ switch (*(p+1))
+ {
+ case 'G' :
+ {
+ if ((pass = Get_Pwnam(username,False))!=NULL)
+ {
+ string_sub(p,"%G",gidtoname(pass->pw_gid));
+ }
+ else
+ {
+ p += 2;
+ }
+ break;
+ }
+ case 'N' : string_sub(p,"%N", automount_server(username)); break;
+ case 'I' : string_sub(p,"%I", client_addr(Client)); break;
+ case 'L' : string_sub(p,"%L", local_machine); break;
+ case 'M' : string_sub(p,"%M", client_name(Client)); break;
+ case 'R' : string_sub(p,"%R", remote_proto); break;
+ case 'T' : string_sub(p,"%T", timestring()); break;
+ case 'U' : string_sub(p,"%U", username); break;
+ case 'a' : string_sub(p,"%a", remote_arch); break;
+ case 'd' :
+ {
+ slprintf(pidstr,sizeof(pidstr) - 1, "%d",(int)getpid());
+ string_sub(p,"%d", pidstr);
+ break;
+ }
+ case 'h' : string_sub(p,"%h", myhostname); break;
+ case 'm' : string_sub(p,"%m", remote_machine); break;
+ case 'v' : string_sub(p,"%v", VERSION); break;
+ case '$' : /* Expand environment variables */
+ {
+ /* Contributed by Branko Cibej <branko.cibej@hermes.si> */
+ fstring envname;
+ char *envval;
+ char *q, *r;
+ int copylen;
+
+ if (*(p+2) != '(')
+ {
+ p+=2;
+ break;
+ }
+ if ((q = strchr(p,')')) == NULL)
+ {
+ DEBUG(0,("standard_sub_basic: Unterminated environment \
+ variable [%s]\n", p));
+ p+=2;
+ break;
+ }
+
+ r = p+3;
+ copylen = MIN((q-r),(sizeof(envname)-1));
+ strncpy(envname,r,copylen);
+ envname[copylen] = '\0';
+
+ if ((envval = getenv(envname)) == NULL)
+ {
+ DEBUG(0,("standard_sub_basic: Environment variable [%s] not set\n",
+ envname));
+ p+=2;
+ break;
+ }
+
+ copylen = MIN((q+1-p),(sizeof(envname)-1));
+ strncpy(envname,p,copylen);
+ envname[copylen] = '\0';
+ string_sub(p,envname,envval);
+ break;
+ }
+ 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) {
+ switch (*(p+1)) {
+ case 'H':
+ if ((home = get_home_dir(conn->user))) {
+ string_sub(p,"%H",home);
+ } else {
+ p += 2;
+ }
+ break;
+
+ case 'P':
+ string_sub(p,"%P",conn->connectpath);
+ break;
+
+ case 'S':
+ string_sub(p,"%S",
+ lp_servicename(SNUM(conn)));
+ break;
+
+ case 'g':
+ string_sub(p,"%g",
+ gidtoname(conn->gid));
+ break;
+ case 'u':
+ string_sub(p,"%u",conn->user);
+ 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))));
+ 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));
}
@@ -4022,34 +3969,6 @@ int PutUniCode(char *dst,char *src)
return(ret);
}
-
-pstring smbrun_path = SMBRUN;
-
-/****************************************************************************
-run a command via system() using smbrun
-****************************************************************************/
-int smbrun(char *cmd,char *outfile)
-{
- int ret;
- pstring syscmd;
-
- if (!file_exist(smbrun_path,NULL))
- {
- DEBUG(0,("SMBRUN ERROR: Can't find %s. Installation problem?\n",smbrun_path));
- return(1);
- }
-
- sprintf(syscmd,"%s \"(%s 2>&1) > %s\"",
- smbrun_path,cmd,
- outfile?outfile:"/dev/null");
-
- DEBUG(5,("smbrun - running %s ",syscmd));
- ret = system(syscmd);
- DEBUG(5,("gave %d\n",ret));
- return(ret);
-}
-
-
/****************************************************************************
a wrapper for gethostbyname() that tries with all lower and all upper case
if the initial name fails
@@ -4065,13 +3984,22 @@ struct hostent *Get_Hostbyname(char *name)
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 = gethostbyname(name2);
+ ret = sys_gethostbyname(name2);
if (ret != NULL)
{
free(name2);
@@ -4080,7 +4008,7 @@ struct hostent *Get_Hostbyname(char *name)
/* try with all lowercase */
strlower(name2);
- ret = gethostbyname(name2);
+ ret = sys_gethostbyname(name2);
if (ret != NULL)
{
free(name2);
@@ -4089,7 +4017,7 @@ struct hostent *Get_Hostbyname(char *name)
/* try with all uppercase */
strupper(name2);
- ret = gethostbyname(name2);
+ ret = sys_gethostbyname(name2);
if (ret != NULL)
{
free(name2);
@@ -4107,32 +4035,7 @@ check if a process exists. Does this work on all unixes?
****************************************************************************/
BOOL process_exists(int pid)
{
-#ifdef LINUX
- fstring s;
- sprintf(s,"/proc/%d",pid);
- return(directory_exist(s,NULL));
-#else
- {
- static BOOL tested=False;
- static BOOL ok=False;
- fstring s;
- if (!tested) {
- tested = True;
- sprintf(s,"/proc/%05d",getpid());
- ok = file_exist(s,NULL);
- }
- if (ok) {
- sprintf(s,"/proc/%05d",pid);
- return(file_exist(s,NULL));
- }
- }
-
- /* a best guess for non root access */
- if (geteuid() != 0) return(True);
-
- /* otherwise use kill */
- return(pid == getpid() || kill(pid,0) == 0);
-#endif
+ return(kill(pid,0) == 0 || errno != ESRCH);
}
@@ -4144,7 +4047,7 @@ char *uidtoname(int uid)
static char name[40];
struct passwd *pass = getpwuid(uid);
if (pass) return(pass->pw_name);
- sprintf(name,"%d",uid);
+ slprintf(name, sizeof(name) - 1, "%d",uid);
return(name);
}
@@ -4153,358 +4056,777 @@ turn a gid into a group name
********************************************************************/
char *gidtoname(int gid)
{
- static char name[40];
- struct group *grp = getgrgid(gid);
- if (grp) return(grp->gr_name);
- sprintf(name,"%d",gid);
- return(name);
+ static char name[40];
+ struct group *grp = getgrgid(gid);
+ if (grp) return(grp->gr_name);
+ slprintf(name,sizeof(name) - 1, "%d",gid);
+ return(name);
}
/*******************************************************************
-block sigs
+something really nasty happened - panic!
********************************************************************/
-void BlockSignals(BOOL block)
-{
-#ifdef USE_SIGBLOCK
- int block_mask = (sigmask(SIGTERM)|sigmask(SIGQUIT)|sigmask(SIGSEGV)
- |sigmask(SIGCHLD)|sigmask(SIGQUIT)|sigmask(SIGBUS)|
- sigmask(SIGINT));
- if (block)
- sigblock(block_mask);
- else
- sigunblock(block_mask);
-#endif
+void smb_panic(char *why)
+{
+ char *cmd = lp_panic_action();
+ if (cmd && *cmd) {
+ system(cmd);
+ }
+ DEBUG(0,("PANIC: %s\n", why));
+ exit(1);
}
-#if AJT
+
/*******************************************************************
-my own panic function - not suitable for general use
+a readdir wrapper which just returns the file name
********************************************************************/
-void ajt_panic(void)
+char *readdirname(void *p)
{
- pstring cmd = "/usr/bin/X11/xedit -display :0 /tmp/ERROR_FAULT &";
- smbrun(cmd,NULL);
-}
+ struct dirent *ptr;
+ char *dname;
+
+ if (!p) return(NULL);
+
+ ptr = (struct dirent *)readdir(p);
+ if (!ptr) return(NULL);
+
+ dname = ptr->d_name;
+
+#ifdef NEXT2
+ if (telldir(p) < 0) return(NULL);
#endif
-#ifdef USE_DIRECT
-#define DIRECT direct
-#else
-#define DIRECT dirent
+#ifdef HAVE_BROKEN_READDIR
+ /* using /usr/ucb/cc is BAD */
+ dname = dname - 2;
#endif
+ {
+ static pstring buf;
+ memcpy(buf, dname, NAMLEN(ptr)+1);
+ unix_to_dos(buf, True);
+ dname = buf;
+ }
+
+ return(dname);
+}
+
/*******************************************************************
-a readdir wrapper which just returns the file name
-also return the inode number if requested
+ Utility function used to decide if the last component
+ of a path matches a (possibly wildcarded) entry in a namelist.
********************************************************************/
-char *readdirname(void *p)
-{
- struct DIRECT *ptr;
- char *dname;
- if (!p) return(NULL);
-
- ptr = (struct DIRECT *)readdir(p);
- if (!ptr) return(NULL);
+BOOL is_in_path(char *name, name_compare_entry *namelist)
+{
+ pstring last_component;
+ char *p;
- dname = ptr->d_name;
+ DEBUG(8, ("is_in_path: %s\n", name));
-#ifdef KANJI
+ /* if we have no list it's obviously not in the path */
+ if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL)))
{
- static pstring buf;
- strcpy(buf, dname);
- unix_to_dos(buf, True);
- dname = buf;
+ DEBUG(8,("is_in_path: no name list.\n"));
+ return False;
}
-#endif
-#ifdef NEXT2
- if (telldir(p) < 0) return(NULL);
-#endif
+ /* Get the last component of the unix name. */
+ p = strrchr(name, '/');
+ strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
+ last_component[sizeof(last_component)-1] = '\0';
-#ifdef SUNOS5
- /* this handles a broken compiler setup, causing a mixture
- of BSD and SYSV headers and libraries */
+ for(; namelist->name != NULL; namelist++)
{
- static BOOL broken_readdir = False;
- if (!broken_readdir && !(*(dname)) && strequal("..",dname-2))
+ 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))
{
- DEBUG(0,("Your readdir() is broken. You have somehow mixed SYSV and BSD headers and libraries\n"));
- broken_readdir = True;
+ DEBUG(8,("is_in_path: mask match succeeded\n"));
+ return True;
}
- if (broken_readdir)
- return(dname-2);
+ }
+ else
+ {
+ if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
+ (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0)))
+ {
+ DEBUG(8,("is_in_path: match succeeded\n"));
+ return True;
+ }
+ }
}
-#endif
-
- return(dname);
+ DEBUG(8,("is_in_path: match not found\n"));
+
+ return False;
}
+/*******************************************************************
+ Strip a '/' separated list into an array of
+ name_compare_enties structures suitable for
+ passing to is_in_path(). We do this for
+ speed so we can pre-parse all the names in the list
+ and don't do it for each call to is_in_path().
+ namelist is modified here and is assumed to be
+ a copy owned by the caller.
+ We also check if the entry contains a wildcard to
+ remove a potentially expensive call to mask_match
+ if possible.
+********************************************************************/
+
+void set_namearray(name_compare_entry **ppname_array, char *namelist)
+{
+ char *name_end;
+ char *nameptr = namelist;
+ int num_entries = 0;
+ int i;
+
+ (*ppname_array) = NULL;
+
+ if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0')))
+ return;
+
+ /* We need to make two passes over the string. The
+ first to count the number of elements, the second
+ to split it.
+ */
+ while(*nameptr)
+ {
+ if ( *nameptr == '/' )
+ {
+ /* cope with multiple (useless) /s) */
+ nameptr++;
+ continue;
+ }
+ /* find the next / */
+ name_end = strchr(nameptr, '/');
+
+ /* oops - the last check for a / didn't find one. */
+ if (name_end == NULL)
+ break;
+
+ /* next segment please */
+ nameptr = name_end + 1;
+ num_entries++;
+ }
+
+ if(num_entries == 0)
+ return;
+
+ if(( (*ppname_array) = (name_compare_entry *)malloc(
+ (num_entries + 1) * sizeof(name_compare_entry))) == NULL)
+ {
+ DEBUG(0,("set_namearray: malloc fail\n"));
+ return;
+ }
+
+ /* Now copy out the names */
+ nameptr = namelist;
+ i = 0;
+ while(*nameptr)
+ {
+ if ( *nameptr == '/' )
+ {
+ /* cope with multiple (useless) /s) */
+ nameptr++;
+ continue;
+ }
+ /* find the next / */
+ if ((name_end = strchr(nameptr, '/')) != NULL)
+ {
+ *name_end = 0;
+ }
+
+ /* oops - the last check for a / didn't find one. */
+ if(name_end == NULL)
+ break;
+
+ (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
+ (strchr( nameptr, '*')!=NULL));
+ if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
+ {
+ DEBUG(0,("set_namearray: malloc fail (1)\n"));
+ return;
+ }
+ /* next segment please */
+ nameptr = name_end + 1;
+ i++;
+ }
+
+ (*ppname_array)[i].name = NULL;
-#if (defined(SecureWare) && defined(SCO))
-/* This is needed due to needing the nap() function but we don't want
- to include the Xenix libraries since that will break other things...
- BTW: system call # 0x0c28 is the same as calling nap() */
-long nap(long milliseconds) {
- return syscall(0x0c28, milliseconds);
+ return;
}
-#endif
-#ifdef NO_INITGROUPS
-#include <sys/types.h>
-#include <limits.h>
-#include <grp.h>
+/****************************************************************************
+routine to free a namearray.
+****************************************************************************/
-#ifndef NULL
-#define NULL (void *)0
-#endif
+void free_namearray(name_compare_entry *name_array)
+{
+ if(name_array == 0)
+ return;
+
+ if(name_array->name != NULL)
+ free(name_array->name);
+
+ free((char *)name_array);
+}
/****************************************************************************
- some systems don't have an initgroups call
+routine to do file locking
****************************************************************************/
-int initgroups(char *name,gid_t id)
+BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
{
-#ifdef NO_SETGROUPS
- /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
- return(0);
-#else
- gid_t grouplst[NGROUPS_MAX];
- int i,j;
- struct group *g;
- char *gr;
-
- grouplst[0] = id;
- i = 1;
- while (i < NGROUPS_MAX &&
- ((g = (struct group *)getgrent()) != (struct group *)NULL))
+#if HAVE_FCNTL_LOCK
+ SMB_STRUCT_FLOCK lock;
+ int ret;
+
+ if(lp_ole_locking_compat()) {
+ SMB_OFF_T mask = ((SMB_OFF_T)0xC) << (SMB_OFF_T_BITS-4);
+ SMB_OFF_T mask2= ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4);
+
+ /* 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 mask = ((SMB_OFF_T)0x8) << (SMB_OFF_T_BITS-4);
+ 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)
{
- if (g->gr_gid == id)
- continue;
- j = 0;
- gr = g->gr_mem[0];
- while (gr && (*gr != (char)NULL)) {
- if (strcmp(name,gr) == 0) {
- grouplst[i] = g->gr_gid;
- i++;
- gr = (char *)NULL;
- break;
- }
- gr = g->gr_mem[++j];
- }
+ offset &= ~mask;
+ mask = ((mask >> 1) & neg_mask);
+ }
+ }
+
+ DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
+
+ lock.l_type = type;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = offset;
+ lock.l_len = count;
+ lock.l_pid = 0;
+
+ 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");
}
- endgrent();
- return(setgroups(i,grouplst));
+ /* 32 bit NFS file system, retry with smaller offset */
+ errno = 0;
+ lock.l_len = count & 0xffffffff;
+ ret = fcntl(fd,op,&lock);
+ }
+
+ if (errno != 0)
+ DEBUG(3,("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()))
+ {
+ DEBUG(3,("fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
+ return(True);
+ }
+
+ /* it must be not locked or locked by me */
+ return(False);
+ }
+
+ /* a lock set or unset */
+ if (ret == -1)
+ {
+ DEBUG(3,("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)
+ {
+ DEBUG(3,("locking not supported? returning True\n"));
+ return(True);
+ }
+
+ return(False);
+ }
+
+ /* everything went OK */
+ DEBUG(8,("Lock call successful\n"));
+
+ return(True);
+#else
+ return(False);
#endif
}
-#endif
+/*******************************************************************
+is the name specified one of my netbios names
+returns true is it is equal, false otherwise
+********************************************************************/
+BOOL is_myname(char *s)
+{
+ int n;
+ BOOL ret = False;
-#if WRAP_MALLOC
+ for (n=0; my_netbios_names[n]; n++) {
+ if (strequal(my_netbios_names[n], s))
+ ret=True;
+ }
+ DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
+ return(ret);
+}
-/* undo the wrapping temporarily */
-#undef malloc
-#undef realloc
-#undef free
+/*******************************************************************
+set the horrid remote_arch string based on an enum.
+********************************************************************/
+void set_remote_arch(enum remote_arch_types type)
+{
+ ra_type = type;
+ switch( type )
+ {
+ case RA_WFWG:
+ fstrcpy(remote_arch, "WfWg");
+ return;
+ case RA_OS2:
+ fstrcpy(remote_arch, "OS2");
+ return;
+ case RA_WIN95:
+ fstrcpy(remote_arch, "Win95");
+ return;
+ case RA_WINNT:
+ fstrcpy(remote_arch, "WinNT");
+ return;
+ case RA_SAMBA:
+ fstrcpy(remote_arch,"Samba");
+ return;
+ default:
+ ra_type = RA_UNKNOWN;
+ fstrcpy(remote_arch, "UNKNOWN");
+ break;
+ }
+}
-/****************************************************************************
-wrapper for malloc() to catch memory errors
-****************************************************************************/
-void *malloc_wrapped(int size,char *file,int line)
+/*******************************************************************
+ Get the remote_arch type.
+********************************************************************/
+enum remote_arch_types get_remote_arch(void)
{
-#ifdef xx_old_malloc
- void *res = xx_old_malloc(size);
-#else
- void *res = malloc(size);
-#endif
- DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
- file,line,
- size,(unsigned int)res));
- return(res);
+ return ra_type;
}
-/****************************************************************************
-wrapper for realloc() to catch memory errors
-****************************************************************************/
-void *realloc_wrapped(void *ptr,int size,char *file,int line)
+
+/*******************************************************************
+skip past some unicode strings in a buffer
+********************************************************************/
+char *skip_unicode_string(char *buf,int n)
{
-#ifdef xx_old_realloc
- void *res = xx_old_realloc(ptr,size);
-#else
- void *res = realloc(ptr,size);
-#endif
- DEBUG(3,("Realloc\n"));
- DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
- file,line,
- (unsigned int)ptr));
- DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
- file,line,
- size,(unsigned int)res));
- return(res);
+ while (n--)
+ {
+ while (*buf)
+ buf += 2;
+ buf += 2;
+ }
+ return(buf);
}
-/****************************************************************************
-wrapper for free() to catch memory errors
-****************************************************************************/
-void free_wrapped(void *ptr,char *file,int line)
+/*******************************************************************
+Return a ascii version of a unicode string
+Hack alert: uses fixed buffer(s) and only handles ascii strings
+********************************************************************/
+#define MAXUNI 1024
+char *unistrn2(uint16 *buf, int len)
{
-#ifdef xx_old_free
- xx_old_free(ptr);
-#else
- free(ptr);
-#endif
- DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
- file,line,(unsigned int)ptr));
- return;
+ static char lbufs[8][MAXUNI];
+ static int nexti;
+ char *lbuf = lbufs[nexti];
+ char *p;
+
+ nexti = (nexti+1)%8;
+
+ DEBUG(10, ("unistrn2: "));
+
+ for (p = lbuf; *buf && p-lbuf < MAXUNI-2 && len > 0; len--, p++, buf++)
+ {
+ DEBUG(10, ("%4x ", *buf));
+ *p = *buf;
+ }
+
+ DEBUG(10,("\n"));
+
+ *p = 0;
+ return lbuf;
}
-/* and re-do the define for spots lower in this file */
-#define malloc(size) malloc_wrapped(size,__FILE__,__LINE__)
-#define realloc(ptr,size) realloc_wrapped(ptr,size,__FILE__,__LINE__)
-#define free(ptr) free_wrapped(ptr,__FILE__,__LINE__)
+/*******************************************************************
+Return a ascii version of a unicode string
+Hack alert: uses fixed buffer(s) and only handles ascii strings
+********************************************************************/
+#define MAXUNI 1024
+char *unistr2(uint16 *buf)
+{
+ static char lbufs[8][MAXUNI];
+ static int nexti;
+ char *lbuf = lbufs[nexti];
+ char *p;
-#endif
+ nexti = (nexti+1)%8;
-#ifdef REPLACE_STRSTR
-/****************************************************************************
-Mips version of strstr doesn't seem to work correctly.
-There is a #define in includes.h to redirect calls to this function.
-****************************************************************************/
-char *Strstr(char *s, char *p)
+ DEBUG(10, ("unistr2: "));
+
+ for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf++)
+ {
+ DEBUG(10, ("%4x ", *buf));
+ *p = *buf;
+ }
+
+ DEBUG(10,("\n"));
+
+ *p = 0;
+ return lbuf;
+}
+
+/*******************************************************************
+create a null-terminated unicode string from a null-terminated ascii string.
+return number of unicode chars copied, excluding the null character.
+
+only handles ascii strings
+********************************************************************/
+#define MAXUNI 1024
+int struni2(uint16 *p, char *buf)
{
- int len = strlen(p);
+ int len = 0;
- while ( *s != '\0' ) {
- if ( strncmp(s, p, len) == 0 )
- return s;
- s++;
+ if (p == NULL) return 0;
+
+ DEBUG(10, ("struni2: "));
+
+ if (buf != NULL)
+ {
+ for (; *buf && len < MAXUNI-2; len++, p++, buf++)
+ {
+ DEBUG(10, ("%2x ", *buf));
+ *p = *buf;
+ }
+
+ DEBUG(10,("\n"));
}
- return NULL;
+ *p = 0;
+
+ return len;
+}
+
+/*******************************************************************
+Return a ascii version of a unicode string
+Hack alert: uses fixed buffer(s) and only handles ascii strings
+********************************************************************/
+#define MAXUNI 1024
+char *unistr(char *buf)
+{
+ static char lbufs[8][MAXUNI];
+ static int nexti;
+ char *lbuf = lbufs[nexti];
+ char *p;
+
+ nexti = (nexti+1)%8;
+
+ for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf += 2)
+ {
+ *p = *buf;
+ }
+ *p = 0;
+ return lbuf;
}
-#endif /* REPLACE_STRSTR */
-#ifdef REPLACE_MKTIME
/*******************************************************************
-a mktime() replacement for those who don't have it - contributed by
-C.A. Lademann <cal@zls.com>
+strcpy for unicode strings. returns length (in num of wide chars)
********************************************************************/
-#define MINUTE 60
-#define HOUR 60*MINUTE
-#define DAY 24*HOUR
-#define YEAR 365*DAY
-time_t Mktime(struct tm *t)
-{
- struct tm *u;
- time_t epoch = 0;
- int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
- y, m, i;
-
- if(t->tm_year < 70)
- return((time_t)-1);
-
- epoch = (t->tm_year - 70) * YEAR +
- (t->tm_year / 4 - 70 / 4 - t->tm_year / 100) * DAY;
-
- y = t->tm_year;
- m = 0;
-
- for(i = 0; i < t->tm_mon; i++) {
- epoch += mon [m] * DAY;
- if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
- epoch += DAY;
-
- if(++m > 11) {
- m = 0;
- y++;
- }
- }
+int unistrcpy(char *dst, char *src)
+{
+ int num_wchars = 0;
- epoch += (t->tm_mday - 1) * DAY;
- epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
-
- if((u = localtime(&epoch)) != NULL) {
- t->tm_sec = u->tm_sec;
- t->tm_min = u->tm_min;
- t->tm_hour = u->tm_hour;
- t->tm_mday = u->tm_mday;
- t->tm_mon = u->tm_mon;
- t->tm_year = u->tm_year;
- t->tm_wday = u->tm_wday;
- t->tm_yday = u->tm_yday;
- t->tm_isdst = u->tm_isdst;
-#ifndef NO_TM_NAME
- memcpy(t->tm_name, u->tm_name, LTZNMAX);
-#endif
- }
+ while (*src)
+ {
+ *dst++ = *src++;
+ *dst++ = *src++;
+ num_wchars++;
+ }
+ *dst++ = 0;
+ *dst++ = 0;
- return(epoch);
+ return num_wchars;
}
-#endif /* REPLACE_MKTIME */
+/*******************************************************************
+safe string copy into a known length string. maxlength does not
+include the terminating zero.
+********************************************************************/
+char *safe_strcpy(char *dest, char *src, int maxlength)
+{
+ int len;
+
+ if (!dest) {
+ DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
+ return NULL;
+ }
+
+ if (!src) {
+ *dest = 0;
+ return dest;
+ }
+ len = strlen(src);
-#ifdef REPLACE_RENAME
-/* Rename a file. (from libiberty in GNU binutils) */
-int
-rename (zfrom, zto)
- const char *zfrom;
- const char *zto;
+ if (len > maxlength) {
+ DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
+ len-maxlength, src));
+ len = maxlength;
+ }
+
+ memcpy(dest, src, len);
+ dest[len] = 0;
+ return dest;
+}
+
+/*******************************************************************
+safe string cat into a string. maxlength does not
+include the terminating zero.
+********************************************************************/
+char *safe_strcat(char *dest, char *src, int maxlength)
{
- if (link (zfrom, zto) < 0)
- {
- if (errno != EEXIST)
- return -1;
- if (unlink (zto) < 0
- || link (zfrom, zto) < 0)
- return -1;
+ int src_len, dest_len;
+
+ if (!dest) {
+ DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
+ return NULL;
+ }
+
+ if (!src) {
+ return dest;
+ }
+
+ src_len = strlen(src);
+ dest_len = strlen(dest);
+
+ if (src_len + dest_len > maxlength) {
+ DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
+ src_len + dest_len - maxlength, src));
+ src_len = maxlength - dest_len;
}
- return unlink (zfrom);
+
+ memcpy(&dest[dest_len], src, src_len);
+ dest[dest_len + src_len] = 0;
+ return dest;
}
-#endif
+/*******************************************************************
+align a pointer to a multiple of 2 bytes
+********************************************************************/
+char *align2(char *q, char *base)
+{
+ if ((q - base) & 1)
+ {
+ q++;
+ }
+ return q;
+}
-#ifdef REPLACE_INNETGR
-/*
- * Search for a match in a netgroup. This replaces it on broken systems.
- */
-int InNetGr(group, host, user, dom)
- char *group, *host, *user, *dom;
+void print_asc(int level, unsigned char *buf,int len)
{
- char *hst, *usr, *dm;
-
- setnetgrent(group);
- while (getnetgrent(&hst, &usr, &dm))
- if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
- ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
- ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
- endnetgrent();
- return (1);
+ 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)
+{
+ unsigned char *buf = (unsigned char *)buf1;
+ int i=0;
+ if (len<=0) return;
+
+ DEBUG(level,("[%03X] ",i));
+ for (i=0;i<len;) {
+ DEBUG(level,("%02X ",(int)buf[i]));
+ i++;
+ if (i%8 == 0) DEBUG(level,(" "));
+ if (i%16 == 0) {
+ print_asc(level,&buf[i-16],8); DEBUG(level,(" "));
+ print_asc(level,&buf[i-8],8); DEBUG(level,("\n"));
+ if (i<len) DEBUG(level,("[%03X] ",i));
}
- endnetgrent();
- return (0);
+ }
+ if (i%16) {
+ int n;
+
+ n = 16 - (i%16);
+ DEBUG(level,(" "));
+ if (n>8) DEBUG(level,(" "));
+ while (n--) DEBUG(level,(" "));
+
+ n = MIN(8,i%16);
+ print_asc(level,&buf[i-(i%16)],n); DEBUG(level,(" "));
+ n = (i%16) - n;
+ if (n>0) print_asc(level,&buf[i-n],n);
+ DEBUG(level,("\n"));
+ }
}
-#endif
+char *tab_depth(int depth)
+{
+ static pstring spaces;
+ memset(spaces, ' ', depth * 4);
+ spaces[depth * 4] = 0;
+ return spaces;
+}
-#if WRAP_MEMCPY
-#undef memcpy
-/*******************************************************************
-a wrapper around memcpy for diagnostic purposes
-********************************************************************/
-void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line)
+/*****************************************************************
+ Convert a SID to an ascii string.
+*****************************************************************/
+
+char *sid_to_string(pstring sidstr_out, DOM_SID *sid)
{
- if (l>64 && (((int)d)%4) != (((int)s)%4))
- DEBUG(4,("Misaligned memcpy(0x%X,0x%X,%d) at %s(%d)\n",d,s,l,fname,line));
-#ifdef xx_old_memcpy
- return(xx_old_memcpy(d,s,l));
-#else
- return(memcpy(d,s,l));
-#endif
+ char subauth[16];
+ int i;
+ /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
+ uint32 ia = (sid->id_auth[5]) +
+ (sid->id_auth[4] << 8 ) +
+ (sid->id_auth[3] << 16) +
+ (sid->id_auth[2] << 24);
+
+ slprintf(sidstr_out, sizeof(pstring) - 1, "S-%d-%d", sid->sid_rev_num, ia);
+
+ for (i = 0; i < sid->num_auths; i++)
+ {
+ slprintf(subauth, sizeof(subauth)-1, "-%d", sid->sub_auths[i]);
+ pstrcat(sidstr_out, subauth);
+ }
+
+ DEBUG(7,("sid_to_string returning %s\n", sidstr_out));
+ return sidstr_out;
}
-#define memcpy(d,s,l) memcpy_wrapped(d,s,l,__FILE__,__LINE__)
-#endif
+/*****************************************************************
+ Convert a string to a SID. Returns True on success, False on fail.
+*****************************************************************/
+
+BOOL string_to_sid(DOM_SID *sidout, char *sidstr)
+{
+ pstring tok;
+ char *p = sidstr;
+ /* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
+ uint32 ia;
+
+ memset((char *)sidout, '\0', sizeof(DOM_SID));
+
+ if(StrnCaseCmp( sidstr, "S-", 2)) {
+ DEBUG(0,("string_to_sid: Sid %s does not start with 'S-'.\n", sidstr));
+ return False;
+ }
+
+ p += 2;
+ if(!next_token(&p, tok, "-", sizeof(tok))) {
+ DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr));
+ return False;
+ }
+
+ /* Get the revision number. */
+ sidout->sid_rev_num = atoi(tok);
+
+ if(!next_token(&p, tok, "-", sizeof(tok))) {
+ DEBUG(0,("string_to_sid: Sid %s is not in a valid format.\n", sidstr));
+ return False;
+ }
+
+ /* identauth in decimal should be < 2^32 */
+ ia = atoi(tok);
+
+ /* NOTE - the ia value is in big-endian format. */
+ sidout->id_auth[0] = 0;
+ sidout->id_auth[1] = 0;
+ sidout->id_auth[2] = (ia & 0xff000000) >> 24;
+ sidout->id_auth[3] = (ia & 0x00ff0000) >> 16;
+ sidout->id_auth[4] = (ia & 0x0000ff00) >> 8;
+ sidout->id_auth[5] = (ia & 0x000000ff);
+
+ sidout->num_auths = 0;
+
+ while(next_token(&p, tok, "-", sizeof(tok)) &&
+ sidout->num_auths < MAXSUBAUTHS) {
+ /*
+ * NOTE - the subauths are in native machine-endian format. They
+ * are converted to little-endian when linearized onto the wire.
+ */
+ sidout->sub_auths[sidout->num_auths++] = atoi(tok);
+ }
+
+ DEBUG(7,("string_to_sid: converted SID %s ok\n", sidstr));
+
+ return True;
+}
+
+/*****************************************************************************
+ * Provide a checksum on a string
+ *
+ * Input: s - the nul-terminated character string for which the checksum
+ * will be calculated.
+ *
+ * Output: The checksum value calculated for s.
+ *
+ * ****************************************************************************
+ */
+int str_checksum(char *s)
+{
+ int res = 0;
+ int c;
+ int i=0;
+
+ while(*s) {
+ c = *s;
+ res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
+ s++;
+ i++;
+ }
+ return(res);
+} /* str_checksum */
+
+/*****************************************************************
+zero a memory area then free it. Used to catch bugs faster
+*****************************************************************/
+void zero_free(void *p, size_t size)
+{
+ memset(p, 0, size);
+ free(p);
+}