diff options
Diffstat (limited to 'libglusterfs/src/common-utils.c')
| -rw-r--r-- | libglusterfs/src/common-utils.c | 1349 | 
1 files changed, 1349 insertions, 0 deletions
diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c new file mode 100644 index 000000000..616c7a8ce --- /dev/null +++ b/libglusterfs/src/common-utils.c @@ -0,0 +1,1349 @@ +/* +  Copyright (c) 2006, 2007, 2008 Z RESEARCH, Inc. <http://www.zresearch.com> +  This file is part of GlusterFS. + +  GlusterFS is free software; you can redistribute it and/or modify +  it under the terms of the GNU General Public License as published +  by the Free Software Foundation; either version 3 of the License, +  or (at your option) any later version. + +  GlusterFS is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  General Public License for more details. + +  You should have received a copy of the GNU General Public License +  along with this program.  If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_BACKTRACE +#include <execinfo.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <unistd.h> +#include <time.h> +#include <locale.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <signal.h> + +#include "logging.h" +#include "common-utils.h" +#include "revision.h" +#include "glusterfs.h" +#include "stack.h" + +typedef int32_t (*rw_op_t)(int32_t fd, char *buf, int32_t size); +typedef int32_t (*rwv_op_t)(int32_t fd, const struct iovec *buf, int32_t size); +static glusterfs_ctx_t *gf_global_ctx; + + +struct dnscache6 { +	struct addrinfo *first; +	struct addrinfo *next; +}; + +int32_t +gf_resolve_ip6 (const char *hostname,  +		uint16_t port,  +		int family,  +		void **dnscache,  +		struct addrinfo **addr_info) +{ +	int32_t ret = 0; +	struct addrinfo hints; +	struct dnscache6 *cache = NULL; +	char service[NI_MAXSERV], host[NI_MAXHOST]; + +	if (!hostname) { +		gf_log ("resolver", GF_LOG_WARNING, "hostname is NULL"); +		return -1; +	} + +	if (!*dnscache) { +		*dnscache = CALLOC (1, sizeof (struct dnscache6)); +	} + +	cache = *dnscache; +	if (cache->first && !cache->next) { +		freeaddrinfo(cache->first); +		cache->first = cache->next = NULL; +		gf_log ("resolver", GF_LOG_DEBUG, +			"flushing DNS cache"); +	} + +	if (!cache->first) { +		char *port_str = NULL; +		gf_log ("resolver", GF_LOG_DEBUG, +			"DNS cache not present, freshly probing hostname: %s", +			hostname); + +		memset(&hints, 0, sizeof(hints)); +		hints.ai_family   = family; +		hints.ai_socktype = SOCK_STREAM; +		hints.ai_flags    = AI_ADDRCONFIG; + +		asprintf (&port_str, "%d", port); +		if ((ret = getaddrinfo(hostname, port_str, &hints, &cache->first)) != 0) { +			gf_log ("resolver", GF_LOG_ERROR, +				"getaddrinfo failed (%s)", gai_strerror (ret)); + +			free (*dnscache); +			*dnscache = NULL; +			free (port_str); +			return -1; +		} +		free (port_str); + +		cache->next = cache->first; +	} + +	if (cache->next) { +		ret = getnameinfo((struct sockaddr *)cache->next->ai_addr, +				  cache->next->ai_addrlen, +				  host, sizeof (host), +				  service, sizeof (service), +				  NI_NUMERICHOST); +		if (ret != 0) { +			gf_log ("resolver", +				GF_LOG_ERROR, +				"getnameinfo failed (%s)", gai_strerror (ret)); +			goto err; +		} + +		gf_log ("resolver", GF_LOG_DEBUG, +			"returning ip-%s (port-%s) for hostname: %s and port: %d", +			host, service, hostname, port); + +		*addr_info = cache->next; +	} + +	cache->next = cache->next->ai_next; +	if (cache->next) { +		ret = getnameinfo((struct sockaddr *)cache->next->ai_addr, +				  cache->next->ai_addrlen, +				  host, sizeof (host), +				  service, sizeof (service), +				  NI_NUMERICHOST); +		if (ret != 0) { +			gf_log ("resolver", +				GF_LOG_ERROR, +				"getnameinfo failed (%s)", gai_strerror (ret)); +			goto err; +		} + +		gf_log ("resolver", GF_LOG_DEBUG, +			"next DNS query will return: ip-%s port-%s", host, service); +	} + +	return 0; + +err: +	freeaddrinfo (cache->first); +	cache->first = cache->next = NULL; +	free (cache); +	*dnscache = NULL; +	return -1; +} + +char *gf_fop_list[GF_FOP_MAXVALUE]; +char *gf_mop_list[GF_MOP_MAXVALUE]; +char *gf_cbk_list[GF_CBK_MAXVALUE]; + +void +gf_global_variable_init() +{ +	gf_fop_list[GF_FOP_STAT]        = "STAT";       /* 0 */ +	gf_fop_list[GF_FOP_READLINK]    = "READLINK";   /* 1 */ +	gf_fop_list[GF_FOP_MKNOD]       = "MKNOD";      /* 2 */ +	gf_fop_list[GF_FOP_MKDIR]       = "MKDIR"; +	gf_fop_list[GF_FOP_UNLINK]      = "UNLINK"; +	gf_fop_list[GF_FOP_RMDIR]       = "RMDIR";      /* 5 */ +	gf_fop_list[GF_FOP_SYMLINK]     = "SYMLINK"; +	gf_fop_list[GF_FOP_RENAME]      = "RENAME"; +	gf_fop_list[GF_FOP_LINK]        = "LINK"; +	gf_fop_list[GF_FOP_CHMOD]       = "CHMOD"; +	gf_fop_list[GF_FOP_CHOWN]       = "CHOWN";      /* 10 */ +	gf_fop_list[GF_FOP_TRUNCATE]    = "TRUNCATE"; +	gf_fop_list[GF_FOP_OPEN]        = "OPEN"; +	gf_fop_list[GF_FOP_READ]        = "READ"; +	gf_fop_list[GF_FOP_WRITE]       = "WRITE"; +	gf_fop_list[GF_FOP_STATFS]      = "STATFS";     /* 15 */ +	gf_fop_list[GF_FOP_FLUSH]       = "FLUSH"; +	gf_fop_list[GF_FOP_FSYNC]       = "FSYNC"; +	gf_fop_list[GF_FOP_SETXATTR]    = "SETXATTR"; +	gf_fop_list[GF_FOP_GETXATTR]    = "GETXATTR";   /* 20 */ +	gf_fop_list[GF_FOP_REMOVEXATTR] = "REMOVEXATTR"; +	gf_fop_list[GF_FOP_OPENDIR]     = "OPENDIR"; +	gf_fop_list[GF_FOP_GETDENTS]    = "GETDENTS"; +	gf_fop_list[GF_FOP_FSYNCDIR]    = "FSYNCDIR";   /* 25 */ +	gf_fop_list[GF_FOP_ACCESS]      = "ACCESS"; +	gf_fop_list[GF_FOP_CREATE]      = "CREATE"; +	gf_fop_list[GF_FOP_FTRUNCATE]   = "FTRUNCATE"; +	gf_fop_list[GF_FOP_FSTAT]       = "FSTAT"; +	gf_fop_list[GF_FOP_LK]          = "LK";         /* 30 */ +	gf_fop_list[GF_FOP_UTIMENS]     = "UTIMENS"; +	gf_fop_list[GF_FOP_FCHMOD]      = "FCHMOD"; +	gf_fop_list[GF_FOP_FCHOWN]      = "FCHOWN"; +	gf_fop_list[GF_FOP_LOOKUP]      = "LOOKUP"; +	gf_fop_list[GF_FOP_SETDENTS]    = "SETDENTS";   /* 35 */ +	gf_fop_list[GF_FOP_READDIR]     = "READDIR"; +	gf_fop_list[GF_FOP_INODELK]     = "INODELK"; +	gf_fop_list[GF_FOP_FINODELK]    = "FINODELK";       +	gf_fop_list[GF_FOP_ENTRYLK]     = "ENTRYLK"; +	gf_fop_list[GF_FOP_FENTRYLK]    = "FENTRYLK";   /* 40 */ +	gf_fop_list[GF_FOP_CHECKSUM]    = "CHECKSUM";   /* 41 */    +	gf_fop_list[GF_FOP_XATTROP]     = "XATTROP"; + +	gf_mop_list[GF_MOP_SETVOLUME]   = "SETVOLUME"; /* 0 */ +	gf_mop_list[GF_MOP_GETVOLUME]   = "GETVOLUME"; /* 1 */ +	gf_mop_list[GF_MOP_STATS]       = "STATS"; +	gf_mop_list[GF_MOP_SETSPEC]     = "SETSPEC"; +	gf_mop_list[GF_MOP_GETSPEC]     = "GETSPEC"; +	 +	gf_cbk_list[GF_CBK_FORGET]      = "FORGET"; +	gf_cbk_list[GF_CBK_RELEASE]     = "RELEASE"; +	gf_cbk_list[GF_CBK_RELEASEDIR]  = "RELEASEDIR"; +	/* Are there any more variables to be included? All global  +	   variables initialization should go here */ + +	return; +} + +void  +set_global_ctx_ptr (glusterfs_ctx_t *ctx) +{ +	gf_global_ctx = ctx; +} + +glusterfs_ctx_t * +get_global_ctx_ptr (void) +{ +	return gf_global_ctx; +} + +void  +gf_log_volume_file (FILE *specfp) +{ +	extern FILE *gf_log_logfile; +	int          lcount = 0; +	char         data[GF_UNIT_KB]; +	 +	fseek (specfp, 0L, SEEK_SET); +	 +	fprintf (gf_log_logfile, "Given volfile:\n"); +	fprintf (gf_log_logfile,  +		 "+---------------------------------------" +		 "---------------------------------------+\n"); +	while (!feof (specfp)) { +		if (fgets (data, GF_UNIT_KB, specfp) == NULL) +			break; +		lcount++; +		fprintf (gf_log_logfile, "%3d: %s", lcount, data); +	} +	fprintf (gf_log_logfile,  +		 "\n+---------------------------------------" +		 "---------------------------------------+\n"); +	fflush (gf_log_logfile); +	fseek (specfp, 0L, SEEK_SET); +} + +static void  +gf_dump_config_flags (int fd) +{ + +	write (fd, "configuration details:\n", 22); + +/* have argp */ +#ifdef HAVE_ARGP +	write (fd, "argp 1\n", 7); +#endif + +/* ifdef if found backtrace */ +#ifdef HAVE_BACKTRACE  +	write (fd, "backtrace 1\n", 12); +#endif + +/* Berkeley-DB version has cursor->get() */ +#ifdef HAVE_BDB_CURSOR_GET  +	write (fd, "bdb->cursor->get 1\n", 19); +#endif + +/* Define to 1 if you have the <db.h> header file. */ +#ifdef HAVE_DB_H  +	write (fd, "db.h 1\n", 7); +#endif + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#ifdef HAVE_DLFCN_H  +	write (fd, "dlfcn 1\n", 8); +#endif + +/* define if fdatasync exists */ +#ifdef HAVE_FDATASYNC  +	write (fd, "fdatasync 1\n", 12); +#endif + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#ifdef HAVE_LIBPTHREAD  +	write (fd, "libpthread 1\n", 13); +#endif + +/* define if llistxattr exists */ +#ifdef HAVE_LLISTXATTR  +	write (fd, "llistxattr 1\n", 13); +#endif + +/* define if found setfsuid setfsgid */ +#ifdef HAVE_SET_FSID  +	write (fd, "setfsid 1\n", 10); +#endif + +/* define if found spinlock */ +#ifdef HAVE_SPINLOCK  +	write (fd, "spinlock 1\n", 11); +#endif + +/* Define to 1 if you have the <sys/epoll.h> header file. */ +#ifdef HAVE_SYS_EPOLL_H  +	write (fd, "epoll.h 1\n", 10); +#endif + +/* Define to 1 if you have the <sys/extattr.h> header file. */ +#ifdef HAVE_SYS_EXTATTR_H  +	write (fd, "extattr.h 1\n", 12); +#endif + +/* Define to 1 if you have the <sys/xattr.h> header file. */ +#ifdef HAVE_SYS_XATTR_H  +	write (fd, "xattr.h 1\n", 10); +#endif + +/* define if found st_atim.tv_nsec */ +#ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC +	write (fd, "st_atim.tv_nsec 1\n", 18); +#endif + +/* define if found st_atimespec.tv_nsec */ +#ifdef HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC +	write (fd, "st_atimespec.tv_nsec 1\n",23); +#endif + +/* Define to the full name and version of this package. */ +#ifdef PACKAGE_STRING  +	{ +		char msg[128]; +		sprintf (msg, "package-string: %s\n", PACKAGE_STRING);  +		write (fd, msg, strlen (msg)); +	} +#endif + +	return; +} + +/* Obtain a backtrace and print it to stdout. */ +/* TODO: It looks like backtrace_symbols allocates memory, +   it may be problem because mostly memory allocation/free causes 'sigsegv' */ +void +gf_print_trace (int32_t signum) +{ +	extern FILE *gf_log_logfile; +	int fd = fileno (gf_log_logfile); +	char msg[1024]; + + +	/* Pending frames, (if any), list them in order */ +	write (fd, "pending frames:\n", 16); +	{ +		extern glusterfs_ctx_t *gf_global_ctx; +		glusterfs_ctx_t *ctx = gf_global_ctx; +		struct list_head *trav = ((call_pool_t *)ctx->pool)->all_frames.next; +		while (trav != (&((call_pool_t *)ctx->pool)->all_frames)) { +			call_frame_t *tmp = (call_frame_t *)(&((call_stack_t *)trav)->frames); +			if ((tmp->root->type == GF_OP_TYPE_FOP_REQUEST) || +			    (tmp->root->type == GF_OP_TYPE_FOP_REPLY)) +				sprintf (msg,"frame : type(%d) op(%s)\n", +					 tmp->root->type,  +					 gf_fop_list[tmp->root->op]); +			if ((tmp->root->type == GF_OP_TYPE_MOP_REQUEST) || +			    (tmp->root->type == GF_OP_TYPE_MOP_REPLY)) +				sprintf (msg,"frame : type(%d) op(%s)\n", +					 tmp->root->type,  +					 gf_mop_list[tmp->root->op]); +			if ((tmp->root->type == GF_OP_TYPE_CBK_REQUEST) || +			    (tmp->root->type == GF_OP_TYPE_CBK_REPLY)) +				sprintf (msg,"frame : type(%d) op(%s)\n", +					 tmp->root->type,  +					 gf_cbk_list[tmp->root->op]); +			 +			write (fd, msg, strlen (msg)); +			trav = trav->next; +		} +		write (fd, "\n", 1); +	} + +	sprintf (msg, "patchset: %s\n", GLUSTERFS_REPOSITORY_REVISION);  +	write (fd, msg, strlen (msg)); + +	sprintf (msg, "signal received: %d\n", signum);  +	write (fd, msg, strlen (msg)); + +	gf_dump_config_flags (fd); +#if HAVE_BACKTRACE +	/* Print 'backtrace' */ +	{ +		void *array[200]; +		size_t size; +     +		size = backtrace (array, 200); +		backtrace_symbols_fd (&array[1], size-1, fd); +		sprintf (msg, "---------\n"); +		write (fd, msg, strlen (msg)); +	} +#endif /* HAVE_BACKTRACE */ +   +	/* Send a signal to terminate the process */ +	signal (signum, SIG_DFL); +	raise (signum); +} + +void +trap (void) +{ + +} + +char * +gf_trim (char *string) +{ +	register char *s, *t; +   +	if (string == NULL) +	{ +		return NULL; +	} +   +	for (s = string; isspace (*s); s++) +		; +   +	if (*s == 0) +		return s; +   +	t = s + strlen (s) - 1; +	while (t > s && isspace (*t)) +		t--; +	*++t = '\0'; +   +	return s; +} + +int  +gf_strsplit (const char *str, const char *delim,  +	     char ***tokens, int *token_count) +{ +	char *_running = NULL; +	char *running = NULL; +	char *token = NULL; +	char **token_list = NULL; +	int count = 0; +	int i = 0; +	int j = 0; +   +	if (str == NULL || delim == NULL || tokens == NULL || token_count == NULL) +	{ +		return -1; +	} +   +	if ((_running = strdup (str)) == NULL) +	{ +		return -1; +	} +	running = _running; +   +	while ((token = strsep (&running, delim)) != NULL) +	{ +		if (token[0] != '\0') +			count++; +	} +	free (_running); +   +	if ((_running = strdup (str)) == NULL) +	{ +		return -1; +	} +	running = _running; +   +	if ((token_list = CALLOC (count, sizeof (char *))) == NULL) +	{ +		free (_running); +		return -1; +	} +   +	while ((token = strsep (&running, delim)) != NULL) +	{ +		if (token[0] == '\0') +			continue; +       +		if ((token_list[i++] = strdup (token)) == NULL) +			goto free_exit; +	} +   +	free (_running); +   +	*tokens = token_list; +	*token_count = count; +	return 0; +   +free_exit: +	free (_running); +	for (j = 0; j < i; j++) +	{ +		free (token_list[j]); +	} +	free (token_list); +	return -1; +} + +int  +gf_volume_name_validate (const char *volume_name) +{ +	const char *vname = NULL; +   +	if (volume_name == NULL) +	{ +		return -1; +	} +   +	if (!isalpha (volume_name[0])) +	{ +		return 1; +	} +   +	for (vname = &volume_name[1]; *vname != '\0'; vname++) +	{ +		if (!(isalnum (*vname) || *vname == '_')) +			return 1; +	} +   +	return 0; +} + + +int  +gf_string2time (const char *str, uint32_t *n) +{ +	unsigned long value = 0; +	char *tail = NULL; +	int old_errno = 0; +	const char *s = NULL; +   +	if (str == NULL || n == NULL) +	{ +		errno = EINVAL; +		return -1; +	} +   +	for (s = str; *s != '\0'; s++) +	{ +		if (isspace (*s)) +		{ +			continue; +		} +		if (*s == '-') +		{ +			return -1; +		} +		break; +	} +   +	old_errno = errno; +	errno = 0; +	value = strtol (str, &tail, 0); +   +	if (errno == ERANGE || errno == EINVAL) +	{ +		return -1; +	} +   +	if (errno == 0) +	{ +		errno = old_errno; +	} +   +	if (!((tail[0] == '\0') ||  +	      ((tail[0] == 's') && (tail[1] == '\0')) || +	      ((tail[0] == 's') && (tail[1] == 'e') && (tail[2] == 'c') && (tail[3] == '\0')))) +	{ +		return -1; +	} +   +	*n = value; +   +	return 0; +} + + +int  +gf_string2percent (const char *str, uint32_t *n) +{ +	unsigned long value = 0; +	char *tail = NULL; +	int old_errno = 0; +	const char *s = NULL; +   +	if (str == NULL || n == NULL) +	{ +		errno = EINVAL; +		return -1; +	} +   +	for (s = str; *s != '\0'; s++) +	{ +		if (isspace (*s)) +		{ +			continue; +		} +		if (*s == '-') +		{ +			return -1; +		} +		break; +	} +   +	old_errno = errno; +	errno = 0; +	value = strtol (str, &tail, 0); +   +	if (errno == ERANGE || errno == EINVAL) +	{ +		return -1; +	} +   +	if (errno == 0) +	{ +		errno = old_errno; +	} +   +	if (!((tail[0] == '\0') ||  +	      ((tail[0] == '%') && (tail[1] == '\0')))) +	{ +		return -1; +	} +   +	*n = value; +   +	return 0; +} + + +static int  +_gf_string2long (const char *str, long *n, int base) +{ +	long value = 0; +	char *tail = NULL; +	int old_errno = 0; +   +	if (str == NULL || n == NULL) +	{ +		errno = EINVAL; +		return -1; +	} +   +	old_errno = errno; +	errno = 0; +	value = strtol (str, &tail, base); +   +	if (errno == ERANGE || errno == EINVAL) +	{ +		return -1; +	} +   +	if (errno == 0) +	{ +		errno = old_errno; +	} + +	if (tail[0] != '\0') +	{ +		/* bala: invalid integer format */ +		return -1; +	} +   +	*n = value; +   +	return 0; +} + +static int  +_gf_string2ulong (const char *str, unsigned long *n, int base) +{ +	unsigned long value = 0; +	char *tail = NULL; +	int old_errno = 0; +	const char *s = NULL; +   +	if (str == NULL || n == NULL) +	{ +		errno = EINVAL; +		return -1; +	} +   +	for (s = str; *s != '\0'; s++) +	{ +		if (isspace (*s)) +		{ +			continue; +		} +		if (*s == '-') +		{ +			/* bala: we do not support suffixed (-) sign and  +			   invalid integer format */ +			return -1; +		} +		break; +	} +   +	old_errno = errno; +	errno = 0; +	value = strtoul (str, &tail, base); +   +	if (errno == ERANGE || errno == EINVAL) +	{ +		return -1; +	} +   +	if (errno == 0) +	{ +		errno = old_errno; +	} +   +	if (tail[0] != '\0') +	{ +		/* bala: invalid integer format */ +		return -1; +	} +   +	*n = value; +   +	return 0; +} + +static int  +_gf_string2uint (const char *str, unsigned int *n, int base) +{ +	unsigned long value = 0; +	char *tail = NULL; +	int old_errno = 0; +	const char *s = NULL; +   +	if (str == NULL || n == NULL) +	{ +		errno = EINVAL; +		return -1; +	} +   +	for (s = str; *s != '\0'; s++) +	{ +		if (isspace (*s)) +		{ +			continue; +		} +		if (*s == '-') +		{ +			/* bala: we do not support suffixed (-) sign and  +			   invalid integer format */ +			return -1; +		} +		break; +	} +   +	old_errno = errno; +	errno = 0; +	value = strtoul (str, &tail, base); +   +	if (errno == ERANGE || errno == EINVAL) +	{ +		return -1; +	} +   +	if (errno == 0) +	{ +		errno = old_errno; +	} +   +	if (tail[0] != '\0') +	{ +		/* bala: invalid integer format */ +		return -1; +	} +   +	*n = (unsigned int)value; +   +	return 0; +} + +static int  +_gf_string2longlong (const char *str, long long *n, int base) +{ +	long long value = 0; +	char *tail = NULL; +	int old_errno = 0; +   +	if (str == NULL || n == NULL) +	{ +		errno = EINVAL; +		return -1; +	} +   +	old_errno = errno; +	errno = 0; +	value = strtoll (str, &tail, base); +   +	if (errno == ERANGE || errno == EINVAL) +	{ +		return -1; +	} +   +	if (errno == 0) +	{ +		errno = old_errno; +	} +   +	if (tail[0] != '\0') +	{ +		/* bala: invalid integer format */ +		return -1; +	} +   +	*n = value; +   +	return 0; +} + +static int  +_gf_string2ulonglong (const char *str, unsigned long long *n, int base) +{ +	unsigned long long value = 0; +	char *tail = NULL; +	int old_errno = 0; +	const char *s = NULL; +   +	if (str == NULL || n == NULL) +	{ +		errno = EINVAL; +		return -1; +	} +   +	for (s = str; *s != '\0'; s++) +	{ +		if (isspace (*s)) +		{ +			continue; +		} +		if (*s == '-') +		{ +			/* bala: we do not support suffixed (-) sign and  +			   invalid integer format */ +			return -1; +		} +		break; +	} +   +	old_errno = errno; +	errno = 0; +	value = strtoull (str, &tail, base); +   +	if (errno == ERANGE || errno == EINVAL) +	{ +		return -1; +	} +   +	if (errno == 0) +	{ +		errno = old_errno; +	} +   +	if (tail[0] != '\0') +	{ +		/* bala: invalid integer format */ +		return -1; +	} +   +	*n = value; +   +	return 0; +} + +int  +gf_string2long (const char *str, long *n) +{ +	return _gf_string2long (str, n, 0); +} + +int  +gf_string2ulong (const char *str, unsigned long *n) +{ +	return _gf_string2ulong (str, n, 0); +} + +int  +gf_string2int (const char *str, int *n) +{ +	return _gf_string2long (str, (long *) n, 0); +} + +int  +gf_string2uint (const char *str, unsigned int *n) +{ +	return _gf_string2uint (str, n, 0); +} + +int  +gf_string2longlong (const char *str, long long *n) +{ +	return _gf_string2longlong (str, n, 0); +} + +int  +gf_string2ulonglong (const char *str, unsigned long long *n) +{ +	return _gf_string2ulonglong (str, n, 0); +} + +int  +gf_string2int8 (const char *str, int8_t *n) +{ +	long l = 0L; +	int rv = 0; +   +	rv = _gf_string2long (str, &l, 0); +	if (rv != 0) +		return rv; +   +	if (l >= INT8_MIN && l <= INT8_MAX) +	{ +		*n = (int8_t) l; +		return 0; +	} +   +	errno = ERANGE; +	return -1; +} + +int  +gf_string2int16 (const char *str, int16_t *n) +{ +	long l = 0L; +	int rv = 0; +   +	rv = _gf_string2long (str, &l, 0); +	if (rv != 0) +		return rv; +   +	if (l >= INT16_MIN && l <= INT16_MAX) +	{ +		*n = (int16_t) l; +		return 0; +	} +   +	errno = ERANGE; +	return -1; +} + +int  +gf_string2int32 (const char *str, int32_t *n) +{ +	long l = 0L; +	int rv = 0; +   +	rv = _gf_string2long (str, &l, 0); +	if (rv != 0) +		return rv; +   +	if (l >= INT32_MIN && l <= INT32_MAX) +	{ +		*n = (int32_t) l; +		return 0; +	} +   +	errno = ERANGE; +	return -1; +} + +int  +gf_string2int64 (const char *str, int64_t *n) +{ +	long long l = 0LL; +	int rv = 0; +   +	rv = _gf_string2longlong (str, &l, 0); +	if (rv != 0) +		return rv; +   +	if (l >= INT64_MIN && l <= INT64_MAX) +	{ +		*n = (int64_t) l; +		return 0; +	} +   +	errno = ERANGE; +	return -1; +} + +int  +gf_string2uint8 (const char *str, uint8_t *n) +{ +	unsigned long l = 0L; +	int rv = 0; +   +	rv = _gf_string2ulong (str, &l, 0); +	if (rv != 0) +		return rv; +   +	if (l >= 0 && l <= UINT8_MAX) +	{ +		*n = (uint8_t) l; +		return 0; +	} +   +	errno = ERANGE; +	return -1; +} + +int  +gf_string2uint16 (const char *str, uint16_t *n) +{ +	unsigned long l = 0L; +	int rv = 0; +   +	rv = _gf_string2ulong (str, &l, 0); +	if (rv != 0) +		return rv; +   +	if (l >= 0 && l <= UINT16_MAX) +	{ +		*n = (uint16_t) l; +		return 0; +	} +   +	errno = ERANGE; +	return -1; +} + +int  +gf_string2uint32 (const char *str, uint32_t *n) +{ +	unsigned long l = 0L; +	int rv = 0; +   +	rv = _gf_string2ulong (str, &l, 0); +	if (rv != 0) +		return rv; +   +	if (l >= 0 && l <= UINT32_MAX) +	{ +		*n = (uint32_t) l; +		return 0; +	} +   +	errno = ERANGE; +	return -1; +} + +int  +gf_string2uint64 (const char *str, uint64_t *n) +{ +	unsigned long long l = 0ULL; +	int rv = 0; +   +	rv = _gf_string2ulonglong (str, &l, 0); +	if (rv != 0) +		return rv; +   +	if (l >= 0 && l <= UINT64_MAX) +	{ +		*n = (uint64_t) l; +		return 0; +	} +   +	errno = ERANGE; +	return -1; +} + +int  +gf_string2ulong_base10 (const char *str, unsigned long *n) +{ +	return _gf_string2ulong (str, n, 10); +} + +int  +gf_string2uint_base10 (const char *str, unsigned int *n) +{ +	return _gf_string2uint (str,  n, 10); +} + +int  +gf_string2uint8_base10 (const char *str, uint8_t *n) +{ +	unsigned long l = 0L; +	int rv = 0; +   +	rv = _gf_string2ulong (str, &l, 10); +	if (rv != 0) +		return rv; +   +	if (l >= 0 && l <= UINT8_MAX) +	{ +		*n = (uint8_t) l; +		return 0; +	} +   +	errno = ERANGE; +	return -1; +} + +int  +gf_string2uint16_base10 (const char *str, uint16_t *n) +{ +	unsigned long l = 0L; +	int rv = 0; +   +	rv = _gf_string2ulong (str, &l, 10); +	if (rv != 0) +		return rv; +   +	if (l >= 0 && l <= UINT16_MAX) +	{ +		*n = (uint16_t) l; +		return 0; +	} +   +	errno = ERANGE; +	return -1; +} + +int  +gf_string2uint32_base10 (const char *str, uint32_t *n) +{ +	unsigned long l = 0L; +	int rv = 0; +   +	rv = _gf_string2ulong (str, &l, 10); +	if (rv != 0) +		return rv; +   +	if (l >= 0 && l <= UINT32_MAX) +	{ +		*n = (uint32_t) l; +		return 0; +	} +   +	errno = ERANGE; +	return -1; +} + +int  +gf_string2uint64_base10 (const char *str, uint64_t *n) +{ +	unsigned long long l = 0ULL; +	int rv = 0; +   +	rv = _gf_string2ulonglong (str, &l, 10); +	if (rv != 0) +		return rv; +   +	if (l >= 0 && l <= UINT64_MAX) +	{ +		*n = (uint64_t) l; +		return 0; +	} +   +	errno = ERANGE; +	return -1; +} + +int  +gf_string2bytesize (const char *str, uint64_t *n) +{ +	uint64_t value = 0ULL; +	char *tail = NULL; +	int old_errno = 0; +	const char *s = NULL; +   +	if (str == NULL || n == NULL) +	{ +		errno = EINVAL; +		return -1; +	} +   +	for (s = str; *s != '\0'; s++) +	{ +		if (isspace (*s)) +		{ +			continue; +		} +		if (*s == '-') +		{ +			/* bala: we do not support suffixed (-) sign and  +			   invalid integer format */ +			return -1; +		} +		break; +	} +   +	old_errno = errno; +	errno = 0; +	value = strtoull (str, &tail, 10); +   +	if (errno == ERANGE || errno == EINVAL) +	{ +		return -1; +	} +   +	if (errno == 0) +	{ +		errno = old_errno; +	} +   +	if (tail[0] != '\0') +	{ +		if (strcasecmp (tail, GF_UNIT_KB_STRING) == 0) +		{ +			value *= GF_UNIT_KB; +		} +		else if (strcasecmp (tail, GF_UNIT_MB_STRING) == 0) +		{ +			value *= GF_UNIT_MB; +		} +		else if (strcasecmp (tail, GF_UNIT_GB_STRING) == 0) +		{ +			value *= GF_UNIT_GB; +		} +		else if (strcasecmp (tail, GF_UNIT_TB_STRING) == 0) +		{ +			value *= GF_UNIT_TB; +		} +		else if (strcasecmp (tail, GF_UNIT_PB_STRING) == 0) +		{ +			value *= GF_UNIT_PB; +		} +		else  +		{ +			/* bala: invalid integer format */ +			return -1; +		} +	} +   +	*n = value; +   +	return 0; +} + +int64_t  +gf_str_to_long_long (const char *number) +{ +	int64_t unit = 1; +	int64_t ret = 0; +	char *endptr = NULL ; +	if (!number) +		return 0; + +	ret = strtoll (number, &endptr, 0); + +	if (endptr) { +		switch (*endptr) { +		case 'G': +		case 'g': +			if ((* (endptr + 1) == 'B') ||(* (endptr + 1) == 'b')) +				unit = 1024 * 1024 * 1024; +			break; +		case 'M': +		case 'm': +			if ((* (endptr + 1) == 'B') ||(* (endptr + 1) == 'b')) +				unit = 1024 * 1024; +			break; +		case 'K': +		case 'k': +			if ((* (endptr + 1) == 'B') ||(* (endptr + 1) == 'b')) +				unit = 1024; +			break; +		case '%': +			unit = 1; +			break; +		default: +			unit = 1; +			break; +		} +	} +	return ret * unit; +} + +int  +gf_string2boolean (const char *str, gf_boolean_t *b) +{ +	if (str == NULL) { +		return -1; +	} +	 +	if ((strcasecmp (str, "1") == 0) ||  +	    (strcasecmp (str, "on") == 0) ||  +	    (strcasecmp (str, "yes") == 0) ||  +	    (strcasecmp (str, "true") == 0) ||  +	    (strcasecmp (str, "enable") == 0)) { +		*b = _gf_true; +		return 0; +	} +	 +	if ((strcasecmp (str, "0") == 0) ||  +	    (strcasecmp (str, "off") == 0) ||  +	    (strcasecmp (str, "no") == 0) ||  +	    (strcasecmp (str, "false") == 0) ||  +	    (strcasecmp (str, "disable") == 0)) { +		*b = _gf_false; +		return 0; +	} +	 +	return -1; +} + + +int  +gf_lockfd (int fd) +{ +	struct flock fl; +	 +	fl.l_type = F_WRLCK; +	fl.l_whence = SEEK_SET; +	fl.l_start = 0; +	fl.l_len = 0; +	 +	return fcntl (fd, F_SETLK, &fl); +} + + +int  +gf_unlockfd (int fd) +{ +	struct flock fl; +	 +	fl.l_type = F_UNLCK; +	fl.l_whence = SEEK_SET; +	fl.l_start = 0; +	fl.l_len = 0; +	 +	return fcntl (fd, F_SETLK, &fl); +} +    | 
