1 /*
2  * Copyright (C) 2012-2015 Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library.  If not, see
16  * <http://www.gnu.org/licenses/>.
17  */
18 
19 #include <config.h>
20 
21 #include <glib/gprintf.h>
22 #include <locale.h>
23 #ifdef WITH_XLOCALE_H
24 # include <xlocale.h>
25 #endif
26 
27 #include "virstring.h"
28 #include "virthread.h"
29 #include "viralloc.h"
30 #include "virbuffer.h"
31 #include "virerror.h"
32 #include "virlog.h"
33 
34 #define VIR_FROM_THIS VIR_FROM_NONE
35 
36 VIR_LOG_INIT("util.string");
37 
38 /* Like strtol, but produce an "int" result, and check more carefully.
39    Return 0 upon success;  return -1 to indicate failure.
40    When END_PTR is NULL, the byte after the final valid digit must be NUL.
41    Otherwise, it's like strtol and lets the caller check any suffix for
42    validity.  This function is careful to return -1 when the string S
43    represents a number that is not representable as an "int". */
44 int
virStrToLong_i(char const * s,char ** end_ptr,int base,int * result)45 virStrToLong_i(char const *s, char **end_ptr, int base, int *result)
46 {
47     long int val;
48     char *p;
49     int err;
50 
51     errno = 0;
52     val = strtol(s, &p, base); /* exempt from syntax-check */
53     err = (errno || (!end_ptr && *p) || p == s || (int) val != val);
54     if (end_ptr)
55         *end_ptr = p;
56     if (err)
57         return -1;
58     *result = val;
59     return 0;
60 }
61 
62 /* Just like virStrToLong_i, above, but produce an "unsigned int"
63  * value.  This version allows twos-complement wraparound of negative
64  * numbers. */
65 int
virStrToLong_ui(char const * s,char ** end_ptr,int base,unsigned int * result)66 virStrToLong_ui(char const *s, char **end_ptr, int base, unsigned int *result)
67 {
68     unsigned long int val;
69     char *p;
70     bool err = false;
71 
72     errno = 0;
73     val = strtoul(s, &p, base); /* exempt from syntax-check */
74 
75     /* This one's tricky.  We _want_ to allow "-1" as shorthand for
76      * UINT_MAX regardless of whether long is 32-bit or 64-bit.  But
77      * strtoul treats "-1" as ULONG_MAX, and going from ulong back
78      * to uint differs depending on the size of long. */
79     if (sizeof(long) > sizeof(int) && memchr(s, '-', p - s)) {
80         if (-val > UINT_MAX)
81             err = true;
82         else
83             val &= 0xffffffff;
84     }
85 
86     err |= (errno || (!end_ptr && *p) || p == s || (unsigned int) val != val);
87     if (end_ptr)
88         *end_ptr = p;
89     if (err)
90         return -1;
91     *result = val;
92     return 0;
93 }
94 
95 /* Just like virStrToLong_i, above, but produce an "unsigned int"
96  * value.  This version rejects any negative signs.  */
97 int
virStrToLong_uip(char const * s,char ** end_ptr,int base,unsigned int * result)98 virStrToLong_uip(char const *s, char **end_ptr, int base, unsigned int *result)
99 {
100     unsigned long int val;
101     char *p;
102     bool err = false;
103 
104     errno = 0;
105     val = strtoul(s, &p, base); /* exempt from syntax-check */
106     err = (memchr(s, '-', p - s) ||
107            errno || (!end_ptr && *p) || p == s || (unsigned int) val != val);
108     if (end_ptr)
109         *end_ptr = p;
110     if (err)
111         return -1;
112     *result = val;
113     return 0;
114 }
115 
116 /* Just like virStrToLong_i, above, but produce a "long" value.  */
117 int
virStrToLong_l(char const * s,char ** end_ptr,int base,long * result)118 virStrToLong_l(char const *s, char **end_ptr, int base, long *result)
119 {
120     long int val;
121     char *p;
122     int err;
123 
124     errno = 0;
125     val = strtol(s, &p, base); /* exempt from syntax-check */
126     err = (errno || (!end_ptr && *p) || p == s);
127     if (end_ptr)
128         *end_ptr = p;
129     if (err)
130         return -1;
131     *result = val;
132     return 0;
133 }
134 
135 /* Just like virStrToLong_i, above, but produce an "unsigned long"
136  * value.  This version allows twos-complement wraparound of negative
137  * numbers. */
138 int
virStrToLong_ul(char const * s,char ** end_ptr,int base,unsigned long * result)139 virStrToLong_ul(char const *s, char **end_ptr, int base, unsigned long *result)
140 {
141     unsigned long int val;
142     char *p;
143     int err;
144 
145     errno = 0;
146     val = strtoul(s, &p, base); /* exempt from syntax-check */
147     err = (errno || (!end_ptr && *p) || p == s);
148     if (end_ptr)
149         *end_ptr = p;
150     if (err)
151         return -1;
152     *result = val;
153     return 0;
154 }
155 
156 /* Just like virStrToLong_i, above, but produce an "unsigned long"
157  * value.  This version rejects any negative signs.  */
158 int
virStrToLong_ulp(char const * s,char ** end_ptr,int base,unsigned long * result)159 virStrToLong_ulp(char const *s, char **end_ptr, int base,
160                  unsigned long *result)
161 {
162     unsigned long int val;
163     char *p;
164     int err;
165 
166     errno = 0;
167     val = strtoul(s, &p, base); /* exempt from syntax-check */
168     err = (memchr(s, '-', p - s) ||
169            errno || (!end_ptr && *p) || p == s);
170     if (end_ptr)
171         *end_ptr = p;
172     if (err)
173         return -1;
174     *result = val;
175     return 0;
176 }
177 
178 /* Just like virStrToLong_i, above, but produce a "long long" value.  */
179 int
virStrToLong_ll(char const * s,char ** end_ptr,int base,long long * result)180 virStrToLong_ll(char const *s, char **end_ptr, int base, long long *result)
181 {
182     long long val;
183     char *p;
184     int err;
185 
186     errno = 0;
187     val = strtoll(s, &p, base); /* exempt from syntax-check */
188     err = (errno || (!end_ptr && *p) || p == s);
189     if (end_ptr)
190         *end_ptr = p;
191     if (err)
192         return -1;
193     *result = val;
194     return 0;
195 }
196 
197 /* Just like virStrToLong_i, above, but produce an "unsigned long
198  * long" value.  This version allows twos-complement wraparound of
199  * negative numbers. */
200 int
virStrToLong_ull(char const * s,char ** end_ptr,int base,unsigned long long * result)201 virStrToLong_ull(char const *s, char **end_ptr, int base,
202                  unsigned long long *result)
203 {
204     unsigned long long val;
205     char *p;
206     int err;
207 
208     errno = 0;
209     val = strtoull(s, &p, base); /* exempt from syntax-check */
210     err = (errno || (!end_ptr && *p) || p == s);
211     if (end_ptr)
212         *end_ptr = p;
213     if (err)
214         return -1;
215     *result = val;
216     return 0;
217 }
218 
219 /* Just like virStrToLong_i, above, but produce an "unsigned long
220  * long" value.  This version rejects any negative signs.  */
221 int
virStrToLong_ullp(char const * s,char ** end_ptr,int base,unsigned long long * result)222 virStrToLong_ullp(char const *s, char **end_ptr, int base,
223                   unsigned long long *result)
224 {
225     unsigned long long val;
226     char *p;
227     int err;
228 
229     errno = 0;
230     val = strtoull(s, &p, base); /* exempt from syntax-check */
231     err = (memchr(s, '-', p - s) ||
232            errno || (!end_ptr && *p) || p == s);
233     if (end_ptr)
234         *end_ptr = p;
235     if (err)
236         return -1;
237     *result = val;
238     return 0;
239 }
240 
241 /* In case thread-safe locales are available */
242 #if WITH_NEWLOCALE
243 
244 typedef locale_t virLocale;
245 static virLocale virLocaleRaw;
246 
247 static int
virLocaleOnceInit(void)248 virLocaleOnceInit(void)
249 {
250     virLocaleRaw = newlocale(LC_ALL_MASK, "C", (locale_t)0);
251     if (!virLocaleRaw)
252         return -1;
253     return 0;
254 }
255 
256 VIR_ONCE_GLOBAL_INIT(virLocale);
257 
258 /**
259  * virLocaleSetRaw:
260  *
261  * @oldlocale: set to old locale pointer
262  *
263  * Sets the locale to 'C' to allow operating on non-localized objects.
264  * Returns 0 on success -1 on error.
265  */
266 static int
virLocaleSetRaw(virLocale * oldlocale)267 virLocaleSetRaw(virLocale *oldlocale)
268 {
269     if (virLocaleInitialize() < 0)
270         return -1;
271     *oldlocale = uselocale(virLocaleRaw);
272     return 0;
273 }
274 
275 static void
virLocaleRevert(virLocale * oldlocale)276 virLocaleRevert(virLocale *oldlocale)
277 {
278     uselocale(*oldlocale);
279 }
280 
281 static void
virLocaleFixupRadix(char ** strp G_GNUC_UNUSED)282 virLocaleFixupRadix(char **strp G_GNUC_UNUSED)
283 {
284 }
285 
286 #else /* !WITH_NEWLOCALE */
287 
288 typedef int virLocale;
289 
290 static int
virLocaleSetRaw(virLocale * oldlocale G_GNUC_UNUSED)291 virLocaleSetRaw(virLocale *oldlocale G_GNUC_UNUSED)
292 {
293     return 0;
294 }
295 
296 static void
virLocaleRevert(virLocale * oldlocale G_GNUC_UNUSED)297 virLocaleRevert(virLocale *oldlocale G_GNUC_UNUSED)
298 {
299 }
300 
301 static void
virLocaleFixupRadix(char ** strp)302 virLocaleFixupRadix(char **strp)
303 {
304     char *radix, *tmp;
305     struct lconv *lc;
306 
307     lc = localeconv();
308     radix = lc->decimal_point;
309     tmp = strstr(*strp, radix);
310     if (tmp) {
311         *tmp = '.';
312         if (strlen(radix) > 1)
313             memmove(tmp + 1, tmp + strlen(radix), strlen(*strp) - (tmp - *strp));
314     }
315 }
316 
317 #endif /* !WITH_NEWLOCALE */
318 
319 
320 /**
321  * virStrToDouble
322  *
323  * converts string with C locale (thread-safe) to double.
324  *
325  * Returns -1 on error or returns 0 on success.
326  */
327 int
virStrToDouble(char const * s,char ** end_ptr,double * result)328 virStrToDouble(char const *s,
329                char **end_ptr,
330                double *result)
331 {
332     virLocale oldlocale;
333     double val;
334     char *p;
335     int err;
336 
337     errno = 0;
338     if (virLocaleSetRaw(&oldlocale) < 0)
339         return -1;
340     val = strtod(s, &p); /* exempt from syntax-check */
341     virLocaleRevert(&oldlocale);
342 
343     err = (errno || (!end_ptr && *p) || p == s);
344     if (end_ptr)
345         *end_ptr = p;
346     if (err)
347         return -1;
348     *result = val;
349     return 0;
350 }
351 
352 /**
353  * virDoubleToStr
354  *
355  * converts double to string with C locale (thread-safe).
356  *
357  * Returns: 0 on success, -1 otherwise.
358  */
359 int
virDoubleToStr(char ** strp,double number)360 virDoubleToStr(char **strp, double number)
361 {
362     virLocale oldlocale;
363 
364     if (virLocaleSetRaw(&oldlocale) < 0)
365         return -1;
366 
367     *strp = g_strdup_printf("%lf", number);
368 
369     virLocaleRevert(&oldlocale);
370     virLocaleFixupRadix(strp);
371 
372     return 0;
373 }
374 
375 
376 /**
377  * virStrcpy:
378  *
379  * @dest: destination buffer
380  * @src: source buffer
381  * @destbytes: number of bytes the destination can accommodate
382  *
383  * Copies @src to @dest. @dest is guaranteed to be 'nul' terminated if
384  * destbytes is 1 or more.
385  *
386  * Returns: 0 on success, -1 if @src doesn't fit into @dest and was truncated.
387  */
388 int
virStrcpy(char * dest,const char * src,size_t destbytes)389 virStrcpy(char *dest, const char *src, size_t destbytes)
390 {
391     if (g_strlcpy(dest, src, destbytes) >= destbytes)
392         return -1;
393 
394     return 0;
395 }
396 
397 /**
398  * virSkipSpaces:
399  * @str: pointer to the char pointer used
400  *
401  * Skip potential blanks, this includes space tabs, line feed,
402  * carriage returns.
403  */
404 void
virSkipSpaces(const char ** str)405 virSkipSpaces(const char **str)
406 {
407     const char *cur = *str;
408 
409     while (g_ascii_isspace(*cur))
410         cur++;
411     *str = cur;
412 }
413 
414 /**
415  * virSkipSpacesAndBackslash:
416  * @str: pointer to the char pointer used
417  *
418  * Like virSkipSpaces, but also skip backslashes erroneously emitted
419  * by xend
420  */
421 void
virSkipSpacesAndBackslash(const char ** str)422 virSkipSpacesAndBackslash(const char **str)
423 {
424     const char *cur = *str;
425 
426     while (g_ascii_isspace(*cur) || *cur == '\\')
427         cur++;
428     *str = cur;
429 }
430 
431 
432 /**
433  * virSkipToDigit:
434  * @str: pointer to the char pointer used
435  *
436  * Skip over any character that is not 0-9
437  */
438 void
virSkipToDigit(const char ** str)439 virSkipToDigit(const char **str)
440 {
441     const char *cur = *str;
442 
443     while (*cur && !g_ascii_isdigit(*cur))
444         cur++;
445     *str = cur;
446 }
447 
448 
449 /**
450  * virTrimSpaces:
451  * @str: string to modify to remove all trailing spaces
452  * @endp: track the end of the string
453  *
454  * If @endp is NULL on entry, then all spaces prior to the trailing
455  * NUL in @str are removed, by writing NUL into the appropriate
456  * location.  If @endp is non-NULL but points to a NULL pointer,
457  * then all spaces prior to the trailing NUL in @str are removed,
458  * NUL is written to the new string end, and endp is set to the
459  * location of the (new) string end.  If @endp is non-NULL and
460  * points to a non-NULL pointer, then that pointer is used as
461  * the end of the string, endp is set to the (new) location, but
462  * no NUL pointer is written into the string.
463  */
464 void
virTrimSpaces(char * str,char ** endp)465 virTrimSpaces(char *str, char **endp)
466 {
467     char *end;
468 
469     if (!endp || !*endp)
470         end = str + strlen(str);
471     else
472         end = *endp;
473     while (end > str && g_ascii_isspace(end[-1]))
474         end--;
475     if (endp) {
476         if (!*endp)
477             *end = '\0';
478         *endp = end;
479     } else {
480         *end = '\0';
481     }
482 }
483 
484 /**
485  * virSkipSpacesBackwards:
486  * @str: start of string
487  * @endp: on entry, *endp must be NULL or a location within @str, on exit,
488  * will be adjusted to skip trailing spaces, or to NULL if @str had nothing
489  * but spaces.
490  */
491 void
virSkipSpacesBackwards(const char * str,char ** endp)492 virSkipSpacesBackwards(const char *str, char **endp)
493 {
494     /* Casting away const is safe, since virTrimSpaces does not
495      * modify string with this particular usage.  */
496     char *s = (char*) str;
497 
498     if (!*endp)
499         *endp = s + strlen(s);
500     virTrimSpaces(s, endp);
501     if (s == *endp)
502         *endp = NULL;
503 }
504 
505 /**
506  * virStringIsEmpty:
507  * @str: string to check
508  *
509  * Returns true if string is empty (may contain only whitespace) or NULL.
510  */
511 bool
virStringIsEmpty(const char * str)512 virStringIsEmpty(const char *str)
513 {
514     if (!str)
515         return true;
516 
517     virSkipSpaces(&str);
518     return str[0] == '\0';
519 }
520 
521 
522 /**
523  * virStringSortCompare:
524  *
525  * A comparator function for sorting strings in
526  * normal order with qsort().
527  */
virStringSortCompare(const void * a,const void * b)528 int virStringSortCompare(const void *a, const void *b)
529 {
530     const char **sa = (const char**)a;
531     const char **sb = (const char**)b;
532 
533     return strcmp(*sa, *sb);
534 }
535 
536 /**
537  * virStringSortRevCompare:
538  *
539  * A comparator function for sorting strings in
540  * reverse order with qsort().
541  */
virStringSortRevCompare(const void * a,const void * b)542 int virStringSortRevCompare(const void *a, const void *b)
543 {
544     const char **sa = (const char**)a;
545     const char **sb = (const char**)b;
546 
547     return strcmp(*sb, *sa);
548 }
549 
550 /**
551  * virStringSearch:
552  * @str: string to search
553  * @regexp: POSIX Extended regular expression pattern used for matching
554  * @max_matches: maximum number of substrings to return
555  * @matches: pointer to an array to be filled with NULL terminated list of matches
556  *
557  * Performs a POSIX extended regex search against a string and return all matching substrings.
558  * The @matches value should be freed with g_strfreev() when no longer
559  * required.
560  *
561  * @code
562  *  char *source = "6853a496-1c10-472e-867a-8244937bd6f0
563  *                  773ab075-4cd7-4fc2-8b6e-21c84e9cb391
564  *                  bbb3c75c-d60f-43b0-b802-fd56b84a4222
565  *                  60c04aa1-0375-4654-8d9f-e149d9885273
566  *                  4548d465-9891-4c34-a184-3b1c34a26aa8";
567  *  char **matches = NULL;
568  *  virStringSearch(source,
569  *                  "([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})",
570  *                  3,
571  *                  &matches);
572  *
573  *  // matches[0] == "6853a496-1c10-472e-867a-8244937bd6f0";
574  *  // matches[1] == "773ab075-4cd7-4fc2-8b6e-21c84e9cb391";
575  *  // matches[2] == "bbb3c75c-d60f-43b0-b802-fd56b84a4222"
576  *  // matches[3] == NULL;
577  *
578  *  g_strfreev(matches);
579  * @endcode
580  *
581  * Returns: -1 on error, or number of matches
582  */
583 ssize_t
virStringSearch(const char * str,const char * regexp,size_t max_matches,char *** matches)584 virStringSearch(const char *str,
585                 const char *regexp,
586                 size_t max_matches,
587                 char ***matches)
588 {
589     g_autoptr(GRegex) regex = NULL;
590     g_autoptr(GError) err = NULL;
591     size_t nmatches = 0;
592     ssize_t ret = -1;
593 
594     *matches = NULL;
595 
596     VIR_DEBUG("search '%s' for '%s'", str, regexp);
597 
598     regex = g_regex_new(regexp, 0, 0, &err);
599     if (!regex) {
600         virReportError(VIR_ERR_INTERNAL_ERROR,
601                        _("Failed to compile regex %s"), err->message);
602         return -1;
603     }
604 
605     if (g_regex_get_capture_count(regex) != 1) {
606         virReportError(VIR_ERR_INTERNAL_ERROR,
607                        _("Regular expression '%s' must have exactly 1 match group, not %d"),
608                        regexp, g_regex_get_capture_count(regex));
609         goto cleanup;
610     }
611 
612     /* '*matches' must always be NULL terminated in every iteration
613      * of the loop, so start by allocating 1 element
614      */
615     VIR_EXPAND_N(*matches, nmatches, 1);
616 
617     while ((nmatches - 1) < max_matches) {
618         g_autoptr(GMatchInfo) info = NULL;
619         char *match;
620         int endpos;
621 
622         if (!g_regex_match(regex, str, 0, &info))
623             break;
624 
625         VIR_EXPAND_N(*matches, nmatches, 1);
626 
627         match = g_match_info_fetch(info, 1);
628 
629         VIR_DEBUG("Got '%s'", match);
630 
631         (*matches)[nmatches-2] = match;
632 
633         g_match_info_fetch_pos(info, 1, NULL, &endpos);
634         str += endpos;
635     }
636 
637     ret = nmatches - 1; /* don't count the trailing null */
638 
639  cleanup:
640     if (ret < 0) {
641         g_strfreev(*matches);
642         *matches = NULL;
643     }
644     return ret;
645 }
646 
647 /**
648  * virStringMatch:
649  * @str: string to match
650  * @regexp: POSIX Extended regular expression pattern used for matching
651  *
652  * Performs a POSIX extended regex match against a string.
653  * Returns true on match, false on error or no match.
654  */
655 bool
virStringMatch(const char * str,const char * regexp)656 virStringMatch(const char *str,
657                const char *regexp)
658 {
659     g_autoptr(GRegex) regex = NULL;
660     g_autoptr(GError) err = NULL;
661 
662     VIR_DEBUG("match '%s' for '%s'", str, regexp);
663 
664     regex = g_regex_new(regexp, 0, 0, &err);
665     if (!regex) {
666         VIR_WARN("Failed to compile regex %s", err->message);
667         return false;
668     }
669 
670     return g_regex_match(regex, str, 0, NULL);
671 }
672 
673 /**
674  * virStringReplace:
675  * @haystack: the source string to process
676  * @oldneedle: the substring to locate
677  * @newneedle: the substring to insert
678  *
679  * Search @haystack and replace all occurrences of @oldneedle with @newneedle.
680  *
681  * Returns: a new string with all the replacements, or NULL on error
682  */
683 char *
virStringReplace(const char * haystack,const char * oldneedle,const char * newneedle)684 virStringReplace(const char *haystack,
685                  const char *oldneedle,
686                  const char *newneedle)
687 {
688     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
689     const char *tmp1, *tmp2;
690     size_t oldneedlelen = strlen(oldneedle);
691     size_t newneedlelen = strlen(newneedle);
692 
693     tmp1 = haystack;
694     tmp2 = NULL;
695 
696     while (tmp1) {
697         tmp2 = strstr(tmp1, oldneedle);
698 
699         if (tmp2) {
700             virBufferAdd(&buf, tmp1, (tmp2 - tmp1));
701             virBufferAdd(&buf, newneedle, newneedlelen);
702             tmp2 += oldneedlelen;
703         } else {
704             virBufferAdd(&buf, tmp1, -1);
705         }
706 
707         tmp1 = tmp2;
708     }
709 
710     return virBufferContentAndReset(&buf);
711 }
712 
713 bool
virStringHasSuffix(const char * str,const char * suffix)714 virStringHasSuffix(const char *str,
715                    const char *suffix)
716 {
717     int len = strlen(str);
718     int suffixlen = strlen(suffix);
719 
720     if (len < suffixlen)
721         return false;
722 
723     return STREQ(str + len - suffixlen, suffix);
724 }
725 
726 bool
virStringHasCaseSuffix(const char * str,const char * suffix)727 virStringHasCaseSuffix(const char *str,
728                        const char *suffix)
729 {
730     int len = strlen(str);
731     int suffixlen = strlen(suffix);
732 
733     if (len < suffixlen)
734         return false;
735 
736     return STRCASEEQ(str + len - suffixlen, suffix);
737 }
738 
739 bool
virStringStripSuffix(char * str,const char * suffix)740 virStringStripSuffix(char *str,
741                      const char *suffix)
742 {
743     int len = strlen(str);
744     int suffixlen = strlen(suffix);
745 
746     if (len < suffixlen)
747         return false;
748 
749     if (STRNEQ(str + len - suffixlen, suffix))
750         return false;
751 
752     str[len - suffixlen] = '\0';
753 
754     return true;
755 }
756 
757 bool
virStringMatchesNameSuffix(const char * file,const char * name,const char * suffix)758 virStringMatchesNameSuffix(const char *file,
759                            const char *name,
760                            const char *suffix)
761 {
762     int filelen = strlen(file);
763     int namelen = strlen(name);
764     int suffixlen = strlen(suffix);
765 
766     if (filelen == (namelen + suffixlen) &&
767         STREQLEN(file, name, namelen) &&
768         STREQ(file + namelen, suffix))
769         return true;
770     else
771         return false;
772 }
773 
774 /**
775  * virStringStripIPv6Brackets:
776  * @str: the string to strip
777  *
778  * Modify the string in-place to remove the leading and closing brackets
779  * from an IPv6 address.
780  */
781 void
virStringStripIPv6Brackets(char * str)782 virStringStripIPv6Brackets(char *str)
783 {
784     size_t len;
785 
786     if (!str)
787         return;
788 
789     len = strlen(str);
790     if (str[0] == '[' && str[len - 1] == ']' && strchr(str, ':')) {
791         memmove(&str[0], &str[1], len - 2);
792         str[len - 2] = '\0';
793     }
794 }
795 
796 
797 /**
798  * virStringHasChars:
799  * @str: string to look for chars in
800  * @chars: chars to find in string @str
801  *
802  * Returns true if @str contains any of the chars in @chars.
803  */
804 bool
virStringHasChars(const char * str,const char * chars)805 virStringHasChars(const char *str,
806                   const char *chars)
807 {
808     if (!str)
809         return false;
810 
811     return str[strcspn(str, chars)] != '\0';
812 }
813 
814 
815 static const char control_chars[] =
816     "\x01\x02\x03\x04\x05\x06\x07"
817     "\x08" /* \t \n */ "\x0B\x0C" /* \r */ "\x0E\x0F"
818     "\x10\x11\x12\x13\x14\x15\x16\x17"
819     "\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";
820 
821 bool
virStringHasControlChars(const char * str)822 virStringHasControlChars(const char *str)
823 {
824     return virStringHasChars(str, control_chars);
825 }
826 
827 
828 /**
829  * virStringStripControlChars:
830  * @str: the string to strip
831  *
832  * Modify the string in-place to remove the control characters
833  * in the interval: [0x01, 0x20)
834  */
835 void
virStringStripControlChars(char * str)836 virStringStripControlChars(char *str)
837 {
838     size_t len, i, j;
839 
840     if (!str)
841         return;
842 
843     len = strlen(str);
844     for (i = 0, j = 0; i < len; i++) {
845         if (strchr(control_chars, str[i]))
846             continue;
847 
848         str[j++] = str[i];
849     }
850     str[j] = '\0';
851 }
852 
853 /**
854  * virStringFilterChars:
855  * @str: the string to strip
856  * @valid: the valid characters for the string
857  *
858  * Modify the string in-place to remove the characters that aren't
859  * in the list of valid ones.
860  */
861 void
virStringFilterChars(char * str,const char * valid)862 virStringFilterChars(char *str, const char *valid)
863 {
864     size_t len, i, j;
865 
866     if (!str)
867         return;
868 
869     len = strlen(str);
870     for (i = 0, j = 0; i < len; i++) {
871         if (strchr(valid, str[i]))
872             str[j++] = str[i];
873     }
874     str[j] = '\0';
875 }
876 
877 /**
878  * virStringToUpper:
879  * @src string to capitalize
880  * @dst: where to store the new capitalized string
881  *
882  * Capitalize the string with replacement of all '-' characters for '_'
883  * characters. Caller frees the result.
884  *
885  * Returns 0 if src is NULL, 1 if capitalization was successful, -1 on failure.
886  */
887 int
virStringToUpper(char ** dst,const char * src)888 virStringToUpper(char **dst, const char *src)
889 {
890     char *cap = NULL;
891     size_t i;
892 
893     if (!src)
894         return 0;
895 
896     cap = g_new0(char, strlen(src) + 1);
897 
898     for (i = 0; src[i]; i++) {
899         cap[i] = g_ascii_toupper(src[i]);
900         if (cap[i] == '-')
901             cap[i] = '_';
902     }
903 
904     *dst = cap;
905     return 1;
906 }
907 
908 
909 /**
910  * virStringIsPrintable:
911  *
912  * Returns true @str contains only printable characters.
913  */
914 bool
virStringIsPrintable(const char * str)915 virStringIsPrintable(const char *str)
916 {
917     size_t i;
918 
919     for (i = 0; str[i]; i++)
920         if (!g_ascii_isprint(str[i]))
921             return false;
922 
923     return true;
924 }
925 
926 
927 /**
928  * virBufferIsPrintable:
929  *
930  * Returns true if @buf of @buflen contains only printable characters
931  */
932 bool
virStringBufferIsPrintable(const uint8_t * buf,size_t buflen)933 virStringBufferIsPrintable(const uint8_t *buf,
934                            size_t buflen)
935 {
936     size_t i;
937 
938     for (i = 0; i < buflen; i++)
939         if (!g_ascii_isprint(buf[i]))
940             return false;
941 
942     return true;
943 }
944 
945 
946 /**
947  * virStringTrimOptionalNewline:
948  * @str: the string to modify in-place
949  *
950  * Modify @str to remove a single '\n' character
951  * from its end, if one exists.
952  */
virStringTrimOptionalNewline(char * str)953 void virStringTrimOptionalNewline(char *str)
954 {
955     size_t len = strlen(str);
956 
957     if (!len)
958         return;
959 
960     if (str[len - 1] == '\n')
961         str[len - 1] = '\0';
962 }
963 
964 
965 /**
966  * virStringParsePort:
967  * @str: port number to parse
968  * @port: pointer to parse port into
969  *
970  * Parses a string representation of a network port and validates it. Returns
971  * 0 on success and -1 on error.
972  */
973 int
virStringParsePort(const char * str,unsigned int * port)974 virStringParsePort(const char *str,
975                    unsigned int *port)
976 {
977     unsigned int p = 0;
978 
979     *port = 0;
980 
981     if (!str)
982         return 0;
983 
984     if (virStrToLong_uip(str, NULL, 10, &p) < 0) {
985         virReportError(VIR_ERR_INVALID_ARG,
986                        _("failed to parse port number '%s'"), str);
987         return -1;
988     }
989 
990     if (p > UINT16_MAX) {
991         virReportError(VIR_ERR_INVALID_ARG,
992                        _("port '%s' out of range"), str);
993         return -1;
994     }
995 
996     *port = p;
997 
998     return 0;
999 }
1000 
1001 
1002 /**
1003  * virStringParseYesNo:
1004  * @str: "yes|no" to parse, must not be NULL.
1005  * @result: pointer to the boolean result of @str conversion
1006  *
1007  * Parses a "yes|no" string and converts it into a boolean.
1008  *
1009  * Returns 0 on success and -1 on error.
1010  */
virStringParseYesNo(const char * str,bool * result)1011 int virStringParseYesNo(const char *str, bool *result)
1012 {
1013     if (STREQ(str, "yes"))
1014         *result = true;
1015     else if (STREQ(str, "no"))
1016         *result = false;
1017     else
1018         return -1;
1019 
1020     return 0;
1021 }
1022