Sync usage with man page.
[netbsd-mini2440.git] / external / gpl2 / lvm2 / dist / lib / misc / lvm-string.c
blob801e47c5fff13db46b42a03719c7036176577ccf
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU Lesser General Public License v.2.1.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #include "lib.h"
19 #include "lvm-string.h"
21 #include <ctype.h>
23 int emit_to_buffer(char **buffer, size_t *size, const char *fmt, ...)
25 int n;
26 va_list ap;
28 va_start(ap, fmt);
29 n = vsnprintf(*buffer, *size, fmt, ap);
30 va_end(ap);
32 if (n < 0 || ((size_t)n == *size))
33 return 0;
35 *buffer += n;
36 *size -= n;
37 return 1;
41 * Count occurences of 'c' in 'str' until we reach a null char.
43 * Returns:
44 * len - incremented for each char we encounter.
45 * count - number of occurrences of 'c' and 'c2'.
47 static void _count_chars(const char *str, size_t *len, int *count,
48 const int c1, const int c2)
50 const char *ptr;
52 for (ptr = str; *ptr; ptr++, (*len)++)
53 if (*ptr == c1 || *ptr == c2)
54 (*count)++;
58 * Count occurences of 'c' in 'str' of length 'size'.
60 * Returns:
61 * Number of occurrences of 'c'
63 unsigned count_chars(const char *str, size_t len, const int c)
65 size_t i;
66 unsigned count = 0;
68 for (i = 0; i < len; i++)
69 if (str[i] == c)
70 count++;
72 return count;
76 * Length of string after escaping double quotes and backslashes.
78 size_t escaped_len(const char *str)
80 size_t len = 1;
81 int count = 0;
83 _count_chars(str, &len, &count, '\"', '\\');
85 return count + len;
89 * Copies a string, quoting orig_char with quote_char.
90 * Optionally also quote quote_char.
92 static void _quote_characters(char **out, const char *src,
93 const int orig_char, const int quote_char,
94 int quote_quote_char)
96 while (*src) {
97 if (*src == orig_char ||
98 (*src == quote_char && quote_quote_char))
99 *(*out)++ = quote_char;
101 *(*out)++ = *src++;
106 * Unquote orig_char in string.
107 * Also unquote quote_char.
109 static void _unquote_characters(char *src, const int orig_char,
110 const int quote_char)
112 char *out = src;
114 while (*src) {
115 if (*src == quote_char &&
116 (*(src + 1) == orig_char || *(src + 1) == quote_char))
117 src++;
119 *out++ = *src++;
122 *out = '\0';
126 * Copies a string, quoting hyphens with hyphens.
128 static void _quote_hyphens(char **out, const char *src)
130 return _quote_characters(out, src, '-', '-', 0);
134 * <vg>-<lv>-<layer> or if !layer just <vg>-<lv>.
136 char *build_dm_name(struct dm_pool *mem, const char *vgname,
137 const char *lvname, const char *layer)
139 size_t len = 1;
140 int hyphens = 1;
141 char *r, *out;
143 _count_chars(vgname, &len, &hyphens, '-', 0);
144 _count_chars(lvname, &len, &hyphens, '-', 0);
146 if (layer && *layer) {
147 _count_chars(layer, &len, &hyphens, '-', 0);
148 hyphens++;
151 len += hyphens;
153 if (!(r = dm_pool_alloc(mem, len))) {
154 log_error("build_dm_name: Allocation failed for %" PRIsize_t
155 " for %s %s %s.", len, vgname, lvname, layer);
156 return NULL;
159 out = r;
160 _quote_hyphens(&out, vgname);
161 *out++ = '-';
162 _quote_hyphens(&out, lvname);
164 if (layer && *layer) {
165 /* No hyphen if the layer begins with _ e.g. _mlog */
166 if (*layer != '_')
167 *out++ = '-';
168 _quote_hyphens(&out, layer);
170 *out = '\0';
172 return r;
176 * Copies a string, quoting double quotes with backslashes.
178 char *escape_double_quotes(char *out, const char *src)
180 char *buf = out;
182 _quote_characters(&buf, src, '\"', '\\', 1);
183 *buf = '\0';
185 return out;
189 * Undo quoting in situ.
191 void unescape_double_quotes(char *src)
193 _unquote_characters(src, '\"', '\\');
197 * Device layer names are all of the form <vg>-<lv>-<layer>, any
198 * other hyphens that appear in these names are quoted with yet
199 * another hyphen. The top layer of any device has no layer
200 * name. eg, vg0-lvol0.
202 int validate_name(const char *n)
204 register char c;
205 register int len = 0;
207 if (!n || !*n)
208 return 0;
210 /* Hyphen used as VG-LV separator - ambiguity if LV starts with it */
211 if (*n == '-')
212 return 0;
214 if (!strcmp(n, ".") || !strcmp(n, ".."))
215 return 0;
217 while ((len++, c = *n++))
218 if (!isalnum(c) && c != '.' && c != '_' && c != '-' && c != '+')
219 return 0;
221 if (len > NAME_LEN)
222 return 0;
224 return 1;