1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 #include <strings.h>
  30 #include <ctype.h>
  31 #include <fm/libtopo.h>
  32 #include <fm/topo_mod.h>
  33 #include <topo_alloc.h>
  34 
  35 char *
  36 topo_hdl_strdup(topo_hdl_t *thp, const char *s)
  37 {
  38         char *p;
  39 
  40         if (s != NULL)
  41                 p = topo_hdl_alloc(thp, strlen(s) + 1);
  42         else
  43                 p = NULL;
  44 
  45         if (p != NULL)
  46                 (void) strcpy(p, s);
  47 
  48         return (p);
  49 }
  50 
  51 void
  52 topo_hdl_strfree(topo_hdl_t *thp, char *s)
  53 {
  54         if (s != NULL)
  55                 topo_hdl_free(thp, s, strlen(s) + 1);
  56 }
  57 
  58 char *
  59 topo_mod_strdup(topo_mod_t *mod, const char *s)
  60 {
  61         return (topo_hdl_strdup(mod->tm_hdl, s));
  62 }
  63 
  64 void
  65 topo_mod_strfree(topo_mod_t *mod, char *s)
  66 {
  67         topo_hdl_strfree(mod->tm_hdl, s);
  68 }
  69 
  70 const char *
  71 topo_strbasename(const char *s)
  72 {
  73         const char *p = strrchr(s, '/');
  74 
  75         if (p == NULL)
  76                 return (s);
  77 
  78         return (++p);
  79 }
  80 
  81 char *
  82 topo_strdirname(char *s)
  83 {
  84         static char slash[] = "/";
  85         static char dot[] = ".";
  86         char *p;
  87 
  88         if (s == NULL || *s == '\0')
  89                 return (dot);
  90 
  91         for (p = s + strlen(s); p != s && *--p == '/'; )
  92                 continue;
  93 
  94         if (p == s && *p == '/')
  95                 return (slash);
  96 
  97         while (p != s) {
  98                 if (*--p == '/') {
  99                         while (*p == '/' && p != s)
 100                                 p--;
 101                         *++p = '\0';
 102                         return (s);
 103                 }
 104         }
 105 
 106         return (dot);
 107 }
 108 
 109 ulong_t
 110 topo_strhash(const char *key)
 111 {
 112         ulong_t g, h = 0;
 113         const char *p;
 114 
 115         for (p = key; *p != '\0'; p++) {
 116                 h = (h << 4) + *p;
 117 
 118                 if ((g = (h & 0xf0000000)) != 0) {
 119                         h ^= (g >> 24);
 120                         h ^= g;
 121                 }
 122         }
 123 
 124         return (h);
 125 }
 126 
 127 /*
 128  * Transform string s inline, converting each embedded C escape sequence string
 129  * to the corresponding character.  For example, the substring "\n" is replaced
 130  * by an inline '\n' character.  The length of the resulting string is returned.
 131  */
 132 size_t
 133 topo_stresc2chr(char *s)
 134 {
 135         char *p, *q, c;
 136         int esc = 0;
 137         int x;
 138 
 139         for (p = q = s; (c = *p) != '\0'; p++) {
 140                 if (esc) {
 141                         switch (c) {
 142                         case '0':
 143                         case '1':
 144                         case '2':
 145                         case '3':
 146                         case '4':
 147                         case '5':
 148                         case '6':
 149                         case '7':
 150                                 c -= '0';
 151                                 p++;
 152 
 153                                 if (*p >= '0' && *p <= '7') {
 154                                         c = c * 8 + *p++ - '0';
 155 
 156                                         if (*p >= '0' && *p <= '7')
 157                                                 c = c * 8 + *p - '0';
 158                                         else
 159                                                 p--;
 160                                 } else
 161                                         p--;
 162 
 163                                 *q++ = c;
 164                                 break;
 165 
 166                         case 'a':
 167                                 *q++ = '\a';
 168                                 break;
 169                         case 'b':
 170                                 *q++ = '\b';
 171                                 break;
 172                         case 'f':
 173                                 *q++ = '\f';
 174                                 break;
 175                         case 'n':
 176                                 *q++ = '\n';
 177                                 break;
 178                         case 'r':
 179                                 *q++ = '\r';
 180                                 break;
 181                         case 't':
 182                                 *q++ = '\t';
 183                                 break;
 184                         case 'v':
 185                                 *q++ = '\v';
 186                                 break;
 187 
 188                         case 'x':
 189                                 for (x = 0; (c = *++p) != '\0'; ) {
 190                                         if (c >= '0' && c <= '9')
 191                                                 x = x * 16 + c - '0';
 192                                         else if (c >= 'a' && c <= 'f')
 193                                                 x = x * 16 + c - 'a' + 10;
 194                                         else if (c >= 'A' && c <= 'F')
 195                                                 x = x * 16 + c - 'A' + 10;
 196                                         else
 197                                                 break;
 198                                 }
 199                                 *q++ = (char)x;
 200                                 p--;
 201                                 break;
 202 
 203                         case '"':
 204                         case '\\':
 205                                 *q++ = c;
 206                                 break;
 207                         default:
 208                                 *q++ = '\\';
 209                                 *q++ = c;
 210                         }
 211 
 212                         esc = 0;
 213 
 214                 } else {
 215                         if ((esc = c == '\\') == 0)
 216                                 *q++ = c;
 217                 }
 218         }
 219 
 220         *q = '\0';
 221         return ((size_t)(q - s));
 222 }
 223 
 224 int
 225 topo_strmatch(const char *s, const char *p)
 226 {
 227         char c;
 228 
 229         if (p == NULL)
 230                 return (0);
 231 
 232         if (s == NULL)
 233                 s = ""; /* treat NULL string as the empty string */
 234 
 235         do {
 236                 if ((c = *p++) == '\0')
 237                         return (*s == '\0');
 238 
 239                 if (c == '*') {
 240                         while (*p == '*')
 241                                 p++; /* consecutive *'s can be collapsed */
 242 
 243                         if (*p == '\0')
 244                                 return (1);
 245 
 246                         while (*s != '\0') {
 247                                 if (topo_strmatch(s++, p) != 0)
 248                                         return (1);
 249                         }
 250 
 251                         return (0);
 252                 }
 253         } while (c == *s++);
 254 
 255         return (0);
 256 }