Home | History | Annotate | Line # | Download | only in misc
lvm-string.c revision 1.1.1.1
      1  1.1  haad /*	$NetBSD: lvm-string.c,v 1.1.1.1 2008/12/22 00:18:13 haad Exp $	*/
      2  1.1  haad 
      3  1.1  haad /*
      4  1.1  haad  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
      5  1.1  haad  * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
      6  1.1  haad  *
      7  1.1  haad  * This file is part of LVM2.
      8  1.1  haad  *
      9  1.1  haad  * This copyrighted material is made available to anyone wishing to use,
     10  1.1  haad  * modify, copy, or redistribute it subject to the terms and conditions
     11  1.1  haad  * of the GNU Lesser General Public License v.2.1.
     12  1.1  haad  *
     13  1.1  haad  * You should have received a copy of the GNU Lesser General Public License
     14  1.1  haad  * along with this program; if not, write to the Free Software Foundation,
     15  1.1  haad  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     16  1.1  haad  */
     17  1.1  haad 
     18  1.1  haad #include "lib.h"
     19  1.1  haad #include "lvm-string.h"
     20  1.1  haad 
     21  1.1  haad #include <ctype.h>
     22  1.1  haad 
     23  1.1  haad int emit_to_buffer(char **buffer, size_t *size, const char *fmt, ...)
     24  1.1  haad {
     25  1.1  haad 	int n;
     26  1.1  haad 	va_list ap;
     27  1.1  haad 
     28  1.1  haad 	va_start(ap, fmt);
     29  1.1  haad 	n = vsnprintf(*buffer, *size, fmt, ap);
     30  1.1  haad 	va_end(ap);
     31  1.1  haad 
     32  1.1  haad 	if (n < 0 || ((size_t)n == *size))
     33  1.1  haad 		return 0;
     34  1.1  haad 
     35  1.1  haad 	*buffer += n;
     36  1.1  haad 	*size -= n;
     37  1.1  haad 	return 1;
     38  1.1  haad }
     39  1.1  haad 
     40  1.1  haad /*
     41  1.1  haad  * Count occurences of 'c' in 'str' until we reach a null char.
     42  1.1  haad  *
     43  1.1  haad  * Returns:
     44  1.1  haad  *  len - incremented for each char we encounter.
     45  1.1  haad  *  count - number of occurrences of 'c' and 'c2'.
     46  1.1  haad  */
     47  1.1  haad static void _count_chars(const char *str, size_t *len, int *count,
     48  1.1  haad 			 const int c1, const int c2)
     49  1.1  haad {
     50  1.1  haad 	const char *ptr;
     51  1.1  haad 
     52  1.1  haad 	for (ptr = str; *ptr; ptr++, (*len)++)
     53  1.1  haad 		if (*ptr == c1 || *ptr == c2)
     54  1.1  haad 			(*count)++;
     55  1.1  haad }
     56  1.1  haad 
     57  1.1  haad /*
     58  1.1  haad  * Count occurences of 'c' in 'str' of length 'size'.
     59  1.1  haad  *
     60  1.1  haad  * Returns:
     61  1.1  haad  *   Number of occurrences of 'c'
     62  1.1  haad  */
     63  1.1  haad unsigned count_chars(const char *str, size_t len, const int c)
     64  1.1  haad {
     65  1.1  haad 	size_t i;
     66  1.1  haad 	unsigned count = 0;
     67  1.1  haad 
     68  1.1  haad 	for (i = 0; i < len; i++)
     69  1.1  haad 		if (str[i] == c)
     70  1.1  haad 			count++;
     71  1.1  haad 
     72  1.1  haad 	return count;
     73  1.1  haad }
     74  1.1  haad 
     75  1.1  haad /*
     76  1.1  haad  * Length of string after escaping double quotes and backslashes.
     77  1.1  haad  */
     78  1.1  haad size_t escaped_len(const char *str)
     79  1.1  haad {
     80  1.1  haad 	size_t len = 1;
     81  1.1  haad 	int count = 0;
     82  1.1  haad 
     83  1.1  haad 	_count_chars(str, &len, &count, '\"', '\\');
     84  1.1  haad 
     85  1.1  haad 	return count + len;
     86  1.1  haad }
     87  1.1  haad 
     88  1.1  haad /*
     89  1.1  haad  * Copies a string, quoting orig_char with quote_char.
     90  1.1  haad  * Optionally also quote quote_char.
     91  1.1  haad  */
     92  1.1  haad static void _quote_characters(char **out, const char *src,
     93  1.1  haad 			      const int orig_char, const int quote_char,
     94  1.1  haad 			      int quote_quote_char)
     95  1.1  haad {
     96  1.1  haad 	while (*src) {
     97  1.1  haad 		if (*src == orig_char ||
     98  1.1  haad 		    (*src == quote_char && quote_quote_char))
     99  1.1  haad 			*(*out)++ = quote_char;
    100  1.1  haad 
    101  1.1  haad 		*(*out)++ = *src++;
    102  1.1  haad 	}
    103  1.1  haad }
    104  1.1  haad 
    105  1.1  haad /*
    106  1.1  haad  * Unquote orig_char in string.
    107  1.1  haad  * Also unquote quote_char.
    108  1.1  haad  */
    109  1.1  haad static void _unquote_characters(char *src, const int orig_char,
    110  1.1  haad 				const int quote_char)
    111  1.1  haad {
    112  1.1  haad 	char *out = src;
    113  1.1  haad 
    114  1.1  haad 	while (*src) {
    115  1.1  haad 		if (*src == quote_char &&
    116  1.1  haad 		    (*(src + 1) == orig_char || *(src + 1) == quote_char))
    117  1.1  haad 			src++;
    118  1.1  haad 
    119  1.1  haad 		*out++ = *src++;
    120  1.1  haad 	}
    121  1.1  haad 
    122  1.1  haad 	*out = '\0';
    123  1.1  haad }
    124  1.1  haad 
    125  1.1  haad /*
    126  1.1  haad  * Copies a string, quoting hyphens with hyphens.
    127  1.1  haad  */
    128  1.1  haad static void _quote_hyphens(char **out, const char *src)
    129  1.1  haad {
    130  1.1  haad 	return _quote_characters(out, src, '-', '-', 0);
    131  1.1  haad }
    132  1.1  haad 
    133  1.1  haad /*
    134  1.1  haad  * <vg>-<lv>-<layer> or if !layer just <vg>-<lv>.
    135  1.1  haad  */
    136  1.1  haad char *build_dm_name(struct dm_pool *mem, const char *vgname,
    137  1.1  haad 		    const char *lvname, const char *layer)
    138  1.1  haad {
    139  1.1  haad 	size_t len = 1;
    140  1.1  haad 	int hyphens = 1;
    141  1.1  haad 	char *r, *out;
    142  1.1  haad 
    143  1.1  haad 	_count_chars(vgname, &len, &hyphens, '-', 0);
    144  1.1  haad 	_count_chars(lvname, &len, &hyphens, '-', 0);
    145  1.1  haad 
    146  1.1  haad 	if (layer && *layer) {
    147  1.1  haad 		_count_chars(layer, &len, &hyphens, '-', 0);
    148  1.1  haad 		hyphens++;
    149  1.1  haad 	}
    150  1.1  haad 
    151  1.1  haad 	len += hyphens;
    152  1.1  haad 
    153  1.1  haad 	if (!(r = dm_pool_alloc(mem, len))) {
    154  1.1  haad 		log_error("build_dm_name: Allocation failed for %" PRIsize_t
    155  1.1  haad 			  " for %s %s %s.", len, vgname, lvname, layer);
    156  1.1  haad 		return NULL;
    157  1.1  haad 	}
    158  1.1  haad 
    159  1.1  haad 	out = r;
    160  1.1  haad 	_quote_hyphens(&out, vgname);
    161  1.1  haad 	*out++ = '-';
    162  1.1  haad 	_quote_hyphens(&out, lvname);
    163  1.1  haad 
    164  1.1  haad 	if (layer && *layer) {
    165  1.1  haad 		/* No hyphen if the layer begins with _ e.g. _mlog */
    166  1.1  haad 		if (*layer != '_')
    167  1.1  haad 			*out++ = '-';
    168  1.1  haad 		_quote_hyphens(&out, layer);
    169  1.1  haad 	}
    170  1.1  haad 	*out = '\0';
    171  1.1  haad 
    172  1.1  haad 	return r;
    173  1.1  haad }
    174  1.1  haad 
    175  1.1  haad /*
    176  1.1  haad  * Copies a string, quoting double quotes with backslashes.
    177  1.1  haad  */
    178  1.1  haad char *escape_double_quotes(char *out, const char *src)
    179  1.1  haad {
    180  1.1  haad 	char *buf = out;
    181  1.1  haad 
    182  1.1  haad 	_quote_characters(&buf, src, '\"', '\\', 1);
    183  1.1  haad 	*buf = '\0';
    184  1.1  haad 
    185  1.1  haad 	return out;
    186  1.1  haad }
    187  1.1  haad 
    188  1.1  haad /*
    189  1.1  haad  * Undo quoting in situ.
    190  1.1  haad  */
    191  1.1  haad void unescape_double_quotes(char *src)
    192  1.1  haad {
    193  1.1  haad 	_unquote_characters(src, '\"', '\\');
    194  1.1  haad }
    195  1.1  haad 
    196  1.1  haad /*
    197  1.1  haad  * Device layer names are all of the form <vg>-<lv>-<layer>, any
    198  1.1  haad  * other hyphens that appear in these names are quoted with yet
    199  1.1  haad  * another hyphen.  The top layer of any device has no layer
    200  1.1  haad  * name.  eg, vg0-lvol0.
    201  1.1  haad  */
    202  1.1  haad int validate_name(const char *n)
    203  1.1  haad {
    204  1.1  haad 	register char c;
    205  1.1  haad 	register int len = 0;
    206  1.1  haad 
    207  1.1  haad 	if (!n || !*n)
    208  1.1  haad 		return 0;
    209  1.1  haad 
    210  1.1  haad 	/* Hyphen used as VG-LV separator - ambiguity if LV starts with it */
    211  1.1  haad 	if (*n == '-')
    212  1.1  haad 		return 0;
    213  1.1  haad 
    214  1.1  haad 	if (!strcmp(n, ".") || !strcmp(n, ".."))
    215  1.1  haad 		return 0;
    216  1.1  haad 
    217  1.1  haad 	while ((len++, c = *n++))
    218  1.1  haad 		if (!isalnum(c) && c != '.' && c != '_' && c != '-' && c != '+')
    219  1.1  haad 			return 0;
    220  1.1  haad 
    221  1.1  haad 	if (len > NAME_LEN)
    222  1.1  haad 		return 0;
    223  1.1  haad 
    224  1.1  haad 	return 1;
    225  1.1  haad }
    226