/*
Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS.
This file is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3 or
later), or the GNU General Public License, version 2 (GPLv2), in all
cases as published by the Free Software Foundation.
*/
#ifndef _COMMON_UTILS_H
#define _COMMON_UTILS_H
#include <stdint.h>
#include <sys/uio.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <pthread.h>
#include <openssl/md5.h>
#ifndef GF_BSD_HOST_OS
#include <alloca.h>
#endif
#include <limits.h>
#include <fnmatch.h>
#include <uuid/uuid.h>
#ifndef ffsll
#define ffsll(x) __builtin_ffsll(x)
#endif
void
trap(void);
#define GF_UNIVERSAL_ANSWER 42 /* :O */
/* To solve type punned error */
#define VOID(ptr) ((void **)((void *)ptr))
#include "glusterfs/logging.h"
#include "glusterfs/glusterfs.h"
#include "glusterfs/locking.h"
#include "glusterfs/mem-pool.h"
#include "glusterfs/compat-uuid.h"
#include "glusterfs/iatt.h"
#include "glusterfs/libglusterfs-messages.h"
#include "protocol-common.h"
#include "glusterfs/iobuf.h"
#define STRINGIFY(val) #val
#define TOSTRING(val) STRINGIFY(val)
#define alloca0(size) \
({ \
void *__ptr; \
__ptr = alloca(size); \
memset(__ptr, 0, size); \
__ptr; \
})
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
#define gf_roof(a, b) ((((a) + (b)-1) / ((b != 0) ? (b) : 1)) * (b))
#define gf_floor(a, b) (((a) / ((b != 0) ? (b) : 1)) * (b))
#define IPv4_ADDR_SIZE 32
#define GF_UNIT_KB 1024ULL
#define GF_UNIT_MB 1048576ULL
#define GF_UNIT_GB 1073741824ULL
#define GF_UNIT_TB 1099511627776ULL
#define GF_UNIT_PB 1125899906842624ULL
#define GF_UNIT_B_STRING "B"
#define GF_UNIT_KB_STRING "KB"
#define GF_UNIT_MB_STRING "MB"
#define GF_UNIT_GB_STRING "GB"
#define GF_UNIT_TB_STRING "TB"
#define GF_UNIT_PB_STRING "PB"
#define GF_UNIT_PERCENT_STRING "%"
#define GEOREP "geo-replication"
#define GHADOOP "glusterfs-hadoop"
#define GLUSTERD_NAME "glusterd"
#define GF_SELINUX_XATTR_KEY "security.selinux"
#define WIPE(statp) \
do { \
typeof(*statp) z = { \
0, \
}; \
if (statp) \
*statp = z; \
} while (0)
#define IS_EXT_FS(fs_name) \
(!strcmp(fs_name, "ext2") || !strcmp(fs_name, "ext3") || \
!strcmp(fs_name, "ext4"))
/* process mode definitions */
#define GF_SERVER_PROCESS 0
#define GF_CLIENT_PROCESS 1
#define GF_GLUSTERD_PROCESS 2
/* Defining this here as it is needed by glusterd for setting
* nfs port in volume status.
*/
#define GF_NFS3_PORT 2049
#define GF_CLIENT_PORT_CEILING 1024
#define GF_IANA_PRIV_PORTS_START 49152 /* RFC 6335 */
#define GF_CLNT_INSECURE_PORT_CEILING (GF_IANA_PRIV_PORTS_START - 1)
#define GF_PORT_MAX 65535
#define GF_PORT_ARRAY_SIZE ((GF_PORT_MAX + 7) / 8)
#define GF_LOCK_TIMER 180
#define GF_MINUTE_IN_SECONDS 60
#define GF_HOUR_IN_SECONDS (60 * 60)
#define GF_DAY_IN_SECONDS (24 * 60 * 60)
#define GF_WEEK_IN_SECONDS (7 * 24 * 60 * 60)
/* Default timeout for both barrier and changelog translator */
#define BARRIER_TIMEOUT "120"
/* Default value of signing waiting time to sign a file for bitrot */
#define SIGNING_TIMEOUT "120"
#define BR_WORKERS "4"
/* xxhash */
#define GF_XXH64_DIGEST_LENGTH 8
#define GF_XXHSUM64_DEFAULT_SEED 0
/* Shard */
#define GF_XATTR_SHARD_FILE_SIZE "trusted.glusterfs.shard.file-size"
#define SHARD_ROOT_GFID "be318638-e8a0-4c6d-977d-7a937aa84806"
#define DOT_SHARD_REMOVE_ME_GFID "77dd5a45-dbf5-4592-b31b-b440382302e9"
/* Lease: buffer length for stringified lease id
* Format: 4hexnum-4hexnum-4hexnum-4hexnum-4hexnum-4hexnum-4hexnum-4hexnum
* Eg:6c69-6431-2d63-6c6e-7431-0000-0000-0000
*/
#define GF_LEASE_ID_BUF_SIZE ((LEASE_ID_SIZE * 2) + (LEASE_ID_SIZE / 2))
#define GF_PERCENTAGE(val, total) (((val)*100) / (total))
/* pthread related */
/* as per the man page, thread-name should be at max 16 bytes */
/* with prefix of 'glfs_' (5), we are left with 11 more bytes */
#define GF_THREAD_NAME_LIMIT 16
#define GF_THREAD_NAME_PREFIX "glfs_"
/*
* we could have initialized these as +ve values and treated
* them as negative while comparing etc.. (which would have
* saved us with the pain of assigning values), but since we
* only have a few clients that use this feature, it's okay.
*/
enum _gf_special_pid {
GF_CLIENT_PID_MAX = 0,
GF_CLIENT_PID_GSYNCD = -1,
GF_CLIENT_PID_HADOOP = -2,
GF_CLIENT_PID_DEFRAG = -3,
GF_CLIENT_PID_NO_ROOT_SQUASH = -4,
GF_CLIENT_PID_QUOTA_MOUNT = -5,
GF_CLIENT_PID_SELF_HEALD = -6,
GF_CLIENT_PID_GLFS_HEAL = -7,
GF_CLIENT_PID_BITD = -8,
GF_CLIENT_PID_SCRUB = -9,
GF_CLIENT_PID_TIER_DEFRAG = -10,
GF_SERVER_PID_TRASH = -11,
GF_CLIENT_PID_ADD_REPLICA_MOUNT = -12
};
enum _gf_xlator_ipc_targets {
GF_IPC_TARGET_CHANGELOG = 0,
GF_IPC_TARGET_CTR = 1,
GF_IPC_TARGET_UPCALL = 2
};
typedef enum _gf_special_pid gf_special_pid_t;
typedef enum _gf_xlator_ipc_targets _gf_xlator_ipc_targets_t;
/* The DHT file rename operation is not a straightforward rename.
* It involves creating linkto and linkfiles, and can unlink or rename the
* source file depending on the hashed and cached subvols for the source
* and target files. this makes it difficult for geo-rep to figure out that
* a rename operation has taken place.
*
* We now send a special key and the values of the source and target pargfids
* and basenames to indicate to changelog that the operation in question
* should be treated as a rename. We are explicitly filling and sending this
* as a binary value in the dictionary as the unlink op will not have the
* source file information. The lengths of the src and target basenames
* are used to calculate where to start reading the names in the structure.
* XFS allows a max of 255 chars for filenames but other file systems might
* not have such restrictions
*/
typedef struct dht_changelog_rename_info {
uuid_t old_pargfid;
uuid_t new_pargfid;
int32_t oldname_len;
int32_t newname_len;
char buffer[1];
} dht_changelog_rename_info_t;
typedef int (*gf_cmp)(void *, void *);
struct _dict;
struct dnscache {
struct _dict *cache_dict;
time_t ttl;
};
struct dnscache_entry {
char *ip;
char *fqdn;
time_t timestamp;
};
struct dnscache6 {
struct addrinfo *first;
struct addrinfo *next;
};
struct list_node {
void *ptr;
struct list_head list;
};
extern char *vol_type_str[];
struct list_node *
list_node_add(void *ptr, struct list_head *list);
struct list_node *
list_node_add_order(void *ptr, struct list_head *list,
int (*compare)(struct list_head *, struct list_head *));
void
list_node_del(struct list_node *node);
struct dnscache *
gf_dnscache_init(time_t ttl);
struct dnscache_entry *
gf_dnscache_entry_init(void);
void
gf_dnscache_entry_deinit(struct dnscache_entry *entry);
char *
gf_rev_dns_lookup_cached(const char *ip, struct dnscache *dnscache);
char *
gf_resolve_path_parent(const char *path);
void
gf_global_variable_init(void);
int32_t
gf_resolve_ip6(const char *hostname, uint16_t port, int family, void **dnscache,
struct addrinfo **addr_info);
void
gf_log_dump_graph(FILE *specfp, glusterfs_graph_t *graph);
void
gf_print_trace(int32_t signal, glusterfs_ctx_t *ctx);
int
gf_set_log_file_path(cmd_args_t *cmd_args, glusterfs_ctx_t *ctx);
int
gf_set_log_ident(cmd_args_t *cmd_args);
int
gf_process_getspec_servers_list(cmd_args_t *cmd_args, const char *servers_list);
int
gf_set_volfile_server_common(cmd_args_t *cmd_args, const char *host,
const char *transport, int port);
static inline void
BIT_SET(unsigned char *array, unsigned int index)
{
unsigned int offset = index / 8;
unsigned int shift = index % 8;
array[offset] |= (1 << shift);
}
static inline void
BIT_CLEAR(unsigned char *array, unsigned int index)
{
unsigned int offset = index / 8;
unsigned int shift = index % 8;
array[offset] &= ~(1 << shift);
}
static inline unsigned int
BIT_VALUE(unsigned char *array, unsigned int index)
{
unsigned int offset = index / 8;
unsigned int shift = index % 8;
return (array[offset] >> shift) & 0x1;
}
#define VECTORSIZE(count) (count * (sizeof(struct iovec)))
#define STRLEN_0(str) (strlen(str) + 1)
#define VALIDATE_OR_GOTO(arg, label) \
do { \
if (!arg) { \
errno = EINVAL; \
gf_msg_callingfn((this ? (this->name) : "(Govinda! Govinda!)"), \
GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG, \
"invalid argument: " #arg); \
goto label; \
} \
} while (0)
#define GF_VALIDATE_OR_GOTO(name, arg, label) \
do { \
if (!arg) { \
errno = EINVAL; \
gf_msg_callingfn(name, GF_LOG_ERROR, errno, LG_MSG_INVALID_ARG, \
"invalid argument: " #arg); \
goto label; \
} \
} while (0)
#define GF_VALIDATE_OR_GOTO_WITH_ERROR(name, arg, label, errno, error) \
do { \
if (!arg) { \
errno = error; \
gf_msg_callingfn(name, GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, \
"invalid argument: " #arg); \
goto label; \
} \
} while (0)
#define GF_CHECK_ALLOC(arg, retval, label) \
do { \
if (!(arg)) { \
retval = -ENOMEM; \
goto label; \
} \
} while (0)
#define GF_CHECK_ALLOC_AND_LOG(name, item, retval, msg, errlabel) \
do { \
if (!(item)) { \
(retval) = -ENOMEM; \
gf_msg(name, GF_LOG_CRITICAL, ENOMEM, LG_MSG_NO_MEMORY, (msg)); \
goto errlabel; \
} \
} while (0)
#define GF_ASSERT_AND_GOTO_WITH_ERROR(name, arg, label, errno, error) \
do { \
if (!arg) { \
GF_ASSERT(0); \
errno = error; \
goto label; \
} \
} while (0)
#define GF_VALIDATE_ABSOLUTE_PATH_OR_GOTO(name, arg, label) \
do { \
GF_VALIDATE_OR_GOTO(name, arg, label); \
if ((arg[0]) != '/') { \
errno = EINVAL; \
gf_msg_callingfn(name, GF_LOG_ERROR, EINVAL, LG_MSG_INVALID_ARG, \
"invalid argument: " #arg); \
goto label; \
} \
} while (0)
#define GF_REMOVE_SLASH_FROM_PATH(path, string) \
do { \
int i = 0; \
for (i = 1; i < strlen(path); i++) { \
string[i - 1] = path[i]; \
if (string[i - 1] == '/') \
string[i - 1] = '-'; \
} \
} while (0)
#define GF_REMOVE_INTERNAL_XATTR(pattern, dict) \
do { \
if (!dict) { \
gf_msg(this->name, GF_LOG_ERROR, 0, LG_MSG_DICT_NULL, \
"dict is null"); \
break; \
} \
dict_foreach_fnmatch(dict, pattern, dict_remove_foreach_fn, NULL); \
} while (0)
#define GF_IF_INTERNAL_XATTR_GOTO(pattern, dict, op_errno, label) \
do { \
if (!dict) { \
gf_msg(this->name, GF_LOG_ERROR, 0, LG_MSG_DICT_NULL, \
"setxattr dict is null"); \
goto label; \
} \
if (dict_foreach_fnmatch(dict, pattern, dict_null_foreach_fn, NULL) > \
0) { \
op_errno = EPERM; \
gf_msg(this->name, GF_LOG_ERROR, op_errno, LG_MSG_NO_PERM, \
"attempt to set internal" \
" xattr: %s", \
pattern); \
goto label; \
} \
} while (0)
#define GF_IF_NATIVE_XATTR_GOTO(pattern, key, op_errno, label) \
do { \
if (!key) { \
gf_msg(this->name, GF_LOG_ERROR, 0, LG_MSG_NO_KEY, \
"no key for removexattr"); \
goto label; \
} \
if (!fnmatch(pattern, key, 0)) { \
op_errno = EPERM; \
gf_msg(this->name, GF_LOG_ERROR, op_errno, LG_MSG_NO_PERM, \
"attempt to remove internal " \
"xattr: %s", \
key); \
goto label; \
} \
} while (0)
#define GF_FILE_CONTENT_REQUESTED(_xattr_req, _content_limit) \
(dict_get_uint64(_xattr_req, "glusterfs.content", _content_limit) == 0)
#ifdef DEBUG
#define GF_ASSERT(x) assert(x);
#else
#define GF_ASSERT(x) \
do { \
if (!(x)) { \
gf_msg_callingfn("", GF_LOG_ERROR, 0, LG_MSG_ASSERTION_FAILED, \
"Assertion failed: " #x); \
} \
} while (0)
#endif
#define GF_ABORT(msg) \
do { \
gf_msg_callingfn("", GF_LOG_CRITICAL, 0, LG_MSG_ASSERTION_FAILED, \
"Assertion failed: " msg); \
abort(); \
} while (0)
#define GF_UUID_ASSERT(u) \
if (gf_uuid_is_null(u)) \
GF_ASSERT(!"uuid null");
#define GF_IGNORE_IF_GSYNCD_SAFE_ERROR(frame, op_errno) \
(((frame->root->pid == GF_CLIENT_PID_GSYNCD) && \
(op_errno == EEXIST || op_errno == ENOENT)) \
? 0 \
: 1)
union gf_sock_union {
struct sockaddr_storage storage;
struct sockaddr_in6 sin6;
struct sockaddr_in sin;
struct sockaddr sa;
};
#define GF_HIDDEN_PATH ".glusterfs"
#define GF_UNLINK_PATH GF_HIDDEN_PATH "/unlink"
#define GF_LANDFILL_PATH GF_HIDDEN_PATH "/landfill"
#define IOV_MIN(n) min(IOV_MAX, n)
#define GF_SKIP_IRRELEVANT_ENTRIES(entry, dir, scr) \
do { \
entry = NULL; \
if (dir) { \
entry = sys_readdir(dir, scr); \
while (entry && (!strcmp(entry->d_name, ".") || \
!fnmatch("*.tmp", entry->d_name, 0) || \
!strcmp(entry->d_name, ".."))) { \
entry = sys_readdir(dir, scr); \
} \
} \
} while (0)
static inline void
iov_free(struct iovec *vector, int count)
{
int i;
for (i = 0; i < count; i++)
FREE(vector[i].iov_base);
GF_FREE(vector);
}
static inline int
iov_length(const struct iovec *vector, int count)
{
int i = 0;
size_t size = 0;
for (i = 0; i < count; i++)
size += vector[i].iov_len;
return size;
}
static inline struct iovec *
iov_dup(const struct iovec *vector, int count)
{
int bytecount = 0;
int i;
struct iovec *newvec = NULL;
bytecount = (count * sizeof(struct iovec));
newvec = GF_MALLOC(bytecount, gf_common_mt_iovec);
if (!newvec)
return NULL;
for (i = 0; i < count; i++) {
newvec[i].iov_len = vector[i].iov_len;
newvec[i].iov_base = vector[i].iov_base;
}
return newvec;
}
static inline int
iov_subset(struct iovec *orig, int orig_count, off_t src_offset,
off_t dst_offset, struct iovec *new)
{
int new_count = 0;
int i;
off_t offset = 0;
size_t start_offset = 0;
size_t end_offset = 0, origin_iov_len = 0;
for (i = 0; i < orig_count; i++) {
origin_iov_len = orig[i].iov_len;
if ((offset + orig[i].iov_len < src_offset) || (offset > dst_offset)) {
goto not_subset;
}
if (!new) {
goto count_only;
}
start_offset = 0;
end_offset = orig[i].iov_len;
if (src_offset >= offset) {
start_offset = (src_offset - offset);
}
if (dst_offset <= (offset + orig[i].iov_len)) {
end_offset = (dst_offset - offset);
}
new[new_count].iov_base = orig[i].iov_base + start_offset;
new[new_count].iov_len = end_offset - start_offset;
count_only:
new_count++;
not_subset:
offset += origin_iov_len;
}
return new_count;
}
static inline void
iov_unload(char *buf, const struct iovec *vector, int count)
{
int i;
int copied = 0;
for (i = 0; i < count; i++) {
memcpy(buf + copied, vector[i].iov_base, vector[i].iov_len);
copied += vector[i].iov_len;
}
}
static inline size_t
iov_load(const struct iovec *vector, int count, char *buf, int size)
{
size_t left = size;
size_t cp = 0;
int ret = 0;
int i = 0;
while (left && i < count) {
cp = min(vector[i].iov_len, left);
if (vector[i].iov_base != buf + (size - left))
memcpy(vector[i].iov_base, buf + (size - left), cp);
ret += cp;
left -= cp;
if (left)
i++;
}
return ret;
}
static inline size_t
iov_copy(const struct iovec *dst, int dcnt, const struct iovec *src, int scnt)
{
size_t ret = 0;
size_t left = 0;
size_t min_i = 0;
int s_i = 0, s_ii = 0;
int d_i = 0, d_ii = 0;
ret = min(iov_length(dst, dcnt), iov_length(src, scnt));
left = ret;
while (left) {
min_i = min(dst[d_i].iov_len - d_ii, src[s_i].iov_len - s_ii);
memcpy(dst[d_i].iov_base + d_ii, src[s_i].iov_base + s_ii, min_i);
d_ii += min_i;
if (d_ii == dst[d_i].iov_len) {
d_ii = 0;
d_i++;
}
s_ii += min_i;
if (s_ii == src[s_i].iov_len) {
s_ii = 0;
s_i++;
}
left -= min_i;
}
return ret;
}
/* based on the amusing discussion @ https://rusty.ozlabs.org/?p=560 */
static bool
memeqzero(const void *data, size_t length)
{
const unsigned char *p = data;
size_t len;
/* Check first 16 bytes manually */
for (len = 0; len < 16; len++) {
if (!length)
return true;
if (*p)
return false;
p++;
length--;
}
/* Now we know that's zero, memcmp with self. */
return memcmp(data, p, length) == 0;
}
static inline int
mem_0filled(const char *buf, size_t size)
{
return !memeqzero(buf, size);
}
static inline int
iov_0filled(const struct iovec *vector, int count)
{
int i = 0;
int ret = 0;
for (i = 0; i < count; i++) {
ret = mem_0filled(vector[i].iov_base, vector[i].iov_len);
if (ret)
break;
}
return ret;
}
static inline void *
memdup(const void *ptr, size_t size)
{
void *newptr = NULL;
newptr = GF_MALLOC(size, gf_common_mt_memdup);
if (!newptr)
return NULL;
memcpy(newptr, ptr, size);
return newptr;
}
typedef enum {
gf_timefmt_default = 0,
gf_timefmt_FT = 0, /* YYYY-MM-DD hh:mm:ss */
gf_timefmt_Ymd_T, /* YYYY/MM-DD-hh:mm:ss */
gf_timefmt_bdT, /* MMM DD hh:mm:ss */
gf_timefmt_F_HMS, /* YYYY-MM-DD hhmmss */
gf_timefmt_dirent,
gf_timefmt_s,
gf_timefmt_last
} gf_timefmts;
static inline char *
gf_time_fmt(char *dst, size_t sz_dst, time_t utime, unsigned int fmt)
{
extern void _gf_timestuff(const char ***, const char ***);
static gf_timefmts timefmt_last = (gf_timefmts)-1;
static const char **fmts;
static const char **zeros;
struct tm tm, *res;
int localtime = 0;
if (timefmt_last == ((gf_timefmts)-1)) {
_gf_timestuff(&fmts, &zeros);
timefmt_last = gf_timefmt_last;
}
if (timefmt_last <= fmt) {
fmt = gf_timefmt_default;
}
localtime = gf_log_get_localtime();
res = localtime ? localtime_r(&utime, &tm) : gmtime_r(&utime, &tm);
if (utime && (res != NULL)) {
strftime(dst, sz_dst, fmts[fmt], &tm);
} else {
strncpy(dst, "N/A", sz_dst);
}
return dst;
}
/* This function helps us use gfid (unique identity) to generate inode's unique
* number in glusterfs.
*/
ino_t
gfid_to_ino(uuid_t gfid);
int
mkdir_p(char *path, mode_t mode, gf_boolean_t allow_symlinks);
/*
* rounds up nr to power of two. If nr is already a power of two, just returns
* nr
*/
int
gf_lstat_dir(const char *path, struct stat *stbuf_in);
int32_t
gf_roundup_power_of_two(int32_t nr);
/*
* rounds up nr to next power of two. If nr is already a power of two, next
* power of two is returned.
*/
int32_t
gf_roundup_next_power_of_two(int32_t nr);
char *
gf_trim(char *string);
int
gf_volume_name_validate(const char *volume_name);
int
gf_string2long(const char *str, long *n);
int
gf_string2ulong(const char *str, unsigned long *n);
int
gf_string2int(const char *str, int *n);
int
gf_string2uint(const char *str, unsigned int *n);
int
gf_string2double(const char *str, double *n);
int
gf_string2longlong(const char *str, long long *n);
int
gf_string2ulonglong(const char *str, unsigned long long *n);
int
gf_string2int8(const char *str, int8_t *n);
int
gf_string2int16(const char *str, int16_t *n);
int
gf_string2int32(const char *str, int32_t *n);
int
gf_string2int64(const char *str, int64_t *n);
int
gf_string2uint8(const char *str, uint8_t *n);
int
gf_string2uint16(const char *str, uint16_t *n);
int
gf_string2uint32(const char *str, uint32_t *n);
int
gf_string2uint64(const char *str, uint64_t *n);
int
gf_strstr(const char *str, const char *delim, const char *match);
int
gf_string2ulong_base10(const char *str, unsigned long *n);
int
gf_string2uint_base10(const char *str, unsigned int *n);
int
gf_string2uint8_base10(const char *str, uint8_t *n);
int
gf_string2uint16_base10(const char *str, uint16_t *n);
int
gf_string2uint32_base10(const char *str, uint32_t *n);
int
gf_string2uint64_base10(const char *str, uint64_t *n);
int
gf_string2bytesize_uint64(const char *str, uint64_t *n);
int
gf_string2bytesize_int64(const char *str, int64_t *n);
int
gf_string2percent_or_bytesize(const char *str, double *n,
gf_boolean_t *is_percent);
int
gf_string2boolean(const char *str, gf_boolean_t *b);
int
gf_string2percent(const char *str, double *n);
int
gf_string2time(const char *str, uint32_t *n);
int
gf_lockfd(int fd);
int
gf_unlockfd(int fd);
int
get_checksum_for_file(int fd, uint32_t *checksum, int op_version);
int
log_base2(unsigned long x);
int
get_checksum_for_path(char *path, uint32_t *checksum, int op_version);
int
get_file_mtime(const char *path, time_t *stamp);
char *
gf_resolve_path_parent(const char *path);
char *
strtail(char *str, const char *pattern);
void
skipwhite(char **s);
char *
nwstrtail(char *str, char *pattern);
/* returns a new string with nth word of given string. n>=1 */
typedef struct token_iter {
char *end;
char sep;
} token_iter_t;
char *
token_iter_init(char *str, char sep, token_iter_t *tit);
gf_boolean_t
next_token(char **tokenp, token_iter_t *tit);
void
drop_token(char *token, token_iter_t *tit);
gf_boolean_t
mask_match(const uint32_t a, const uint32_t b, const uint32_t m);
gf_boolean_t
gf_is_ip_in_net(const char *network, const char *ip_str);
char
valid_host_name(char *address, int length);
char
valid_ipv4_address(char *address, int length, gf_boolean_t wildcard_acc);
char
valid_ipv6_address(char *address, int length, gf_boolean_t wildcard_acc);
char
valid_internet_address(char *address, gf_boolean_t wildcard_acc,
gf_boolean_t cidr);
gf_boolean_t
valid_mount_auth_address(char *address);
gf_boolean_t
valid_ipv4_subnetwork(const char *address);
gf_boolean_t
gf_sock_union_equal_addr(union gf_sock_union *a, union gf_sock_union *b);
char *
gf_rev_dns_lookup(const char *ip);
char *
uuid_utoa(uuid_t uuid);
char *
uuid_utoa_r(uuid_t uuid, char *dst);
char *
lkowner_utoa(gf_lkowner_t *lkowner);
char *
lkowner_utoa_r(gf_lkowner_t *lkowner, char *dst, int len);
char *
leaseid_utoa(const char *lease_id);
gf_boolean_t
is_valid_lease_id(const char *lease_id);
char *
gf_leaseid_get(void);
char *
gf_existing_leaseid(void);
void
gf_array_insertionsort(void *a, int l, int r, size_t elem_size, gf_cmp cmp);
int
gf_is_str_int(const char *value);
char *gf_uint64_2human_readable(uint64_t);
int
get_vol_type(int type, int dist_count, int brick_count);
int
validate_brick_name(char *brick);
char *
get_host_name(char *word, char **host);
char *
get_path_name(char *word, char **path);
void
gf_path_strip_trailing_slashes(char *path);
uint64_t
get_mem_size(void);
int
gf_strip_whitespace(char *str, int len);
int
gf_canonicalize_path(char *path);
char *
generate_glusterfs_ctx_id(void);
char *
gf_get_reserved_ports(void);
int
gf_process_reserved_ports(unsigned char *ports, uint32_t ceiling);
gf_boolean_t
gf_ports_reserved(char *blocked_port, unsigned char *ports, uint32_t ceiling);
int
gf_get_hostname_from_ip(char *client_ip, char **hostname);
gf_boolean_t
gf_is_local_addr(char *hostname);
gf_boolean_t
gf_is_same_address(char *host1, char *host2);
void
gf_xxh64_wrapper(const unsigned char *data, size_t const len,
unsigned long long const seed, char *xxh64);
int
gf_gfid_generate_from_xxh64(uuid_t gfid, char *key);
int
gf_set_timestamp(const char *src, const char *dest);
int
gf_thread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg, const char *name,
...) __attribute__((__format__(__printf__, 5, 6)));
int
gf_thread_vcreate(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg, const char *name,
va_list args);
int
gf_thread_create_detached(pthread_t *thread, void *(*start_routine)(void *),
void *arg, const char *name, ...)
__attribute__((__format__(__printf__, 4, 5)));
void
gf_thread_set_name(pthread_t thread, const char *name, ...)
__attribute__((__format__(__printf__, 2, 3)));
void
gf_thread_set_vname(pthread_t thread, const char *name, va_list args);
gf_boolean_t
gf_is_pid_running(int pid);
gf_boolean_t
gf_is_service_running(char *pidfile, int *pid);
gf_boolean_t
gf_valid_pid(const char *pid, int length);
int
gf_skip_header_section(int fd, int header_len);
struct iatt;
struct _dict;
gf_boolean_t
dht_is_linkfile(struct iatt *buf, struct _dict *dict);
int
gf_check_log_format(const char *value);
int
gf_check_logger(const char *value);
gf_boolean_t
gf_compare_sockaddr(const struct sockaddr *addr1, const struct sockaddr *addr2);
char *
gf_backtrace_save(char *buf);
void
gf_backtrace_done(char *buf);
gf_loglevel_t
fop_log_level(glusterfs_fop_t fop, int op_errno);
int32_t
gf_build_absolute_path(char *current_path, char *relative_path, char **path);
int
recursive_rmdir(const char *delete_path);
int
gf_get_index_by_elem(char **array, char *elem);
int
glusterfs_is_local_pathinfo(char *pathinfo, gf_boolean_t *local);
int
gf_thread_cleanup_xint(pthread_t thread);
ssize_t
gf_nread(int fd, void *buf, size_t count);
ssize_t
gf_nwrite(int fd, const void *buf, size_t count);
void
_mask_cancellation(void);
void
_unmask_cancellation(void);
gf_boolean_t
gf_is_zero_filled_stat(struct iatt *buf);
void
gf_zero_fill_stat(struct iatt *buf);
gf_boolean_t
gf_is_valid_xattr_namespace(char *k);
const char *
gf_inode_type_to_str(ia_type_t type);
int32_t
gf_bits_count(uint64_t n);
int32_t
gf_bits_index(uint64_t n);
const char *
gf_fop_string(glusterfs_fop_t fop);
int
gf_fop_int(char *fop);
char *
get_ip_from_addrinfo(struct addrinfo *addr, char **ip);
int
close_fds_except(int *fdv, size_t count);
int
gf_getgrouplist(const char *user, gid_t group, gid_t **groups);
int
glusterfs_compute_sha256(const unsigned char *content, size_t size,
char *sha256_hash);
char *
get_struct_variable(int mem_num, gf_gsync_status_t *sts_val);
char *
gf_strncpy(char *dest, const char *src, const size_t dest_size);
void
gf_strTrim(char **s);
int
gf_replace_old_iatt_in_dict(struct _dict *);
int
gf_replace_new_iatt_in_dict(struct _dict *);
xlator_cmdline_option_t *
find_xlator_option_in_cmd_args_t(const char *option_name, cmd_args_t *args);
int
gf_d_type_from_ia_type(ia_type_t type);
#endif /* _COMMON_UTILS_H */