186d7f5d3SJohn Marino /* $NetBSD: libdm-string.c,v 1.1.1.2 2009/12/02 00:26:08 haad Exp $ */
286d7f5d3SJohn Marino
386d7f5d3SJohn Marino /*
486d7f5d3SJohn Marino * Copyright (C) 2006-2007 Red Hat, Inc. All rights reserved.
586d7f5d3SJohn Marino *
686d7f5d3SJohn Marino * This file is part of the device-mapper userspace tools.
786d7f5d3SJohn Marino *
886d7f5d3SJohn Marino * This copyrighted material is made available to anyone wishing to use,
986d7f5d3SJohn Marino * modify, copy, or redistribute it subject to the terms and conditions
1086d7f5d3SJohn Marino * of the GNU Lesser General Public License v.2.1.
1186d7f5d3SJohn Marino *
1286d7f5d3SJohn Marino * You should have received a copy of the GNU Lesser General Public License
1386d7f5d3SJohn Marino * along with this program; if not, write to the Free Software Foundation,
1486d7f5d3SJohn Marino * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1586d7f5d3SJohn Marino */
1686d7f5d3SJohn Marino
1786d7f5d3SJohn Marino #include "dmlib.h"
1886d7f5d3SJohn Marino #include "libdevmapper.h"
1986d7f5d3SJohn Marino
2086d7f5d3SJohn Marino #include <ctype.h>
2186d7f5d3SJohn Marino
2286d7f5d3SJohn Marino /*
2386d7f5d3SJohn Marino * consume characters while they match the predicate function.
2486d7f5d3SJohn Marino */
_consume(char * buffer,int (* fn)(int))2586d7f5d3SJohn Marino static char *_consume(char *buffer, int (*fn) (int))
2686d7f5d3SJohn Marino {
2786d7f5d3SJohn Marino while (*buffer && fn(*buffer))
2886d7f5d3SJohn Marino buffer++;
2986d7f5d3SJohn Marino
3086d7f5d3SJohn Marino return buffer;
3186d7f5d3SJohn Marino }
3286d7f5d3SJohn Marino
_isword(int c)3386d7f5d3SJohn Marino static int _isword(int c)
3486d7f5d3SJohn Marino {
3586d7f5d3SJohn Marino return !isspace(c);
3686d7f5d3SJohn Marino }
3786d7f5d3SJohn Marino
3886d7f5d3SJohn Marino /*
3986d7f5d3SJohn Marino * Split buffer into NULL-separated words in argv.
4086d7f5d3SJohn Marino * Returns number of words.
4186d7f5d3SJohn Marino */
dm_split_words(char * buffer,unsigned max,unsigned ignore_comments __attribute ((unused)),char ** argv)4286d7f5d3SJohn Marino int dm_split_words(char *buffer, unsigned max,
4386d7f5d3SJohn Marino unsigned ignore_comments __attribute((unused)),
4486d7f5d3SJohn Marino char **argv)
4586d7f5d3SJohn Marino {
4686d7f5d3SJohn Marino unsigned arg;
4786d7f5d3SJohn Marino
4886d7f5d3SJohn Marino for (arg = 0; arg < max; arg++) {
4986d7f5d3SJohn Marino buffer = _consume(buffer, isspace);
5086d7f5d3SJohn Marino if (!*buffer)
5186d7f5d3SJohn Marino break;
5286d7f5d3SJohn Marino
5386d7f5d3SJohn Marino argv[arg] = buffer;
5486d7f5d3SJohn Marino buffer = _consume(buffer, _isword);
5586d7f5d3SJohn Marino
5686d7f5d3SJohn Marino if (*buffer) {
5786d7f5d3SJohn Marino *buffer = '\0';
5886d7f5d3SJohn Marino buffer++;
5986d7f5d3SJohn Marino }
6086d7f5d3SJohn Marino }
6186d7f5d3SJohn Marino
6286d7f5d3SJohn Marino return arg;
6386d7f5d3SJohn Marino }
6486d7f5d3SJohn Marino
6586d7f5d3SJohn Marino /*
6686d7f5d3SJohn Marino * Remove hyphen quoting from a component of a name.
6786d7f5d3SJohn Marino * NULL-terminates the component and returns start of next component.
6886d7f5d3SJohn Marino */
_unquote(char * component)6986d7f5d3SJohn Marino static char *_unquote(char *component)
7086d7f5d3SJohn Marino {
7186d7f5d3SJohn Marino char *c = component;
7286d7f5d3SJohn Marino char *o = c;
7386d7f5d3SJohn Marino char *r;
7486d7f5d3SJohn Marino
7586d7f5d3SJohn Marino while (*c) {
7686d7f5d3SJohn Marino if (*(c + 1)) {
7786d7f5d3SJohn Marino if (*c == '-') {
7886d7f5d3SJohn Marino if (*(c + 1) == '-')
7986d7f5d3SJohn Marino c++;
8086d7f5d3SJohn Marino else
8186d7f5d3SJohn Marino break;
8286d7f5d3SJohn Marino }
8386d7f5d3SJohn Marino }
8486d7f5d3SJohn Marino *o = *c;
8586d7f5d3SJohn Marino o++;
8686d7f5d3SJohn Marino c++;
8786d7f5d3SJohn Marino }
8886d7f5d3SJohn Marino
8986d7f5d3SJohn Marino r = (*c) ? c + 1 : c;
9086d7f5d3SJohn Marino *o = '\0';
9186d7f5d3SJohn Marino
9286d7f5d3SJohn Marino return r;
9386d7f5d3SJohn Marino }
9486d7f5d3SJohn Marino
dm_split_lvm_name(struct dm_pool * mem,const char * dmname,char ** vgname,char ** lvname,char ** layer)9586d7f5d3SJohn Marino int dm_split_lvm_name(struct dm_pool *mem, const char *dmname,
9686d7f5d3SJohn Marino char **vgname, char **lvname, char **layer)
9786d7f5d3SJohn Marino {
9886d7f5d3SJohn Marino if (mem && !(*vgname = dm_pool_strdup(mem, dmname)))
9986d7f5d3SJohn Marino return 0;
10086d7f5d3SJohn Marino
10186d7f5d3SJohn Marino _unquote(*layer = _unquote(*lvname = _unquote(*vgname)));
10286d7f5d3SJohn Marino
10386d7f5d3SJohn Marino return 1;
10486d7f5d3SJohn Marino }
10586d7f5d3SJohn Marino
10686d7f5d3SJohn Marino /*
10786d7f5d3SJohn Marino * On error, up to glibc 2.0.6, snprintf returned -1 if buffer was too small;
10886d7f5d3SJohn Marino * From glibc 2.1 it returns number of chars (excl. trailing null) that would
10986d7f5d3SJohn Marino * have been written had there been room.
11086d7f5d3SJohn Marino *
11186d7f5d3SJohn Marino * dm_snprintf reverts to the old behaviour.
11286d7f5d3SJohn Marino */
dm_snprintf(char * buf,size_t bufsize,const char * format,...)11386d7f5d3SJohn Marino int dm_snprintf(char *buf, size_t bufsize, const char *format, ...)
11486d7f5d3SJohn Marino {
11586d7f5d3SJohn Marino int n;
11686d7f5d3SJohn Marino va_list ap;
11786d7f5d3SJohn Marino
11886d7f5d3SJohn Marino va_start(ap, format);
11986d7f5d3SJohn Marino n = vsnprintf(buf, bufsize, format, ap);
12086d7f5d3SJohn Marino va_end(ap);
12186d7f5d3SJohn Marino
12286d7f5d3SJohn Marino if (n < 0 || ((unsigned) n + 1 > bufsize))
12386d7f5d3SJohn Marino return -1;
12486d7f5d3SJohn Marino
12586d7f5d3SJohn Marino return n;
12686d7f5d3SJohn Marino }
12786d7f5d3SJohn Marino
dm_basename(const char * path)12886d7f5d3SJohn Marino char *dm_basename(const char *path)
12986d7f5d3SJohn Marino {
13086d7f5d3SJohn Marino char *p = strrchr(path, '/');
13186d7f5d3SJohn Marino
13286d7f5d3SJohn Marino return p ? p + 1 : (char *) path;
13386d7f5d3SJohn Marino }
13486d7f5d3SJohn Marino
dm_asprintf(char ** result,const char * format,...)13586d7f5d3SJohn Marino int dm_asprintf(char **result, const char *format, ...)
13686d7f5d3SJohn Marino {
13786d7f5d3SJohn Marino int n, ok = 0, size = 32;
13886d7f5d3SJohn Marino va_list ap;
13986d7f5d3SJohn Marino char *buf = dm_malloc(size);
14086d7f5d3SJohn Marino
14186d7f5d3SJohn Marino *result = 0;
14286d7f5d3SJohn Marino
14386d7f5d3SJohn Marino if (!buf)
14486d7f5d3SJohn Marino return -1;
14586d7f5d3SJohn Marino
14686d7f5d3SJohn Marino while (!ok) {
14786d7f5d3SJohn Marino va_start(ap, format);
14886d7f5d3SJohn Marino n = vsnprintf(buf, size, format, ap);
14986d7f5d3SJohn Marino if (0 <= n && n < size)
15086d7f5d3SJohn Marino ok = 1;
15186d7f5d3SJohn Marino else {
15286d7f5d3SJohn Marino dm_free(buf);
15386d7f5d3SJohn Marino size *= 2;
15486d7f5d3SJohn Marino buf = dm_malloc(size);
15586d7f5d3SJohn Marino if (!buf)
15686d7f5d3SJohn Marino return -1;
15786d7f5d3SJohn Marino };
15886d7f5d3SJohn Marino va_end(ap);
15986d7f5d3SJohn Marino }
16086d7f5d3SJohn Marino
16186d7f5d3SJohn Marino *result = dm_strdup(buf);
16286d7f5d3SJohn Marino dm_free(buf);
16386d7f5d3SJohn Marino return n + 1;
16486d7f5d3SJohn Marino }
165