145
144
va_start(ap, format);
146
145
n = vsnprintf(buf, size, format, ap);
149
148
if (0 <= n && n < size)
152
/* Up to glibc 2.0.6 returns -1 */
153
size = (n < 0) ? size * 2 : n + 1;
154
if (!(buf = dm_malloc(size)))
159
/* Reallocating more then once? */
160
if (!(*result = dm_strdup(buf))) {
154
buf = dm_malloc(size);
160
*result = dm_strdup(buf);
172
* Count occurences of 'c' in 'str' until we reach a null char.
175
* len - incremented for each char we encounter.
176
* count - number of occurrences of 'c' and 'c2'.
178
static void _count_chars(const char *str, size_t *len, int *count,
179
const int c1, const int c2)
183
for (ptr = str; *ptr; ptr++, (*len)++)
184
if (*ptr == c1 || *ptr == c2)
189
* Count occurrences of 'c' in 'str' of length 'size'.
192
* Number of occurrences of 'c'
194
unsigned dm_count_chars(const char *str, size_t len, const int c)
199
for (i = 0; i < len; i++)
207
* Length of string after escaping double quotes and backslashes.
209
size_t dm_escaped_len(const char *str)
214
_count_chars(str, &len, &count, '\"', '\\');
220
* Copies a string, quoting orig_char with quote_char.
221
* Optionally also quote quote_char.
223
static void _quote_characters(char **out, const char *src,
224
const int orig_char, const int quote_char,
225
int quote_quote_char)
228
if (*src == orig_char ||
229
(*src == quote_char && quote_quote_char))
230
*(*out)++ = quote_char;
236
static void _unquote_one_character(char *src, const char orig_char,
237
const char quote_char)
242
/* Optimise for the common case where no changes are needed. */
243
while ((s = *src++)) {
244
if (s == quote_char &&
245
((n = *src) == orig_char || n == quote_char)) {
249
while ((s = *src++)) {
250
if (s == quote_char &&
251
((n = *src) == orig_char || n == quote_char)) {
266
* Unquote each character given in orig_char array and unquote quote_char
267
* as well. Also save the first occurrence of each character from orig_char
268
* that was found unquoted in arr_substr_first_unquoted array. This way we can
269
* process several characters in one go.
271
static void _unquote_characters(char *src, const char *orig_chars,
272
size_t num_orig_chars,
273
const char quote_char,
274
char *arr_substr_first_unquoted[])
280
while ((s = *src++)) {
281
for (i = 0; i < num_orig_chars; i++) {
283
if (s == quote_char &&
284
((n = *src) == c || n == quote_char)) {
289
if (arr_substr_first_unquoted && (s == c) &&
290
!arr_substr_first_unquoted[i])
291
arr_substr_first_unquoted[i] = out;
300
* Copies a string, quoting hyphens with hyphens.
302
static void _quote_hyphens(char **out, const char *src)
304
_quote_characters(out, src, '-', '-', 0);
308
* <vg>-<lv>-<layer> or if !layer just <vg>-<lv>.
310
char *dm_build_dm_name(struct dm_pool *mem, const char *vgname,
311
const char *lvname, const char *layer)
317
_count_chars(vgname, &len, &hyphens, '-', 0);
318
_count_chars(lvname, &len, &hyphens, '-', 0);
320
if (layer && *layer) {
321
_count_chars(layer, &len, &hyphens, '-', 0);
327
if (!(r = dm_pool_alloc(mem, len))) {
328
log_error("build_dm_name: Allocation failed for %" PRIsize_t
329
" for %s %s %s.", len, vgname, lvname, layer);
334
_quote_hyphens(&out, vgname);
336
_quote_hyphens(&out, lvname);
338
if (layer && *layer) {
339
/* No hyphen if the layer begins with _ e.g. _mlog */
342
_quote_hyphens(&out, layer);
349
char *dm_build_dm_uuid(struct dm_pool *mem, const char *uuid_prefix, const char *lvid, const char *layer)
357
len = strlen(uuid_prefix) + strlen(lvid) + strlen(layer) + 2;
359
if (!(dmuuid = dm_pool_alloc(mem, len))) {
360
log_error("build_dm_name: Allocation failed for %" PRIsize_t
361
" %s %s.", len, lvid, layer);
365
sprintf(dmuuid, "%s%s%s%s", uuid_prefix, lvid, (*layer) ? "-" : "", layer);
371
* Copies a string, quoting double quotes with backslashes.
373
char *dm_escape_double_quotes(char *out, const char *src)
377
_quote_characters(&buf, src, '\"', '\\', 1);
384
* Undo quoting in situ.
386
void dm_unescape_double_quotes(char *src)
388
_unquote_one_character(src, '\"', '\\');
392
* Unescape colons and "at" signs in situ and save the substrings
393
* starting at the position of the first unescaped colon and the
394
* first unescaped "at" sign. This is normally used to unescape
395
* device names used as PVs.
397
void dm_unescape_colons_and_at_signs(char *src,
398
char **substr_first_unquoted_colon,
399
char **substr_first_unquoted_at_sign)
401
const char *orig_chars = ":@";
402
char *arr_substr_first_unquoted[] = {NULL, NULL, NULL};
404
_unquote_characters(src, orig_chars, 2, '\\', arr_substr_first_unquoted);
406
if (substr_first_unquoted_colon)
407
*substr_first_unquoted_colon = arr_substr_first_unquoted[0];
409
if (substr_first_unquoted_at_sign)
410
*substr_first_unquoted_at_sign = arr_substr_first_unquoted[1];
413
int dm_strncpy(char *dest, const char *src, size_t n)
415
if (memccpy(dest, src, 0, n))