xref: /dflybsd-src/contrib/lvm2/dist/libdm/libdm-string.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
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