diff --git a/libcfs/include/libcfs/Makefile.am b/libcfs/include/libcfs/Makefile.am index c9f9478babfd761b6ec157cc5622142c38d5b98f..7b1959ec9d486219adacdd50697974aad5139798 100644 --- a/libcfs/include/libcfs/Makefile.am +++ b/libcfs/include/libcfs/Makefile.am @@ -9,4 +9,4 @@ EXTRA_DIST := curproc.h libcfs_private.h libcfs.h list.h lltrace.h \ user-tcpip.h user-bitops.h bitmap.h \ libcfs_prim.h libcfs_time.h libcfs_hash.h \ libcfs_debug.h libcfsutil.h libcfs_ioctl.h \ - libcfs_pack.h libcfs_unpack.h + libcfs_pack.h libcfs_unpack.h libcfs_string.h diff --git a/libcfs/include/libcfs/libcfs.h b/libcfs/include/libcfs/libcfs.h index 08be6207826d860acf14a3bf90da88fef28f7e16..d8886701cc3b64e88e0a62ba7c1df1b5c9e6006f 100644 --- a/libcfs/include/libcfs/libcfs.h +++ b/libcfs/include/libcfs/libcfs.h @@ -283,6 +283,7 @@ int cfs_univ2oflags(int flags); #include <libcfs/libcfs_ioctl.h> #include <libcfs/libcfs_prim.h> #include <libcfs/libcfs_time.h> +#include <libcfs/libcfs_string.h> /* container_of depends on "likely" which is defined in libcfs_private.h */ static inline void *__container_of(void *ptr, unsigned long shift) diff --git a/libcfs/include/libcfs/libcfs_string.h b/libcfs/include/libcfs/libcfs_string.h new file mode 100644 index 0000000000000000000000000000000000000000..72a5ef9aa310fac703334a46f52543bfd937a18b --- /dev/null +++ b/libcfs/include/libcfs/libcfs_string.h @@ -0,0 +1,52 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + * GPL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Use is subject to license terms. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * Lustre is a trademark of Sun Microsystems, Inc. + * + * libcfs/include/libcfs/libcfs_string.h + * + * Generic string manipulation functions. + * + * Author: Nathan Rutman <nathan.rutman@sun.com> + */ + +#ifndef __LIBCFS_STRING_H__ +#define __LIBCFS_STRING_H__ + +/* libcfs_string.c */ +/* Convert a text string to a bitmask */ +int libcfs_str2mask(const char *str, const char *(*bit2str)(int bit), + int *oldmask, int minmask, int allmask); + + +#endif diff --git a/libcfs/libcfs/Makefile.in b/libcfs/libcfs/Makefile.in index 823782a22e49ab7935f780ebbad06958015d135c..d106b09faeb29007b376894645bcfe401a695d13 100644 --- a/libcfs/libcfs/Makefile.in +++ b/libcfs/libcfs/Makefile.in @@ -24,7 +24,8 @@ sources: endif -libcfs-all-objs := debug.o nidstrings.o lwt.o module.o tracefile.o watchdog.o +libcfs-all-objs := debug.o nidstrings.o lwt.o module.o tracefile.o watchdog.o \ + libcfs_string.o libcfs-objs := $(libcfs-linux-objs) $(libcfs-all-objs) diff --git a/libcfs/libcfs/debug.c b/libcfs/libcfs/debug.c index 23b1b7880a67a9b51954772d704f79e440b285d6..dd40428822844643db43db89745fad283b7f9f1d 100644 --- a/libcfs/libcfs/debug.c +++ b/libcfs/libcfs/debug.c @@ -127,7 +127,7 @@ int libcfs_panic_in_progress; const char * libcfs_debug_subsys2str(int subsys) { - switch (subsys) { + switch (1 << subsys) { default: return NULL; case S_UNDEFINED: @@ -184,7 +184,7 @@ libcfs_debug_subsys2str(int subsys) const char * libcfs_debug_dbg2str(int debug) { - switch (debug) { + switch (1 << debug) { default: return NULL; case D_TRACE: @@ -253,7 +253,6 @@ libcfs_debug_mask2str(char *str, int size, int mask, int is_subsys) libcfs_debug_dbg2str; int len = 0; const char *token; - int bit; int i; if (mask == 0) { /* "0" */ @@ -262,12 +261,10 @@ libcfs_debug_mask2str(char *str, int size, int mask, int is_subsys) len = 1; } else { /* space-separated tokens */ for (i = 0; i < 32; i++) { - bit = 1 << i; - - if ((mask & bit) == 0) + if ((mask & (1 << i)) == 0) continue; - token = fn(bit); + token = fn(i); if (token == NULL) /* unused bit */ continue; @@ -296,55 +293,11 @@ libcfs_debug_mask2str(char *str, int size, int mask, int is_subsys) } int -libcfs_debug_token2mask(int *mask, const char *str, int len, int is_subsys) +libcfs_debug_str2mask(int *mask, const char *str, int is_subsys) { const char *(*fn)(int bit) = is_subsys ? libcfs_debug_subsys2str : libcfs_debug_dbg2str; - int i; - int j; - int bit; - const char *token; - - /* match against known tokens */ - for (i = 0; i < 32; i++) { - bit = 1 << i; - - token = fn(bit); - if (token == NULL) /* unused? */ - continue; - - /* strcasecmp */ - for (j = 0; ; j++) { - if (j == len) { /* end of token */ - if (token[j] == 0) { - *mask = bit; - return 0; - } - break; - } - - if (token[j] == 0) - break; - - if (str[j] == token[j]) - continue; - - if (str[j] < 'A' || 'Z' < str[j]) - break; - - if (str[j] - 'A' + 'a' != token[j]) - break; - } - } - - return -EINVAL; /* no match */ -} - -int -libcfs_debug_str2mask(int *mask, const char *str, int is_subsys) -{ int m = 0; - char op = 0; int matched; int n; int t; @@ -362,55 +315,8 @@ libcfs_debug_str2mask(int *mask, const char *str, int is_subsys) return 0; } - /* <str> must be a list of debug tokens or numbers separated by - * whitespace and optionally an operator ('+' or '-'). If an operator - * appears first in <str>, '*mask' is used as the starting point - * (relative), otherwise 0 is used (absolute). An operator applies to - * all following tokens up to the next operator. */ - - matched = 0; - while (*str != 0) { - while (isspace(*str)) /* skip whitespace */ - str++; - - if (*str == 0) - break; - - if (*str == '+' || *str == '-') { - op = *str++; - - /* op on first token == relative */ - if (!matched) - m = *mask; - - while (isspace(*str)) /* skip whitespace */ - str++; - - if (*str == 0) /* trailing op */ - return -EINVAL; - } - - /* find token length */ - for (n = 0; str[n] != 0 && !isspace(str[n]); n++); - - /* match token */ - if (libcfs_debug_token2mask(&t, str, n, is_subsys) != 0) - return -EINVAL; - - matched = 1; - if (op == '-') - m &= ~t; - else - m |= t; - - str += n; - } - - if (!matched) - return -EINVAL; - - *mask = m; - return 0; + return libcfs_str2mask(str, fn, mask, is_subsys ? 0 : D_CANTMASK, + 0xffffffff); } /** diff --git a/libcfs/libcfs/libcfs_string.c b/libcfs/libcfs/libcfs_string.c new file mode 100644 index 0000000000000000000000000000000000000000..40e5ebba23cd2f018e2669b7d3cc9faff3777aa8 --- /dev/null +++ b/libcfs/libcfs/libcfs_string.c @@ -0,0 +1,132 @@ +/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- + * vim:expandtab:shiftwidth=8:tabstop=8: + * + * GPL HEADER START + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 only, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License version 2 for more details (a copy is included + * in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; If not, see + * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + * GPL HEADER END + */ +/* + * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Use is subject to license terms. + */ +/* + * This file is part of Lustre, http://www.lustre.org/ + * Lustre is a trademark of Sun Microsystems, Inc. + * + * String manipulation functions. + * + * libcfs/libcfs/libcfs_string.c + * + * Author: Nathan Rutman <nathan.rutman@sun.com> + */ + +#ifndef EXPORT_SYMTAB +# define EXPORT_SYMTAB +#endif + +#include <libcfs/libcfs.h> + +/* non-0 = don't match */ +static int libcfs_strncasecmp(const char *s1, const char *s2, size_t n) +{ + if (s1 == NULL || s2 == NULL) + return 1; + + if (n == 0) + return 0; + + while (n-- != 0 && tolower(*s1) == tolower(*s2)) { + if (n == 0 || *s1 == '\0' || *s2 == '\0') + break; + s1++; + s2++; + } + + return tolower(*(unsigned char *)s1) - tolower(*(unsigned char *)s2); +} + +/* Convert a text string to a bitmask */ +int libcfs_str2mask(const char *str, const char *(*bit2str)(int bit), + int *oldmask, int minmask, int allmask) +{ + char op = 0; + int newmask = minmask, i, len, found = 0; + ENTRY; + + /* <str> must be a list of tokens separated by whitespace + * and optionally an operator ('+' or '-'). If an operator + * appears first in <str>, '*oldmask' is used as the starting point + * (relative), otherwise minmask is used (absolute). An operator + * applies to all following tokens up to the next operator. */ + while (*str != 0) { + while (isspace(*str)) + str++; + if (*str == 0) + break; + if (*str == '+' || *str == '-') { + op = *str++; + if (!found) + /* only if first token is relative */ + newmask = *oldmask; + while (isspace(*str)) + str++; + if (*str == 0) /* trailing op */ + return -EINVAL; + } + + /* find token length */ + for (len = 0; str[len] != 0 && !isspace(str[len]) && + str[len] != '+' && str[len] != '-'; len++); + + /* match token */ + found = 0; + for (i = 0; i < 32; i++) { + if (libcfs_strncasecmp(str, bit2str(i), len) == 0) { + if (op == '-') + newmask &= ~(1 << i); + else + newmask |= (1 << i); + found = 1; + break; + } + } + if (!found && (libcfs_strncasecmp(str, "ALL", len) == 0)) { + if (op == '-') + newmask = minmask; + else + newmask = allmask; + found = 1; + } + if (!found) { + CWARN("unknown mask '%.*s'.\n" + "mask usage: [+|-]<all|type> ...\n", len, str); + return -EINVAL; + } + str += len; + } + + *oldmask = newmask; + return 0; +} +EXPORT_SYMBOL(libcfs_str2mask); +