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