Fixed bug found by John Blair where trim_string wasn't
[samba.git] / source / lib / util.c
index c1307336cc18220deecf0b462abf141a8d4d5483..58106acd46877fd31319781e26007d3221d6a439 100644 (file)
@@ -1116,9 +1116,29 @@ char *skip_string(char *buf,int n)
   return(buf);
 }
 
+/*******************************************************************
+ Count the number of characters in a string. Normally this will
+ be the same as the number of bytes in a string for single byte strings,
+ but will be different for multibyte.
+ 16.oct.98, jdblair@cobaltnet.com.
+********************************************************************/
+
+size_t str_charnum(char *s)
+{
+  size_t len = 0;
+  
+  while (*s != '\0') {
+    int skip = skip_multibyte_char(*s);
+    s += (skip ? skip : 1);
+    len++;
+  }
+  return len;
+}
+
 /*******************************************************************
 trim the specified elements off the front and back of a string
 ********************************************************************/
+
 BOOL trim_string(char *s,char *front,char *back)
 {
   BOOL ret = False;
@@ -1138,14 +1158,76 @@ BOOL trim_string(char *s,char *front,char *back)
     }
   }
 
-  s_len = strlen(s);
-  while (back_len && s_len >= back_len && 
-        (strncmp(s + s_len - back_len, back, back_len)==0))  
+  /*
+   * We split out the multibyte code page
+   * case here for speed purposes. Under a
+   * multibyte code page we need to walk the
+   * string forwards only and multiple times.
+   * Thanks to John Blair for finding this
+   * one. JRA.
+   */
+
+  if(back_len)
   {
-    ret = True;
-    s[s_len - back_len] = 0;
-    s_len = strlen(s);
-  }
+    if(!is_multibyte_codepage())
+    {
+      s_len = strlen(s);
+      while ((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);
+      }
+    }
+    else
+    {
+
+      /*
+       * Multibyte code page case.
+       * Keep going through the string, trying
+       * to match the 'back' string with the end
+       * of the string. If we get a match, truncate
+       * 'back' off the end of the string and
+       * go through the string again from the
+       * start. Keep doing this until we have
+       * gone through the string with no match
+       * at the string end.
+       */
+
+      size_t mb_back_len = str_charnum(back);
+      size_t mb_s_len = str_charnum(s);
+
+      while(mb_s_len >= mb_back_len)
+      {
+        size_t charcount = 0;
+        char *mbp = s;
+
+        while(charcount < (mb_s_len - mb_back_len))
+        {
+          size_t skip = skip_multibyte_char(*mbp);
+          mbp += (skip ? skip : 1);
+          charcount++;
+        }
+
+        /*
+         * mbp now points at mb_back_len multibyte
+         * characters from the end of s.
+         */
+
+        if(strcmp(mbp, back) == 0)
+        {
+          ret = True;
+          *mbp = '\0';
+          mb_s_len = str_charnum(s);
+          mbp = s;
+        }
+        else
+          break;
+      } /* end while mb_s_len... */
+    } /* end else .. */
+  } /* end if back_len .. */
+
   return(ret);
 }
 
@@ -2262,8 +2344,10 @@ BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout)
   {
     ret = receive_smb(fd, buffer, timeout);
 
-    if(ret == False)
+    if (!ret)
+    {
       return ret;
+    }
 
     /* Ignore session keepalive packets. */
     if(CVAL(buffer,0) != 0x85)
@@ -3082,7 +3166,7 @@ int set_filelen(int fd, SMB_OFF_T len)
   char c = 0;
   SMB_OFF_T currpos = sys_lseek(fd, (SMB_OFF_T)0, SEEK_CUR);
 
-  if(currpos < 0)
+  if(currpos == -1)
     return -1;
   /* Do an fstat to see if the file is longer than
      the requested size (call ftruncate),
@@ -3105,7 +3189,8 @@ int set_filelen(int fd, SMB_OFF_T len)
   if(write(fd, &c, 1)!=1)
     return -1;
   /* Seek to where we were */
-  sys_lseek(fd, currpos, SEEK_SET);
+  if(sys_lseek(fd, currpos, SEEK_SET) != currpos)
+    return -1;
   return 0;
 #endif
 }
@@ -4489,16 +4574,11 @@ char *unistrn2(uint16 *buf, int len)
 
        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;
 }
@@ -4517,16 +4597,11 @@ char *unistr2(uint16 *buf)
 
        nexti = (nexti+1)%8;
 
-       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;
 }
@@ -4544,17 +4619,12 @@ int struni2(uint16 *p, char *buf)
 
        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"));
        }
 
        *p = 0;
@@ -4849,9 +4919,9 @@ void zero_free(void *p, size_t size)
 
 
 /*****************************************************************
-set our open file limit to the max and return the limit
+set our open file limit to a requested max and return the limit
 *****************************************************************/  
-int set_maxfiles(void)
+int set_maxfiles(int requested_max)
 {
 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
        struct rlimit rlp;
@@ -4860,13 +4930,14 @@ int set_maxfiles(void)
         * account for the extra fd we need 
         * as well as the log files and standard
         * handles etc.  */
-       rlp.rlim_cur = rlp.rlim_max;
+       rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
        setrlimit(RLIMIT_NOFILE, &rlp);
        getrlimit(RLIMIT_NOFILE, &rlp);
        return rlp.rlim_cur;
 #else
-       /* just guess ... */
-       return 1024;
+       /*
+        * No way to know - just guess...
+        */
+       return requested_max;
 #endif
 }
-