Whamcloud - gitweb
Mass conversion of all copyright messages to Oracle.
[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 libcfs_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 libcfs_str2mask(const char *str, const char *(*bit2str)(int bit),
70                     int *oldmask, int minmask, int allmask)
71 {
72         char op = 0;
73         int newmask = minmask, i, len, found = 0;
74         ENTRY;
75
76         /* <str> must be a list of tokens separated by whitespace
77          * and optionally an operator ('+' or '-').  If an operator
78          * appears first in <str>, '*oldmask' is used as the starting point
79          * (relative), otherwise minmask is used (absolute).  An operator
80          * applies to all following tokens up to the next operator. */
81         while (*str != 0) {
82                 while (isspace(*str))
83                         str++;
84                 if (*str == 0)
85                         break;
86                 if (*str == '+' || *str == '-') {
87                         op = *str++;
88                         if (!found)
89                                 /* only if first token is relative */
90                                 newmask = *oldmask;
91                         while (isspace(*str))
92                                 str++;
93                         if (*str == 0)          /* trailing op */
94                                 return -EINVAL;
95                 }
96
97                 /* find token length */
98                 for (len = 0; str[len] != 0 && !isspace(str[len]) &&
99                       str[len] != '+' && str[len] != '-'; len++);
100
101                 /* match token */
102                 found = 0;
103                 for (i = 0; i < 32; i++) {
104                         if (libcfs_strncasecmp(str, bit2str(i), len) == 0) {
105                                 if (op == '-')
106                                         newmask &= ~(1 << i);
107                                 else
108                                         newmask |= (1 << i);
109                                 found = 1;
110                                 break;
111                         }
112                 }
113                 if (!found && (libcfs_strncasecmp(str, "ALL", len) == 0)) {
114                         if (op == '-')
115                                 newmask = minmask;
116                         else
117                                 newmask = allmask;
118                         found = 1;
119                 }
120                 if (!found) {
121                         CWARN("unknown mask '%.*s'.\n"
122                               "mask usage: [+|-]<all|type> ...\n", len, str);
123                         return -EINVAL;
124                 }
125                 str += len;
126         }
127
128         *oldmask = newmask;
129         return 0;
130 }
131
132 /* Duplicate a string in a platform-independent way */
133 char *libcfs_strdup(const char *str, u_int32_t flags)
134 {
135         size_t lenz; /* length of str + zero byte */
136         char *dup_str;
137
138         lenz = strlen(str) + 1;
139
140         dup_str = cfs_alloc(lenz, flags);
141         if (dup_str == NULL)
142                 return NULL;
143
144         memcpy(dup_str, str, lenz);
145
146         return dup_str;
147 }
148
149 EXPORT_SYMBOL(libcfs_str2mask);
150 EXPORT_SYMBOL(libcfs_strdup);