summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>1999-07-14 13:12:13 +0000
committerAndrew Tridgell <tridge@samba.org>1999-07-14 13:12:13 +0000
commit2a274a8755210e13da6bbf29d25f834f53275752 (patch)
tree6e9f0c1c5147d1d4e4b164f975a0720f9558e4b5
parent9db19ffa0b7d5cf5bc9f7f0a597f3ac5e915548b (diff)
downloadsamba-2a274a8755210e13da6bbf29d25f834f53275752.tar.gz
lib changes from the 2.0 branch
this includes the wildcard fixes, some grotesque reformatting and some pid_t stuff
-rw-r--r--source/lib/smbrun.c10
-rw-r--r--source/lib/system.c79
-rw-r--r--source/lib/username.c184
-rw-r--r--source/lib/util.c21
-rw-r--r--source/lib/util_sock.c371
-rw-r--r--source/lib/util_str.c92
6 files changed, 535 insertions, 222 deletions
diff --git a/source/lib/smbrun.c b/source/lib/smbrun.c
index 366657129de..5a016cd5cd8 100644
--- a/source/lib/smbrun.c
+++ b/source/lib/smbrun.c
@@ -80,7 +80,8 @@ if shared is not set then open the file with O_EXCL set
****************************************************************************/
int smbrun(char *cmd,char *outfile,BOOL shared)
{
- int fd,pid;
+ int fd;
+ pid_t pid;
uid_t uid = current_user.uid;
gid_t gid = current_user.gid;
@@ -149,9 +150,14 @@ int smbrun(char *cmd,char *outfile,BOOL shared)
CatchChild();
if (wpid != pid) {
- DEBUG(2,("waitpid(%d) : %s\n",pid,strerror(errno)));
+ DEBUG(2,("waitpid(%d) : %s\n",(int)pid,strerror(errno)));
return -1;
}
+#if defined(WIFEXITED) && defined(WEXITSTATUS)
+ if (WIFEXITED(status)) {
+ return WEXITSTATUS(status);
+ }
+#endif
return status;
}
diff --git a/source/lib/system.c b/source/lib/system.c
index e0b19fd1581..a59f94a6a96 100644
--- a/source/lib/system.c
+++ b/source/lib/system.c
@@ -179,11 +179,15 @@ A stat() wrapper that will deal with 64 bit filesizes.
int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
{
+ int ret;
#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
- return stat64(fname, sbuf);
+ ret = stat64(fname, sbuf);
#else
- return stat(fname, sbuf);
+ ret = stat(fname, sbuf);
#endif
+ /* we always want directories to appear zero size */
+ if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
+ return ret;
}
/*******************************************************************
@@ -192,11 +196,15 @@ int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
{
+ int ret;
#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
- return fstat64(fd, sbuf);
+ ret = fstat64(fd, sbuf);
#else
- return fstat(fd, sbuf);
+ ret = fstat(fd, sbuf);
#endif
+ /* we always want directories to appear zero size */
+ if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
+ return ret;
}
/*******************************************************************
@@ -205,11 +213,15 @@ int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf)
int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf)
{
+ int ret;
#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
- return lstat64(fname, sbuf);
+ ret = lstat64(fname, sbuf);
#else
- return lstat(fname, sbuf);
+ ret = lstat(fname, sbuf);
#endif
+ /* we always want directories to appear zero size */
+ if (ret == 0 && S_ISDIR(sbuf->st_mode)) sbuf->st_size = 0;
+ return ret;
}
/*******************************************************************
@@ -655,3 +667,58 @@ int sys_setgroups(int setlen, gid_t *gidset)
}
#endif /* HAVE_SETGROUPS */
+
+/*
+ * We only wrap pw_name and pw_passwd for now as these
+ * are the only potentially modified fields.
+ */
+
+/**************************************************************************
+ Helper function for getpwnam/getpwuid wrappers.
+****************************************************************************/
+
+static struct passwd *setup_pwret(struct passwd *pass)
+{
+ static pstring pw_name;
+ static pstring pw_passwd;
+ static struct passwd pw_ret;
+
+ if (pass == NULL)
+ {
+ return NULL;
+ }
+
+ memcpy((char *)&pw_ret, pass, sizeof(struct passwd));
+
+ if (pass->pw_name)
+ {
+ pw_ret.pw_name = pw_name;
+ pstrcpy(pw_ret.pw_name, pass->pw_name);
+ }
+
+ if (pass->pw_passwd)
+ {
+ pw_ret.pw_passwd = pw_passwd;
+ pstrcpy(pw_ret.pw_passwd, pass->pw_passwd);
+ }
+
+ return &pw_ret;
+}
+
+/**************************************************************************
+ Wrapper for getpwnam(). Always returns a static that can be modified.
+****************************************************************************/
+
+struct passwd *sys_getpwnam(const char *name)
+{
+ return setup_pwret(getpwnam(name));
+}
+
+/**************************************************************************
+ Wrapper for getpwuid(). Always returns a static that can be modified.
+****************************************************************************/
+
+struct passwd *sys_getpwuid(uid_t uid)
+{
+ return setup_pwret(getpwuid(uid));
+}
diff --git a/source/lib/username.c b/source/lib/username.c
index f04314ab36d..cb647317bc8 100644
--- a/source/lib/username.c
+++ b/source/lib/username.c
@@ -27,8 +27,9 @@ static struct passwd *uname_string_combinations(char *s, struct passwd * (*fn) (
static struct passwd *uname_string_combinations2(char *s, int offset, struct passwd * (*fn) (char *), int N);
/****************************************************************************
-get a users home directory.
+ Get a users home directory.
****************************************************************************/
+
char *get_home_dir(char *user)
{
static struct passwd *pass;
@@ -41,15 +42,16 @@ char *get_home_dir(char *user)
/*******************************************************************
-map a username from a dos name to a unix name by looking in the username
-map. Note that this modifies the name in place.
-This is the main function that should be called *once* on
-any incoming or new username - in order to canonicalize the name.
-This is being done to de-couple the case conversions from the user mapping
-function. Previously, the map_username was being called
-every time Get_Pwnam was called.
-Returns True if username was changed, false otherwise.
+ Map a username from a dos name to a unix name by looking in the username
+ map. Note that this modifies the name in place.
+ This is the main function that should be called *once* on
+ any incoming or new username - in order to canonicalize the name.
+ This is being done to de-couple the case conversions from the user mapping
+ function. Previously, the map_username was being called
+ every time Get_Pwnam was called.
+ Returns True if username was changed, false otherwise.
********************************************************************/
+
BOOL map_username(char *user)
{
static BOOL initialised=False;
@@ -144,36 +146,34 @@ BOOL map_username(char *user)
}
/****************************************************************************
-Get_Pwnam wrapper
+ Get_Pwnam wrapper
****************************************************************************/
+
static struct passwd *_Get_Pwnam(char *s)
{
struct passwd *ret;
- ret = getpwnam(s);
- if (ret)
- {
+ ret = sys_getpwnam(s);
+ if (ret) {
#ifdef HAVE_GETPWANAM
- struct passwd_adjunct *pwret;
- pwret = getpwanam(s);
- if (pwret)
- {
- free(ret->pw_passwd);
- ret->pw_passwd = pwret->pwa_passwd;
- }
-#endif
-
+ struct passwd_adjunct *pwret;
+ pwret = getpwanam(s);
+ if (pwret && pwret->pwa_passwd) {
+ pstrcpy(ret->pw_passwd,pwret->pwa_passwd);
}
+#endif
+ }
return(ret);
}
/****************************************************************************
-a wrapper for getpwnam() that tries with all lower and all upper case
-if the initial name fails. Also tried with first letter capitalised
-Note that this can change user!
+ A wrapper for getpwnam() that tries with all lower and all upper case
+ if the initial name fails. Also tried with first letter capitalised
+ Note that this can change user!
****************************************************************************/
+
struct passwd *Get_Pwnam(char *user,BOOL allow_change)
{
fstring user2;
@@ -192,33 +192,39 @@ struct passwd *Get_Pwnam(char *user,BOOL allow_change)
}
ret = _Get_Pwnam(user);
- if (ret) return(ret);
+ if (ret)
+ return(ret);
strlower(user);
ret = _Get_Pwnam(user);
- if (ret) return(ret);
+ if (ret)
+ return(ret);
strupper(user);
ret = _Get_Pwnam(user);
- if (ret) return(ret);
+ if (ret)
+ return(ret);
- /* try with first letter capitalised */
+ /* Try with first letter capitalised. */
if (strlen(user) > 1)
strlower(user+1);
ret = _Get_Pwnam(user);
- if (ret) return(ret);
+ if (ret)
+ return(ret);
/* try with last letter capitalised */
strlower(user);
last_char = strlen(user)-1;
user[last_char] = toupper(user[last_char]);
ret = _Get_Pwnam(user);
- if (ret) return(ret);
+ if (ret)
+ return(ret);
- /* try all combinations up to usernamelevel */
+ /* Try all combinations up to usernamelevel. */
strlower(user);
ret = uname_string_combinations(user, _Get_Pwnam, usernamelevel);
- if (ret) return(ret);
+ if (ret)
+ return(ret);
if (allow_change)
fstrcpy(user,user2);
@@ -227,8 +233,9 @@ struct passwd *Get_Pwnam(char *user,BOOL allow_change)
}
/****************************************************************************
-check if a user is in a netgroup user list
+ Check if a user is in a netgroup user list.
****************************************************************************/
+
static BOOL user_in_netgroup_list(char *user,char *ngname)
{
#ifdef HAVE_NETGROUP
@@ -236,12 +243,9 @@ static BOOL user_in_netgroup_list(char *user,char *ngname)
if (mydomain == NULL)
yp_get_default_domain(&mydomain);
- if(mydomain == NULL)
- {
+ if(mydomain == NULL) {
DEBUG(5,("Unable to get default yp domain\n"));
- }
- else
- {
+ } else {
DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
user, mydomain, ngname));
DEBUG(5,("innetgr is %s\n",
@@ -256,8 +260,9 @@ static BOOL user_in_netgroup_list(char *user,char *ngname)
}
/****************************************************************************
-check if a user is in a UNIX user list
+ Check if a user is in a UNIX user list.
****************************************************************************/
+
static BOOL user_in_group_list(char *user,char *gname)
{
#ifdef HAVE_GETGRNAM
@@ -265,8 +270,7 @@ static BOOL user_in_group_list(char *user,char *gname)
char **member;
struct passwd *pass = Get_Pwnam(user,False);
- if (pass)
- {
+ if (pass) {
gptr = getgrgid(pass->pw_gid);
if (gptr && strequal(gptr->gr_name,gname))
return(True);
@@ -274,11 +278,9 @@ static BOOL user_in_group_list(char *user,char *gname)
gptr = (struct group *)getgrnam(gname);
- if (gptr)
- {
+ if (gptr) {
member = gptr->gr_mem;
- while (member && *member)
- {
+ while (member && *member) {
if (strequal(*member,user))
return(True);
member++;
@@ -289,16 +291,16 @@ static BOOL user_in_group_list(char *user,char *gname)
}
/****************************************************************************
-check if a user is in a user list - can check combinations of UNIX
-and netgroup lists.
+ Check if a user is in a user list - can check combinations of UNIX
+ and netgroup lists.
****************************************************************************/
+
BOOL user_in_list(char *user,char *list)
{
pstring tok;
char *p=list;
- while (next_token(&p,tok,LIST_SEP, sizeof(tok)))
- {
+ while (next_token(&p,tok,LIST_SEP, sizeof(tok))) {
/*
* Check raw username.
*/
@@ -310,8 +312,7 @@ BOOL user_in_list(char *user,char *list)
* of UNIX and netgroups has been specified.
*/
- if(*tok == '@')
- {
+ if(*tok == '@') {
/*
* Old behaviour. Check netgroup list
* followed by UNIX list.
@@ -320,11 +321,9 @@ BOOL user_in_list(char *user,char *list)
return True;
if(user_in_group_list(user,&tok[1]))
return True;
- }
- else if (*tok == '+')
- {
- if(tok[1] == '&')
- {
+ } else if (*tok == '+') {
+
+ if(tok[1] == '&') {
/*
* Search UNIX list followed by netgroup.
*/
@@ -332,20 +331,20 @@ BOOL user_in_list(char *user,char *list)
return True;
if(user_in_netgroup_list(user,&tok[2]))
return True;
- }
- else
- {
+
+ } else {
+
/*
* Just search UNIX list.
*/
+
if(user_in_group_list(user,&tok[1]))
return True;
}
- }
- else if (*tok == '&')
- {
- if(tok[1] == '&')
- {
+
+ } else if (*tok == '&') {
+
+ if(tok[1] == '&') {
/*
* Search netgroup list followed by UNIX list.
*/
@@ -353,9 +352,7 @@ BOOL user_in_list(char *user,char *list)
return True;
if(user_in_group_list(user,&tok[2]))
return True;
- }
- else
- {
+ } else {
/*
* Just search netgroup list.
*/
@@ -369,15 +366,16 @@ BOOL user_in_list(char *user,char *list)
/* The functions below have been taken from password.c and slightly modified */
/****************************************************************************
-apply a function to upper/lower case combinations
-of a string and return true if one of them returns true.
-try all combinations with N uppercase letters.
-offset is the first char to try and change (start with 0)
-it assumes the string starts lowercased
+ Apply a function to upper/lower case combinations
+ of a string and return true if one of them returns true.
+ Try all combinations with N uppercase letters.
+ offset is the first char to try and change (start with 0)
+ it assumes the string starts lowercased
****************************************************************************/
+
static struct passwd *uname_string_combinations2(char *s,int offset,struct passwd *(*fn)(char *),int N)
{
- int len = strlen(s);
+ size_t len = strlen(s);
int i;
struct passwd *ret;
@@ -388,36 +386,36 @@ static struct passwd *uname_string_combinations2(char *s,int offset,struct passw
if (N <= 0 || offset >= len)
return(fn(s));
-
- for (i=offset;i<(len-(N-1));i++)
-
- {
- char c = s[i];
- if (!islower(c)) continue;
- s[i] = toupper(c);
- ret = uname_string_combinations2(s,i+1,fn,N-1);
- if(ret) return(ret);
- s[i] = c;
- }
+ for (i=offset;i<(len-(N-1));i++) {
+ char c = s[i];
+ if (!islower(c))
+ continue;
+ s[i] = toupper(c);
+ ret = uname_string_combinations2(s,i+1,fn,N-1);
+ if(ret)
+ return(ret);
+ s[i] = c;
+ }
return(NULL);
}
/****************************************************************************
-apply a function to upper/lower case combinations
-of a string and return true if one of them returns true.
-try all combinations with up to N uppercase letters.
-offset is the first char to try and change (start with 0)
-it assumes the string starts lowercased
+ Apply a function to upper/lower case combinations
+ of a string and return true if one of them returns true.
+ Try all combinations with up to N uppercase letters.
+ offset is the first char to try and change (start with 0)
+ it assumes the string starts lowercased
****************************************************************************/
+
static struct passwd * uname_string_combinations(char *s,struct passwd * (*fn)(char *),int N)
{
int n;
struct passwd *ret;
- for (n=1;n<=N;n++)
- {
+ for (n=1;n<=N;n++) {
ret = uname_string_combinations2(s,0,fn,n);
- if(ret) return(ret);
+ if(ret)
+ return(ret);
}
return(NULL);
}
diff --git a/source/lib/util.c b/source/lib/util.c
index cc9501cc61a..346dc64954f 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -1385,6 +1385,7 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
char *fp, *rp, *cp2, *cp1;
BOOL last_wcard_was_star = False;
int num_path_components, num_regexp_components;
+ enum remote_arch_types ra_type = get_remote_arch();
pstrcpy(te_pattern,t_pattern);
pstrcpy(te_filename,t_filename);
@@ -1417,6 +1418,13 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
if(!do_match(cp2, cp1, case_sig))
break;
+ /*
+ * Ugly ! Special case for non-NT. If filename is XXXX and pattern extension
+ * is '*' or all '?' then disallow match.
+ */
+ if (*cp2 == '\0' && (ra_type != RA_WINNT) && (strequal(eext, "*") || str_is_all(eext, '?')))
+ break;
+
cp1 = rp ? rp + 1 : NULL;
cp2 = fp ? fp + 1 : "";
@@ -1525,6 +1533,13 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
/* pattern has extension */
matched = do_match(sbase, ebase, case_sig)
&& do_match(sext, eext, case_sig);
+ /*
+ * Special case. If filename is XXXX and pattern extension
+ * is '*' or all '?' then disallow match.
+ */
+ if (matched && (strequal(eext, "*") || str_is_all(eext, '?')))
+ matched = False;
+
} else {
matched = do_match(sbase, ebase, case_sig);
#ifdef EMULATE_WEIRD_W95_MATCHING
@@ -2329,7 +2344,7 @@ struct hostent *Get_Hostbyname(const char *name)
check if a process exists. Does this work on all unixes?
****************************************************************************/
-BOOL process_exists(int pid)
+BOOL process_exists(pid_t pid)
{
return(kill(pid,0) == 0 || errno != ESRCH);
}
@@ -2341,7 +2356,7 @@ turn a uid into a user name
char *uidtoname(uid_t uid)
{
static char name[40];
- struct passwd *pass = getpwuid(uid);
+ struct passwd *pass = sys_getpwuid(uid);
if (pass) return(pass->pw_name);
slprintf(name, sizeof(name) - 1, "%d",(int)uid);
return(name);
@@ -2366,7 +2381,7 @@ turn a user name into a uid
********************************************************************/
uid_t nametouid(const char *name)
{
- struct passwd *pass = getpwnam(name);
+ struct passwd *pass = sys_getpwnam(name);
if (pass) return(pass->pw_uid);
return (uid_t)-1;
}
diff --git a/source/lib/util_sock.c b/source/lib/util_sock.c
index e73c6b40539..724d7a3f6dc 100644
--- a/source/lib/util_sock.c
+++ b/source/lib/util_sock.c
@@ -41,13 +41,12 @@ struct in_addr lastip;
/* the last port received from */
int lastport=0;
-
int smb_read_error = 0;
-
/****************************************************************************
-determine if a file descriptor is in fact a socket
+ Determine if a file descriptor is in fact a socket.
****************************************************************************/
+
BOOL is_a_socket(int fd)
{
int v,l;
@@ -55,7 +54,6 @@ BOOL is_a_socket(int fd)
return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
}
-
enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
struct
@@ -98,69 +96,63 @@ struct
#endif
{NULL,0,0,0,0}};
-
-
/****************************************************************************
-set user socket options
+ Set user socket options.
****************************************************************************/
+
void set_socket_options(int fd, char *options)
{
- fstring tok;
-
- while (next_token(&options,tok," \t,", sizeof(tok)))
- {
- int ret=0,i;
- int value = 1;
- char *p;
- BOOL got_value = False;
-
- if ((p = strchr(tok,'=')))
- {
- *p = 0;
- value = atoi(p+1);
- got_value = True;
- }
+ fstring tok;
+
+ while (next_token(&options,tok," \t,", sizeof(tok))) {
+ int ret=0,i;
+ int value = 1;
+ char *p;
+ BOOL got_value = False;
+
+ if ((p = strchr(tok,'='))) {
+ *p = 0;
+ value = atoi(p+1);
+ got_value = True;
+ }
- for (i=0;socket_options[i].name;i++)
- if (strequal(socket_options[i].name,tok))
- break;
+ for (i=0;socket_options[i].name;i++)
+ if (strequal(socket_options[i].name,tok))
+ break;
- if (!socket_options[i].name)
- {
- DEBUG(0,("Unknown socket option %s\n",tok));
- continue;
- }
+ if (!socket_options[i].name) {
+ DEBUG(0,("Unknown socket option %s\n",tok));
+ continue;
+ }
- switch (socket_options[i].opttype)
- {
- case OPT_BOOL:
- case OPT_INT:
- ret = setsockopt(fd,socket_options[i].level,
- socket_options[i].option,(char *)&value,sizeof(int));
- break;
-
- case OPT_ON:
- if (got_value)
- DEBUG(0,("syntax error - %s does not take a value\n",tok));
-
- {
- int on = socket_options[i].value;
- ret = setsockopt(fd,socket_options[i].level,
- socket_options[i].option,(char *)&on,sizeof(int));
- }
- break;
- }
+ switch (socket_options[i].opttype) {
+ case OPT_BOOL:
+ case OPT_INT:
+ ret = setsockopt(fd,socket_options[i].level,
+ socket_options[i].option,(char *)&value,sizeof(int));
+ break;
+
+ case OPT_ON:
+ if (got_value)
+ DEBUG(0,("syntax error - %s does not take a value\n",tok));
+
+ {
+ int on = socket_options[i].value;
+ ret = setsockopt(fd,socket_options[i].level,
+ socket_options[i].option,(char *)&on,sizeof(int));
+ }
+ break;
+ }
- if (ret != 0)
- DEBUG(0,("Failed to set socket option %s\n",tok));
- }
+ if (ret != 0)
+ DEBUG(0,("Failed to set socket option %s (Error %s)\n",tok, strerror(errno) ));
+ }
}
-
-
/****************************************************************************
- close the socket communication
+ Close the socket communication.
****************************************************************************/
+
void close_sockets(void )
{
#ifdef WITH_SSL
@@ -171,31 +163,10 @@ void close_sockets(void )
Client = -1;
}
-
-
/****************************************************************************
-write to a socket
+ Read from a socket.
****************************************************************************/
-ssize_t write_socket(int fd,char *buf,size_t len)
-{
- ssize_t ret=0;
- if (passive)
- return(len);
- DEBUG(6,("write_socket(%d,%d)\n",fd,(int)len));
- ret = write_data(fd,buf,len);
-
- DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,(int)len,(int)ret));
- if(ret <= 0)
- DEBUG(0,("write_socket: Error writing %d bytes to socket %d: ERRNO = %s\n",
- (int)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;
@@ -220,12 +191,125 @@ ssize_t read_udp_socket(int fd,char *buf,size_t len)
return(ret);
}
+/****************************************************************************
+ Read data from a socket with a timout in msec.
+ mincount = if timeout, minimum to read before returning
+ maxcount = number to be read.
+ time_out = timeout in milliseconds
+****************************************************************************/
+
+static ssize_t read_socket_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out)
+{
+ fd_set fds;
+ int selrtn;
+ ssize_t readret;
+ size_t nread = 0;
+ struct timeval timeout;
+
+ /* just checking .... */
+ if (maxcnt <= 0)
+ return(0);
+
+ smb_read_error = 0;
+
+ /* Blocking read */
+ if (time_out <= 0) {
+ if (mincnt == 0) mincnt = maxcnt;
+
+ while (nread < mincnt) {
+#ifdef WITH_SSL
+ if(fd == sslFd){
+ readret = SSL_read(ssl, buf + nread, maxcnt - nread);
+ }else{
+ readret = recv(fd, buf + nread, maxcnt - nread, MSG_WAITALL);
+ }
+#else /* WITH_SSL */
+ readret = recv(fd, buf + nread, maxcnt - nread, MSG_WAITALL);
+#endif /* WITH_SSL */
+
+ if (readret == 0) {
+ DEBUG(5,("read_socket_with_timeout: blocking read. EOF from client.\n"));
+ smb_read_error = READ_EOF;
+ return -1;
+ }
+
+ if (readret == -1) {
+ DEBUG(0,("read_socket_with_timeout: read error = %s.\n", strerror(errno) ));
+ smb_read_error = READ_ERROR;
+ return -1;
+ }
+ nread += readret;
+ }
+ return((ssize_t)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 returns true on disk files */
+
+ /* Set initial timeout */
+ timeout.tv_sec = (time_t)(time_out / 1000);
+ timeout.tv_usec = (long)(1000 * (time_out % 1000));
+
+ for (nread=0; nread < mincnt; ) {
+ FD_ZERO(&fds);
+ FD_SET(fd,&fds);
+
+ selrtn = sys_select(fd+1,&fds,&timeout);
+
+ /* Check if error */
+ if(selrtn == -1) {
+ /* something is wrong. Maybe the socket is dead? */
+ DEBUG(0,("read_socket_with_timeout: timeout read. select error = %s.\n", strerror(errno) ));
+ smb_read_error = READ_ERROR;
+ return -1;
+ }
+
+ /* Did we timeout ? */
+ if (selrtn == 0) {
+ DEBUG(10,("read_socket_with_timeout: timeout read. select timed out.\n"));
+ smb_read_error = READ_TIMEOUT;
+ return -1;
+ }
+
+#ifdef WITH_SSL
+ if(fd == sslFd){
+ readret = SSL_read(ssl, buf + nread, maxcnt - nread);
+ }else{
+ readret = recv(fd, buf + nread, maxcnt - nread, MSG_WAITALL);
+ }
+#else /* WITH_SSL */
+ readret = recv(fd, buf+nread, maxcnt-nread, MSG_WAITALL);
+#endif /* WITH_SSL */
+
+ if (readret == 0) {
+ /* we got EOF on the file descriptor */
+ DEBUG(5,("read_socket_with_timeout: timeout read. EOF from client.\n"));
+ smb_read_error = READ_EOF;
+ return -1;
+ }
+
+ if (readret == -1) {
+ /* the descriptor is probably dead */
+ DEBUG(0,("read_socket_with_timeout: timeout read. read error = %s.\n", strerror(errno) ));
+ smb_read_error = READ_ERROR;
+ return -1;
+ }
+
+ nread += readret;
+ }
+
+ /* Return the number we got */
+ return((ssize_t)nread);
+}
/****************************************************************************
-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
+ Read data from a fd with a timout in msec.
+ mincount = if timeout, minimum to read before returning
+ maxcount = number to be read.
+ time_out = timeout in milliseconds
****************************************************************************/
ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned int time_out)
@@ -237,7 +321,8 @@ ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned
struct timeval timeout;
/* just checking .... */
- if (maxcnt <= 0) return(0);
+ if (maxcnt <= 0)
+ return(0);
smb_read_error = 0;
@@ -282,8 +367,7 @@ ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned
timeout.tv_sec = (time_t)(time_out / 1000);
timeout.tv_usec = (long)(1000 * (time_out % 1000));
- for (nread=0; nread < mincnt; )
- {
+ for (nread=0; nread < mincnt; ) {
FD_ZERO(&fds);
FD_SET(fd,&fds);
@@ -335,10 +419,10 @@ ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,unsigned
return((ssize_t)nread);
}
-
/****************************************************************************
send a keepalive packet (rfc1002)
****************************************************************************/
+
BOOL send_keepalive(int client)
{
unsigned char buf[4];
@@ -346,14 +430,13 @@ BOOL send_keepalive(int client)
buf[0] = 0x85;
buf[1] = buf[2] = buf[3] = 0;
- return(write_data(client,(char *)buf,4) == 4);
+ return(write_socket_data(client,(char *)buf,4) == 4);
}
-
-
/****************************************************************************
read data from the client, reading exactly N bytes.
****************************************************************************/
+
ssize_t read_data(int fd,char *buffer,size_t N)
{
ssize_t ret;
@@ -390,10 +473,50 @@ ssize_t read_data(int fd,char *buffer,size_t N)
return (ssize_t)total;
}
+/****************************************************************************
+ Read data from a socket, reading exactly N bytes.
+****************************************************************************/
+
+static ssize_t read_socket_data(int fd,char *buffer,size_t N)
+{
+ 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 = recv(fd,buffer + total,N - total, MSG_WAITALL);
+ }
+#else /* WITH_SSL */
+ ret = recv(fd,buffer + total,N - total, MSG_WAITALL);
+#endif /* WITH_SSL */
+
+ if (ret == 0)
+ {
+ DEBUG(10,("read_socket_data: recv of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) ));
+ smb_read_error = READ_EOF;
+ return 0;
+ }
+ if (ret == -1)
+ {
+ DEBUG(0,("read_socket_data: recv failure for %d. Error = %s\n", (int)(N - total), strerror(errno) ));
+ smb_read_error = READ_ERROR;
+ return -1;
+ }
+ total += ret;
+ }
+ return (ssize_t)total;
+}
/****************************************************************************
- write data to a fd
+ Write data to a fd.
****************************************************************************/
+
ssize_t write_data(int fd,char *buffer,size_t N)
{
size_t total=0;
@@ -422,7 +545,58 @@ ssize_t write_data(int fd,char *buffer,size_t N)
return (ssize_t)total;
}
+/****************************************************************************
+ Write data to a socket - use send rather than write.
+****************************************************************************/
+
+ssize_t write_socket_data(int fd,char *buffer,size_t N)
+{
+ size_t total=0;
+ ssize_t ret;
+
+ while (total < N)
+ {
+#ifdef WITH_SSL
+ if(fd == sslFd){
+ ret = SSL_write(ssl,buffer + total,N - total);
+ }else{
+ ret = send(fd,buffer + total,N - total, 0);
+ }
+#else /* WITH_SSL */
+ ret = send(fd,buffer + total,N - total,0);
+#endif /* WITH_SSL */
+
+ if (ret == -1) {
+ DEBUG(0,("write_socket_data: write failure. Error = %s\n", strerror(errno) ));
+ return -1;
+ }
+ if (ret == 0) return total;
+
+ total += ret;
+ }
+ return (ssize_t)total;
+}
+
+/****************************************************************************
+write to a socket
+****************************************************************************/
+ssize_t write_socket(int fd,char *buf,size_t len)
+{
+ ssize_t ret=0;
+
+ if (passive)
+ return(len);
+ DEBUG(6,("write_socket(%d,%d)\n",fd,(int)len));
+ ret = write_socket_data(fd,buf,len);
+
+ DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,(int)len,(int)ret));
+ if(ret <= 0)
+ DEBUG(0,("write_socket: Error writing %d bytes to socket %d: ERRNO = %s\n",
+ (int)len, fd, strerror(errno) ));
+
+ return(ret);
+}
/****************************************************************************
read 4 bytes of a smb packet and return the smb length of the packet
@@ -431,6 +605,7 @@ This version of the function will return a length of zero on receiving
a keepalive packet.
timeout is in milliseconds.
****************************************************************************/
+
static ssize_t read_smb_length_return_keepalive(int fd,char *inbuf,unsigned int timeout)
{
ssize_t len=0;
@@ -440,9 +615,9 @@ static ssize_t read_smb_length_return_keepalive(int fd,char *inbuf,unsigned int
while (!ok)
{
if (timeout > 0)
- ok = (read_with_timeout(fd,inbuf,4,4,timeout) == 4);
+ ok = (read_socket_with_timeout(fd,inbuf,4,4,timeout) == 4);
else
- ok = (read_data(fd,inbuf,4) == 4);
+ ok = (read_socket_data(fd,inbuf,4) == 4);
if (!ok)
return(-1);
@@ -465,6 +640,7 @@ 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;
@@ -493,6 +669,7 @@ ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout)
This function will return on a
receipt of a session keepalive packet.
****************************************************************************/
+
BOOL receive_smb(int fd,char *buffer, unsigned int timeout)
{
ssize_t len,ret;
@@ -517,7 +694,7 @@ BOOL receive_smb(int fd,char *buffer, unsigned int timeout)
}
if(len > 0) {
- ret = read_data(fd,buffer+4,len);
+ ret = read_socket_data(fd,buffer+4,len);
if (ret != len) {
smb_read_error = READ_ERROR;
return False;
@@ -591,6 +768,7 @@ BOOL send_null_session_msg(int fd)
/****************************************************************************
send an smb to a fd
****************************************************************************/
+
BOOL send_smb(int fd,char *buffer)
{
size_t len;
@@ -613,11 +791,10 @@ BOOL send_smb(int fd,char *buffer)
return True;
}
-
-
/****************************************************************************
send a single packet to a port on another machine
****************************************************************************/
+
BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
{
BOOL ret;
@@ -656,10 +833,10 @@ BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
return(ret);
}
-
/****************************************************************************
open a socket of the specified type, port and address for incoming data
****************************************************************************/
+
int open_socket_in(int type, int port, int dlevel,uint32 socket_addr, BOOL rebind)
{
struct hostent *hp;
@@ -723,10 +900,10 @@ int open_socket_in(int type, int port, int dlevel,uint32 socket_addr, BOOL rebin
return res;
}
-
/****************************************************************************
create an outgoing socket. timeout is in milliseconds.
**************************************************************************/
+
int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
{
struct sockaddr_in sock_out;
@@ -819,6 +996,7 @@ void reset_globals_after_fork(void)
/*******************************************************************
return the DNS name of the client
******************************************************************/
+
char *client_name(int fd)
{
struct sockaddr sa;
@@ -865,6 +1043,7 @@ char *client_name(int fd)
/*******************************************************************
return the IP addr of the client as a string
******************************************************************/
+
char *client_addr(int fd)
{
struct sockaddr sa;
diff --git a/source/lib/util_str.c b/source/lib/util_str.c
index 16d951c0be8..f1de1d74126 100644
--- a/source/lib/util_str.c
+++ b/source/lib/util_str.c
@@ -733,7 +733,54 @@ size_t count_chars(const char *s,char c)
return(count);
}
+/*******************************************************************
+Return True if a string consists only of one particular character.
+********************************************************************/
+
+BOOL str_is_all(const char *s,char c)
+{
+#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 (is_shift_jis (*s))
+ s += 2;
+ else
+ {
+ if (*s != c)
+ return False;
+ s++;
+ }
+ }
+ }
+ else
+#endif /* KANJI_WIN95_COMPATIBILITY */
+ {
+ while (*s)
+ {
+ size_t skip = skip_multibyte_char( *s );
+ if( skip != 0 )
+ s += skip;
+ else {
+ if (*s != c)
+ return False;
+ s++;
+ }
+ }
+ }
+ return True;
+}
/*******************************************************************
safe string copy into a known length string. maxlength does not
@@ -805,37 +852,39 @@ char *safe_strcat(char *dest, const char *src, size_t maxlength)
char *alpha_strcpy(char *dest, const char *src, size_t maxlength)
{
- size_t len, i;
+ size_t len, i;
- if (!dest) {
- DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
- return NULL;
- }
+ if (!dest) {
+ DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
+ return NULL;
+ }
- if (!src) {
- *dest = 0;
- return dest;
- }
+ if (!src) {
+ *dest = 0;
+ return dest;
+ }
- len = strlen(src);
- if (len >= maxlength)
- len = maxlength - 1;
+ len = strlen(src);
+ if (len >= maxlength)
+ len = maxlength - 1;
- for(i = 0; i < len; i++) {
- if(isupper(src[i]) ||islower(src[i]) || isdigit(src[i]))
- dest[i] = src[i];
- else
- dest[i] = '_';
- }
+ for(i = 0; i < len; i++) {
+ if(isupper(src[i]) ||islower(src[i]) || isdigit(src[i]))
+ dest[i] = src[i];
+ else
+ dest[i] = '_';
+ }
- dest[i] = '\0';
+ dest[i] = '\0';
- return dest;
+ return dest;
}
/****************************************************************************
-like strncpy but always null terminates. Make sure there is room!
+ Like strncpy but always null terminates. Make sure there is room!
+ The variable n should always be one less than the available size.
****************************************************************************/
+
char *StrnCpy(char *dest,const char *src,size_t n)
{
char *d = dest;
@@ -849,7 +898,6 @@ char *StrnCpy(char *dest,const char *src,size_t n)
return(dest);
}
-
/****************************************************************************
like strncpy but copies up to the character marker. always null terminates.
returns a pointer to the character marker in the source string (src).