Fixed bug found by John Blair where trim_string wasn't
[samba.git] / source / lib / util.c
index 2738bc894ae93acef781116696a2c667378f2690..58106acd46877fd31319781e26007d3221d6a439 100644 (file)
@@ -500,7 +500,7 @@ int name_mangle( char *In, char *Out, char name_type )
 
   /* Safely copy the input string, In, into buf[]. */
   (void)memset( buf, 0, 20 );
-  if( '*' == In[0] )
+  if (strcmp(In,"*") == 0)
     buf[0] = '*';
   else
     (void)slprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, name_type );
@@ -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)
@@ -2334,21 +2418,23 @@ int name_extract(char *buf,int ofs,char *name)
 /****************************************************************************
 return the total storage length of a mangled name
 ****************************************************************************/
-int name_len( char *s )
+int name_len(char *s1)
 {
-  int len;
+       /* NOTE: this argument _must_ be unsigned */
+       unsigned char *s = (unsigned char *)s1;
+       int len;
 
-  /* If the two high bits of the byte are set, return 2. */
-  if( 0xC0 == (*(unsigned char *)s & 0xC0) )
-    return(2);
+       /* If the two high bits of the byte are set, return 2. */
+       if (0xC0 == (*s & 0xC0))
+               return(2);
 
-  /* Add up the length bytes. */
-  for( len = 1; (*s); s += (*s) + 1 )
-    {
-    len += *s + 1;
-    }
+       /* Add up the length bytes. */
+       for (len = 1; (*s); s += (*s) + 1) {
+               len += *s + 1;
+               SMB_ASSERT(len < 80);
+       }
 
-  return( len );
+       return(len);
 } /* name_len */
 
 /****************************************************************************
@@ -3080,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),
@@ -3103,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
 }
@@ -4044,7 +4131,6 @@ BOOL process_exists(int pid)
 /*******************************************************************
 turn a uid into a user name
 ********************************************************************/
-
 char *uidtoname(uid_t uid)
 {
   static char name[40];
@@ -4054,6 +4140,7 @@ char *uidtoname(uid_t uid)
   return(name);
 }
 
+
 /*******************************************************************
 turn a gid into a group name
 ********************************************************************/
@@ -4067,6 +4154,16 @@ char *gidtoname(gid_t gid)
        return(name);
 }
 
+/*******************************************************************
+turn a user name into a uid
+********************************************************************/
+uid_t nametouid(const char *name)
+{
+       struct passwd *pass = getpwnam(name);
+       if (pass) return(pass->pw_uid);
+       return (uid_t)-1;
+}
+
 /*******************************************************************
 something really nasty happened - panic!
 ********************************************************************/
@@ -4477,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;
 }
@@ -4505,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;
 }
@@ -4532,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;
@@ -4809,7 +4891,7 @@ BOOL string_to_sid(DOM_SID *sidout, char *sidstr)
  *
  * ****************************************************************************
  */
-int str_checksum(char *s)
+int str_checksum(const char *s)
 {
        int res = 0;
        int c;
@@ -4834,3 +4916,28 @@ void zero_free(void *p, size_t size)
        memset(p, 0, size);
        free(p);
 }
+
+
+/*****************************************************************
+set our open file limit to a requested max and return the limit
+*****************************************************************/  
+int set_maxfiles(int requested_max)
+{
+#if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
+       struct rlimit rlp;
+       getrlimit(RLIMIT_NOFILE, &rlp);
+       /* Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
+        * account for the extra fd we need 
+        * as well as the log files and standard
+        * handles etc.  */
+       rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
+       setrlimit(RLIMIT_NOFILE, &rlp);
+       getrlimit(RLIMIT_NOFILE, &rlp);
+       return rlp.rlim_cur;
+#else
+       /*
+        * No way to know - just guess...
+        */
+       return requested_max;
+#endif
+}