diff options
author | Andrew Tridgell <tridge@samba.org> | 1999-07-14 13:12:13 +0000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 1999-07-14 13:12:13 +0000 |
commit | 2a274a8755210e13da6bbf29d25f834f53275752 (patch) | |
tree | 6e9f0c1c5147d1d4e4b164f975a0720f9558e4b5 | |
parent | 9db19ffa0b7d5cf5bc9f7f0a597f3ac5e915548b (diff) | |
download | samba-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.c | 10 | ||||
-rw-r--r-- | source/lib/system.c | 79 | ||||
-rw-r--r-- | source/lib/username.c | 184 | ||||
-rw-r--r-- | source/lib/util.c | 21 | ||||
-rw-r--r-- | source/lib/util_sock.c | 371 | ||||
-rw-r--r-- | source/lib/util_str.c | 92 |
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). |