Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / lib / string.c
index d501855..e5878de 100644 (file)
  *                    Matthew Hawkins <matt@mh.dropbear.id.au>
  * -  Kissed strtok() goodbye
  */
+
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/ctype.h>
-#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/bug.h>
+#include <linux/errno.h>
 
 #ifndef __HAVE_ARCH_STRNICMP
 /**
@@ -36,25 +39,52 @@ int strnicmp(const char *s1, const char *s2, size_t len)
        /* Yes, Virginia, it had better be unsigned */
        unsigned char c1, c2;
 
-       c1 = 0; c2 = 0;
-       if (len) {
-               do {
-                       c1 = *s1; c2 = *s2;
-                       s1++; s2++;
-                       if (!c1)
-                               break;
-                       if (!c2)
-                               break;
-                       if (c1 == c2)
-                               continue;
-                       c1 = tolower(c1);
-                       c2 = tolower(c2);
-                       if (c1 != c2)
-                               break;
-               } while (--len);
-       }
+       if (!len)
+               return 0;
+
+       do {
+               c1 = *s1++;
+               c2 = *s2++;
+               if (!c1 || !c2)
+                       break;
+               if (c1 == c2)
+                       continue;
+               c1 = tolower(c1);
+               c2 = tolower(c2);
+               if (c1 != c2)
+                       break;
+       } while (--len);
        return (int)c1 - (int)c2;
 }
+EXPORT_SYMBOL(strnicmp);
+#endif
+
+#ifndef __HAVE_ARCH_STRCASECMP
+int strcasecmp(const char *s1, const char *s2)
+{
+       int c1, c2;
+
+       do {
+               c1 = tolower(*s1++);
+               c2 = tolower(*s2++);
+       } while (c1 == c2 && c1 != 0);
+       return c1 - c2;
+}
+EXPORT_SYMBOL(strcasecmp);
+#endif
+
+#ifndef __HAVE_ARCH_STRNCASECMP
+int strncasecmp(const char *s1, const char *s2, size_t n)
+{
+       int c1, c2;
+
+       do {
+               c1 = tolower(*s1++);
+               c2 = tolower(*s2++);
+       } while ((--n > 0) && c1 == c2 && c1 != 0);
+       return c1 - c2;
+}
+EXPORT_SYMBOL(strncasecmp);
 #endif
 
 #ifndef __HAVE_ARCH_STRCPY
@@ -63,7 +93,8 @@ int strnicmp(const char *s1, const char *s2, size_t len)
  * @dest: Where to copy the string to
  * @src: Where to copy the string from
  */
-char * strcpy(char * dest,const char *src)
+#undef strcpy
+char *strcpy(char *dest, const char *src)
 {
        char *tmp = dest;
 
@@ -71,6 +102,7 @@ char * strcpy(char * dest,const char *src)
                /* nothing */;
        return tmp;
 }
+EXPORT_SYMBOL(strcpy);
 #endif
 
 #ifndef __HAVE_ARCH_STRNCPY
@@ -82,19 +114,24 @@ char * strcpy(char * dest,const char *src)
  *
  * The result is not %NUL-terminated if the source exceeds
  * @count bytes.
+ *
+ * In the case where the length of @src is less than  that  of
+ * count, the remainder of @dest will be padded with %NUL.
+ *
  */
-char * strncpy(char * dest,const char *src,size_t count)
+char *strncpy(char *dest, const char *src, size_t count)
 {
        char *tmp = dest;
 
-       while (count && (*dest++ = *src++) != '\0')
-               count--;
        while (count) {
-               *dest++ = 0;
+               if ((*tmp = *src) != 0)
+                       src++;
+               tmp++;
                count--;
        }
-       return tmp;
+       return dest;
 }
+EXPORT_SYMBOL(strncpy);
 #endif
 
 #ifndef __HAVE_ARCH_STRLCPY
@@ -114,7 +151,7 @@ size_t strlcpy(char *dest, const char *src, size_t size)
        size_t ret = strlen(src);
 
        if (size) {
-               size_t len = (ret >= size) ? size-1 : ret;
+               size_t len = (ret >= size) ? size - 1 : ret;
                memcpy(dest, src, len);
                dest[len] = '\0';
        }
@@ -129,7 +166,8 @@ EXPORT_SYMBOL(strlcpy);
  * @dest: The string to be appended to
  * @src: The string to append to it
  */
-char * strcat(char * dest, const char * src)
+#undef strcat
+char *strcat(char *dest, const char *src)
 {
        char *tmp = dest;
 
@@ -137,9 +175,9 @@ char * strcat(char * dest, const char * src)
                dest++;
        while ((*dest++ = *src++) != '\0')
                ;
-
        return tmp;
 }
+EXPORT_SYMBOL(strcat);
 #endif
 
 #ifndef __HAVE_ARCH_STRNCAT
@@ -149,26 +187,26 @@ char * strcat(char * dest, const char * src)
  * @src: The string to append to it
  * @count: The maximum numbers of bytes to copy
  *
- * Note that in contrast to strncpy, strncat ensures the result is
+ * Note that in contrast to strncpy(), strncat() ensures the result is
  * terminated.
  */
-char * strncat(char *dest, const char *src, size_t count)
+char *strncat(char *dest, const char *src, size_t count)
 {
        char *tmp = dest;
 
        if (count) {
                while (*dest)
                        dest++;
-               while ((*dest++ = *src++)) {
+               while ((*dest++ = *src++) != 0) {
                        if (--count == 0) {
                                *dest = '\0';
                                break;
                        }
                }
        }
-
        return tmp;
 }
+EXPORT_SYMBOL(strncat);
 #endif
 
 #ifndef __HAVE_ARCH_STRLCAT
@@ -204,17 +242,22 @@ EXPORT_SYMBOL(strlcat);
  * @cs: One string
  * @ct: Another string
  */
-int strcmp(const char * cs,const char * ct)
+#undef strcmp
+int strcmp(const char *cs, const char *ct)
 {
-       register signed char __res;
+       unsigned char c1, c2;
 
        while (1) {
-               if ((__res = *cs - *ct++) != 0 || !*cs++)
+               c1 = *cs++;
+               c2 = *ct++;
+               if (c1 != c2)
+                       return c1 < c2 ? -1 : 1;
+               if (!c1)
                        break;
        }
-
-       return __res;
+       return 0;
 }
+EXPORT_SYMBOL(strcmp);
 #endif
 
 #ifndef __HAVE_ARCH_STRNCMP
@@ -224,18 +267,22 @@ int strcmp(const char * cs,const char * ct)
  * @ct: Another string
  * @count: The maximum number of bytes to compare
  */
-int strncmp(const char * cs,const char * ct,size_t count)
+int strncmp(const char *cs, const char *ct, size_t count)
 {
-       register signed char __res = 0;
+       unsigned char c1, c2;
 
        while (count) {
-               if ((__res = *cs - *ct++) != 0 || !*cs++)
+               c1 = *cs++;
+               c2 = *ct++;
+               if (c1 != c2)
+                       return c1 < c2 ? -1 : 1;
+               if (!c1)
                        break;
                count--;
        }
-
-       return __res;
+       return 0;
 }
+EXPORT_SYMBOL(strncmp);
 #endif
 
 #ifndef __HAVE_ARCH_STRCHR
@@ -244,13 +291,14 @@ int strncmp(const char * cs,const char * ct,size_t count)
  * @s: The string to be searched
  * @c: The character to search for
  */
-char * strchr(const char * s, int c)
+char *strchr(const char *s, int c)
 {
-       for(; *s != (char) c; ++s)
+       for (; *s != (char)c; ++s)
                if (*s == '\0')
                        return NULL;
-       return (char *) s;
+       return (char *)s;
 }
+EXPORT_SYMBOL(strchr);
 #endif
 
 #ifndef __HAVE_ARCH_STRRCHR
@@ -259,7 +307,7 @@ char * strchr(const char * s, int c)
  * @s: The string to be searched
  * @c: The character to search for
  */
-char * strrchr(const char * s, int c)
+char *strrchr(const char *s, int c)
 {
        const char *p = s + strlen(s);
        do {
@@ -268,14 +316,72 @@ char * strrchr(const char * s, int c)
        } while (--p >= s);
        return NULL;
 }
+EXPORT_SYMBOL(strrchr);
 #endif
 
+#ifndef __HAVE_ARCH_STRNCHR
+/**
+ * strnchr - Find a character in a length limited string
+ * @s: The string to be searched
+ * @count: The number of characters to be searched
+ * @c: The character to search for
+ */
+char *strnchr(const char *s, size_t count, int c)
+{
+       for (; count-- && *s != '\0'; ++s)
+               if (*s == (char)c)
+                       return (char *)s;
+       return NULL;
+}
+EXPORT_SYMBOL(strnchr);
+#endif
+
+/**
+ * skip_spaces - Removes leading whitespace from @str.
+ * @str: The string to be stripped.
+ *
+ * Returns a pointer to the first non-whitespace character in @str.
+ */
+char *skip_spaces(const char *str)
+{
+       while (isspace(*str))
+               ++str;
+       return (char *)str;
+}
+EXPORT_SYMBOL(skip_spaces);
+
+/**
+ * strim - Removes leading and trailing whitespace from @s.
+ * @s: The string to be stripped.
+ *
+ * Note that the first trailing whitespace is replaced with a %NUL-terminator
+ * in the given string @s. Returns a pointer to the first non-whitespace
+ * character in @s.
+ */
+char *strim(char *s)
+{
+       size_t size;
+       char *end;
+
+       size = strlen(s);
+       if (!size)
+               return s;
+
+       end = s + size - 1;
+       while (end >= s && isspace(*end))
+               end--;
+       *(end + 1) = '\0';
+
+       return skip_spaces(s);
+}
+EXPORT_SYMBOL(strim);
+
 #ifndef __HAVE_ARCH_STRLEN
 /**
  * strlen - Find the length of a string
  * @s: The string to be sized
  */
-size_t strlen(const char * s)
+size_t strlen(const char *s)
 {
        const char *sc;
 
@@ -283,6 +389,7 @@ size_t strlen(const char * s)
                /* nothing */;
        return sc - s;
 }
+EXPORT_SYMBOL(strlen);
 #endif
 
 #ifndef __HAVE_ARCH_STRNLEN
@@ -291,7 +398,7 @@ size_t strlen(const char * s)
  * @s: The string to be sized
  * @count: The maximum number of bytes to search
  */
-size_t strnlen(const char * s, size_t count)
+size_t strnlen(const char *s, size_t count)
 {
        const char *sc;
 
@@ -299,12 +406,12 @@ size_t strnlen(const char * s, size_t count)
                /* nothing */;
        return sc - s;
 }
+EXPORT_SYMBOL(strnlen);
 #endif
 
 #ifndef __HAVE_ARCH_STRSPN
 /**
- * strspn - Calculate the length of the initial substring of @s which only
- *     contain letters in @accept
+ * strspn - Calculate the length of the initial substring of @s which only contain letters in @accept
  * @s: The string to be searched
  * @accept: The string to search for
  */
@@ -323,14 +430,15 @@ size_t strspn(const char *s, const char *accept)
                        return count;
                ++count;
        }
-
        return count;
 }
+
+EXPORT_SYMBOL(strspn);
 #endif
 
+#ifndef __HAVE_ARCH_STRCSPN
 /**
- * strcspn - Calculate the length of the initial substring of @s which does
- *     not contain letters in @reject
+ * strcspn - Calculate the length of the initial substring of @s which does not contain letters in @reject
  * @s: The string to be searched
  * @reject: The string to avoid
  */
@@ -347,9 +455,10 @@ size_t strcspn(const char *s, const char *reject)
                }
                ++count;
        }
-
        return count;
-}      
+}
+EXPORT_SYMBOL(strcspn);
+#endif
 
 #ifndef __HAVE_ARCH_STRPBRK
 /**
@@ -357,18 +466,19 @@ size_t strcspn(const char *s, const char *reject)
  * @cs: The string to be searched
  * @ct: The characters to search for
  */
-char * strpbrk(const char * cs,const char * ct)
+char *strpbrk(const char *cs, const char *ct)
 {
-       const char *sc1,*sc2;
+       const char *sc1, *sc2;
 
-       for( sc1 = cs; *sc1 != '\0'; ++sc1) {
-               for( sc2 = ct; *sc2 != '\0'; ++sc2) {
+       for (sc1 = cs; *sc1 != '\0'; ++sc1) {
+               for (sc2 = ct; *sc2 != '\0'; ++sc2) {
                        if (*sc1 == *sc2)
-                               return (char *) sc1;
+                               return (char *)sc1;
                }
        }
        return NULL;
 }
+EXPORT_SYMBOL(strpbrk);
 #endif
 
 #ifndef __HAVE_ARCH_STRSEP
@@ -383,9 +493,10 @@ char * strpbrk(const char * cs,const char * ct)
  * of that name. In fact, it was stolen from glibc2 and de-fancy-fied.
  * Same semantics, slimmer shape. ;)
  */
-char * strsep(char **s, const char *ct)
+char *strsep(char **s, const char *ct)
 {
-       char *sbegin = *s, *end;
+       char *sbegin = *s;
+       char *end;
 
        if (sbegin == NULL)
                return NULL;
@@ -394,53 +505,85 @@ char * strsep(char **s, const char *ct)
        if (end)
                *end++ = '\0';
        *s = end;
-
        return sbegin;
 }
+EXPORT_SYMBOL(strsep);
 #endif
 
-#ifndef __HAVE_ARCH_MEMSET
 /**
- * memset - Fill a region of memory with the given value
- * @s: Pointer to the start of the area.
- * @c: The byte to fill the area with
- * @count: The size of the area.
+ * sysfs_streq - return true if strings are equal, modulo trailing newline
+ * @s1: one string
+ * @s2: another string
  *
- * Do not use memset() to access IO space, use memset_io() instead.
+ * This routine returns true iff two strings are equal, treating both
+ * NUL and newline-then-NUL as equivalent string terminations.  It's
+ * geared for use with sysfs input strings, which generally terminate
+ * with newlines but are compared against values without newlines.
  */
-void * memset(void * s,int c,size_t count)
+bool sysfs_streq(const char *s1, const char *s2)
 {
-       char *xs = (char *) s;
+       while (*s1 && *s1 == *s2) {
+               s1++;
+               s2++;
+       }
 
-       while (count--)
-               *xs++ = c;
+       if (*s1 == *s2)
+               return true;
+       if (!*s1 && *s2 == '\n' && !s2[1])
+               return true;
+       if (*s1 == '\n' && !s1[1] && !*s2)
+               return true;
+       return false;
+}
+EXPORT_SYMBOL(sysfs_streq);
 
-       return s;
+/**
+ * strtobool - convert common user inputs into boolean values
+ * @s: input string
+ * @res: result
+ *
+ * This routine returns 0 iff the first character is one of 'Yy1Nn0'.
+ * Otherwise it will return -EINVAL.  Value pointed to by res is
+ * updated upon finding a match.
+ */
+int strtobool(const char *s, bool *res)
+{
+       switch (s[0]) {
+       case 'y':
+       case 'Y':
+       case '1':
+               *res = true;
+               break;
+       case 'n':
+       case 'N':
+       case '0':
+               *res = false;
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
 }
-#endif
+EXPORT_SYMBOL(strtobool);
 
-#ifndef __HAVE_ARCH_BCOPY
+#ifndef __HAVE_ARCH_MEMSET
 /**
- * bcopy - Copy one area of memory to another
- * @src: Where to copy from
- * @dest: Where to copy to
+ * memset - Fill a region of memory with the given value
+ * @s: Pointer to the start of the area.
+ * @c: The byte to fill the area with
  * @count: The size of the area.
  *
- * Note that this is the same as memcpy(), with the arguments reversed.
- * memcpy() is the standard, bcopy() is a legacy BSD function.
- *
- * You should not use this function to access IO space, use memcpy_toio()
- * or memcpy_fromio() instead.
+ * Do not use memset() to access IO space, use memset_io() instead.
  */
-char * bcopy(const char * src, char * dest, int count)
+void *memset(void *s, int c, size_t count)
 {
-       char *tmp = dest;
+       char *xs = s;
 
        while (count--)
-               *tmp++ = *src++;
-
-       return dest;
+               *xs++ = c;
+       return s;
 }
+EXPORT_SYMBOL(memset);
 #endif
 
 #ifndef __HAVE_ARCH_MEMCPY
@@ -453,15 +596,16 @@ char * bcopy(const char * src, char * dest, int count)
  * You should not use this function to access IO space, use memcpy_toio()
  * or memcpy_fromio() instead.
  */
-void * memcpy(void * dest,const void *src,size_t count)
+void *memcpy(void *dest, const void *src, size_t count)
 {
-       char *tmp = (char *) dest, *s = (char *) src;
+       char *tmp = dest;
+       const char *s = src;
 
        while (count--)
                *tmp++ = *s++;
-
        return dest;
 }
+EXPORT_SYMBOL(memcpy);
 #endif
 
 #ifndef __HAVE_ARCH_MEMMOVE
@@ -473,25 +617,27 @@ void * memcpy(void * dest,const void *src,size_t count)
  *
  * Unlike memcpy(), memmove() copes with overlapping areas.
  */
-void * memmove(void * dest,const void *src,size_t count)
+void *memmove(void *dest, const void *src, size_t count)
 {
-       char *tmp, *s;
+       char *tmp;
+       const char *s;
 
        if (dest <= src) {
-               tmp = (char *) dest;
-               s = (char *) src;
+               tmp = dest;
+               s = src;
                while (count--)
                        *tmp++ = *s++;
-               }
-       else {
-               tmp = (char *) dest + count;
-               s = (char *) src + count;
+       } else {
+               tmp = dest;
+               tmp += count;
+               s = src;
+               s += count;
                while (count--)
                        *--tmp = *--s;
-               }
-
+       }
        return dest;
 }
+EXPORT_SYMBOL(memmove);
 #endif
 
 #ifndef __HAVE_ARCH_MEMCMP
@@ -501,16 +647,18 @@ void * memmove(void * dest,const void *src,size_t count)
  * @ct: Another area of memory
  * @count: The size of the area.
  */
-int memcmp(const void * cs,const void * ct,size_t count)
+#undef memcmp
+int memcmp(const void *cs, const void *ct, size_t count)
 {
        const unsigned char *su1, *su2;
        int res = 0;
 
-       for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+       for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
                if ((res = *su1 - *su2) != 0)
                        break;
        return res;
 }
+EXPORT_SYMBOL(memcmp);
 #endif
 
 #ifndef __HAVE_ARCH_MEMSCAN
@@ -523,18 +671,19 @@ int memcmp(const void * cs,const void * ct,size_t count)
  * returns the address of the first occurrence of @c, or 1 byte past
  * the area if @c is not found
  */
-void * memscan(void * addr, int c, size_t size)
+void *memscan(void *addr, int c, size_t size)
 {
-       unsigned char * p = (unsigned char *) addr;
+       unsigned char *p = addr;
 
        while (size) {
                if (*p == c)
-                       return (void *) p;
+                       return (void *)p;
                p++;
                size--;
        }
-       return (void *) p;
+       return (void *)p;
 }
+EXPORT_SYMBOL(memscan);
 #endif
 
 #ifndef __HAVE_ARCH_STRSTR
@@ -543,22 +692,48 @@ void * memscan(void * addr, int c, size_t size)
  * @s1: The string to be searched
  * @s2: The string to search for
  */
-char * strstr(const char * s1,const char * s2)
+char *strstr(const char *s1, const char *s2)
 {
-       int l1, l2;
+       size_t l1, l2;
 
        l2 = strlen(s2);
        if (!l2)
-               return (char *) s1;
+               return (char *)s1;
        l1 = strlen(s1);
        while (l1 >= l2) {
                l1--;
-               if (!memcmp(s1,s2,l2))
-                       return (char *) s1;
+               if (!memcmp(s1, s2, l2))
+                       return (char *)s1;
                s1++;
        }
        return NULL;
 }
+EXPORT_SYMBOL(strstr);
+#endif
+
+#ifndef __HAVE_ARCH_STRNSTR
+/**
+ * strnstr - Find the first substring in a length-limited string
+ * @s1: The string to be searched
+ * @s2: The string to search for
+ * @len: the maximum number of characters to search
+ */
+char *strnstr(const char *s1, const char *s2, size_t len)
+{
+       size_t l2;
+
+       l2 = strlen(s2);
+       if (!l2)
+               return (char *)s1;
+       while (len >= l2) {
+               len--;
+               if (!memcmp(s1, s2, l2))
+                       return (char *)s1;
+               s1++;
+       }
+       return NULL;
+}
+EXPORT_SYMBOL(strnstr);
 #endif
 
 #ifndef __HAVE_ARCH_MEMCHR
@@ -576,10 +751,76 @@ void *memchr(const void *s, int c, size_t n)
        const unsigned char *p = s;
        while (n-- != 0) {
                if ((unsigned char)c == *p++) {
-                       return (void *)(p-1);
+                       return (void *)(p - 1);
                }
        }
        return NULL;
 }
+EXPORT_SYMBOL(memchr);
+#endif
+
+static void *check_bytes8(const u8 *start, u8 value, unsigned int bytes)
+{
+       while (bytes) {
+               if (*start != value)
+                       return (void *)start;
+               start++;
+               bytes--;
+       }
+       return NULL;
+}
 
+/**
+ * memchr_inv - Find an unmatching character in an area of memory.
+ * @start: The memory area
+ * @c: Find a character other than c
+ * @bytes: The size of the area.
+ *
+ * returns the address of the first character other than @c, or %NULL
+ * if the whole buffer contains just @c.
+ */
+void *memchr_inv(const void *start, int c, size_t bytes)
+{
+       u8 value = c;
+       u64 value64;
+       unsigned int words, prefix;
+
+       if (bytes <= 16)
+               return check_bytes8(start, value, bytes);
+
+       value64 = value;
+#if defined(ARCH_HAS_FAST_MULTIPLIER) && BITS_PER_LONG == 64
+       value64 *= 0x0101010101010101;
+#elif defined(ARCH_HAS_FAST_MULTIPLIER)
+       value64 *= 0x01010101;
+       value64 |= value64 << 32;
+#else
+       value64 |= value64 << 8;
+       value64 |= value64 << 16;
+       value64 |= value64 << 32;
 #endif
+
+       prefix = (unsigned long)start % 8;
+       if (prefix) {
+               u8 *r;
+
+               prefix = 8 - prefix;
+               r = check_bytes8(start, value, prefix);
+               if (r)
+                       return r;
+               start += prefix;
+               bytes -= prefix;
+       }
+
+       words = bytes / 8;
+
+       while (words) {
+               if (*(u64 *)start != value64)
+                       return check_bytes8(start, value, 8);
+               start += 8;
+               words--;
+       }
+
+       return check_bytes8(start, value, bytes % 8);
+}
+EXPORT_SYMBOL(memchr_inv);