Whamcloud - gitweb
b=24170 checking len of debug string before matching
[fs/lustre-release.git] / libcfs / libcfs / libcfs_string.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * String manipulation functions.
37  *
38  * libcfs/libcfs/libcfs_string.c
39  *
40  * Author: Nathan Rutman <nathan.rutman@sun.com>
41  */
42
43 #ifndef EXPORT_SYMTAB
44 # define EXPORT_SYMTAB
45 #endif
46
47 #include <libcfs/libcfs.h>
48
49 /* non-0 = don't match */
50 static int cfs_strncasecmp(const char *s1, const char *s2, size_t n)
51 {
52         if (s1 == NULL || s2 == NULL)
53                 return 1;
54
55         if (n == 0)
56                 return 0;
57
58         while (n-- != 0 && tolower(*s1) == tolower(*s2)) {
59                 if (n == 0 || *s1 == '\0' || *s2 == '\0')
60                         break;
61                 s1++;
62                 s2++;
63         }
64
65         return tolower(*(unsigned char *)s1) - tolower(*(unsigned char *)s2);
66 }
67
68 /* Convert a text string to a bitmask */
69 int cfs_str2mask(const char *str, const char *(*bit2str)(int bit),
70                  int *oldmask, int minmask, int allmask)
71 {
72         const char *debugstr;
73         char op = 0;
74         int newmask = minmask, i, len, found = 0;
75         ENTRY;
76
77         /* <str> must be a list of tokens separated by whitespace
78          * and optionally an operator ('+' or '-').  If an operator
79          * appears first in <str>, '*oldmask' is used as the starting point
80          * (relative), otherwise minmask is used (absolute).  An operator
81          * applies to all following tokens up to the next operator. */
82         while (*str != 0) {
83                 while (isspace(*str))
84                         str++;
85                 if (*str == 0)
86                         break;
87                 if (*str == '+' || *str == '-') {
88                         op = *str++;
89                         if (!found)
90                                 /* only if first token is relative */
91                                 newmask = *oldmask;
92                         while (isspace(*str))
93                                 str++;
94                         if (*str == 0)          /* trailing op */
95                                 return -EINVAL;
96                 }
97
98                 /* find token length */
99                 for (len = 0; str[len] != 0 && !isspace(str[len]) &&
100                       str[len] != '+' && str[len] != '-'; len++);
101
102                 /* match token */
103                 found = 0;
104                 for (i = 0; i < 32; i++) {
105                         debugstr = bit2str(i);
106                         if (debugstr != NULL &&
107                             strlen(debugstr) == len &&
108                             cfs_strncasecmp(str, debugstr, len) == 0) {
109                                 if (op == '-')
110                                         newmask &= ~(1 << i);
111                                 else
112                                         newmask |= (1 << i);
113                                 found = 1;
114                                 break;
115                         }
116                 }
117                 if (!found && len == 3 &&
118                     (cfs_strncasecmp(str, "ALL", len) == 0)) {
119                         if (op == '-')
120                                 newmask = minmask;
121                         else
122                                 newmask = allmask;
123                         found = 1;
124                 }
125                 if (!found) {
126                         CWARN("unknown mask '%.*s'.\n"
127                               "mask usage: [+|-]<all|type> ...\n", len, str);
128                         return -EINVAL;
129                 }
130                 str += len;
131         }
132
133         *oldmask = newmask;
134         return 0;
135 }
136 EXPORT_SYMBOL(cfs_str2mask);
137
138 /* Duplicate a string in a platform-independent way */
139 char *cfs_strdup(const char *str, u_int32_t flags)
140 {
141         size_t lenz; /* length of str + zero byte */
142         char *dup_str;
143
144         lenz = strlen(str) + 1;
145
146         dup_str = cfs_alloc(lenz, flags);
147         if (dup_str == NULL)
148                 return NULL;
149
150         memcpy(dup_str, str, lenz);
151
152         return dup_str;
153 }
154 EXPORT_SYMBOL(cfs_strdup);
155
156 /**
157  * cfs_{v}snprintf() return the actual size that is printed rather than
158  * the size that would be printed in standard functions.
159  */
160 /* safe vsnprintf */
161 int cfs_vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
162 {
163         int i;
164
165         LASSERT(size > 0);
166         i = vsnprintf(buf, size, fmt, args);
167
168         return  (i >= size ? size - 1 : i);
169 }
170 EXPORT_SYMBOL(cfs_vsnprintf);
171
172 /* safe snprintf */
173 int cfs_snprintf(char *buf, size_t size, const char *fmt, ...)
174 {
175         va_list args;
176         int i;
177
178         va_start(args, fmt);
179         i = cfs_vsnprintf(buf, size, fmt, args);
180         va_end(args);
181
182         return  i;
183 }
184 EXPORT_SYMBOL(cfs_snprintf);