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