"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.2/libglusterfs/src/common-utils.c" (16 Sep 2020, 131433 Bytes) of package /linux/misc/glusterfs-8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "common-utils.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 8.1_vs_8.2.

    1 /*
    2   Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
    3   This file is part of GlusterFS.
    4 
    5   This file is licensed to you under your choice of the GNU Lesser
    6   General Public License, version 3 or any later version (LGPLv3 or
    7   later), or the GNU General Public License, version 2 (GPLv2), in all
    8   cases as published by the Free Software Foundation.
    9 */
   10 
   11 #ifdef HAVE_BACKTRACE
   12 #include <execinfo.h>
   13 #else
   14 #include "execinfo_compat.h"
   15 #endif
   16 
   17 #include <stdio.h>
   18 #include <stdlib.h>
   19 #include <string.h>
   20 #include <ctype.h>
   21 #include <errno.h>
   22 #include <limits.h>
   23 #include <unistd.h>
   24 #include <time.h>
   25 #include <locale.h>
   26 #include <sys/socket.h>
   27 #include <netinet/in.h>
   28 #include <arpa/inet.h>
   29 #include <signal.h>
   30 #include <assert.h>
   31 #include <libgen.h> /* for dirname() */
   32 #include <grp.h>
   33 
   34 #if defined(GF_BSD_HOST_OS) || defined(GF_DARWIN_HOST_OS)
   35 #include <sys/sysctl.h>
   36 #endif
   37 #ifndef GF_LINUX_HOST_OS
   38 #include <sys/resource.h>
   39 #endif
   40 
   41 #include "glusterfs/compat-errno.h"
   42 #include "glusterfs/common-utils.h"
   43 #include "glusterfs/revision.h"
   44 #include "glusterfs/glusterfs.h"
   45 #include "glusterfs/stack.h"
   46 #include "glusterfs/lkowner.h"
   47 #include "glusterfs/syscall.h"
   48 #include "glusterfs/globals.h"
   49 #define XXH_INLINE_ALL
   50 #include "xxhash.h"
   51 #include <ifaddrs.h>
   52 #include "glusterfs/libglusterfs-messages.h"
   53 #ifdef __FreeBSD__
   54 #include <pthread_np.h>
   55 #undef BIT_SET
   56 #endif
   57 
   58 #ifndef AI_ADDRCONFIG
   59 #define AI_ADDRCONFIG 0
   60 #endif /* AI_ADDRCONFIG */
   61 
   62 char *vol_type_str[] = {
   63     "Distribute",
   64     "Stripe [NOT SUPPORTED from v6.0]",
   65     "Replicate",
   66     "Striped-Replicate [NOT SUPPORTED from v6.0]",
   67     "Disperse",
   68     "Tier [NOT SUPPORTED from v6.0]",
   69     "Distributed-Stripe [NOT SUPPORTED from v6.0]",
   70     "Distributed-Replicate",
   71     "Distributed-Striped-Replicate [NOT SUPPORTED from v6.0]",
   72     "Distributed-Disperse",
   73 };
   74 
   75 typedef int32_t (*rw_op_t)(int32_t fd, char *buf, int32_t size);
   76 typedef int32_t (*rwv_op_t)(int32_t fd, const struct iovec *buf, int32_t size);
   77 
   78 void
   79 gf_xxh64_wrapper(const unsigned char *data, size_t const len,
   80                  unsigned long long const seed, char *xxh64)
   81 {
   82     unsigned short i = 0;
   83     const unsigned short lim = GF_XXH64_DIGEST_LENGTH * 2 + 1;
   84     XXH64_hash_t hash = 0;
   85     XXH64_canonical_t c_hash = {
   86         {
   87             0,
   88         },
   89     };
   90     const uint8_t *p = (const uint8_t *)&c_hash;
   91 
   92     hash = XXH64(data, len, seed);
   93     XXH64_canonicalFromHash(&c_hash, hash);
   94 
   95     for (i = 0; i < GF_XXH64_DIGEST_LENGTH; i++)
   96         snprintf(xxh64 + i * 2, lim - i * 2, "%02x", p[i]);
   97 }
   98 
   99 /**
  100  * This function takes following arguments
  101  * @this: xlator
  102  * @gfid: The gfid which has to be filled
  103  * @hash: the 8 byte hash which has to be filled inside the gfid
  104  * @index: the array element of the uuid_t structure (which is
  105  *         a array of unsigned char) from where the 8 bytes of
  106  *         the hash has to be filled. Since uuid_t contains 16
  107  *        char elements in the array, each byte of the hash has
  108  *        to be filled in one array element.
  109  *
  110  * This function is called twice for 2 hashes (of 8 byte each) to
  111  * be filled in the gfid.
  112  *
  113  * The for loop in this function actually is doing these 2 things
  114  * for each hash
  115  *
  116  * 1) One of the hashes
  117  *      tmp[0] = (hash_2 >> 56) & 0xff;
  118  *      tmp[1] = (hash_2 >> 48) & 0xff;
  119  *      tmp[2] = (hash_2 >> 40) & 0xff;
  120  *      tmp[3] = (hash_2 >> 32) & 0xff;
  121  *      tmp[4] = (hash_2 >> 24) & 0xff;
  122  *      tmp[5] = (hash_2 >> 16) & 0xff;
  123  *      tmp[6] = (hash_2 >> 8) & 0xff;
  124  *      tmp[7] = (hash_2) & 0xff;
  125  *
  126  * 2) The other hash:
  127  *      tmp[8] = (hash_1 >> 56) & 0xff;
  128  *      tmp[9] = (hash_1 >> 48) & 0xff;
  129  *      tmp[10] = (hash_1 >> 40) & 0xff;
  130  *      tmp[11] = (hash_1 >> 32) & 0xff;
  131  *      tmp[12] = (hash_1 >> 24) & 0xff;
  132  *      tmp[13] = (hash_1 >> 16) & 0xff;
  133  *      tmp[14] = (hash_1 >> 8) & 0xff;
  134  *      tmp[15] = (hash_1) & 0xff;
  135  **/
  136 static int
  137 gf_gfid_from_xxh64(xlator_t *this, uuid_t gfid, XXH64_hash_t hash,
  138                    unsigned short index)
  139 {
  140     int ret = -1;
  141     int i = -1;
  142 
  143     if ((index != 0) && (index != 8)) {
  144         gf_msg_callingfn("gfid-from-xxh64", GF_LOG_WARNING, 0,
  145                          LG_MSG_INDEX_NOT_FOUND,
  146                          "index can only be either 0 or 8, as this"
  147                          "function's purpose is to encode a 8 byte "
  148                          "hash inside the gfid (index: %d)",
  149                          index);
  150         goto out;
  151     }
  152 
  153     for (i = 0; i < sizeof(hash); i++) {
  154         /*
  155          * As of now the below statement is equivalent of this.
  156          * gfid[index+i] = (hash >> (64 - (8 * (i+1)))) & 0xff;
  157          */
  158         gfid[index + i] = (hash >> ((sizeof(hash) * 8) - (8 * (i + 1)))) &
  159                           (0xff);
  160     }
  161 
  162     ret = 0;
  163 
  164 out:
  165     return ret;
  166 }
  167 
  168 /**
  169  * This function does the same thing as gf_xxh64_wrapper. But gf_xxh64_wrapper
  170  * does not return anything and in this xlator there is a need for both the
  171  * actual hash and the canonicalized form of the hash.
  172  *
  173  * To summarize:
  174  * - XXH64_hash_t is needed as return because, those bytes which contain the
  175  *   hash can be used for different purposes as needed. One example is
  176  *   to have those bytes copied into the uuid_t structure to be used as gfid
  177  * - xxh64 string is needed because, it can be used as the key for generating
  178  *   the next hash (and any other purpose which might require canonical form
  179  *   of the hash).
  180  **/
  181 XXH64_hash_t
  182 gf_xxh64_hash_wrapper(const unsigned char *data, size_t const len,
  183                       unsigned long long const seed, char *xxh64)
  184 {
  185     unsigned short i = 0;
  186     const unsigned short lim = GF_XXH64_DIGEST_LENGTH * 2 + 1;
  187     XXH64_hash_t hash = 0;
  188     XXH64_canonical_t c_hash = {
  189         {
  190             0,
  191         },
  192     };
  193     const uint8_t *p = (const uint8_t *)&c_hash;
  194 
  195     hash = XXH64(data, len, seed);
  196     XXH64_canonicalFromHash(&c_hash, hash);
  197 
  198     for (i = 0; i < GF_XXH64_DIGEST_LENGTH; i++)
  199         snprintf(xxh64 + i * 2, lim - i * 2, "%02x", p[i]);
  200 
  201     return hash;
  202 }
  203 
  204 /**
  205  * This is the algorithm followed for generating new gfid
  206  * 1) generate xxh64 hash using snapname and original gfid of the object
  207  * 2) Using the canonicalized form of above hash as the key, generate
  208  *    another hash
  209  * 3) Combine both of the  8 byte hashes to generate a 16 byte uuid_t type
  210  * 4) Use the above uuid as the gfid
  211  *
  212  * Each byte of the hash is stored separately in different elements of the
  213  * character array represented by uuid_t
  214  * Ex: tmp[0] = (hash_2 >> 56) & 0xFF
  215  *     This saves the most significant byte of hash_2 in tmp[0]
  216  *     tmp[1] = (hash_2 >> 48) & 0xFF
  217  *     This saves next most significant byte of hash_2 in tmp[1]
  218  *     .
  219  *     .
  220  *     So on.
  221  *     tmp[0] - tmp[7] holds the contents of hash_2
  222  *     tmp[8] - tmp[15] hold the conents of hash_1
  223  *
  224  * The hash generated (i.e. of type XXH64_hash_t) is 8 bytes long. And for
  225  * gfid 16 byte uuid is needed. Hecne the 2 hashes are combined to form
  226  * one 16 byte entity.
  227  **/
  228 int
  229 gf_gfid_generate_from_xxh64(uuid_t gfid, char *key)
  230 {
  231     char xxh64_1[GF_XXH64_DIGEST_LENGTH * 2 + 1] = {
  232         0,
  233     };
  234     char xxh64_2[GF_XXH64_DIGEST_LENGTH * 2 + 1] = {
  235         0,
  236     };
  237     XXH64_hash_t hash_1 = 0;
  238     XXH64_hash_t hash_2 = 0;
  239     int ret = -1;
  240     xlator_t *this = THIS;
  241 
  242     hash_1 = gf_xxh64_hash_wrapper((unsigned char *)key, strlen(key),
  243                                    GF_XXHSUM64_DEFAULT_SEED, xxh64_1);
  244 
  245     hash_2 = gf_xxh64_hash_wrapper((unsigned char *)xxh64_1, strlen(xxh64_1),
  246                                    GF_XXHSUM64_DEFAULT_SEED, xxh64_2);
  247 
  248     /* hash_2 is saved in 1st 8 elements of uuid_t char array */
  249     if (gf_gfid_from_xxh64(this, gfid, hash_2, 0)) {
  250         gf_msg_callingfn(this->name, GF_LOG_WARNING, 0,
  251                          LG_MSG_XXH64_TO_GFID_FAILED,
  252                          "failed to encode the hash %llx into the 1st"
  253                          "half of gfid",
  254                          hash_2);
  255         goto out;
  256     }
  257 
  258     /* hash_1 is saved in the remaining 8 elements of uuid_t */
  259     if (gf_gfid_from_xxh64(this, gfid, hash_1, 8)) {
  260         gf_msg_callingfn(this->name, GF_LOG_WARNING, 0,
  261                          LG_MSG_XXH64_TO_GFID_FAILED,
  262                          "failed to encode the hash %llx into the 2nd"
  263                          "half of gfid",
  264                          hash_1);
  265         goto out;
  266     }
  267 
  268     gf_msg_debug(this->name, 0,
  269                  "gfid generated is %s (hash1: %llx) "
  270                  "hash2: %llx, xxh64_1: %s xxh64_2: %s",
  271                  uuid_utoa(gfid), hash_1, hash_2, xxh64_1, xxh64_2);
  272 
  273     ret = 0;
  274 
  275 out:
  276     return ret;
  277 }
  278 
  279 /* works similar to mkdir(1) -p.
  280  */
  281 int
  282 mkdir_p(char *path, mode_t mode, gf_boolean_t allow_symlinks)
  283 {
  284     int i = 0;
  285     int ret = -1;
  286     char dir[PATH_MAX] = {
  287         0,
  288     };
  289     struct stat stbuf = {
  290         0,
  291     };
  292 
  293     const int path_len = min(strlen(path), PATH_MAX - 1);
  294 
  295     snprintf(dir, path_len + 1, "%s", path);
  296 
  297     i = (dir[0] == '/') ? 1 : 0;
  298     do {
  299         if (path[i] != '/' && path[i] != '\0')
  300             continue;
  301 
  302         dir[i] = '\0';
  303         ret = sys_mkdir(dir, mode);
  304         if (ret && errno != EEXIST) {
  305             gf_smsg("", GF_LOG_ERROR, errno, LG_MSG_DIR_OP_FAILED, NULL);
  306             goto out;
  307         }
  308 
  309         if (ret && errno == EEXIST && !allow_symlinks) {
  310             ret = sys_lstat(dir, &stbuf);
  311             if (ret)
  312                 goto out;
  313 
  314             if (S_ISLNK(stbuf.st_mode)) {
  315                 ret = -1;
  316                 gf_smsg("", GF_LOG_ERROR, 0, LG_MSG_DIR_IS_SYMLINK, "dir=%s",
  317                         dir, NULL);
  318                 goto out;
  319             }
  320         }
  321         dir[i] = '/';
  322 
  323     } while (path[i++] != '\0');
  324 
  325     ret = sys_stat(dir, &stbuf);
  326     if (ret || !S_ISDIR(stbuf.st_mode)) {
  327         if (ret == 0)
  328             errno = 0;
  329         ret = -1;
  330         gf_smsg("", GF_LOG_ERROR, errno, LG_MSG_DIR_OP_FAILED,
  331                 "possibly some of the components"
  332                 " were not directories",
  333                 NULL);
  334         goto out;
  335     }
  336 
  337     ret = 0;
  338 out:
  339 
  340     return ret;
  341 }
  342 
  343 int
  344 gf_lstat_dir(const char *path, struct stat *stbuf_in)
  345 {
  346     int ret = -1;
  347     struct stat stbuf = {
  348         0,
  349     };
  350 
  351     if (path == NULL) {
  352         errno = EINVAL;
  353         goto out;
  354     }
  355 
  356     ret = sys_lstat(path, &stbuf);
  357     if (ret)
  358         goto out;
  359 
  360     if (!S_ISDIR(stbuf.st_mode)) {
  361         errno = ENOTDIR;
  362         ret = -1;
  363         goto out;
  364     }
  365     ret = 0;
  366 
  367 out:
  368     if (!ret && stbuf_in)
  369         *stbuf_in = stbuf;
  370 
  371     return ret;
  372 }
  373 
  374 int
  375 log_base2(unsigned long x)
  376 {
  377     int val = 0;
  378 
  379     while (x > 1) {
  380         x /= 2;
  381         val++;
  382     }
  383 
  384     return val;
  385 }
  386 
  387 /**
  388  * gf_rev_dns_lookup -- Perform a reverse DNS lookup on the IP address.
  389  *
  390  * @ip: The IP address to perform a reverse lookup on
  391  *
  392  * @return: success: Allocated string containing the hostname
  393  *          failure: NULL
  394  */
  395 char *
  396 gf_rev_dns_lookup(const char *ip)
  397 {
  398     char *fqdn = NULL;
  399     int ret = 0;
  400 
  401     GF_VALIDATE_OR_GOTO("resolver", ip, out);
  402 
  403     /* Get the FQDN */
  404     ret = gf_get_hostname_from_ip((char *)ip, &fqdn);
  405     if (ret != 0) {
  406         gf_smsg("resolver", GF_LOG_INFO, errno, LG_MSG_RESOLVE_HOSTNAME_FAILED,
  407                 "hostname=%s", ip, NULL);
  408     }
  409 out:
  410     return fqdn;
  411 }
  412 
  413 /**
  414  * gf_resolve_path_parent -- Given a path, returns an allocated string
  415  *                           containing the parent's path.
  416  * @path: Path to parse
  417  * @return: The parent path if found, NULL otherwise
  418  */
  419 char *
  420 gf_resolve_path_parent(const char *path)
  421 {
  422     char *parent = NULL;
  423     char *tmp = NULL;
  424     char *pathc = NULL;
  425 
  426     GF_VALIDATE_OR_GOTO(THIS->name, path, out);
  427 
  428     if (strlen(path) <= 0) {
  429         gf_msg_callingfn(THIS->name, GF_LOG_DEBUG, 0, LG_MSG_INVALID_STRING,
  430                          "invalid string for 'path'");
  431         goto out;
  432     }
  433 
  434     /* dup the parameter, we don't want to modify it */
  435     pathc = strdupa(path);
  436     if (!pathc) {
  437         goto out;
  438     }
  439 
  440     /* Get the parent directory */
  441     tmp = dirname(pathc);
  442     if (strcmp(tmp, "/") == 0)
  443         goto out;
  444 
  445     parent = gf_strdup(tmp);
  446 out:
  447     return parent;
  448 }
  449 
  450 int32_t
  451 gf_resolve_ip6(const char *hostname, uint16_t port, int family, void **dnscache,
  452                struct addrinfo **addr_info)
  453 {
  454     int32_t ret = 0;
  455     struct addrinfo hints;
  456     struct dnscache6 *cache = NULL;
  457     char service[NI_MAXSERV], host[NI_MAXHOST];
  458 
  459     if (!hostname) {
  460         gf_msg_callingfn("resolver", GF_LOG_WARNING, 0, LG_MSG_HOSTNAME_NULL,
  461                          "hostname is NULL");
  462         return -1;
  463     }
  464 
  465     if (!*dnscache) {
  466         *dnscache = GF_CALLOC(1, sizeof(struct dnscache6),
  467                               gf_common_mt_dnscache6);
  468         if (!*dnscache)
  469             return -1;
  470     }
  471 
  472     cache = *dnscache;
  473     if (cache->first && !cache->next) {
  474         freeaddrinfo(cache->first);
  475         cache->first = cache->next = NULL;
  476         gf_msg_trace("resolver", 0, "flushing DNS cache");
  477     }
  478 
  479     if (!cache->first) {
  480         char *port_str = NULL;
  481         gf_msg_trace("resolver", 0,
  482                      "DNS cache not present, freshly "
  483                      "probing hostname: %s",
  484                      hostname);
  485 
  486         memset(&hints, 0, sizeof(hints));
  487         hints.ai_family = family;
  488         hints.ai_socktype = SOCK_STREAM;
  489 
  490         ret = gf_asprintf(&port_str, "%d", port);
  491         if (-1 == ret) {
  492             return -1;
  493         }
  494         if ((ret = getaddrinfo(hostname, port_str, &hints, &cache->first)) !=
  495             0) {
  496             gf_smsg("resolver", GF_LOG_ERROR, 0, LG_MSG_GETADDRINFO_FAILED,
  497                     "family=%d", family, "ret=%s", gai_strerror(ret), NULL);
  498 
  499             GF_FREE(*dnscache);
  500             *dnscache = NULL;
  501             GF_FREE(port_str);
  502             return -1;
  503         }
  504         GF_FREE(port_str);
  505 
  506         cache->next = cache->first;
  507     }
  508 
  509     if (cache->next) {
  510         ret = getnameinfo((struct sockaddr *)cache->next->ai_addr,
  511                           cache->next->ai_addrlen, host, sizeof(host), service,
  512                           sizeof(service), NI_NUMERICHOST);
  513         if (ret != 0) {
  514             gf_smsg("resolver", GF_LOG_ERROR, 0, LG_MSG_GETNAMEINFO_FAILED,
  515                     "ret=%s", gai_strerror(ret), NULL);
  516             goto err;
  517         }
  518 
  519         gf_msg_debug("resolver", 0,
  520                      "returning ip-%s (port-%s) for "
  521                      "hostname: %s and port: %d",
  522                      host, service, hostname, port);
  523 
  524         *addr_info = cache->next;
  525     }
  526 
  527     if (cache->next)
  528         cache->next = cache->next->ai_next;
  529     if (cache->next) {
  530         ret = getnameinfo((struct sockaddr *)cache->next->ai_addr,
  531                           cache->next->ai_addrlen, host, sizeof(host), service,
  532                           sizeof(service), NI_NUMERICHOST);
  533         if (ret != 0) {
  534             gf_smsg("resolver", GF_LOG_ERROR, 0, LG_MSG_GETNAMEINFO_FAILED,
  535                     "ret=%s", gai_strerror(ret), NULL);
  536             goto err;
  537         }
  538 
  539         gf_msg_debug("resolver", 0,
  540                      "next DNS query will return: "
  541                      "ip-%s port-%s",
  542                      host, service);
  543     }
  544 
  545     return 0;
  546 
  547 err:
  548     freeaddrinfo(cache->first);
  549     cache->first = cache->next = NULL;
  550     GF_FREE(cache);
  551     *dnscache = NULL;
  552     return -1;
  553 }
  554 
  555 /**
  556  * gf_dnscache_init -- Initializes a dnscache struct and sets the ttl
  557  *                     to the specified value in the parameter.
  558  *
  559  * @ttl: the TTL in seconds
  560  * @return: SUCCESS: Pointer to an allocated dnscache struct
  561  *          FAILURE: NULL
  562  */
  563 struct dnscache *
  564 gf_dnscache_init(time_t ttl)
  565 {
  566     struct dnscache *cache = GF_MALLOC(sizeof(*cache), gf_common_mt_dnscache);
  567     if (!cache)
  568         return NULL;
  569 
  570     cache->cache_dict = dict_new();
  571     if (!cache->cache_dict) {
  572         GF_FREE(cache);
  573         cache = NULL;
  574     } else {
  575         cache->ttl = ttl;
  576     }
  577 
  578     return cache;
  579 }
  580 
  581 /**
  582  * gf_dnscache_deinit -- cleanup resources used by struct dnscache
  583  */
  584 void
  585 gf_dnscache_deinit(struct dnscache *cache)
  586 {
  587     if (!cache) {
  588         gf_msg_plain(GF_LOG_WARNING, "dnscache is NULL");
  589         return;
  590     }
  591     dict_unref(cache->cache_dict);
  592     GF_FREE(cache);
  593 }
  594 
  595 /**
  596  * gf_dnscache_entry_init -- Initialize a dnscache entry
  597  *
  598  * @return: SUCCESS: Pointer to an allocated dnscache entry struct
  599  *          FAILURE: NULL
  600  */
  601 struct dnscache_entry *
  602 gf_dnscache_entry_init()
  603 {
  604     struct dnscache_entry *entry = GF_CALLOC(1, sizeof(*entry),
  605                                              gf_common_mt_dnscache_entry);
  606     return entry;
  607 }
  608 
  609 /**
  610  * gf_dnscache_entry_deinit -- Free memory used by a dnscache entry
  611  *
  612  * @entry: Pointer to deallocate
  613  */
  614 void
  615 gf_dnscache_entry_deinit(struct dnscache_entry *entry)
  616 {
  617     GF_FREE(entry->ip);
  618     GF_FREE(entry->fqdn);
  619     GF_FREE(entry);
  620 }
  621 
  622 /**
  623  * gf_rev_dns_lookup -- Perform a reverse DNS lookup on the IP address.
  624  *
  625  * @ip: The IP address to perform a reverse lookup on
  626  *
  627  * @return: success: Allocated string containing the hostname
  628  *          failure: NULL
  629  */
  630 char *
  631 gf_rev_dns_lookup_cached(const char *ip, struct dnscache *dnscache)
  632 {
  633     char *fqdn = NULL;
  634     int ret = 0;
  635     dict_t *cache = NULL;
  636     data_t *entrydata = NULL;
  637     struct dnscache_entry *dnsentry = NULL;
  638     gf_boolean_t from_cache = _gf_false;
  639 
  640     if (!dnscache)
  641         goto out;
  642 
  643     cache = dnscache->cache_dict;
  644 
  645     /* Quick cache lookup to see if we already hold it */
  646     entrydata = dict_get(cache, (char *)ip);
  647     if (entrydata) {
  648         dnsentry = (struct dnscache_entry *)entrydata->data;
  649         /* First check the TTL & timestamp */
  650         if (time(NULL) - dnsentry->timestamp > dnscache->ttl) {
  651             gf_dnscache_entry_deinit(dnsentry);
  652             entrydata->data = NULL; /* Mark this as 'null' so
  653                                      * dict_del () doesn't try free
  654                                      * this after we've already
  655                                      * freed it.
  656                                      */
  657 
  658             dict_del(cache, (char *)ip); /* Remove this entry */
  659         } else {
  660             /* Cache entry is valid, get the FQDN and return */
  661             fqdn = dnsentry->fqdn;
  662             from_cache = _gf_true; /* Mark this as from cache */
  663             goto out;
  664         }
  665     }
  666 
  667     /* Get the FQDN */
  668     ret = gf_get_hostname_from_ip((char *)ip, &fqdn);
  669     if (ret != 0)
  670         goto out;
  671 
  672     if (!fqdn) {
  673         gf_log_callingfn("resolver", GF_LOG_CRITICAL,
  674                          "Allocation failed for the host address");
  675         goto out;
  676     }
  677 
  678     from_cache = _gf_false;
  679 out:
  680     /* Insert into the cache */
  681     if (fqdn && !from_cache) {
  682         struct dnscache_entry *entry = gf_dnscache_entry_init();
  683 
  684         if (!entry) {
  685             goto out;
  686         }
  687         entry->fqdn = fqdn;
  688         if (!ip) {
  689             gf_dnscache_entry_deinit(entry);
  690             goto out;
  691         }
  692 
  693         entry->ip = gf_strdup(ip);
  694         entry->timestamp = time(NULL);
  695 
  696         entrydata = bin_to_data(entry, sizeof(*entry));
  697         dict_set(cache, (char *)ip, entrydata);
  698     }
  699     return fqdn;
  700 }
  701 
  702 struct xldump {
  703     int lineno;
  704 };
  705 
  706 /* to catch any format discrepencies that may arise in code */
  707 static int
  708 nprintf(struct xldump *dump, const char *fmt, ...)
  709     __attribute__((__format__(__printf__, 2, 3)));
  710 static int
  711 nprintf(struct xldump *dump, const char *fmt, ...)
  712 {
  713     va_list ap;
  714     char *msg = NULL;
  715     char header[32];
  716     int ret = 0;
  717 
  718     ret = snprintf(header, 32, "%3d:", ++dump->lineno);
  719     if (ret < 0)
  720         goto out;
  721 
  722     va_start(ap, fmt);
  723     ret = vasprintf(&msg, fmt, ap);
  724     va_end(ap);
  725     if (-1 == ret)
  726         goto out;
  727 
  728     /* NOTE: No ret value from gf_msg_plain, so unable to compute printed
  729      * characters. The return value from nprintf is not used, so for now
  730      * living with it */
  731     gf_msg_plain(GF_LOG_WARNING, "%s %s", header, msg);
  732 
  733 out:
  734     FREE(msg);
  735     return 0;
  736 }
  737 
  738 static int
  739 xldump_options(dict_t *this, char *key, data_t *value, void *d)
  740 {
  741     nprintf(d, "    option %s %s", key, value->data);
  742     return 0;
  743 }
  744 
  745 static void
  746 xldump_subvolumes(xlator_t *this, void *d)
  747 {
  748     xlator_list_t *subv = NULL;
  749     int len = 0;
  750     char *subvstr = NULL;
  751 
  752     if (!this->children)
  753         return;
  754 
  755     for (subv = this->children; subv; subv = subv->next)
  756         len += (strlen(subv->xlator->name) + 1);
  757 
  758     subvstr = GF_MALLOC(len, gf_common_mt_strdup);
  759 
  760     len = 0;
  761     for (subv = this->children; subv; subv = subv->next)
  762         len += sprintf(subvstr + len, "%s%s", subv->xlator->name,
  763                        subv->next ? " " : "");
  764 
  765     nprintf(d, "    subvolumes %s", subvstr);
  766 
  767     GF_FREE(subvstr);
  768 }
  769 
  770 static void
  771 xldump(xlator_t *each, void *d)
  772 {
  773     nprintf(d, "volume %s", each->name);
  774     nprintf(d, "    type %s", each->type);
  775     dict_foreach(each->options, xldump_options, d);
  776 
  777     xldump_subvolumes(each, d);
  778 
  779     nprintf(d, "end-volume");
  780     nprintf(d, " ");
  781 }
  782 
  783 void
  784 gf_log_dump_graph(FILE *specfp, glusterfs_graph_t *graph)
  785 {
  786     struct xldump xld = {
  787         0,
  788     };
  789 
  790     gf_msg_plain(GF_LOG_WARNING, "Final graph:");
  791     gf_msg_plain(GF_LOG_WARNING,
  792                  "+---------------------------------------"
  793                  "---------------------------------------+");
  794 
  795     xlator_foreach_depth_first(graph->top, xldump, &xld);
  796 
  797     gf_msg_plain(GF_LOG_WARNING,
  798                  "+---------------------------------------"
  799                  "---------------------------------------+");
  800 }
  801 
  802 static void
  803 gf_dump_config_flags()
  804 {
  805     gf_msg_plain_nomem(GF_LOG_ALERT, "configuration details:");
  806 
  807 /* have argp */
  808 #ifdef HAVE_ARGP
  809     gf_msg_plain_nomem(GF_LOG_ALERT, "argp 1");
  810 #endif
  811 
  812 /* ifdef if found backtrace */
  813 #ifdef HAVE_BACKTRACE
  814     gf_msg_plain_nomem(GF_LOG_ALERT, "backtrace 1");
  815 #endif
  816 
  817 /* Berkeley-DB version has cursor->get() */
  818 #ifdef HAVE_BDB_CURSOR_GET
  819     gf_msg_plain_nomem(GF_LOG_ALERT, "bdb->cursor->get 1");
  820 #endif
  821 
  822 /* Define to 1 if you have the <db.h> header file. */
  823 #ifdef HAVE_DB_H
  824     gf_msg_plain_nomem(GF_LOG_ALERT, "db.h 1");
  825 #endif
  826 
  827 /* Define to 1 if you have the <dlfcn.h> header file. */
  828 #ifdef HAVE_DLFCN_H
  829     gf_msg_plain_nomem(GF_LOG_ALERT, "dlfcn 1");
  830 #endif
  831 
  832 /* define if fdatasync exists */
  833 #ifdef HAVE_FDATASYNC
  834     gf_msg_plain_nomem(GF_LOG_ALERT, "fdatasync 1");
  835 #endif
  836 
  837 /* Define to 1 if you have the `pthread' library (-lpthread). */
  838 #ifdef HAVE_LIBPTHREAD
  839     gf_msg_plain_nomem(GF_LOG_ALERT, "libpthread 1");
  840 #endif
  841 
  842 /* define if llistxattr exists */
  843 #ifdef HAVE_LLISTXATTR
  844     gf_msg_plain_nomem(GF_LOG_ALERT, "llistxattr 1");
  845 #endif
  846 
  847 /* define if found setfsuid setfsgid */
  848 #ifdef HAVE_SET_FSID
  849     gf_msg_plain_nomem(GF_LOG_ALERT, "setfsid 1");
  850 #endif
  851 
  852 /* define if found spinlock */
  853 #ifdef HAVE_SPINLOCK
  854     gf_msg_plain_nomem(GF_LOG_ALERT, "spinlock 1");
  855 #endif
  856 
  857 /* Define to 1 if you have the <sys/epoll.h> header file. */
  858 #ifdef HAVE_SYS_EPOLL_H
  859     gf_msg_plain_nomem(GF_LOG_ALERT, "epoll.h 1");
  860 #endif
  861 
  862 /* Define to 1 if you have the <sys/extattr.h> header file. */
  863 #ifdef HAVE_SYS_EXTATTR_H
  864     gf_msg_plain_nomem(GF_LOG_ALERT, "extattr.h 1");
  865 #endif
  866 
  867 /* Define to 1 if you have the <sys/xattr.h> header file. */
  868 #ifdef HAVE_SYS_XATTR_H
  869     gf_msg_plain_nomem(GF_LOG_ALERT, "xattr.h 1");
  870 #endif
  871 
  872 /* define if found st_atim.tv_nsec */
  873 #ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
  874     gf_msg_plain_nomem(GF_LOG_ALERT, "st_atim.tv_nsec 1");
  875 #endif
  876 
  877 /* define if found st_atimespec.tv_nsec */
  878 #ifdef HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC
  879     gf_msg_plain_nomem(GF_LOG_ALERT, "st_atimespec.tv_nsec 1");
  880 #endif
  881 
  882 /* Define to the full name and version of this package. */
  883 #ifdef PACKAGE_STRING
  884     {
  885         char *msg = NULL;
  886         int ret = -1;
  887 
  888         ret = gf_asprintf(&msg, "package-string: %s", PACKAGE_STRING);
  889         if (ret >= 0) {
  890             gf_msg_plain_nomem(GF_LOG_ALERT, msg);
  891             GF_FREE(msg);
  892         }
  893     }
  894 #endif
  895 
  896     return;
  897 }
  898 
  899 /* Obtain a backtrace and print it to the log */
  900 void
  901 gf_print_trace(int32_t signum, glusterfs_ctx_t *ctx)
  902 {
  903     char msg[1024] = {
  904         0,
  905     };
  906     char timestr[64] = {
  907         0,
  908     };
  909     call_stack_t *stack = NULL;
  910 
  911     /* Now every gf_log call will just write to a buffer and when the
  912      * buffer becomes full, its written to the log-file. Suppose the process
  913      * crashes and prints the backtrace in the log-file, then the previous
  914      * log information will still be in the buffer itself. So flush the
  915      * contents of the buffer to the log file before printing the backtrace
  916      * which helps in debugging.
  917      */
  918     gf_log_flush();
  919 
  920     gf_log_disable_suppression_before_exit(ctx);
  921 
  922     /* Pending frames, (if any), list them in order */
  923     gf_msg_plain_nomem(GF_LOG_ALERT, "pending frames:");
  924     {
  925         /* FIXME: traversing stacks outside pool->lock */
  926         list_for_each_entry(stack, &ctx->pool->all_frames, all_frames)
  927         {
  928             if (stack->type == GF_OP_TYPE_FOP)
  929                 sprintf(msg, "frame : type(%d) op(%s)", stack->type,
  930                         gf_fop_list[stack->op]);
  931             else
  932                 sprintf(msg, "frame : type(%d) op(%d)", stack->type, stack->op);
  933 
  934             gf_msg_plain_nomem(GF_LOG_ALERT, msg);
  935         }
  936     }
  937 
  938     sprintf(msg, "patchset: %s", GLUSTERFS_REPOSITORY_REVISION);
  939     gf_msg_plain_nomem(GF_LOG_ALERT, msg);
  940 
  941     sprintf(msg, "signal received: %d", signum);
  942     gf_msg_plain_nomem(GF_LOG_ALERT, msg);
  943     {
  944         /* Dump the timestamp of the crash too, so the previous logs
  945            can be related */
  946         gf_time_fmt(timestr, sizeof timestr, time(NULL), gf_timefmt_FT);
  947         gf_msg_plain_nomem(GF_LOG_ALERT, "time of crash: ");
  948         gf_msg_plain_nomem(GF_LOG_ALERT, timestr);
  949     }
  950 
  951     gf_dump_config_flags();
  952     gf_msg_backtrace_nomem(GF_LOG_ALERT, 200);
  953     sprintf(msg, "---------");
  954     gf_msg_plain_nomem(GF_LOG_ALERT, msg);
  955 
  956     /* Send a signal to terminate the process */
  957     signal(signum, SIG_DFL);
  958     raise(signum);
  959 }
  960 
  961 void
  962 trap(void)
  963 {
  964 }
  965 
  966 char *
  967 gf_trim(char *string)
  968 {
  969     register char *s, *t;
  970 
  971     if (string == NULL) {
  972         return NULL;
  973     }
  974 
  975     for (s = string; isspace(*s); s++)
  976         ;
  977 
  978     if (*s == 0)
  979         return s;
  980 
  981     t = s + strlen(s) - 1;
  982     while (t > s && isspace(*t))
  983         t--;
  984     *++t = '\0';
  985 
  986     return s;
  987 }
  988 
  989 int
  990 gf_strstr(const char *str, const char *delim, const char *match)
  991 {
  992     char *tmp = NULL;
  993     char *save_ptr = NULL;
  994     char *tmp_str = NULL;
  995 
  996     int ret = 0;
  997 
  998     tmp_str = strdup(str);
  999 
 1000     if (str == NULL || delim == NULL || match == NULL || tmp_str == NULL) {
 1001         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1002                          "argument invalid");
 1003         ret = -1;
 1004         goto out;
 1005     }
 1006 
 1007     tmp = strtok_r(tmp_str, delim, &save_ptr);
 1008 
 1009     while (tmp) {
 1010         ret = strcmp(tmp, match);
 1011 
 1012         if (ret == 0)
 1013             break;
 1014 
 1015         tmp = strtok_r(NULL, delim, &save_ptr);
 1016     }
 1017 
 1018 out:
 1019     free(tmp_str);
 1020 
 1021     return ret;
 1022 }
 1023 
 1024 int
 1025 gf_volume_name_validate(const char *volume_name)
 1026 {
 1027     const char *vname = NULL;
 1028 
 1029     if (volume_name == NULL) {
 1030         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1031                          "argument invalid");
 1032         return -1;
 1033     }
 1034 
 1035     if (!isalpha(volume_name[0]))
 1036         return 1;
 1037 
 1038     for (vname = &volume_name[1]; *vname != '\0'; vname++) {
 1039         if (!(isalnum(*vname) || *vname == '_'))
 1040             return 1;
 1041     }
 1042 
 1043     return 0;
 1044 }
 1045 
 1046 int
 1047 gf_string2time(const char *str, uint32_t *n)
 1048 {
 1049     unsigned long value = 0;
 1050     char *tail = NULL;
 1051     int old_errno = 0;
 1052     const char *s = NULL;
 1053 
 1054     if (str == NULL || n == NULL) {
 1055         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1056                          "argument invalid");
 1057         errno = EINVAL;
 1058         return -1;
 1059     }
 1060 
 1061     for (s = str; *s != '\0'; s++) {
 1062         if (isspace(*s))
 1063             continue;
 1064         if (*s == '-')
 1065             return -1;
 1066         break;
 1067     }
 1068 
 1069     old_errno = errno;
 1070     errno = 0;
 1071     value = strtol(str, &tail, 0);
 1072     if (str == tail)
 1073         errno = EINVAL;
 1074 
 1075     if (errno == ERANGE || errno == EINVAL)
 1076         return -1;
 1077 
 1078     if (errno == 0)
 1079         errno = old_errno;
 1080 
 1081     if (((tail[0] == '\0') || ((tail[0] == 's') && (tail[1] == '\0')) ||
 1082          ((tail[0] == 's') && (tail[1] == 'e') && (tail[2] == 'c') &&
 1083           (tail[3] == '\0'))))
 1084         goto out;
 1085 
 1086     else if (((tail[0] == 'm') && (tail[1] == '\0')) ||
 1087              ((tail[0] == 'm') && (tail[1] == 'i') && (tail[2] == 'n') &&
 1088               (tail[3] == '\0'))) {
 1089         value = value * GF_MINUTE_IN_SECONDS;
 1090         goto out;
 1091     }
 1092 
 1093     else if (((tail[0] == 'h') && (tail[1] == '\0')) ||
 1094              ((tail[0] == 'h') && (tail[1] == 'r') && (tail[2] == '\0'))) {
 1095         value = value * GF_HOUR_IN_SECONDS;
 1096         goto out;
 1097     }
 1098 
 1099     else if (((tail[0] == 'd') && (tail[1] == '\0')) ||
 1100              ((tail[0] == 'd') && (tail[1] == 'a') && (tail[2] == 'y') &&
 1101               (tail[3] == 's') && (tail[4] == '\0'))) {
 1102         value = value * GF_DAY_IN_SECONDS;
 1103         goto out;
 1104     }
 1105 
 1106     else if (((tail[0] == 'w') && (tail[1] == '\0')) ||
 1107              ((tail[0] == 'w') && (tail[1] == 'k') && (tail[2] == '\0'))) {
 1108         value = value * GF_WEEK_IN_SECONDS;
 1109         goto out;
 1110     } else {
 1111         return -1;
 1112     }
 1113 
 1114 out:
 1115     *n = value;
 1116 
 1117     return 0;
 1118 }
 1119 
 1120 int
 1121 gf_string2percent(const char *str, double *n)
 1122 {
 1123     double value = 0;
 1124     char *tail = NULL;
 1125     int old_errno = 0;
 1126     const char *s = NULL;
 1127 
 1128     if (str == NULL || n == NULL) {
 1129         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1130                          "argument invalid");
 1131         errno = EINVAL;
 1132         return -1;
 1133     }
 1134 
 1135     for (s = str; *s != '\0'; s++) {
 1136         if (isspace(*s))
 1137             continue;
 1138         if (*s == '-')
 1139             return -1;
 1140         break;
 1141     }
 1142 
 1143     old_errno = errno;
 1144     errno = 0;
 1145     value = strtod(str, &tail);
 1146     if (str == tail)
 1147         errno = EINVAL;
 1148 
 1149     if (errno == ERANGE || errno == EINVAL)
 1150         return -1;
 1151 
 1152     if (errno == 0)
 1153         errno = old_errno;
 1154 
 1155     if (!((tail[0] == '\0') || ((tail[0] == '%') && (tail[1] == '\0'))))
 1156         return -1;
 1157 
 1158     *n = value;
 1159 
 1160     return 0;
 1161 }
 1162 
 1163 static int
 1164 _gf_string2long(const char *str, long *n, int base)
 1165 {
 1166     long value = 0;
 1167     char *tail = NULL;
 1168     int old_errno = 0;
 1169 
 1170     if (str == NULL || n == NULL) {
 1171         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1172                          "argument invalid");
 1173         errno = EINVAL;
 1174         return -1;
 1175     }
 1176 
 1177     old_errno = errno;
 1178     errno = 0;
 1179     value = strtol(str, &tail, base);
 1180     if (str == tail)
 1181         errno = EINVAL;
 1182 
 1183     if (errno == ERANGE || errno == EINVAL)
 1184         return -1;
 1185 
 1186     if (errno == 0)
 1187         errno = old_errno;
 1188 
 1189     if (tail[0] != '\0')
 1190         return -1;
 1191 
 1192     *n = value;
 1193 
 1194     return 0;
 1195 }
 1196 
 1197 static int
 1198 _gf_string2ulong(const char *str, unsigned long *n, int base)
 1199 {
 1200     unsigned long value = 0;
 1201     char *tail = NULL;
 1202     int old_errno = 0;
 1203     const char *s = NULL;
 1204 
 1205     if (str == NULL || n == NULL) {
 1206         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1207                          "argument invalid");
 1208         errno = EINVAL;
 1209         return -1;
 1210     }
 1211 
 1212     for (s = str; *s != '\0'; s++) {
 1213         if (isspace(*s))
 1214             continue;
 1215         if (*s == '-')
 1216             return -1;
 1217         break;
 1218     }
 1219 
 1220     old_errno = errno;
 1221     errno = 0;
 1222     value = strtoul(str, &tail, base);
 1223     if (str == tail)
 1224         errno = EINVAL;
 1225 
 1226     if (errno == ERANGE || errno == EINVAL)
 1227         return -1;
 1228 
 1229     if (errno == 0)
 1230         errno = old_errno;
 1231 
 1232     if (tail[0] != '\0')
 1233         return -1;
 1234 
 1235     *n = value;
 1236 
 1237     return 0;
 1238 }
 1239 
 1240 static int
 1241 _gf_string2uint(const char *str, unsigned int *n, int base)
 1242 {
 1243     unsigned long value = 0;
 1244     char *tail = NULL;
 1245     int old_errno = 0;
 1246     const char *s = NULL;
 1247 
 1248     if (str == NULL || n == NULL) {
 1249         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1250                          "argument invalid");
 1251         errno = EINVAL;
 1252         return -1;
 1253     }
 1254 
 1255     for (s = str; *s != '\0'; s++) {
 1256         if (isspace(*s))
 1257             continue;
 1258         if (*s == '-')
 1259             return -1;
 1260         break;
 1261     }
 1262 
 1263     old_errno = errno;
 1264     errno = 0;
 1265     value = strtoul(str, &tail, base);
 1266     if (str == tail)
 1267         errno = EINVAL;
 1268 
 1269     if (errno == ERANGE || errno == EINVAL)
 1270         return -1;
 1271 
 1272     if (errno == 0)
 1273         errno = old_errno;
 1274 
 1275     if (tail[0] != '\0')
 1276         return -1;
 1277 
 1278     *n = (unsigned int)value;
 1279 
 1280     return 0;
 1281 }
 1282 
 1283 static int
 1284 _gf_string2double(const char *str, double *n)
 1285 {
 1286     double value = 0.0;
 1287     char *tail = NULL;
 1288     int old_errno = 0;
 1289 
 1290     if (str == NULL || n == NULL) {
 1291         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1292                          "argument invalid");
 1293         errno = EINVAL;
 1294         return -1;
 1295     }
 1296 
 1297     old_errno = errno;
 1298     errno = 0;
 1299     value = strtod(str, &tail);
 1300     if (str == tail)
 1301         errno = EINVAL;
 1302 
 1303     if (errno == ERANGE || errno == EINVAL)
 1304         return -1;
 1305 
 1306     if (errno == 0)
 1307         errno = old_errno;
 1308 
 1309     if (tail[0] != '\0')
 1310         return -1;
 1311 
 1312     *n = value;
 1313 
 1314     return 0;
 1315 }
 1316 
 1317 static int
 1318 _gf_string2longlong(const char *str, long long *n, int base)
 1319 {
 1320     long long value = 0;
 1321     char *tail = NULL;
 1322     int old_errno = 0;
 1323 
 1324     if (str == NULL || n == NULL) {
 1325         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1326                          "argument invalid");
 1327         errno = EINVAL;
 1328         return -1;
 1329     }
 1330 
 1331     old_errno = errno;
 1332     errno = 0;
 1333     value = strtoll(str, &tail, base);
 1334     if (str == tail)
 1335         errno = EINVAL;
 1336 
 1337     if (errno == ERANGE || errno == EINVAL)
 1338         return -1;
 1339 
 1340     if (errno == 0)
 1341         errno = old_errno;
 1342 
 1343     if (tail[0] != '\0')
 1344         return -1;
 1345 
 1346     *n = value;
 1347 
 1348     return 0;
 1349 }
 1350 
 1351 static int
 1352 _gf_string2ulonglong(const char *str, unsigned long long *n, int base)
 1353 {
 1354     unsigned long long value = 0;
 1355     char *tail = NULL;
 1356     int old_errno = 0;
 1357     const char *s = NULL;
 1358 
 1359     if (str == NULL || n == NULL) {
 1360         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1361                          "argument invalid");
 1362         errno = EINVAL;
 1363         return -1;
 1364     }
 1365 
 1366     for (s = str; *s != '\0'; s++) {
 1367         if (isspace(*s))
 1368             continue;
 1369         if (*s == '-')
 1370             return -1;
 1371         break;
 1372     }
 1373 
 1374     old_errno = errno;
 1375     errno = 0;
 1376     value = strtoull(str, &tail, base);
 1377     if (str == tail)
 1378         errno = EINVAL;
 1379 
 1380     if (errno == ERANGE || errno == EINVAL)
 1381         return -1;
 1382 
 1383     if (errno == 0)
 1384         errno = old_errno;
 1385 
 1386     if (tail[0] != '\0')
 1387         return -1;
 1388 
 1389     *n = value;
 1390 
 1391     return 0;
 1392 }
 1393 
 1394 int
 1395 gf_string2long(const char *str, long *n)
 1396 {
 1397     return _gf_string2long(str, n, 0);
 1398 }
 1399 
 1400 int
 1401 gf_string2ulong(const char *str, unsigned long *n)
 1402 {
 1403     return _gf_string2ulong(str, n, 0);
 1404 }
 1405 
 1406 int
 1407 gf_string2int(const char *str, int *n)
 1408 {
 1409     long l = 0;
 1410     int ret = 0;
 1411 
 1412     ret = _gf_string2long(str, &l, 0);
 1413 
 1414     *n = l;
 1415     return ret;
 1416 }
 1417 
 1418 int
 1419 gf_string2uint(const char *str, unsigned int *n)
 1420 {
 1421     return _gf_string2uint(str, n, 0);
 1422 }
 1423 
 1424 int
 1425 gf_string2double(const char *str, double *n)
 1426 {
 1427     return _gf_string2double(str, n);
 1428 }
 1429 
 1430 int
 1431 gf_string2longlong(const char *str, long long *n)
 1432 {
 1433     return _gf_string2longlong(str, n, 0);
 1434 }
 1435 
 1436 int
 1437 gf_string2ulonglong(const char *str, unsigned long long *n)
 1438 {
 1439     return _gf_string2ulonglong(str, n, 0);
 1440 }
 1441 
 1442 int
 1443 gf_string2int8(const char *str, int8_t *n)
 1444 {
 1445     long l = 0L;
 1446     int rv = 0;
 1447 
 1448     rv = _gf_string2long(str, &l, 0);
 1449     if (rv != 0)
 1450         return rv;
 1451 
 1452     if ((l >= INT8_MIN) && (l <= INT8_MAX)) {
 1453         *n = (int8_t)l;
 1454         return 0;
 1455     }
 1456 
 1457     errno = ERANGE;
 1458     return -1;
 1459 }
 1460 
 1461 int
 1462 gf_string2int16(const char *str, int16_t *n)
 1463 {
 1464     long l = 0L;
 1465     int rv = 0;
 1466 
 1467     rv = _gf_string2long(str, &l, 0);
 1468     if (rv != 0)
 1469         return rv;
 1470 
 1471     if ((l >= INT16_MIN) && (l <= INT16_MAX)) {
 1472         *n = (int16_t)l;
 1473         return 0;
 1474     }
 1475 
 1476     errno = ERANGE;
 1477     return -1;
 1478 }
 1479 
 1480 int
 1481 gf_string2int32(const char *str, int32_t *n)
 1482 {
 1483     long l = 0L;
 1484     int rv = 0;
 1485 
 1486     rv = _gf_string2long(str, &l, 0);
 1487     if (rv != 0)
 1488         return rv;
 1489 
 1490     if ((l >= INT32_MIN) && (l <= INT32_MAX)) {
 1491         *n = (int32_t)l;
 1492         return 0;
 1493     }
 1494 
 1495     errno = ERANGE;
 1496     return -1;
 1497 }
 1498 
 1499 int
 1500 gf_string2int64(const char *str, int64_t *n)
 1501 {
 1502     long long l = 0LL;
 1503     int rv = 0;
 1504 
 1505     rv = _gf_string2longlong(str, &l, 0);
 1506     if (rv != 0)
 1507         return rv;
 1508 
 1509     *n = (int64_t)l;
 1510     return 0;
 1511 }
 1512 
 1513 int
 1514 gf_string2uint8(const char *str, uint8_t *n)
 1515 {
 1516     unsigned long l = 0L;
 1517     int rv = 0;
 1518 
 1519     rv = _gf_string2ulong(str, &l, 0);
 1520     if (rv != 0)
 1521         return rv;
 1522 
 1523     if (l <= UINT8_MAX) {
 1524         *n = (uint8_t)l;
 1525         return 0;
 1526     }
 1527 
 1528     errno = ERANGE;
 1529     return -1;
 1530 }
 1531 
 1532 int
 1533 gf_string2uint16(const char *str, uint16_t *n)
 1534 {
 1535     unsigned long l = 0L;
 1536     int rv = 0;
 1537 
 1538     rv = _gf_string2ulong(str, &l, 0);
 1539     if (rv != 0)
 1540         return rv;
 1541 
 1542     if (l <= UINT16_MAX) {
 1543         *n = (uint16_t)l;
 1544         return 0;
 1545     }
 1546 
 1547     errno = ERANGE;
 1548     return -1;
 1549 }
 1550 
 1551 int
 1552 gf_string2uint32(const char *str, uint32_t *n)
 1553 {
 1554     unsigned long l = 0L;
 1555     int rv = 0;
 1556 
 1557     rv = _gf_string2ulong(str, &l, 0);
 1558     if (rv != 0)
 1559         return rv;
 1560 
 1561     if (l <= UINT32_MAX) {
 1562         *n = (uint32_t)l;
 1563         return 0;
 1564     }
 1565 
 1566     errno = ERANGE;
 1567     return -1;
 1568 }
 1569 
 1570 int
 1571 gf_string2uint64(const char *str, uint64_t *n)
 1572 {
 1573     unsigned long long l = 0ULL;
 1574     int rv = 0;
 1575 
 1576     rv = _gf_string2ulonglong(str, &l, 0);
 1577     if (rv != 0)
 1578         return rv;
 1579 
 1580     if (l <= UINT64_MAX) {
 1581         *n = (uint64_t)l;
 1582         return 0;
 1583     }
 1584 
 1585     errno = ERANGE;
 1586     return -1;
 1587 }
 1588 
 1589 int
 1590 gf_string2ulong_base10(const char *str, unsigned long *n)
 1591 {
 1592     return _gf_string2ulong(str, n, 10);
 1593 }
 1594 
 1595 int
 1596 gf_string2uint_base10(const char *str, unsigned int *n)
 1597 {
 1598     return _gf_string2uint(str, n, 10);
 1599 }
 1600 
 1601 int
 1602 gf_string2uint8_base10(const char *str, uint8_t *n)
 1603 {
 1604     unsigned long l = 0L;
 1605     int rv = 0;
 1606 
 1607     rv = _gf_string2ulong(str, &l, 10);
 1608     if (rv != 0)
 1609         return rv;
 1610 
 1611     if (l <= UINT8_MAX) {
 1612         *n = (uint8_t)l;
 1613         return 0;
 1614     }
 1615 
 1616     errno = ERANGE;
 1617     return -1;
 1618 }
 1619 
 1620 int
 1621 gf_string2uint16_base10(const char *str, uint16_t *n)
 1622 {
 1623     unsigned long l = 0L;
 1624     int rv = 0;
 1625 
 1626     rv = _gf_string2ulong(str, &l, 10);
 1627     if (rv != 0)
 1628         return rv;
 1629 
 1630     if (l <= UINT16_MAX) {
 1631         *n = (uint16_t)l;
 1632         return 0;
 1633     }
 1634 
 1635     errno = ERANGE;
 1636     return -1;
 1637 }
 1638 
 1639 int
 1640 gf_string2uint32_base10(const char *str, uint32_t *n)
 1641 {
 1642     unsigned long l = 0L;
 1643     int rv = 0;
 1644 
 1645     rv = _gf_string2ulong(str, &l, 10);
 1646     if (rv != 0)
 1647         return rv;
 1648 
 1649     if (l <= UINT32_MAX) {
 1650         *n = (uint32_t)l;
 1651         return 0;
 1652     }
 1653 
 1654     errno = ERANGE;
 1655     return -1;
 1656 }
 1657 
 1658 int
 1659 gf_string2uint64_base10(const char *str, uint64_t *n)
 1660 {
 1661     unsigned long long l = 0ULL;
 1662     int rv = 0;
 1663 
 1664     rv = _gf_string2ulonglong(str, &l, 10);
 1665     if (rv != 0)
 1666         return rv;
 1667 
 1668     if (l <= UINT64_MAX) {
 1669         *n = (uint64_t)l;
 1670         return 0;
 1671     }
 1672 
 1673     errno = ERANGE;
 1674     return -1;
 1675 }
 1676 
 1677 char *
 1678 gf_uint64_2human_readable(uint64_t n)
 1679 {
 1680     int ret = 0;
 1681     char *str = NULL;
 1682 
 1683     if (n >= GF_UNIT_PB) {
 1684         ret = gf_asprintf(&str, "%.1lfPB", ((double)n) / GF_UNIT_PB);
 1685         if (ret < 0)
 1686             goto err;
 1687     } else if (n >= GF_UNIT_TB) {
 1688         ret = gf_asprintf(&str, "%.1lfTB", ((double)n) / GF_UNIT_TB);
 1689         if (ret < 0)
 1690             goto err;
 1691     } else if (n >= GF_UNIT_GB) {
 1692         ret = gf_asprintf(&str, "%.1lfGB", ((double)n) / GF_UNIT_GB);
 1693         if (ret < 0)
 1694             goto err;
 1695     } else if (n >= GF_UNIT_MB) {
 1696         ret = gf_asprintf(&str, "%.1lfMB", ((double)n) / GF_UNIT_MB);
 1697         if (ret < 0)
 1698             goto err;
 1699     } else if (n >= GF_UNIT_KB) {
 1700         ret = gf_asprintf(&str, "%.1lfKB", ((double)n) / GF_UNIT_KB);
 1701         if (ret < 0)
 1702             goto err;
 1703     } else {
 1704         ret = gf_asprintf(&str, "%" PRIu64 "Bytes", n);
 1705         if (ret < 0)
 1706             goto err;
 1707     }
 1708     return str;
 1709 err:
 1710     return NULL;
 1711 }
 1712 
 1713 int
 1714 gf_string2bytesize_range(const char *str, uint64_t *n, uint64_t umax)
 1715 {
 1716     double value = 0.0;
 1717     int64_t int_value = 0;
 1718     uint64_t unit = 0;
 1719     int64_t max = 0;
 1720     char *tail = NULL;
 1721     int old_errno = 0;
 1722     const char *s = NULL;
 1723     gf_boolean_t fraction = _gf_false;
 1724 
 1725     if (str == NULL || n == NULL) {
 1726         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1727                          "argument invalid");
 1728         errno = EINVAL;
 1729         return -1;
 1730     }
 1731 
 1732     max = umax & 0x7fffffffffffffffLL;
 1733 
 1734     for (s = str; *s != '\0'; s++) {
 1735         if (isspace(*s))
 1736             continue;
 1737         if (*s == '-')
 1738             return -1;
 1739         break;
 1740     }
 1741 
 1742     if (strrchr(str, '.'))
 1743         fraction = _gf_true;
 1744 
 1745     old_errno = errno;
 1746     errno = 0;
 1747     if (fraction)
 1748         value = strtod(str, &tail);
 1749     else
 1750         int_value = strtoll(str, &tail, 10);
 1751 
 1752     if (str == tail)
 1753         errno = EINVAL;
 1754 
 1755     if (errno == ERANGE || errno == EINVAL)
 1756         return -1;
 1757 
 1758     if (errno == 0)
 1759         errno = old_errno;
 1760 
 1761     if (tail[0] != '\0') {
 1762         if (strcasecmp(tail, GF_UNIT_KB_STRING) == 0)
 1763             unit = GF_UNIT_KB;
 1764         else if (strcasecmp(tail, GF_UNIT_MB_STRING) == 0)
 1765             unit = GF_UNIT_MB;
 1766         else if (strcasecmp(tail, GF_UNIT_GB_STRING) == 0)
 1767             unit = GF_UNIT_GB;
 1768         else if (strcasecmp(tail, GF_UNIT_TB_STRING) == 0)
 1769             unit = GF_UNIT_TB;
 1770         else if (strcasecmp(tail, GF_UNIT_PB_STRING) == 0)
 1771             unit = GF_UNIT_PB;
 1772         else if (strcasecmp(tail, GF_UNIT_B_STRING) != 0)
 1773             return -1;
 1774 
 1775         if (unit > 0) {
 1776             if (fraction)
 1777                 value *= unit;
 1778             else
 1779                 int_value *= unit;
 1780         }
 1781     }
 1782 
 1783     if (fraction) {
 1784         if ((max - value) < 0) {
 1785             errno = ERANGE;
 1786             return -1;
 1787         }
 1788         *n = (uint64_t)value;
 1789     } else {
 1790         if ((max - int_value) < 0) {
 1791             errno = ERANGE;
 1792             return -1;
 1793         }
 1794         *n = int_value;
 1795     }
 1796 
 1797     return 0;
 1798 }
 1799 
 1800 int
 1801 gf_string2bytesize_uint64(const char *str, uint64_t *n)
 1802 {
 1803     return gf_string2bytesize_range(str, n, UINT64_MAX);
 1804 }
 1805 
 1806 int
 1807 gf_string2bytesize_int64(const char *str, int64_t *n)
 1808 {
 1809     uint64_t u64 = 0;
 1810     int ret = 0;
 1811 
 1812     ret = gf_string2bytesize_range(str, &u64, INT64_MAX);
 1813     *n = (int64_t)u64;
 1814     return ret;
 1815 }
 1816 
 1817 int
 1818 gf_string2percent_or_bytesize(const char *str, double *n,
 1819                               gf_boolean_t *is_percent)
 1820 {
 1821     double value = 0ULL;
 1822     char *tail = NULL;
 1823     int old_errno = 0;
 1824     const char *s = NULL;
 1825 
 1826     if (str == NULL || n == NULL) {
 1827         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1828                          "argument invalid");
 1829         errno = EINVAL;
 1830         return -1;
 1831     }
 1832 
 1833     for (s = str; *s != '\0'; s++) {
 1834         if (isspace(*s))
 1835             continue;
 1836         if (*s == '-')
 1837             return -1;
 1838         break;
 1839     }
 1840 
 1841     old_errno = errno;
 1842     errno = 0;
 1843     value = strtod(str, &tail);
 1844     if (str == tail)
 1845         errno = EINVAL;
 1846 
 1847     if (errno == ERANGE || errno == EINVAL)
 1848         return -1;
 1849 
 1850     if (errno == 0)
 1851         errno = old_errno;
 1852 
 1853     /*Maximum accepted value for 64 bit OS will be (2^14 -1)PB*/
 1854     if (tail[0] != '\0') {
 1855         if (strcasecmp(tail, GF_UNIT_KB_STRING) == 0)
 1856             value *= GF_UNIT_KB;
 1857         else if (strcasecmp(tail, GF_UNIT_MB_STRING) == 0)
 1858             value *= GF_UNIT_MB;
 1859         else if (strcasecmp(tail, GF_UNIT_GB_STRING) == 0)
 1860             value *= GF_UNIT_GB;
 1861         else if (strcasecmp(tail, GF_UNIT_TB_STRING) == 0)
 1862             value *= GF_UNIT_TB;
 1863         else if (strcasecmp(tail, GF_UNIT_PB_STRING) == 0)
 1864             value *= GF_UNIT_PB;
 1865         else if (strcasecmp(tail, GF_UNIT_PERCENT_STRING) == 0)
 1866             *is_percent = _gf_true;
 1867         else
 1868             return -1;
 1869     }
 1870 
 1871     /* Error out if we cannot store the value in uint64 */
 1872     if ((UINT64_MAX - value) < 0) {
 1873         errno = ERANGE;
 1874         return -1;
 1875     }
 1876 
 1877     *n = value;
 1878 
 1879     return 0;
 1880 }
 1881 
 1882 int64_t
 1883 gf_str_to_long_long(const char *number)
 1884 {
 1885     int64_t unit = 1;
 1886     int64_t ret = 0;
 1887     char *endptr = NULL;
 1888     if (!number)
 1889         return 0;
 1890 
 1891     ret = strtoll(number, &endptr, 0);
 1892 
 1893     if (endptr) {
 1894         switch (*endptr) {
 1895             case 'G':
 1896             case 'g':
 1897                 if ((*(endptr + 1) == 'B') || (*(endptr + 1) == 'b'))
 1898                     unit = 1024 * 1024 * 1024;
 1899                 break;
 1900             case 'M':
 1901             case 'm':
 1902                 if ((*(endptr + 1) == 'B') || (*(endptr + 1) == 'b'))
 1903                     unit = 1024 * 1024;
 1904                 break;
 1905             case 'K':
 1906             case 'k':
 1907                 if ((*(endptr + 1) == 'B') || (*(endptr + 1) == 'b'))
 1908                     unit = 1024;
 1909                 break;
 1910             case '%':
 1911                 unit = 1;
 1912                 break;
 1913             default:
 1914                 unit = 1;
 1915                 break;
 1916         }
 1917     }
 1918     return ret * unit;
 1919 }
 1920 
 1921 int
 1922 gf_string2boolean(const char *str, gf_boolean_t *b)
 1923 {
 1924     if (str == NULL) {
 1925         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1926                          "argument invalid");
 1927         return -1;
 1928     }
 1929 
 1930     if ((strcasecmp(str, "1") == 0) || (strcasecmp(str, "on") == 0) ||
 1931         (strcasecmp(str, "yes") == 0) || (strcasecmp(str, "true") == 0) ||
 1932         (strcasecmp(str, "enable") == 0)) {
 1933         *b = _gf_true;
 1934         return 0;
 1935     }
 1936 
 1937     if ((strcasecmp(str, "0") == 0) || (strcasecmp(str, "off") == 0) ||
 1938         (strcasecmp(str, "no") == 0) || (strcasecmp(str, "false") == 0) ||
 1939         (strcasecmp(str, "disable") == 0)) {
 1940         *b = _gf_false;
 1941         return 0;
 1942     }
 1943 
 1944     return -1;
 1945 }
 1946 
 1947 int
 1948 gf_strn2boolean(const char *str, const int len, gf_boolean_t *b)
 1949 {
 1950     if (str == NULL) {
 1951         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 1952                          "argument invalid");
 1953         return -1;
 1954     }
 1955 
 1956     switch (len) {
 1957         case 1:
 1958             if (strcasecmp(str, "1") == 0) {
 1959                 *b = _gf_true;
 1960                 return 0;
 1961             } else if (strcasecmp(str, "0") == 0) {
 1962                 *b = _gf_false;
 1963                 return 0;
 1964             }
 1965             break;
 1966         case 2:
 1967             if (strcasecmp(str, "on") == 0) {
 1968                 *b = _gf_true;
 1969                 return 0;
 1970             } else if (strcasecmp(str, "no") == 0) {
 1971                 *b = _gf_false;
 1972                 return 0;
 1973             }
 1974             break;
 1975         case 3:
 1976             if (strcasecmp(str, "yes") == 0) {
 1977                 *b = _gf_true;
 1978                 return 0;
 1979             } else if (strcasecmp(str, "off") == 0) {
 1980                 *b = _gf_false;
 1981                 return 0;
 1982             }
 1983             break;
 1984         case 4:
 1985             if (strcasecmp(str, "true") == 0) {
 1986                 *b = _gf_true;
 1987                 return 0;
 1988             }
 1989             break;
 1990         case 5:
 1991             if (strcasecmp(str, "false") == 0) {
 1992                 *b = _gf_false;
 1993                 return 0;
 1994             }
 1995             break;
 1996         case 6:
 1997             if (strcasecmp(str, "enable") == 0) {
 1998                 *b = _gf_true;
 1999                 return 0;
 2000             }
 2001             break;
 2002         case 7:
 2003             if (strcasecmp(str, "disable") == 0) {
 2004                 *b = _gf_false;
 2005                 return 0;
 2006             }
 2007             break;
 2008         default:
 2009             return -1;
 2010             break;
 2011     }
 2012     return -1;
 2013 }
 2014 
 2015 int
 2016 gf_lockfd(int fd)
 2017 {
 2018     struct gf_flock fl;
 2019 
 2020     fl.l_type = F_WRLCK;
 2021     fl.l_whence = SEEK_SET;
 2022     fl.l_start = 0;
 2023     fl.l_len = 0;
 2024 
 2025     return fcntl(fd, F_SETLK, &fl);
 2026 }
 2027 
 2028 int
 2029 gf_unlockfd(int fd)
 2030 {
 2031     struct gf_flock fl;
 2032 
 2033     fl.l_type = F_UNLCK;
 2034     fl.l_whence = SEEK_SET;
 2035     fl.l_start = 0;
 2036     fl.l_len = 0;
 2037 
 2038     return fcntl(fd, F_SETLK, &fl);
 2039 }
 2040 
 2041 static void
 2042 compute_checksum(char *buf, const ssize_t size, uint32_t *checksum)
 2043 {
 2044     int ret = -1;
 2045     char *checksum_buf = NULL;
 2046 
 2047     checksum_buf = (char *)(checksum);
 2048 
 2049     if (!(*checksum)) {
 2050         checksum_buf[0] = 0xba;
 2051         checksum_buf[1] = 0xbe;
 2052         checksum_buf[2] = 0xb0;
 2053         checksum_buf[3] = 0x0b;
 2054     }
 2055 
 2056     for (ret = 0; ret < (size - 4); ret += 4) {
 2057         checksum_buf[0] ^= (buf[ret]);
 2058         checksum_buf[1] ^= (buf[ret + 1] << 1);
 2059         checksum_buf[2] ^= (buf[ret + 2] << 2);
 2060         checksum_buf[3] ^= (buf[ret + 3] << 3);
 2061     }
 2062 
 2063     for (ret = 0; ret <= (size % 4); ret++) {
 2064         checksum_buf[ret] ^= (buf[(size - 4) + ret] << ret);
 2065     }
 2066 
 2067     return;
 2068 }
 2069 
 2070 #define GF_CHECKSUM_BUF_SIZE 1024
 2071 
 2072 int
 2073 get_checksum_for_file(int fd, uint32_t *checksum, int op_version)
 2074 {
 2075     int ret = -1;
 2076     char buf[GF_CHECKSUM_BUF_SIZE] = {
 2077         0,
 2078     };
 2079 
 2080     /* goto first place */
 2081     sys_lseek(fd, 0L, SEEK_SET);
 2082     do {
 2083         ret = sys_read(fd, &buf, GF_CHECKSUM_BUF_SIZE);
 2084         if (ret > 0) {
 2085             if (op_version < GD_OP_VERSION_5_4)
 2086                 compute_checksum(buf, GF_CHECKSUM_BUF_SIZE, checksum);
 2087             else
 2088                 compute_checksum(buf, ret, checksum);
 2089         }
 2090     } while (ret > 0);
 2091 
 2092     /* set it back */
 2093     sys_lseek(fd, 0L, SEEK_SET);
 2094 
 2095     return ret;
 2096 }
 2097 
 2098 int
 2099 get_checksum_for_path(char *path, uint32_t *checksum, int op_version)
 2100 {
 2101     int ret = -1;
 2102     int fd = -1;
 2103 
 2104     GF_ASSERT(path);
 2105     GF_ASSERT(checksum);
 2106 
 2107     fd = open(path, O_RDWR);
 2108 
 2109     if (fd == -1) {
 2110         gf_smsg(THIS->name, GF_LOG_ERROR, errno, LG_MSG_PATH_OPEN_FAILED,
 2111                 "path=%s", path, NULL);
 2112         goto out;
 2113     }
 2114 
 2115     ret = get_checksum_for_file(fd, checksum, op_version);
 2116 
 2117 out:
 2118     if (fd != -1)
 2119         sys_close(fd);
 2120 
 2121     return ret;
 2122 }
 2123 
 2124 /**
 2125  * get_file_mtime -- Given a path, get the mtime for the file
 2126  *
 2127  * @path: The filepath to check the mtime on
 2128  * @stamp: The parameter to set after we get the mtime
 2129  *
 2130  * @returns: success: 0
 2131  *           errors : Errors returned by the stat () call
 2132  */
 2133 int
 2134 get_file_mtime(const char *path, time_t *stamp)
 2135 {
 2136     struct stat f_stat = {0};
 2137     int ret = -EINVAL;
 2138 
 2139     GF_VALIDATE_OR_GOTO(THIS->name, path, out);
 2140     GF_VALIDATE_OR_GOTO(THIS->name, stamp, out);
 2141 
 2142     ret = sys_stat(path, &f_stat);
 2143     if (ret < 0) {
 2144         gf_smsg(THIS->name, GF_LOG_ERROR, errno, LG_MSG_FILE_STAT_FAILED,
 2145                 "path=%s", path, NULL);
 2146         goto out;
 2147     }
 2148 
 2149     /* Set the mtime */
 2150     *stamp = f_stat.st_mtime;
 2151 out:
 2152     return ret;
 2153 }
 2154 
 2155 /**
 2156  * gf_is_ip_in_net -- Checks if an IP Address is in a network.
 2157  *                    A network should be specified by something like
 2158  *                    '10.5.153.0/24' (in CIDR notation).
 2159  *
 2160  * @result : Sets to true if the IP is in the network
 2161  * @ip_str : The IP to check
 2162  * @network: The network to check the IP against.
 2163  *
 2164  * @return: success: _gf_true
 2165  *          failure: -EINVAL for bad args, retval of inet_pton otherwise
 2166  */
 2167 gf_boolean_t
 2168 gf_is_ip_in_net(const char *network, const char *ip_str)
 2169 {
 2170     unsigned long ip_buf = 0;
 2171     unsigned long net_ip_buf = 0;
 2172     unsigned long subnet_mask = 0;
 2173     int ret = -EINVAL;
 2174     char *slash = NULL;
 2175     char *net_ip = NULL;
 2176     char *subnet = NULL;
 2177     char *net_str = NULL;
 2178     int family = AF_INET;
 2179     gf_boolean_t result = _gf_false;
 2180 
 2181     GF_ASSERT(network);
 2182     GF_ASSERT(ip_str);
 2183 
 2184     if (strchr(network, ':'))
 2185         family = AF_INET6;
 2186     else if (strchr(network, '.'))
 2187         family = AF_INET;
 2188     else {
 2189         goto out;
 2190     }
 2191 
 2192     net_str = strdupa(network);
 2193     slash = strchr(net_str, '/');
 2194     if (!slash)
 2195         goto out;
 2196     *slash = '\0';
 2197 
 2198     subnet = slash + 1;
 2199     net_ip = net_str;
 2200 
 2201     /* Convert IP address to a long */
 2202     ret = inet_pton(family, ip_str, &ip_buf);
 2203     if (ret < 0)
 2204         gf_smsg("common-utils", GF_LOG_ERROR, errno, LG_MSG_INET_PTON_FAILED,
 2205                 NULL);
 2206 
 2207     /* Convert network IP address to a long */
 2208     ret = inet_pton(family, net_ip, &net_ip_buf);
 2209     if (ret < 0) {
 2210         gf_smsg("common-utils", GF_LOG_ERROR, errno, LG_MSG_INET_PTON_FAILED,
 2211                 NULL);
 2212         goto out;
 2213     }
 2214 
 2215     /* Converts /x into a mask */
 2216     subnet_mask = (1 << atoi(subnet)) - 1;
 2217 
 2218     result = ((ip_buf & subnet_mask) == (net_ip_buf & subnet_mask));
 2219 out:
 2220     return result;
 2221 }
 2222 
 2223 char *
 2224 strtail(char *str, const char *pattern)
 2225 {
 2226     int i = 0;
 2227 
 2228     for (i = 0; str[i] == pattern[i] && str[i]; i++)
 2229         ;
 2230 
 2231     if (pattern[i] == '\0')
 2232         return str + i;
 2233 
 2234     return NULL;
 2235 }
 2236 
 2237 void
 2238 skipwhite(char **s)
 2239 {
 2240     while (isspace(**s))
 2241         (*s)++;
 2242 }
 2243 
 2244 void
 2245 gf_strTrim(char **s)
 2246 {
 2247     char *end = NULL;
 2248 
 2249     end = *s + strlen(*s) - 1;
 2250     while (end > *s && isspace((unsigned char)*end))
 2251         end--;
 2252 
 2253     *(end + 1) = '\0';
 2254 
 2255     while (isspace(**s))
 2256         (*s)++;
 2257 
 2258     return;
 2259 }
 2260 
 2261 char *
 2262 nwstrtail(char *str, char *pattern)
 2263 {
 2264     for (;;) {
 2265         skipwhite(&str);
 2266         skipwhite(&pattern);
 2267 
 2268         if (*str != *pattern || !*str)
 2269             break;
 2270 
 2271         str++;
 2272         pattern++;
 2273     }
 2274 
 2275     return *pattern ? NULL : str;
 2276 }
 2277 
 2278 /**
 2279  * token_iter_init -- initialize tokenization
 2280  *
 2281  * @str: string to be tokenized
 2282  * @sep: token separator character
 2283  * @tit: pointer to iteration state
 2284  *
 2285  * @return: token string
 2286  *
 2287  * The returned token string and tit are
 2288  * not to be used directly, but through
 2289  * next_token().
 2290  */
 2291 char *
 2292 token_iter_init(char *str, char sep, token_iter_t *tit)
 2293 {
 2294     tit->end = str + strlen(str);
 2295     tit->sep = sep;
 2296 
 2297     return str;
 2298 }
 2299 
 2300 /**
 2301  * next_token -- fetch next token in tokenization
 2302  * inited by token_iter_init().
 2303  *
 2304  * @tokenp: pointer to token
 2305  * @tit:    pointer to iteration state
 2306  *
 2307  * @return: true if iteration ends, else false
 2308  *
 2309  * The token pointed by @tokenp can be used
 2310  * after a call to next_token(). When next_token()
 2311  * returns true the iteration is to be stopped
 2312  * and the string with which the tokenization
 2313  * was inited (see token_iter_init() is restored,
 2314  * apart from dropped tokens (see drop_token()).
 2315  */
 2316 gf_boolean_t
 2317 next_token(char **tokenp, token_iter_t *tit)
 2318 {
 2319     char *cursor = NULL;
 2320     gf_boolean_t is_last = _gf_false;
 2321 
 2322     for (cursor = *tokenp; *cursor; cursor++)
 2323         ;
 2324     if (cursor < tit->end) {
 2325         /*
 2326          * We detect that in between current token and end a zero
 2327          * marker has already been inserted. This means that the
 2328          * token has already been returned. We restore the
 2329          * separator and move ahead.
 2330          */
 2331         *cursor = tit->sep;
 2332         *tokenp = cursor + 1;
 2333     }
 2334 
 2335     for (cursor = *tokenp; *cursor && *cursor != tit->sep; cursor++)
 2336         ;
 2337     /* If the cursor ended up on a zero byte, then it's the last token. */
 2338     is_last = !*cursor;
 2339     /* Zero-terminate the token. */
 2340     *cursor = 0;
 2341 
 2342     return is_last;
 2343 }
 2344 
 2345 /*
 2346  * drop_token -- drop a token during iterated calls of next_token().
 2347  *
 2348  * Sample program that uses these functions to tokenize
 2349  * a comma-separated first argument while dropping the
 2350  * rest of the arguments if they occur as token:
 2351  *
 2352  * #include <stdio.h>
 2353  * #include <stdlib.h>
 2354  * #include <string.h>
 2355  * #include "glusterfs/common-utils.h"
 2356  *
 2357  * int
 2358  * main (int argc, char **argv)
 2359  * {
 2360  *         char *buf;
 2361  *         char *token;
 2362  *         token_iter_t tit;
 2363  *         int i;
 2364  *         gf_boolean_t iter_end;
 2365  *
 2366  *         if (argc <= 1)
 2367  *                 abort();
 2368  *
 2369  *         buf = strdup (argv[1]);
 2370  *         if (!buf)
 2371  *                 abort();
 2372  *
 2373  *         for (token = token_iter_init (buf, ',', &tit) ;;) {
 2374  *                 iter_end = next_token (&token, &tit);
 2375  *                 printf("found token: '%s'\n", token);
 2376  *                 for (i = 2; i < argc; i++) {
 2377  *                         if (strcmp (argv[i], token) == 0) {
 2378  *                                 printf ("%s\n", "dropping token!");
 2379  *                                 drop_token (token, &tit);
 2380  *                                 break;
 2381  *                          }
 2382  *                 }
 2383  *                 if (iter_end)
 2384  *                         break;
 2385  *         }
 2386  *
 2387  *         printf ("finally: '%s'\n", buf);
 2388  *
 2389  *         return 0;
 2390  * }
 2391  */
 2392 void
 2393 drop_token(char *token, token_iter_t *tit)
 2394 {
 2395     char *cursor = NULL;
 2396 
 2397     for (cursor = token; *cursor; cursor++)
 2398         ;
 2399     if (cursor < tit->end) {
 2400         /*
 2401          * We detect a zero inserted by next_token().
 2402          * Step the cursor and copy what comes after
 2403          * to token.
 2404          */
 2405         for (cursor++; cursor < tit->end; *token++ = *cursor++)
 2406             ;
 2407     }
 2408 
 2409     /*
 2410      * Zero out the remainder of the buffer.
 2411      * It would be enough to insert just a single zero,
 2412      * but we continue 'till the end to have cleaner
 2413      * memory content.
 2414      */
 2415     for (cursor = token; cursor < tit->end; *cursor++ = 0)
 2416         ;
 2417 
 2418     /* Adjust the end to point to the new terminating zero. */
 2419     tit->end = token;
 2420 }
 2421 
 2422 /* Syntax formed according to RFC 1912 (RFC 1123 & 952 are more restrictive)  *
 2423    <hname> ::= <gen-name>*["."<gen-name>]                                     *
 2424    <gen-name> ::= <let-or-digit> <[*[<let-or-digit-or-hyphen>]<let-or-digit>] */
 2425 char
 2426 valid_host_name(char *address, int length)
 2427 {
 2428     int i = 0;
 2429     int str_len = 0;
 2430     char ret = 1;
 2431     char *dup_addr = NULL;
 2432     char *temp_str = NULL;
 2433     char *save_ptr = NULL;
 2434 
 2435     if ((length > _POSIX_HOST_NAME_MAX) || (length < 1)) {
 2436         ret = 0;
 2437         goto out;
 2438     }
 2439 
 2440     dup_addr = gf_strdup(address);
 2441     if (!dup_addr) {
 2442         ret = 0;
 2443         goto out;
 2444     }
 2445 
 2446     if (!isalnum(dup_addr[length - 1]) && (dup_addr[length - 1] != '*')) {
 2447         ret = 0;
 2448         goto out;
 2449     }
 2450 
 2451     /* Check for consecutive dots, which is invalid in a hostname and is
 2452      * ignored by strtok()
 2453      */
 2454     if (strstr(dup_addr, "..")) {
 2455         ret = 0;
 2456         goto out;
 2457     }
 2458 
 2459     /* gen-name */
 2460     temp_str = strtok_r(dup_addr, ".", &save_ptr);
 2461     do {
 2462         str_len = strlen(temp_str);
 2463 
 2464         if (!isalnum(temp_str[0]) || !isalnum(temp_str[str_len - 1])) {
 2465             ret = 0;
 2466             goto out;
 2467         }
 2468         for (i = 1; i < str_len; i++) {
 2469             if (!isalnum(temp_str[i]) && (temp_str[i] != '-')) {
 2470                 ret = 0;
 2471                 goto out;
 2472             }
 2473         }
 2474     } while ((temp_str = strtok_r(NULL, ".", &save_ptr)));
 2475 
 2476 out:
 2477     GF_FREE(dup_addr);
 2478     return ret;
 2479 }
 2480 
 2481 /*  Matches all ipv4 address, if wildcard_acc is true  '*' wildcard pattern for*
 2482   subnets is considered as valid strings as well */
 2483 char
 2484 valid_ipv4_address(char *address, int length, gf_boolean_t wildcard_acc)
 2485 {
 2486     int octets = 0;
 2487     int value = 0;
 2488     char *tmp = NULL, *ptr = NULL, *prev = NULL, *endptr = NULL;
 2489     char ret = 1;
 2490     int is_wildcard = 0;
 2491 
 2492     tmp = gf_strdup(address);
 2493 
 2494     /*
 2495      * To prevent cases where last character is '.' and which have
 2496      * consecutive dots like ".." as strtok ignore consecutive
 2497      * delimiters.
 2498      */
 2499     if (length <= 0 || (strstr(address, "..")) ||
 2500         (!isdigit(tmp[length - 1]) && (tmp[length - 1] != '*'))) {
 2501         ret = 0;
 2502         goto out;
 2503     }
 2504 
 2505     prev = strtok_r(tmp, ".", &ptr);
 2506 
 2507     while (prev != NULL) {
 2508         octets++;
 2509         if (wildcard_acc && !strcmp(prev, "*")) {
 2510             is_wildcard = 1;
 2511         } else {
 2512             value = strtol(prev, &endptr, 10);
 2513             if ((value > 255) || (value < 0) ||
 2514                 (endptr != NULL && *endptr != '\0')) {
 2515                 ret = 0;
 2516                 goto out;
 2517             }
 2518         }
 2519         prev = strtok_r(NULL, ".", &ptr);
 2520     }
 2521 
 2522     if ((octets > 4) || (octets < 4 && !is_wildcard)) {
 2523         ret = 0;
 2524     }
 2525 
 2526 out:
 2527     GF_FREE(tmp);
 2528     return ret;
 2529 }
 2530 
 2531 char
 2532 valid_cidr_address(char *cidr_address, gf_boolean_t wildcard_acc)
 2533 {
 2534     unsigned int net_mask = 0, len = 0;
 2535     char *temp = NULL, *cidr_str = NULL, ret = 1;
 2536 
 2537     cidr_str = strdupa(cidr_address);
 2538     temp = strstr(cidr_str, "/");
 2539     if (temp == NULL)
 2540         return 0; /* Since Invalid cidr ip address we return 0 */
 2541 
 2542     *temp = '\0';
 2543     temp++;
 2544     net_mask = (unsigned int)atoi(temp);
 2545 
 2546     if (net_mask > 32 || net_mask < 1)
 2547         return 0; /* Since Invalid cidr ip address we return 0*/
 2548 
 2549     len = strlen(cidr_str);
 2550 
 2551     ret = valid_ipv4_address(cidr_str, len, wildcard_acc);
 2552 
 2553     return ret;
 2554 }
 2555 
 2556 /**
 2557  * valid_ipv4_subnetwork() takes the pattern and checks if it contains
 2558  * a valid ipv4 subnetwork pattern i.e. xx.xx.xx.xx/n. IPv4 address
 2559  * part (xx.xx.xx.xx) and mask bits length part (n). The mask bits length
 2560  * must be in 0-32 range (ipv4 addr is 32 bit). The pattern must be
 2561  * in this format.
 2562  *
 2563  * Returns _gf_true if both IP addr and mask bits len are valid
 2564  *         _gf_false otherwise.
 2565  */
 2566 gf_boolean_t
 2567 valid_ipv4_subnetwork(const char *address)
 2568 {
 2569     char *slash = NULL;
 2570     char *paddr = NULL;
 2571     char *endptr = NULL;
 2572     long prefixlen = -1;
 2573     gf_boolean_t retv = _gf_true;
 2574 
 2575     if (address == NULL) {
 2576         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 2577                          "argument invalid");
 2578         return _gf_false;
 2579     }
 2580 
 2581     paddr = gf_strdup(address);
 2582     if (paddr == NULL) /* ENOMEM */
 2583         return _gf_false;
 2584 
 2585     /*
 2586      * INVALID: If '/' is not present OR
 2587      *          Nothing specified after '/'
 2588      */
 2589     slash = strchr(paddr, '/');
 2590     if ((slash == NULL) || (slash[1] == '\0')) {
 2591         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0,
 2592                          LG_MSG_INVALID_IPV4_FORMAT,
 2593                          "Invalid IPv4 "
 2594                          "subnetwork format");
 2595         retv = _gf_false;
 2596         goto out;
 2597     }
 2598 
 2599     *slash = '\0';
 2600     retv = valid_ipv4_address(paddr, strlen(paddr), _gf_false);
 2601     if (retv == _gf_false) {
 2602         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0,
 2603                          LG_MSG_INVALID_IPV4_FORMAT,
 2604                          "Invalid IPv4 subnetwork address");
 2605         goto out;
 2606     }
 2607     /*
 2608      * Reset errno before checking it
 2609      */
 2610     errno = 0;
 2611     prefixlen = strtol(slash + 1, &endptr, 10);
 2612     if ((errno != 0) || (*endptr != '\0') || (prefixlen < 0) ||
 2613         (prefixlen > IPv4_ADDR_SIZE)) {
 2614         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, 0,
 2615                          LG_MSG_INVALID_IPV4_FORMAT,
 2616                          "Invalid IPv4 subnetwork mask");
 2617         retv = _gf_false;
 2618         goto out;
 2619     }
 2620 
 2621     retv = _gf_true;
 2622 out:
 2623     GF_FREE(paddr);
 2624     return retv;
 2625 }
 2626 
 2627 char
 2628 valid_ipv6_address(char *address, int length, gf_boolean_t wildcard_acc)
 2629 {
 2630     int hex_numbers = 0;
 2631     int value = 0;
 2632     int i = 0;
 2633     char *tmp = NULL, *ptr = NULL, *prev = NULL, *endptr = NULL;
 2634     char ret = 1;
 2635     int is_wildcard = 0;
 2636     int is_compressed = 0;
 2637 
 2638     tmp = gf_strdup(address);
 2639 
 2640     /* Check for '%' for link local addresses */
 2641     endptr = strchr(tmp, '%');
 2642     if (endptr) {
 2643         *endptr = '\0';
 2644         length = strlen(tmp);
 2645         endptr = NULL;
 2646     }
 2647 
 2648     /* Check for compressed form */
 2649     if (length <= 0 || tmp[length - 1] == ':') {
 2650         ret = 0;
 2651         goto out;
 2652     }
 2653     for (i = 0; i < (length - 1); i++) {
 2654         if (tmp[i] == ':' && tmp[i + 1] == ':') {
 2655             if (is_compressed == 0)
 2656                 is_compressed = 1;
 2657             else {
 2658                 ret = 0;
 2659                 goto out;
 2660             }
 2661         }
 2662     }
 2663 
 2664     prev = strtok_r(tmp, ":", &ptr);
 2665 
 2666     while (prev != NULL) {
 2667         hex_numbers++;
 2668         if (wildcard_acc && !strcmp(prev, "*")) {
 2669             is_wildcard = 1;
 2670         } else {
 2671             value = strtol(prev, &endptr, 16);
 2672             if ((value > 0xffff) || (value < 0) ||
 2673                 (endptr != NULL && *endptr != '\0')) {
 2674                 ret = 0;
 2675                 goto out;
 2676             }
 2677         }
 2678         prev = strtok_r(NULL, ":", &ptr);
 2679     }
 2680 
 2681     if ((hex_numbers > 8) ||
 2682         (hex_numbers < 8 && !is_wildcard && !is_compressed)) {
 2683         ret = 0;
 2684     }
 2685 
 2686 out:
 2687     GF_FREE(tmp);
 2688     return ret;
 2689 }
 2690 
 2691 char
 2692 valid_internet_address(char *address, gf_boolean_t wildcard_acc,
 2693                        gf_boolean_t cidr)
 2694 {
 2695     char ret = 0;
 2696     int length = 0;
 2697 
 2698     if (address == NULL) {
 2699         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 2700                          "argument invalid");
 2701         goto out;
 2702     }
 2703 
 2704     length = strlen(address);
 2705     if (length == 0)
 2706         goto out;
 2707 
 2708     if (cidr && valid_cidr_address(address, wildcard_acc)) {
 2709         ret = 1;
 2710     }
 2711 
 2712     if (valid_ipv4_address(address, length, wildcard_acc) ||
 2713         valid_ipv6_address(address, length, wildcard_acc) ||
 2714         valid_host_name(address, length))
 2715         ret = 1;
 2716 
 2717 out:
 2718     return ret;
 2719 }
 2720 
 2721 /**
 2722  * valid_mount_auth_address - Validate the rpc-auth.addr.allow/reject pattern
 2723  *
 2724  * @param address - Pattern to be validated
 2725  *
 2726  * @return _gf_true if "address" is "*" (anonymous) 'OR'
 2727  *                  if "address" is valid FQDN or valid IPv4/6 address 'OR'
 2728  *                  if "address" contains wildcard chars e.g. "'*' or '?' or
 2729  * '['" if "address" is valid ipv4 subnet pattern (xx.xx.xx.xx/n) _gf_false
 2730  * otherwise
 2731  *
 2732  *
 2733  * NB: If the user/admin set for wildcard pattern, then it does not have
 2734  *     to be validated. Make it similar to the way exportfs (kNFS) works.
 2735  */
 2736 gf_boolean_t
 2737 valid_mount_auth_address(char *address)
 2738 {
 2739     int length = 0;
 2740     char *cp = NULL;
 2741 
 2742     /* 1. Check for "NULL and empty string */
 2743     if ((address == NULL) || (address[0] == '\0')) {
 2744         gf_msg_callingfn(THIS->name, GF_LOG_WARNING, EINVAL, LG_MSG_INVALID_ARG,
 2745                          "argument invalid");
 2746         return _gf_false;
 2747     }
 2748 
 2749     /* 2. Check for Anonymous */
 2750     if (strcmp(address, "*") == 0)
 2751         return _gf_true;
 2752 
 2753     for (cp = address; *cp; cp++) {
 2754         /* 3. Check for wildcard pattern */
 2755         if (*cp == '*' || *cp == '?' || *cp == '[') {
 2756             return _gf_true;
 2757         }
 2758 
 2759         /*
 2760          * 4. check for IPv4 subnetwork i.e. xx.xx.xx.xx/n
 2761          * TODO: check for IPv6 subnetwork
 2762          * NB: Wildcard must not be mixed with subnetwork.
 2763          */
 2764         if (*cp == '/') {
 2765             return valid_ipv4_subnetwork(address);
 2766         }
 2767     }
 2768 
 2769     /* 5. Check for v4/v6 IP addr and FQDN/hostname */
 2770     length = strlen(address);
 2771     if ((valid_ipv4_address(address, length, _gf_false)) ||
 2772         (valid_ipv6_address(address, length, _gf_false)) ||
 2773         (valid_host_name(address, length))) {
 2774         return _gf_true;
 2775     }
 2776 
 2777     return _gf_false;
 2778 }
 2779 
 2780 /**
 2781  * gf_sock_union_equal_addr - check if two given gf_sock_unions have same addr
 2782  *
 2783  * @param a - first sock union
 2784  * @param b - second sock union
 2785  * @return _gf_true if a and b have same ipv{4,6} addr, _gf_false otherwise
 2786  */
 2787 gf_boolean_t
 2788 gf_sock_union_equal_addr(union gf_sock_union *a, union gf_sock_union *b)
 2789 {
 2790     if (!a || !b) {
 2791         gf_smsg("common-utils", GF_LOG_ERROR, 0, LG_MSG_INVALID_ENTRY,
 2792                 "gf_sock_union_equal_addr", NULL);
 2793         return _gf_false;
 2794     }
 2795 
 2796     if (a->storage.ss_family != b->storage.ss_family)
 2797         return _gf_false;
 2798 
 2799     switch (a->storage.ss_family) {
 2800         case AF_INET:
 2801             if (a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr)
 2802                 return _gf_true;
 2803             else
 2804                 return _gf_false;
 2805 
 2806         case AF_INET6:
 2807             if (memcmp((void *)(&a->sin6.sin6_addr),
 2808                        (void *)(&b->sin6.sin6_addr), sizeof(a->sin6.sin6_addr)))
 2809                 return _gf_false;
 2810             else
 2811                 return _gf_true;
 2812 
 2813         default:
 2814             gf_msg_debug("common-utils", 0,
 2815                          "Unsupported/invalid address "
 2816                          "family");
 2817             break;
 2818     }
 2819 
 2820     return _gf_false;
 2821 }
 2822 
 2823 /*
 2824  * Check if both have same network address.
 2825  * Extract the network address from the sockaddr(s) addr by applying the
 2826  * network mask. If they match, return boolean _gf_true, _gf_false otherwise.
 2827  *
 2828  * (x == y) <=> (x ^ y == 0)
 2829  * (x & y) ^ (x & z) <=> x & (y ^ z)
 2830  *
 2831  * ((ip1 & mask) == (ip2 & mask)) <=> ((mask & (ip1 ^ ip2)) == 0)
 2832  */
 2833 gf_boolean_t
 2834 mask_match(const uint32_t a, const uint32_t b, const uint32_t m)
 2835 {
 2836     return (((a ^ b) & m) == 0);
 2837 }
 2838 
 2839 /*Thread safe conversion function*/
 2840 char *
 2841 uuid_utoa(uuid_t uuid)
 2842 {
 2843     char *uuid_buffer = glusterfs_uuid_buf_get();
 2844     gf_uuid_unparse(uuid, uuid_buffer);
 2845     return uuid_buffer;
 2846 }
 2847 
 2848 /*Re-entrant conversion function*/
 2849 char *
 2850 uuid_utoa_r(uuid_t uuid, char *dst)
 2851 {
 2852     if (!dst)
 2853         return NULL;
 2854     gf_uuid_unparse(uuid, dst);
 2855     return dst;
 2856 }
 2857 
 2858 /*Thread safe conversion function*/
 2859 char *
 2860 lkowner_utoa(gf_lkowner_t *lkowner)
 2861 {
 2862     char *lkowner_buffer = glusterfs_lkowner_buf_get();
 2863     lkowner_unparse(lkowner, lkowner_buffer, GF_LKOWNER_BUF_SIZE);
 2864     return lkowner_buffer;
 2865 }
 2866 
 2867 /*Re-entrant conversion function*/
 2868 char *
 2869 lkowner_utoa_r(gf_lkowner_t *lkowner, char *dst, int len)
 2870 {
 2871     if (!dst)
 2872         return NULL;
 2873     lkowner_unparse(lkowner, dst, len);
 2874     return dst;
 2875 }
 2876 
 2877 gf_boolean_t
 2878 is_valid_lease_id(const char *lease_id)
 2879 {
 2880     int i = 0;
 2881     gf_boolean_t valid = _gf_false;
 2882 
 2883     for (i = 0; i < LEASE_ID_SIZE; i++) {
 2884         if (lease_id[i] != 0) {
 2885             valid = _gf_true;
 2886             goto out;
 2887         }
 2888     }
 2889 out:
 2890     return valid;
 2891 }
 2892 
 2893 /* Lease_id can be a either in printable or non printable binary
 2894  * format. This function can be used to print any lease_id.
 2895  *
 2896  * This function returns a pointer to a buf, containing the ascii
 2897  * representation of the value in lease_id, in the following format:
 2898  * 4hexnum-4hexnum-4hexnum-4hexnum-4hexnum-4hexnum-4hexnum-4hexnum
 2899  *
 2900  * Eg: If lease_id = "lid1-clnt1" the printable string would be:
 2901  * 6c69-6431-2d63-6c6e-7431-0000-0000-0000
 2902  *
 2903  * Note: The pointer returned should not be stored for further use, as any
 2904  * subsequent call to this function will override the same buffer.
 2905  */
 2906 char *
 2907 leaseid_utoa(const char *lease_id)
 2908 {
 2909     char *buf = NULL;
 2910     int i = 0;
 2911     int j = 0;
 2912 
 2913     buf = glusterfs_leaseid_buf_get();
 2914     if (!buf)
 2915         goto out;
 2916 
 2917     for (i = 0; i < LEASE_ID_SIZE; i++) {
 2918         if (i && !(i % 2)) {
 2919             buf[j] = '-';
 2920             j++;
 2921         }
 2922         sprintf(&buf[j], "%02hhx", lease_id[i]);
 2923         j += 2;
 2924         if (j == GF_LEASE_ID_BUF_SIZE)
 2925             break;
 2926     }
 2927     buf[GF_LEASE_ID_BUF_SIZE - 1] = '\0';
 2928 out:
 2929     return buf;
 2930 }
 2931 
 2932 char *
 2933 gf_leaseid_get()
 2934 {
 2935     return glusterfs_leaseid_buf_get();
 2936 }
 2937 
 2938 char *
 2939 gf_existing_leaseid()
 2940 {
 2941     return glusterfs_leaseid_exist();
 2942 }
 2943 
 2944 void *
 2945 gf_array_elem(void *a, int index, size_t elem_size)
 2946 {
 2947     uint8_t *ptr = a;
 2948     return (void *)(ptr + index * elem_size);
 2949 }
 2950 
 2951 void
 2952 gf_elem_swap(void *x, void *y, size_t l)
 2953 {
 2954     uint8_t *a = x, *b = y, c;
 2955     while (l--) {
 2956         c = *a;
 2957         *a++ = *b;
 2958         *b++ = c;
 2959     }
 2960 }
 2961 
 2962 void
 2963 gf_array_insertionsort(void *A, int l, int r, size_t elem_size, gf_cmp cmp)
 2964 {
 2965     int i = l;
 2966     int N = r + 1;
 2967     void *Temp = NULL;
 2968     int j = 0;
 2969 
 2970     for (i = l; i < N; i++) {
 2971         Temp = gf_array_elem(A, i, elem_size);
 2972         j = i - 1;
 2973         while (j >= 0 && (cmp(Temp, gf_array_elem(A, j, elem_size)) < 0)) {
 2974             gf_elem_swap(Temp, gf_array_elem(A, j, elem_size), elem_size);
 2975             Temp = gf_array_elem(A, j, elem_size);
 2976             j = j - 1;
 2977         }
 2978     }
 2979 }
 2980 
 2981 int
 2982 gf_is_str_int(const char *value)
 2983 {
 2984     int flag = 0;
 2985     char *str = NULL;
 2986     char *fptr = NULL;
 2987 
 2988     GF_VALIDATE_OR_GOTO(THIS->name, value, out);
 2989 
 2990     str = gf_strdup(value);
 2991     if (!str)
 2992         goto out;
 2993 
 2994     fptr = str;
 2995 
 2996     while (*str) {
 2997         if (!isdigit(*str)) {
 2998             flag = 1;
 2999             goto out;
 3000         }
 3001         str++;
 3002     }
 3003 
 3004 out:
 3005     GF_FREE(fptr);
 3006 
 3007     return flag;
 3008 }
 3009 /*
 3010  * rounds up nr to power of two. If nr is already a power of two, just returns
 3011  * nr
 3012  */
 3013 
 3014 int32_t
 3015 gf_roundup_power_of_two(int32_t nr)
 3016 {
 3017     int32_t result = 1;
 3018 
 3019     if (nr < 0) {
 3020         gf_smsg("common-utils", GF_LOG_WARNING, 0, LG_MSG_NEGATIVE_NUM_PASSED,
 3021                 NULL);
 3022         result = -1;
 3023         goto out;
 3024     }
 3025 
 3026     while (result < nr)
 3027         result *= 2;
 3028 
 3029 out:
 3030     return result;
 3031 }
 3032 
 3033 /*
 3034  * rounds up nr to next power of two. If nr is already a power of two, next
 3035  * power of two is returned.
 3036  */
 3037 
 3038 int32_t
 3039 gf_roundup_next_power_of_two(int32_t nr)
 3040 {
 3041     int32_t result = 1;
 3042 
 3043     if (nr < 0) {
 3044         gf_smsg("common-utils", GF_LOG_WARNING, 0, LG_MSG_NEGATIVE_NUM_PASSED,
 3045                 NULL);
 3046         result = -1;
 3047         goto out;
 3048     }
 3049 
 3050     while (result <= nr)
 3051         result *= 2;
 3052 
 3053 out:
 3054     return result;
 3055 }
 3056 
 3057 int
 3058 validate_brick_name(char *brick)
 3059 {
 3060     char *delimiter = NULL;
 3061     int ret = 0;
 3062     delimiter = strrchr(brick, ':');
 3063     if (!delimiter || delimiter == brick || *(delimiter + 1) != '/')
 3064         ret = -1;
 3065 
 3066     return ret;
 3067 }
 3068 
 3069 char *
 3070 get_host_name(char *word, char **host)
 3071 {
 3072     char *delimiter = NULL;
 3073     delimiter = strrchr(word, ':');
 3074     if (delimiter)
 3075         *delimiter = '\0';
 3076     else
 3077         return NULL;
 3078     *host = word;
 3079     return *host;
 3080 }
 3081 
 3082 char *
 3083 get_path_name(char *word, char **path)
 3084 {
 3085     char *delimiter = NULL;
 3086     delimiter = strchr(word, '/');
 3087     if (!delimiter)
 3088         return NULL;
 3089     *path = delimiter;
 3090     return *path;
 3091 }
 3092 
 3093 void
 3094 gf_path_strip_trailing_slashes(char *path)
 3095 {
 3096     int i = 0;
 3097     int len = 0;
 3098 
 3099     if (!path)
 3100         return;
 3101 
 3102     len = strlen(path);
 3103     for (i = len - 1; i > 0; i--) {
 3104         if (path[i] != '/')
 3105             break;
 3106     }
 3107 
 3108     if (i < (len - 1))
 3109         path[i + 1] = '\0';
 3110 
 3111     return;
 3112 }
 3113 
 3114 uint64_t
 3115 get_mem_size()
 3116 {
 3117     uint64_t memsize = -1;
 3118 
 3119 #if defined GF_LINUX_HOST_OS || defined GF_SOLARIS_HOST_OS
 3120 
 3121     uint64_t page_size = 0;
 3122     uint64_t num_pages = 0;
 3123 
 3124     page_size = sysconf(_SC_PAGESIZE);
 3125     num_pages = sysconf(_SC_PHYS_PAGES);
 3126 
 3127     memsize = page_size * num_pages;
 3128 #endif
 3129 
 3130 #if defined GF_DARWIN_HOST_OS
 3131 
 3132     size_t len = sizeof(memsize);
 3133     int name[] = {CTL_HW, HW_PHYSMEM};
 3134 
 3135     sysctl(name, 2, &memsize, &len, NULL, 0);
 3136 #endif
 3137 
 3138 #if defined __NetBSD__
 3139 
 3140     size_t len = sizeof(memsize);
 3141     int name64[] = {CTL_HW, HW_PHYSMEM64};
 3142 
 3143     sysctl(name64, 2, &memsize, &len, NULL, 0);
 3144     if (memsize == -1)
 3145         sysctl(name64, 2, &memsize, &len, NULL, 0);
 3146 #endif
 3147     return memsize;
 3148 }
 3149 
 3150 /* Strips all whitespace characters in a string and returns length of new string
 3151  * on success
 3152  */
 3153 int
 3154 gf_strip_whitespace(char *str, int len)
 3155 {
 3156     int i = 0;
 3157     int new_len = 0;
 3158     char *new_str = NULL;
 3159 
 3160     GF_ASSERT(str);
 3161 
 3162     new_str = GF_MALLOC(len + 1, gf_common_mt_char);
 3163     if (new_str == NULL)
 3164         return -1;
 3165 
 3166     for (i = 0; i < len; i++) {
 3167         if (!isspace(str[i]))
 3168             new_str[new_len++] = str[i];
 3169     }
 3170     new_str[new_len] = '\0';
 3171 
 3172     if (new_len != len) {
 3173         snprintf(str, new_len + 1, "%s", new_str);
 3174     }
 3175 
 3176     GF_FREE(new_str);
 3177     return new_len;
 3178 }
 3179 
 3180 int
 3181 gf_canonicalize_path(char *path)
 3182 {
 3183     int ret = -1;
 3184     int path_len = 0;
 3185     int dir_path_len = 0;
 3186     char *tmppath = NULL;
 3187     char *dir = NULL;
 3188     char *tmpstr = NULL;
 3189 
 3190     if (!path || *path != '/')
 3191         goto out;
 3192 
 3193     if (!strcmp(path, "/"))
 3194         return 0;
 3195 
 3196     tmppath = gf_strdup(path);
 3197     if (!tmppath)
 3198         goto out;
 3199 
 3200     /* Strip the extra slashes and return */
 3201     bzero(path, strlen(path));
 3202     path[0] = '/';
 3203     dir = strtok_r(tmppath, "/", &tmpstr);
 3204 
 3205     while (dir) {
 3206         dir_path_len = strlen(dir);
 3207         memcpy((path + path_len + 1), dir, dir_path_len);
 3208         path_len += dir_path_len + 1;
 3209         dir = strtok_r(NULL, "/", &tmpstr);
 3210         if (dir) {
 3211             path[path_len] = '/';
 3212         }
 3213     }
 3214     path[path_len] = '\0';
 3215     ret = 0;
 3216 
 3217 out:
 3218     if (ret)
 3219         gf_smsg("common-utils", GF_LOG_ERROR, 0, LG_MSG_PATH_ERROR, NULL);
 3220 
 3221     GF_FREE(tmppath);
 3222 
 3223     return ret;
 3224 }
 3225 
 3226 static const char *__gf_timefmts[] = {
 3227     "%F %T", "%Y/%m/%d-%T", "%b %d %T", "%F %H%M%S", "%Y-%m-%d-%T", "%s",
 3228 };
 3229 
 3230 static const char *__gf_zerotimes[] = {
 3231     "0000-00-00 00:00:00", "0000/00/00-00:00:00", "xxx 00 00:00:00",
 3232     "0000-00-00 000000",   "0000-00-00-00:00:00", "0",
 3233 };
 3234 
 3235 void
 3236 _gf_timestuff(const char ***fmts, const char ***zeros)
 3237 {
 3238     *fmts = __gf_timefmts;
 3239     *zeros = __gf_zerotimes;
 3240 }
 3241 
 3242 char *
 3243 generate_glusterfs_ctx_id(void)
 3244 {
 3245     uuid_t ctxid;
 3246     char *tmp = NULL;
 3247 
 3248     gf_uuid_generate(ctxid);
 3249     tmp = uuid_utoa(ctxid);
 3250 
 3251     return gf_strdup(tmp);
 3252 }
 3253 
 3254 char *
 3255 gf_get_reserved_ports()
 3256 {
 3257     char *ports_info = NULL;
 3258 #if defined GF_LINUX_HOST_OS
 3259     int proc_fd = -1;
 3260     char *proc_file = "/proc/sys/net/ipv4/ip_local_reserved_ports";
 3261     char buffer[4096] = {
 3262         0,
 3263     };
 3264     int32_t ret = -1;
 3265 
 3266     proc_fd = open(proc_file, O_RDONLY);
 3267     if (proc_fd == -1) {
 3268         /* What should be done in this case? error out from here
 3269          * and thus stop the glusterfs process from starting or
 3270          * continue with older method of using any of the available
 3271          * port? For now 2nd option is considered.
 3272          */
 3273         gf_smsg("glusterfs", GF_LOG_WARNING, errno, LG_MSG_FILE_OP_FAILED,
 3274                 " /proc/sys/net/ipv4/ip_local_reserved_ports", NULL);
 3275         goto out;
 3276     }
 3277 
 3278     ret = sys_read(proc_fd, buffer, sizeof(buffer) - 1);
 3279     if (ret < 0) {
 3280         gf_smsg("glusterfs", GF_LOG_WARNING, errno, LG_MSG_FILE_OP_FAILED,
 3281                 "file=%s", proc_file, NULL);
 3282         goto out;
 3283     }
 3284 
 3285     buffer[ret] = '\0';
 3286     ports_info = gf_strdup(buffer);
 3287 
 3288 out:
 3289     if (proc_fd != -1)
 3290         sys_close(proc_fd);
 3291 #endif /* GF_LINUX_HOST_OS */
 3292     return ports_info;
 3293 }
 3294 
 3295 int
 3296 gf_process_reserved_ports(unsigned char *ports, uint32_t ceiling)
 3297 {
 3298     int ret = -1;
 3299 
 3300     memset(ports, 0, GF_PORT_ARRAY_SIZE);
 3301 
 3302 #if defined GF_LINUX_HOST_OS
 3303     char *ports_info = NULL;
 3304     char *tmp = NULL;
 3305     char *blocked_port = NULL;
 3306 
 3307     ports_info = gf_get_reserved_ports();
 3308     if (!ports_info) {
 3309         gf_smsg("glusterfs", GF_LOG_WARNING, 0, LG_MSG_RESERVED_PORTS_ERROR,
 3310                 NULL);
 3311         goto out;
 3312     }
 3313 
 3314     blocked_port = strtok_r(ports_info, ",\n", &tmp);
 3315 
 3316     while (blocked_port) {
 3317         gf_ports_reserved(blocked_port, ports, ceiling);
 3318         blocked_port = strtok_r(NULL, ",\n", &tmp);
 3319     }
 3320 
 3321     ret = 0;
 3322 
 3323 out:
 3324     GF_FREE(ports_info);
 3325 
 3326 #else  /* FIXME: Non Linux Host */
 3327     ret = 0;
 3328 #endif /* GF_LINUX_HOST_OS */
 3329 
 3330     return ret;
 3331 }
 3332 
 3333 gf_boolean_t
 3334 gf_ports_reserved(char *blocked_port, unsigned char *ports, uint32_t ceiling)
 3335 {
 3336     gf_boolean_t result = _gf_false;
 3337     char *range_port = NULL;
 3338     int32_t tmp_port1 = -1;
 3339     int32_t tmp_port2 = -1;
 3340 
 3341     if (strstr(blocked_port, "-") == NULL) {
 3342         /* get rid of the new line character*/
 3343         if (blocked_port[strlen(blocked_port) - 1] == '\n')
 3344             blocked_port[strlen(blocked_port) - 1] = '\0';
 3345         if (gf_string2int32(blocked_port, &tmp_port1) == 0) {
 3346             if (tmp_port1 > GF_PORT_MAX || tmp_port1 < 0) {
 3347                 gf_smsg("glusterfs-socket", GF_LOG_WARNING, 0,
 3348                         LG_MSG_INVALID_PORT, "port=%d", tmp_port1, NULL);
 3349                 result = _gf_true;
 3350                 goto out;
 3351             } else {
 3352                 gf_msg_debug("glusterfs", 0,
 3353                              "blocking port "
 3354                              "%d",
 3355                              tmp_port1);
 3356                 BIT_SET(ports, tmp_port1);
 3357             }
 3358         } else {
 3359             gf_smsg("glusterfs-socket", GF_LOG_WARNING, 0, LG_MSG_INVALID_PORT,
 3360                     "port=%s", blocked_port, NULL);
 3361             result = _gf_true;
 3362             goto out;
 3363         }
 3364     } else {
 3365         range_port = strtok(blocked_port, "-");
 3366         if (!range_port) {
 3367             result = _gf_true;
 3368             goto out;
 3369         }
 3370         if (gf_string2int32(range_port, &tmp_port1) == 0) {
 3371             if (tmp_port1 > ceiling)
 3372                 tmp_port1 = ceiling;
 3373             if (tmp_port1 < 0)
 3374                 tmp_port1 = 0;
 3375         }
 3376         range_port = strtok(NULL, "-");
 3377         if (!range_port) {
 3378             result = _gf_true;
 3379             goto out;
 3380         }
 3381         /* get rid of the new line character*/
 3382         if (range_port[strlen(range_port) - 1] == '\n')
 3383             range_port[strlen(range_port) - 1] = '\0';
 3384         if (gf_string2int32(range_port, &tmp_port2) == 0) {
 3385             if (tmp_port2 > ceiling)
 3386                 tmp_port2 = ceiling;
 3387             if (tmp_port2 < 0)
 3388                 tmp_port2 = 0;
 3389         }
 3390         gf_msg_debug("glusterfs", 0, "lower: %d, higher: %d", tmp_port1,
 3391                      tmp_port2);
 3392         for (; tmp_port1 <= tmp_port2; tmp_port1++)
 3393             BIT_SET(ports, tmp_port1);
 3394     }
 3395 
 3396 out:
 3397     return result;
 3398 }
 3399 
 3400 /* Takes in client ip{v4,v6} and returns associated hostname, if any
 3401  * Also, allocates memory for the hostname.
 3402  * Returns: 0 for success, -1 for failure
 3403  */
 3404 int
 3405 gf_get_hostname_from_ip(char *client_ip, char **hostname)
 3406 {
 3407     int ret = -1;
 3408     struct sockaddr *client_sockaddr = NULL;
 3409     struct sockaddr_in client_sock_in = {0};
 3410     struct sockaddr_in6 client_sock_in6 = {0};
 3411     char client_hostname[NI_MAXHOST] = {0};
 3412     char *client_ip_copy = NULL;
 3413     char *tmp = NULL;
 3414     char *ip = NULL;
 3415     size_t addr_sz = 0;
 3416 
 3417     /* if ipv4, reverse lookup the hostname to
 3418      * allow FQDN based rpc authentication
 3419      */
 3420     if (!valid_ipv6_address(client_ip, strlen(client_ip), 0) &&
 3421         !valid_ipv4_address(client_ip, strlen(client_ip), 0)) {
 3422         /* most times, we get a.b.c.d:port form, so check that */
 3423         client_ip_copy = gf_strdup(client_ip);
 3424         if (!client_ip_copy)
 3425             goto out;
 3426 
 3427         ip = strtok_r(client_ip_copy, ":", &tmp);
 3428     } else {
 3429         ip = client_ip;
 3430     }
 3431 
 3432     if (valid_ipv4_address(ip, strlen(ip), 0) == _gf_true) {
 3433         client_sockaddr = (struct sockaddr *)&client_sock_in;
 3434         addr_sz = sizeof(client_sock_in);
 3435         client_sock_in.sin_family = AF_INET;
 3436         ret = inet_pton(AF_INET, ip, (void *)&client_sock_in.sin_addr.s_addr);
 3437 
 3438     } else if (valid_ipv6_address(ip, strlen(ip), 0) == _gf_true) {
 3439         client_sockaddr = (struct sockaddr *)&client_sock_in6;
 3440         addr_sz = sizeof(client_sock_in6);
 3441 
 3442         client_sock_in6.sin6_family = AF_INET6;
 3443         ret = inet_pton(AF_INET6, ip, (void *)&client_sock_in6.sin6_addr);
 3444     } else {
 3445         goto out;
 3446     }
 3447 
 3448     if (ret != 1) {
 3449         ret = -1;
 3450         goto out;
 3451     }
 3452 
 3453     /* You cannot just use sizeof (*client_sockaddr), as per the man page
 3454      * the (getnameinfo) size must be the size of the underlying sockaddr
 3455      * struct e.g. sockaddr_in6 or sockaddr_in.  Failure to do so will
 3456      * break IPv6 hostname resolution (IPv4 will work only because
 3457      * the sockaddr_in struct happens to be of the correct size).
 3458      */
 3459     ret = getnameinfo(client_sockaddr, addr_sz, client_hostname,
 3460                       sizeof(client_hostname), NULL, 0, 0);
 3461     if (ret) {
 3462         gf_smsg("common-utils", GF_LOG_ERROR, 0, LG_MSG_GETNAMEINFO_FAILED,
 3463                 "ip=%s", client_ip, "ret=%s", gai_strerror(ret), NULL);
 3464         ret = -1;
 3465         goto out;
 3466     }
 3467 
 3468     *hostname = gf_strdup((char *)client_hostname);
 3469 out:
 3470     if (client_ip_copy)
 3471         GF_FREE(client_ip_copy);
 3472 
 3473     return ret;
 3474 }
 3475 
 3476 gf_boolean_t
 3477 gf_interface_search(char *ip)
 3478 {
 3479     int32_t ret = -1;
 3480     gf_boolean_t found = _gf_false;
 3481     struct ifaddrs *ifaddr, *ifa;
 3482     int family;
 3483     char host[NI_MAXHOST];
 3484     xlator_t *this = NULL;
 3485     char *pct = NULL;
 3486 
 3487     this = THIS;
 3488 
 3489     ret = getifaddrs(&ifaddr);
 3490 
 3491     if (ret != 0) {
 3492         gf_smsg(this->name, GF_LOG_ERROR, 0, LG_MSG_GETIFADDRS_FAILED, "ret=%s",
 3493                 gai_strerror(ret), NULL);
 3494         goto out;
 3495     }
 3496 
 3497     for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
 3498         if (!ifa->ifa_addr) {
 3499             /*
 3500              * This seemingly happens if an interface hasn't
 3501              * been bound to a particular protocol (seen with
 3502              * TUN devices).
 3503              */
 3504             continue;
 3505         }
 3506         family = ifa->ifa_addr->sa_family;
 3507 
 3508         if (family != AF_INET && family != AF_INET6)
 3509             continue;
 3510 
 3511         ret = getnameinfo(ifa->ifa_addr,
 3512                           (family == AF_INET) ? sizeof(struct sockaddr_in)
 3513                                               : sizeof(struct sockaddr_in6),
 3514                           host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
 3515 
 3516         if (ret != 0) {
 3517             gf_smsg(this->name, GF_LOG_ERROR, 0, LG_MSG_GETNAMEINFO_FAILED,
 3518                     "ret=%s", gai_strerror(ret), NULL);
 3519             goto out;
 3520         }
 3521 
 3522         /*
 3523          * Sometimes the address comes back as addr%eth0 or
 3524          * similar.  Since % is an invalid character, we can
 3525          * strip it out with confidence that doing so won't
 3526          * harm anything.
 3527          */
 3528         pct = index(host, '%');
 3529         if (pct) {
 3530             *pct = '\0';
 3531         }
 3532 
 3533         if (strncmp(ip, host, NI_MAXHOST) == 0) {
 3534             gf_msg_debug(this->name, 0,
 3535                          "%s is local address at "
 3536                          "interface %s",
 3537                          ip, ifa->ifa_name);
 3538             found = _gf_true;
 3539             goto out;
 3540         }
 3541     }
 3542 out:
 3543     if (ifaddr)
 3544         freeifaddrs(ifaddr);
 3545     return found;
 3546 }
 3547 
 3548 char *
 3549 get_ip_from_addrinfo(struct addrinfo *addr, char **ip)
 3550 {
 3551     char buf[64];
 3552     void *in_addr = NULL;
 3553     struct sockaddr_in *s4 = NULL;
 3554     struct sockaddr_in6 *s6 = NULL;
 3555 
 3556     switch (addr->ai_family) {
 3557         case AF_INET:
 3558             s4 = (struct sockaddr_in *)addr->ai_addr;
 3559             in_addr = &s4->sin_addr;
 3560             break;
 3561 
 3562         case AF_INET6:
 3563             s6 = (struct sockaddr_in6 *)addr->ai_addr;
 3564             in_addr = &s6->sin6_addr;
 3565             break;
 3566 
 3567         default:
 3568             gf_smsg("glusterd", GF_LOG_ERROR, 0, LG_MSG_INVALID_FAMILY, NULL);
 3569             return NULL;
 3570     }
 3571 
 3572     if (!inet_ntop(addr->ai_family, in_addr, buf, sizeof(buf))) {
 3573         gf_smsg("glusterd", GF_LOG_ERROR, 0, LG_MSG_CONVERSION_FAILED, NULL);
 3574         return NULL;
 3575     }
 3576 
 3577     *ip = gf_strdup(buf);
 3578     return *ip;
 3579 }
 3580 
 3581 gf_boolean_t
 3582 gf_is_loopback_localhost(const struct sockaddr *sa, char *hostname)
 3583 {
 3584     GF_ASSERT(sa);
 3585 
 3586     gf_boolean_t is_local = _gf_false;
 3587     const struct in_addr *addr4 = NULL;
 3588     const struct in6_addr *addr6 = NULL;
 3589     uint8_t *ap = NULL;
 3590     struct in6_addr loopbackaddr6 = IN6ADDR_LOOPBACK_INIT;
 3591 
 3592     switch (sa->sa_family) {
 3593         case AF_INET:
 3594             addr4 = &(((struct sockaddr_in *)sa)->sin_addr);
 3595             ap = (uint8_t *)&addr4->s_addr;
 3596             if (ap[0] == 127)
 3597                 is_local = _gf_true;
 3598             break;
 3599 
 3600         case AF_INET6:
 3601             addr6 = &(((struct sockaddr_in6 *)sa)->sin6_addr);
 3602             if (memcmp(addr6, &loopbackaddr6, sizeof(loopbackaddr6)) == 0)
 3603                 is_local = _gf_true;
 3604             break;
 3605 
 3606         default:
 3607             if (hostname)
 3608                 gf_smsg("glusterd", GF_LOG_ERROR, 0, LG_MSG_INVALID_FAMILY,
 3609                         "family=%d", sa->sa_family, "hostname=%s", hostname,
 3610                         NULL);
 3611             break;
 3612     }
 3613 
 3614     return is_local;
 3615 }
 3616 
 3617 gf_boolean_t
 3618 gf_is_local_addr(char *hostname)
 3619 {
 3620     int32_t ret = -1;
 3621     struct addrinfo *result = NULL;
 3622     struct addrinfo *res = NULL;
 3623     gf_boolean_t found = _gf_false;
 3624     char *ip = NULL;
 3625     xlator_t *this = NULL;
 3626     struct addrinfo hints;
 3627 
 3628     this = THIS;
 3629 
 3630     memset(&hints, 0, sizeof(hints));
 3631     /*
 3632      * Removing AI_ADDRCONFIG from default_hints
 3633      * for being able to use link local ipv6 addresses
 3634      */
 3635     hints.ai_family = AF_UNSPEC;
 3636 
 3637     ret = getaddrinfo(hostname, NULL, &hints, &result);
 3638 
 3639     if (ret != 0) {
 3640         gf_smsg(this->name, GF_LOG_ERROR, 0, LG_MSG_GETADDRINFO_FAILED,
 3641                 "ret=%s", gai_strerror(ret), NULL);
 3642         goto out;
 3643     }
 3644 
 3645     for (res = result; res != NULL; res = res->ai_next) {
 3646         get_ip_from_addrinfo(res, &ip);
 3647         gf_msg_debug(this->name, 0, "%s ", ip);
 3648 
 3649         if (ip) {
 3650             found = (gf_is_loopback_localhost(res->ai_addr, hostname) ||
 3651                      gf_interface_search(ip));
 3652         }
 3653         if (found) {
 3654             GF_FREE(ip);
 3655             goto out;
 3656         }
 3657         GF_FREE(ip);
 3658         /* the above free will not set ip to NULL, and hence, there is
 3659            double free possible as the loop continues. set ip to NULL. */
 3660         ip = NULL;
 3661     }
 3662 
 3663 out:
 3664     if (result)
 3665         freeaddrinfo(result);
 3666 
 3667     if (!found)
 3668         gf_msg_debug(this->name, 0, "%s is not local", hostname);
 3669 
 3670     return found;
 3671 }
 3672 
 3673 gf_boolean_t
 3674 gf_is_same_address(char *name1, char *name2)
 3675 {
 3676     struct addrinfo *addr1 = NULL;
 3677     struct addrinfo *addr2 = NULL;
 3678     struct addrinfo *p = NULL;
 3679     struct addrinfo *q = NULL;
 3680     gf_boolean_t ret = _gf_false;
 3681     int gai_err = 0;
 3682     struct addrinfo hints;
 3683 
 3684     memset(&hints, 0, sizeof(hints));
 3685     hints.ai_family = AF_UNSPEC;
 3686 
 3687     gai_err = getaddrinfo(name1, NULL, &hints, &addr1);
 3688     if (gai_err != 0) {
 3689         gf_smsg(name1, GF_LOG_WARNING, 0, LG_MSG_GETADDRINFO_FAILED, "error=%s",
 3690                 gai_strerror(gai_err), NULL);
 3691         goto out;
 3692     }
 3693 
 3694     gai_err = getaddrinfo(name2, NULL, &hints, &addr2);
 3695     if (gai_err != 0) {
 3696         gf_smsg(name2, GF_LOG_WARNING, 0, LG_MSG_GETADDRINFO_FAILED, "error=%s",
 3697                 gai_strerror(gai_err), NULL);
 3698         goto out;
 3699     }
 3700 
 3701     for (p = addr1; p; p = p->ai_next) {
 3702         for (q = addr2; q; q = q->ai_next) {
 3703             if (p->ai_addrlen != q->ai_addrlen) {
 3704                 continue;
 3705             }
 3706             if (memcmp(p->ai_addr, q->ai_addr, p->ai_addrlen)) {
 3707                 continue;
 3708             }
 3709             ret = _gf_true;
 3710             goto out;
 3711         }
 3712     }
 3713 
 3714 out:
 3715     if (addr1) {
 3716         freeaddrinfo(addr1);
 3717     }
 3718     if (addr2) {
 3719         freeaddrinfo(addr2);
 3720     }
 3721     return ret;
 3722 }
 3723 
 3724 /*
 3725  * Processes list of volfile servers.
 3726  * Format: <host1>:<port1> <host2>:<port2>...
 3727  */
 3728 int
 3729 gf_process_getspec_servers_list(cmd_args_t *cmd_args, const char *servers_list)
 3730 {
 3731     char *tmp = NULL;
 3732     char *address = NULL;
 3733     char *host = NULL;
 3734     char *last_colon = NULL;
 3735     char *save_ptr = NULL;
 3736     int port = 0;
 3737     int ret = -1;
 3738 
 3739     tmp = gf_strdup(servers_list);
 3740     if (!tmp) {
 3741         errno = ENOMEM;
 3742         goto out;
 3743     }
 3744 
 3745     address = strtok_r(tmp, " ", &save_ptr);
 3746     if (!address) {
 3747         errno = EINVAL;
 3748         goto out;
 3749     }
 3750 
 3751     while (1) {
 3752         last_colon = strrchr(address, ':');
 3753         if (!last_colon) {
 3754             errno = EINVAL;
 3755             ret = -1;
 3756             break;
 3757         }
 3758         *last_colon = '\0';
 3759         host = address;
 3760         port = atoi(last_colon + 1);
 3761         if (port <= 0) {
 3762             errno = EINVAL;
 3763             ret = -1;
 3764             break;
 3765         }
 3766         ret = gf_set_volfile_server_common(cmd_args, host,
 3767                                            GF_DEFAULT_VOLFILE_TRANSPORT, port);
 3768         if (ret && errno != EEXIST) {
 3769             break;
 3770         }
 3771         address = strtok_r(NULL, " ", &save_ptr);
 3772         if (!address) {
 3773             errno = 0;
 3774             ret = 0;
 3775             break;
 3776         }
 3777     }
 3778 
 3779 out:
 3780     if (tmp) {
 3781         GF_FREE(tmp);
 3782     }
 3783 
 3784     return ret;
 3785 }
 3786 
 3787 int
 3788 gf_set_volfile_server_common(cmd_args_t *cmd_args, const char *host,
 3789                              const char *transport, int port)
 3790 {
 3791     server_cmdline_t *server = NULL;
 3792     server_cmdline_t *tmp = NULL;
 3793     int ret = -1;
 3794 
 3795     GF_VALIDATE_OR_GOTO(THIS->name, cmd_args, out);
 3796     GF_VALIDATE_OR_GOTO(THIS->name, host, out);
 3797     GF_VALIDATE_OR_GOTO(THIS->name, transport, out);
 3798 
 3799     server = GF_CALLOC(1, sizeof(server_cmdline_t),
 3800                        gf_common_mt_server_cmdline_t);
 3801     if (!server) {
 3802         errno = ENOMEM;
 3803         goto out;
 3804     }
 3805 
 3806     INIT_LIST_HEAD(&server->list);
 3807 
 3808     server->volfile_server = gf_strdup(host);
 3809     if (!server->volfile_server) {
 3810         errno = ENOMEM;
 3811         goto out;
 3812     }
 3813 
 3814     server->transport = gf_strdup(transport);
 3815     if (!server->transport) {
 3816         errno = ENOMEM;
 3817         goto out;
 3818     }
 3819 
 3820     server->port = port;
 3821 
 3822     if (!cmd_args->volfile_server) {
 3823         cmd_args->volfile_server = server->volfile_server;
 3824         cmd_args->volfile_server_transport = server->transport;
 3825         cmd_args->volfile_server_port = server->port;
 3826         cmd_args->curr_server = server;
 3827     }
 3828 
 3829     list_for_each_entry(tmp, &cmd_args->volfile_servers, list)
 3830     {
 3831         if ((!strcmp(tmp->volfile_server, server->volfile_server) &&
 3832              !strcmp(tmp->transport, server->transport) &&
 3833              (tmp->port == server->port))) {
 3834             /* Duplicate option given, log and ignore */
 3835             gf_smsg("gluster", GF_LOG_INFO, EEXIST, LG_MSG_DUPLICATE_ENTRY,
 3836                     NULL);
 3837             ret = 0;
 3838             goto out;
 3839         }
 3840     }
 3841 
 3842     list_add_tail(&server->list, &cmd_args->volfile_servers);
 3843 
 3844     ret = 0;
 3845 out:
 3846     if (-1 == ret) {
 3847         if (server) {
 3848             GF_FREE(server->volfile_server);
 3849             GF_FREE(server->transport);
 3850             GF_FREE(server);
 3851         }
 3852     }
 3853 
 3854     return ret;
 3855 }
 3856 
 3857 /* Sets log file path from user provided arguments */
 3858 int
 3859 gf_set_log_file_path(cmd_args_t *cmd_args, glusterfs_ctx_t *ctx)
 3860 {
 3861     int i = 0;
 3862     int j = 0;
 3863     int ret = 0;
 3864     int tmp_len = 0;
 3865     char tmp_str[1024] = {
 3866         0,
 3867     };
 3868 
 3869     if (!cmd_args)
 3870         goto done;
 3871 
 3872     if (cmd_args->mount_point) {
 3873         j = 0;
 3874         i = 0;
 3875         if (cmd_args->mount_point[0] == '/')
 3876             i = 1;
 3877         for (; i < strlen(cmd_args->mount_point); i++, j++) {
 3878             tmp_str[j] = cmd_args->mount_point[i];
 3879             if (cmd_args->mount_point[i] == '/')
 3880                 tmp_str[j] = '-';
 3881         }
 3882 
 3883         ret = gf_asprintf(&cmd_args->log_file,
 3884                           DEFAULT_LOG_FILE_DIRECTORY "/%s.log", tmp_str);
 3885         if (ret > 0)
 3886             ret = 0;
 3887         goto done;
 3888     }
 3889 
 3890     if (ctx && GF_GLUSTERD_PROCESS == ctx->process_mode) {
 3891         ret = gf_asprintf(&cmd_args->log_file,
 3892                           DEFAULT_LOG_FILE_DIRECTORY "/%s.log", GLUSTERD_NAME);
 3893         if (ret > 0)
 3894             ret = 0;
 3895 
 3896         goto done;
 3897     }
 3898 
 3899     if (cmd_args->volfile) {
 3900         j = 0;
 3901         i = 0;
 3902         if (cmd_args->volfile[0] == '/')
 3903             i = 1;
 3904         for (; i < strlen(cmd_args->volfile); i++, j++) {
 3905             tmp_str[j] = cmd_args->volfile[i];
 3906             if (cmd_args->volfile[i] == '/')
 3907                 tmp_str[j] = '-';
 3908         }
 3909         ret = gf_asprintf(&cmd_args->log_file,
 3910                           DEFAULT_LOG_FILE_DIRECTORY "/%s.log", tmp_str);
 3911         if (ret > 0)
 3912             ret = 0;
 3913         goto done;
 3914     }
 3915 
 3916     if (cmd_args->volfile_server) {
 3917         if (strncmp(cmd_args->volfile_server_transport, "unix", 4) == 0) {
 3918             if (cmd_args->volfile_server[0] == '/')
 3919                 i = 1;
 3920             tmp_len = strlen(cmd_args->volfile_server);
 3921             for (j = 0; i < tmp_len; i++, j++) {
 3922                 tmp_str[j] = cmd_args->volfile_server[i];
 3923                 if (cmd_args->volfile_server[i] == '/')
 3924                     tmp_str[j] = '-';
 3925             }
 3926             ret = gf_asprintf(&cmd_args->log_file, "%s/%s-%s-%d.log",
 3927                               DEFAULT_LOG_FILE_DIRECTORY, tmp_str,
 3928                               cmd_args->volfile_id, getpid());
 3929         } else {
 3930             ret = gf_asprintf(&cmd_args->log_file, "%s/%s-%s-%d.log",
 3931                               DEFAULT_LOG_FILE_DIRECTORY,
 3932                               cmd_args->volfile_server, cmd_args->volfile_id,
 3933                               getpid());
 3934         }
 3935         if (ret > 0)
 3936             ret = 0;
 3937     }
 3938 done:
 3939     return ret;
 3940 }
 3941 
 3942 int
 3943 gf_set_log_ident(cmd_args_t *cmd_args)
 3944 {
 3945     int ret = 0;
 3946     char *ptr = NULL;
 3947 
 3948     if (cmd_args->log_file == NULL) {
 3949         /* no ident source */
 3950         return 0;
 3951     }
 3952 
 3953     /* TODO: Some idents would look like, etc-glusterfs-glusterd.vol, which
 3954      * seems ugly and can be bettered? */
 3955     /* just get the filename as the ident */
 3956     if (NULL != (ptr = strrchr(cmd_args->log_file, '/'))) {
 3957         ret = gf_asprintf(&cmd_args->log_ident, "%s", ptr + 1);
 3958     } else {
 3959         ret = gf_asprintf(&cmd_args->log_ident, "%s", cmd_args->log_file);
 3960     }
 3961 
 3962     if (ret > 0)
 3963         ret = 0;
 3964     else
 3965         return ret;
 3966 
 3967     /* remove .log suffix */
 3968     if (NULL != (ptr = strrchr(cmd_args->log_ident, '.'))) {
 3969         if (strcmp(ptr, ".log") == 0) {
 3970             ptr[0] = '\0';
 3971         }
 3972     }
 3973 
 3974     return ret;
 3975 }
 3976 
 3977 int
 3978 gf_thread_cleanup_xint(pthread_t thread)
 3979 {
 3980     int ret = 0;
 3981     void *res = NULL;
 3982 
 3983     ret = pthread_cancel(thread);
 3984     if (ret != 0)
 3985         goto error_return;
 3986 
 3987     ret = pthread_join(thread, &res);
 3988     if (ret != 0)
 3989         goto error_return;
 3990 
 3991     if (res != PTHREAD_CANCELED)
 3992         goto error_return;
 3993 
 3994     ret = 0;
 3995 
 3996 error_return:
 3997     return ret;
 3998 }
 3999 
 4000 void
 4001 gf_thread_set_vname(pthread_t thread, const char *name, va_list args)
 4002 {
 4003     char thread_name[GF_THREAD_NAME_LIMIT];
 4004     int ret;
 4005 
 4006     /* Initialize the thread name with the prefix (not NULL terminated). */
 4007     memcpy(thread_name, GF_THREAD_NAME_PREFIX,
 4008            sizeof(GF_THREAD_NAME_PREFIX) - 1);
 4009 
 4010     ret = vsnprintf(thread_name + sizeof(GF_THREAD_NAME_PREFIX) - 1,
 4011                     sizeof(thread_name) - sizeof(GF_THREAD_NAME_PREFIX) + 1,
 4012                     name, args);
 4013     if (ret < 0) {
 4014         gf_smsg(THIS->name, GF_LOG_WARNING, 0, LG_MSG_PTHREAD_NAMING_FAILED,
 4015                 "name=%s", name, NULL);
 4016         return;
 4017     }
 4018 
 4019     if (ret >= sizeof(thread_name)) {
 4020         gf_smsg(THIS->name, GF_LOG_WARNING, 0, LG_MSG_THREAD_NAME_TOO_LONG,
 4021                 "name=%s", thread_name, NULL);
 4022     }
 4023 
 4024 #ifdef GF_LINUX_HOST_OS
 4025     ret = pthread_setname_np(thread, thread_name);
 4026 #elif defined(__NetBSD__)
 4027     ret = pthread_setname_np(thread, thread_name, NULL);
 4028 #elif defined(__FreeBSD__)
 4029     pthread_set_name_np(thread, thread_name);
 4030     ret = 0;
 4031 #else
 4032     ret = ENOSYS;
 4033 #endif
 4034     if (ret != 0) {
 4035         gf_smsg(THIS->name, GF_LOG_WARNING, ret, LG_MSG_SET_THREAD_FAILED,
 4036                 "name=%s", thread_name, NULL);
 4037     }
 4038 }
 4039 
 4040 void
 4041 gf_thread_set_name(pthread_t thread, const char *name, ...)
 4042 {
 4043     va_list args;
 4044 
 4045     va_start(args, name);
 4046     gf_thread_set_vname(thread, name, args);
 4047     va_end(args);
 4048 }
 4049 
 4050 int
 4051 gf_thread_vcreate(pthread_t *thread, const pthread_attr_t *attr,
 4052                   void *(*start_routine)(void *), void *arg, const char *name,
 4053                   va_list args)
 4054 {
 4055     sigset_t set, old;
 4056     int ret;
 4057 
 4058     sigemptyset(&old);
 4059     sigfillset(&set);
 4060     sigdelset(&set, SIGSEGV);
 4061     sigdelset(&set, SIGBUS);
 4062     sigdelset(&set, SIGILL);
 4063     sigdelset(&set, SIGSYS);
 4064     sigdelset(&set, SIGFPE);
 4065     sigdelset(&set, SIGABRT);
 4066 
 4067     pthread_sigmask(SIG_BLOCK, &set, &old);
 4068 
 4069     ret = pthread_create(thread, attr, start_routine, arg);
 4070     if (ret != 0) {
 4071         gf_smsg(THIS->name, GF_LOG_ERROR, ret, LG_MSG_THREAD_CREATE_FAILED,
 4072                 NULL);
 4073         ret = -1;
 4074     } else if (name != NULL) {
 4075         gf_thread_set_vname(*thread, name, args);
 4076     }
 4077 
 4078     pthread_sigmask(SIG_SETMASK, &old, NULL);
 4079 
 4080     return ret;
 4081 }
 4082 
 4083 int
 4084 gf_thread_create(pthread_t *thread, const pthread_attr_t *attr,
 4085                  void *(*start_routine)(void *), void *arg, const char *name,
 4086                  ...)
 4087 {
 4088     va_list args;
 4089     int ret;
 4090 
 4091     va_start(args, name);
 4092     ret = gf_thread_vcreate(thread, attr, start_routine, arg, name, args);
 4093     va_end(args);
 4094 
 4095     return ret;
 4096 }
 4097 
 4098 int
 4099 gf_thread_create_detached(pthread_t *thread, void *(*start_routine)(void *),
 4100                           void *arg, const char *name, ...)
 4101 {
 4102     pthread_attr_t attr;
 4103     va_list args;
 4104     int ret = -1;
 4105 
 4106     ret = pthread_attr_init(&attr);
 4107     if (ret) {
 4108         gf_smsg(THIS->name, GF_LOG_ERROR, ret, LG_MSG_PTHREAD_ATTR_INIT_FAILED,
 4109                 NULL);
 4110         return -1;
 4111     }
 4112 
 4113     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 4114 
 4115     va_start(args, name);
 4116     ret = gf_thread_vcreate(thread, &attr, start_routine, arg, name, args);
 4117     va_end(args);
 4118 
 4119     pthread_attr_destroy(&attr);
 4120 
 4121     return ret;
 4122 }
 4123 
 4124 int
 4125 gf_skip_header_section(int fd, int header_len)
 4126 {
 4127     int ret = -1;
 4128 
 4129     ret = sys_lseek(fd, header_len, SEEK_SET);
 4130     if (ret == (off_t)-1) {
 4131         gf_smsg("", GF_LOG_ERROR, 0, LG_MSG_SKIP_HEADER_FAILED, NULL);
 4132     } else {
 4133         ret = 0;
 4134     }
 4135 
 4136     return ret;
 4137 }
 4138 
 4139 /* Below function is use to check at runtime if pid is running */
 4140 
 4141 gf_boolean_t
 4142 gf_is_pid_running(int pid)
 4143 {
 4144     char fname[32] = {
 4145         0,
 4146     };
 4147     int fd = -1;
 4148 
 4149     snprintf(fname, sizeof(fname), "/proc/%d/cmdline", pid);
 4150 
 4151     fd = sys_open(fname, O_RDONLY, 0);
 4152     if (fd < 0) {
 4153         return _gf_false;
 4154     }
 4155 
 4156     sys_close(fd);
 4157     return _gf_true;
 4158 }
 4159 
 4160 gf_boolean_t
 4161 gf_is_service_running(char *pidfile, int *pid)
 4162 {
 4163     FILE *file = NULL;
 4164     gf_boolean_t running = _gf_false;
 4165     int ret = 0;
 4166     int fno = 0;
 4167 
 4168     file = fopen(pidfile, "r+");
 4169     if (!file) {
 4170         goto out;
 4171     }
 4172 
 4173     fno = fileno(file);
 4174     ret = lockf(fno, F_TEST, 0);
 4175     if (ret == -1) {
 4176         running = _gf_true;
 4177     }
 4178 
 4179     ret = fscanf(file, "%d", pid);
 4180     if (ret <= 0) {
 4181         gf_smsg("", GF_LOG_ERROR, errno, LG_MSG_FILE_OP_FAILED, "pidfile=%s",
 4182                 pidfile, NULL);
 4183         *pid = -1;
 4184         running = _gf_false;
 4185         goto out;
 4186     }
 4187 
 4188     running = gf_is_pid_running(*pid);
 4189 out:
 4190     if (file)
 4191         fclose(file);
 4192     return running;
 4193 }
 4194 
 4195 /* Check if the pid is > 0 */
 4196 gf_boolean_t
 4197 gf_valid_pid(const char *pid, int length)
 4198 {
 4199     gf_boolean_t ret = _gf_true;
 4200     pid_t value = 0;
 4201     char *end_ptr = NULL;
 4202 
 4203     if (length <= 0) {
 4204         ret = _gf_false;
 4205         goto out;
 4206     }
 4207 
 4208     value = strtol(pid, &end_ptr, 10);
 4209     if (value <= 0) {
 4210         ret = _gf_false;
 4211     }
 4212 out:
 4213     return ret;
 4214 }
 4215 
 4216 static int
 4217 dht_is_linkfile_key(dict_t *this, char *key, data_t *value, void *data)
 4218 {
 4219     gf_boolean_t *linkfile_key_found = NULL;
 4220 
 4221     if (!data)
 4222         goto out;
 4223 
 4224     linkfile_key_found = data;
 4225 
 4226     *linkfile_key_found = _gf_true;
 4227 out:
 4228     return 0;
 4229 }
 4230 
 4231 gf_boolean_t
 4232 dht_is_linkfile(struct iatt *buf, dict_t *dict)
 4233 {
 4234     gf_boolean_t linkfile_key_found = _gf_false;
 4235 
 4236     if (!IS_DHT_LINKFILE_MODE(buf))
 4237         return _gf_false;
 4238 
 4239     dict_foreach_fnmatch(dict, "*." DHT_LINKFILE_STR, dht_is_linkfile_key,
 4240                          &linkfile_key_found);
 4241 
 4242     return linkfile_key_found;
 4243 }
 4244 
 4245 int
 4246 gf_check_log_format(const char *value)
 4247 {
 4248     int log_format = -1;
 4249 
 4250     if (!strcasecmp(value, GF_LOG_FORMAT_NO_MSG_ID))
 4251         log_format = gf_logformat_traditional;
 4252     else if (!strcasecmp(value, GF_LOG_FORMAT_WITH_MSG_ID))
 4253         log_format = gf_logformat_withmsgid;
 4254 
 4255     if (log_format == -1)
 4256         gf_smsg(THIS->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_LOG,
 4257                 "possible_values=" GF_LOG_FORMAT_NO_MSG_ID
 4258                 "|" GF_LOG_FORMAT_WITH_MSG_ID,
 4259                 NULL);
 4260 
 4261     return log_format;
 4262 }
 4263 
 4264 int
 4265 gf_check_logger(const char *value)
 4266 {
 4267     int logger = -1;
 4268 
 4269     if (!strcasecmp(value, GF_LOGGER_GLUSTER_LOG))
 4270         logger = gf_logger_glusterlog;
 4271     else if (!strcasecmp(value, GF_LOGGER_SYSLOG))
 4272         logger = gf_logger_syslog;
 4273 
 4274     if (logger == -1)
 4275         gf_smsg(THIS->name, GF_LOG_ERROR, 0, LG_MSG_INVALID_LOG,
 4276                 "possible_values=" GF_LOGGER_GLUSTER_LOG "|" GF_LOGGER_SYSLOG,
 4277                 NULL);
 4278 
 4279     return logger;
 4280 }
 4281 
 4282 /* gf_compare_sockaddr compares the given addresses @addr1 and @addr2 for
 4283  * equality, ie. if they both refer to the same address.
 4284  *
 4285  * This was inspired by sock_addr_cmp_addr() from
 4286  * https://www.opensource.apple.com/source/postfix/postfix-197/postfix/src/util/sock_addr.c
 4287  */
 4288 gf_boolean_t
 4289 gf_compare_sockaddr(const struct sockaddr *addr1, const struct sockaddr *addr2)
 4290 {
 4291     GF_ASSERT(addr1 != NULL);
 4292     GF_ASSERT(addr2 != NULL);
 4293 
 4294     /* Obviously, the addresses don't match if their families are different
 4295      */
 4296     if (addr1->sa_family != addr2->sa_family)
 4297         return _gf_false;
 4298 
 4299     if (AF_INET == addr1->sa_family) {
 4300         if (((struct sockaddr_in *)addr1)->sin_addr.s_addr ==
 4301             ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
 4302             return _gf_true;
 4303 
 4304     } else if (AF_INET6 == addr1->sa_family) {
 4305         if (memcmp((char *)&((struct sockaddr_in6 *)addr1)->sin6_addr,
 4306                    (char *)&((struct sockaddr_in6 *)addr2)->sin6_addr,
 4307                    sizeof(struct in6_addr)) == 0)
 4308             return _gf_true;
 4309     }
 4310     return _gf_false;
 4311 }
 4312 
 4313 /*
 4314  * gf_set_timestamp:
 4315  *      It sets the mtime and atime of 'dest' file as of 'src'.
 4316  */
 4317 
 4318 int
 4319 gf_set_timestamp(const char *src, const char *dest)
 4320 {
 4321     struct stat sb = {
 4322         0,
 4323     };
 4324 #if defined(HAVE_UTIMENSAT)
 4325     struct timespec new_time[2] = {{
 4326                                        0,
 4327                                    },
 4328                                    {
 4329                                        0,
 4330                                    }};
 4331 #else
 4332     struct timeval new_time[2] = {{
 4333                                       0,
 4334                                   },
 4335                                   {
 4336                                       0,
 4337                                   }};
 4338 #endif
 4339     int ret = 0;
 4340     xlator_t *this = NULL;
 4341 
 4342     this = THIS;
 4343     GF_ASSERT(this);
 4344     GF_ASSERT(src);
 4345     GF_ASSERT(dest);
 4346 
 4347     ret = sys_stat(src, &sb);
 4348     if (ret) {
 4349         gf_smsg(this->name, GF_LOG_ERROR, errno, LG_MSG_FILE_STAT_FAILED,
 4350                 "stat=%s", src, NULL);
 4351         goto out;
 4352     }
 4353     /* The granularity is nano seconds if `utimensat()` is available,
 4354      * and micro seconds otherwise.
 4355      */
 4356 #if defined(HAVE_UTIMENSAT)
 4357     new_time[0].tv_sec = sb.st_atime;
 4358     new_time[0].tv_nsec = ST_ATIM_NSEC(&sb);
 4359 
 4360     new_time[1].tv_sec = sb.st_mtime;
 4361     new_time[1].tv_nsec = ST_MTIM_NSEC(&sb);
 4362 
 4363     /* dirfd = 0 is ignored because `dest` is an absolute path. */
 4364     ret = sys_utimensat(AT_FDCWD, dest, new_time, AT_SYMLINK_NOFOLLOW);
 4365     if (ret) {
 4366         gf_smsg(this->name, GF_LOG_ERROR, errno, LG_MSG_UTIMENSAT_FAILED,
 4367                 "dest=%s", dest, NULL);
 4368     }
 4369 #else
 4370     new_time[0].tv_sec = sb.st_atime;
 4371     new_time[0].tv_usec = ST_ATIM_NSEC(&sb) / 1000;
 4372 
 4373     new_time[1].tv_sec = sb.st_mtime;
 4374     new_time[1].tv_usec = ST_MTIM_NSEC(&sb) / 1000;
 4375 
 4376     ret = sys_utimes(dest, new_time);
 4377     if (ret) {
 4378         gf_smsg(this->name, GF_LOG_ERROR, errno, LG_MSG_UTIMES_FAILED,
 4379                 "dest=%s", dest, NULL);
 4380     }
 4381 #endif
 4382 out:
 4383     return ret;
 4384 }
 4385 
 4386 static void
 4387 gf_backtrace_end(char *buf, size_t frames)
 4388 {
 4389     size_t pos = 0;
 4390 
 4391     if (!buf)
 4392         return;
 4393 
 4394     pos = strlen(buf);
 4395 
 4396     frames = min(frames, GF_BACKTRACE_LEN - pos - 1);
 4397 
 4398     if (frames <= 0)
 4399         return;
 4400 
 4401     memset(buf + pos, ')', frames);
 4402     buf[pos + frames] = '\0';
 4403 }
 4404 
 4405 /*Returns bytes written*/
 4406 static int
 4407 gf_backtrace_append(char *buf, size_t pos, char *framestr)
 4408 {
 4409     if (pos >= GF_BACKTRACE_LEN)
 4410         return -1;
 4411     return snprintf(buf + pos, GF_BACKTRACE_LEN - pos, "(--> %s ", framestr);
 4412 }
 4413 
 4414 static int
 4415 gf_backtrace_fillframes(char *buf)
 4416 {
 4417     void *array[GF_BACKTRACE_FRAME_COUNT];
 4418     size_t frames = 0;
 4419     FILE *fp = NULL;
 4420     char callingfn[GF_BACKTRACE_FRAME_COUNT - 2][1024] = {
 4421         {0},
 4422     };
 4423     int ret = -1;
 4424     int fd = -1;
 4425     size_t idx = 0;
 4426     size_t pos = 0;
 4427     size_t inc = 0;
 4428     char tmpl[] = "/tmp/glfs-bt-XXXXXX";
 4429 
 4430     frames = backtrace(array, GF_BACKTRACE_FRAME_COUNT);
 4431     if (!frames)
 4432         return -1;
 4433 
 4434     /* coverity[secure_temp] mkstemp uses 0600 as the mode and is safe */
 4435     fd = mkstemp(tmpl);
 4436     if (fd == -1)
 4437         return -1;
 4438 
 4439     /* Calling unlink so that when the file is closed or program
 4440      * terminates the temporary file is deleted.
 4441      */
 4442     ret = sys_unlink(tmpl);
 4443     if (ret < 0) {
 4444         gf_smsg(THIS->name, GF_LOG_INFO, 0, LG_MSG_FILE_DELETE_FAILED,
 4445                 "temporary_file=%s", tmpl, NULL);
 4446     }
 4447 
 4448     /*The most recent two frames are the calling function and
 4449      * gf_backtrace_save, which we can infer.*/
 4450 
 4451     backtrace_symbols_fd(&array[2], frames - 2, fd);
 4452 
 4453     fp = fdopen(fd, "r");
 4454     if (!fp) {
 4455         sys_close(fd);
 4456         goto out;
 4457     }
 4458 
 4459     ret = fseek(fp, 0L, SEEK_SET);
 4460     if (ret)
 4461         goto out;
 4462 
 4463     pos = 0;
 4464     for (idx = 0; idx < frames - 2; idx++) {
 4465         ret = fscanf(fp, "%1023s", callingfn[idx]);
 4466         if (ret == EOF)
 4467             break;
 4468         inc = gf_backtrace_append(buf, pos, callingfn[idx]);
 4469         if (inc == -1)
 4470             break;
 4471         pos += inc;
 4472     }
 4473     gf_backtrace_end(buf, idx);
 4474 
 4475 out:
 4476     if (fp)
 4477         fclose(fp);
 4478 
 4479     return (idx > 0) ? 0 : -1;
 4480 }
 4481 
 4482 /* Optionally takes @buf to save backtrace.  If @buf is NULL, uses the
 4483  * pre-allocated ctx->btbuf to avoid allocating memory while printing
 4484  * backtrace.
 4485  * TODO: This API doesn't provide flexibility in terms of no. of frames
 4486  * of the backtrace is being saved in the buffer. Deferring fixing it
 4487  * when there is a real-use for that.*/
 4488 
 4489 char *
 4490 gf_backtrace_save(char *buf)
 4491 {
 4492     char *bt = NULL;
 4493 
 4494     if (!buf) {
 4495         bt = THIS->ctx->btbuf;
 4496         GF_ASSERT(bt);
 4497 
 4498     } else {
 4499         bt = buf;
 4500     }
 4501 
 4502     if ((0 == gf_backtrace_fillframes(bt)))
 4503         return bt;
 4504 
 4505     gf_smsg(THIS->name, GF_LOG_WARNING, 0, LG_MSG_BACKTRACE_SAVE_FAILED, NULL);
 4506     return NULL;
 4507 }
 4508 
 4509 gf_loglevel_t
 4510 fop_log_level(glusterfs_fop_t fop, int op_errno)
 4511 {
 4512     /* if gfid doesn't exist ESTALE comes */
 4513     if (op_errno == ENOENT || op_errno == ESTALE)
 4514         return GF_LOG_DEBUG;
 4515 
 4516     if ((fop == GF_FOP_ENTRYLK) || (fop == GF_FOP_FENTRYLK) ||
 4517         (fop == GF_FOP_FINODELK) || (fop == GF_FOP_INODELK) ||
 4518         (fop == GF_FOP_LK)) {
 4519         /*
 4520          * if non-blocking lock fails EAGAIN comes
 4521          * if locks xlator is not loaded ENOSYS comes
 4522          */
 4523         if (op_errno == EAGAIN || op_errno == ENOSYS)
 4524             return GF_LOG_DEBUG;
 4525     }
 4526 
 4527     if ((fop == GF_FOP_GETXATTR) || (fop == GF_FOP_FGETXATTR)) {
 4528         if (op_errno == ENOTSUP || op_errno == ENODATA)
 4529             return GF_LOG_DEBUG;
 4530     }
 4531 
 4532     if ((fop == GF_FOP_SETXATTR) || (fop == GF_FOP_FSETXATTR) ||
 4533         (fop == GF_FOP_REMOVEXATTR) || (fop == GF_FOP_FREMOVEXATTR)) {
 4534         if (op_errno == ENOTSUP)
 4535             return GF_LOG_DEBUG;
 4536     }
 4537 
 4538     if (fop == GF_FOP_MKNOD || fop == GF_FOP_MKDIR)
 4539         if (op_errno == EEXIST)
 4540             return GF_LOG_DEBUG;
 4541 
 4542     if (fop == GF_FOP_SEEK) {
 4543 #ifdef HAVE_SEEK_HOLE
 4544         if (op_errno == ENXIO) {
 4545             return GF_LOG_DEBUG;
 4546         }
 4547 #else
 4548         return GF_LOG_DEBUG;
 4549 #endif
 4550     }
 4551 
 4552     return GF_LOG_ERROR;
 4553 }
 4554 
 4555 /* This function will build absolute path of file/directory from the
 4556  * current location and relative path given from the current location
 4557  * For example consider our current path is /a/b/c/ and relative path
 4558  * from current location is ./../x/y/z .After parsing through this
 4559  * function the absolute path becomes /a/b/x/y/z/.
 4560  *
 4561  * The function gives a pointer to absolute path if it is successful
 4562  * and also returns zero.
 4563  * Otherwise function gives NULL pointer with returning an err value.
 4564  *
 4565  * So the user need to free memory allocated for path.
 4566  *
 4567  */
 4568 
 4569 int32_t
 4570 gf_build_absolute_path(char *current_path, char *relative_path, char **path)
 4571 {
 4572     char *absolute_path = NULL;
 4573     char *token = NULL;
 4574     char *component = NULL;
 4575     char *saveptr = NULL;
 4576     char *end = NULL;
 4577     int ret = 0;
 4578     size_t relativepath_len = 0;
 4579     size_t currentpath_len = 0;
 4580     size_t max_absolutepath_len = 0;
 4581 
 4582     GF_ASSERT(current_path);
 4583     GF_ASSERT(relative_path);
 4584     GF_ASSERT(path);
 4585 
 4586     if (!path || !current_path || !relative_path) {
 4587         ret = -EFAULT;
 4588         goto err;
 4589     }
 4590     /* Check for current and relative path
 4591      * current path should be absolute one and  start from '/'
 4592      * relative path should not start from '/'
 4593      */
 4594     currentpath_len = strlen(current_path);
 4595     if (current_path[0] != '/' || (currentpath_len > PATH_MAX)) {
 4596         gf_smsg(THIS->name, GF_LOG_ERROR, 0, LG_MSG_WRONG_VALUE,
 4597                 "current-path=%s", current_path, NULL);
 4598         ret = -EINVAL;
 4599         goto err;
 4600     }
 4601 
 4602     relativepath_len = strlen(relative_path);
 4603     if (relative_path[0] == '/' || (relativepath_len > PATH_MAX)) {
 4604         gf_smsg(THIS->name, GF_LOG_ERROR, 0, LG_MSG_WRONG_VALUE,
 4605                 "relative-path=%s", relative_path, NULL);
 4606         ret = -EINVAL;
 4607         goto err;
 4608     }
 4609 
 4610     /* It is maximum possible value for absolute path */
 4611     max_absolutepath_len = currentpath_len + relativepath_len + 2;
 4612 
 4613     absolute_path = GF_CALLOC(1, max_absolutepath_len, gf_common_mt_char);
 4614     if (!absolute_path) {
 4615         ret = -ENOMEM;
 4616         goto err;
 4617     }
 4618     absolute_path[0] = '\0';
 4619 
 4620     /* If current path is root i.e contains only "/", we do not
 4621      * need to copy it
 4622      */
 4623     if (strcmp(current_path, "/") != 0) {
 4624         strcpy(absolute_path, current_path);
 4625 
 4626         /* We trim '/' at the end for easier string manipulation */
 4627         gf_path_strip_trailing_slashes(absolute_path);
 4628     }
 4629 
 4630     /* Used to spilt relative path based on '/' */
 4631     component = gf_strdup(relative_path);
 4632     if (!component) {
 4633         ret = -ENOMEM;
 4634         goto err;
 4635     }
 4636 
 4637     /* In the relative path, we want to consider ".." and "."
 4638      * if token is ".." , we just need to reduce one level hierarchy
 4639      * if token is "." , we just ignore it
 4640      * if token is NULL , end of relative path
 4641      * if absolute path becomes '\0' and still "..", then it is a bad
 4642      * relative path,  it points to out of boundary area and stop
 4643      * building the absolute path
 4644      * All other cases we just concatenate token to the absolute path
 4645      */
 4646     for (token = strtok_r(component, "/", &saveptr),
 4647         end = strchr(absolute_path, '\0');
 4648          token; token = strtok_r(NULL, "/", &saveptr)) {
 4649         if (strcmp(token, ".") == 0)
 4650             continue;
 4651 
 4652         else if (strcmp(token, "..") == 0) {
 4653             if (absolute_path[0] == '\0') {
 4654                 ret = -EACCES;
 4655                 goto err;
 4656             }
 4657 
 4658             end = strrchr(absolute_path, '/');
 4659             *end = '\0';
 4660         } else {
 4661             ret = snprintf(end, max_absolutepath_len - strlen(absolute_path),
 4662                            "/%s", token);
 4663             end = strchr(absolute_path, '\0');
 4664         }
 4665     }
 4666 
 4667     if (strlen(absolute_path) > PATH_MAX) {
 4668         ret = -EINVAL;
 4669         goto err;
 4670     }
 4671     *path = gf_strdup(absolute_path);
 4672 
 4673 err:
 4674     if (component)
 4675         GF_FREE(component);
 4676     if (absolute_path)
 4677         GF_FREE(absolute_path);
 4678     return ret;
 4679 }
 4680 
 4681 /* This is an utility function which will recursively delete
 4682  * a folder and its contents.
 4683  *
 4684  * @param delete_path folder to be deleted.
 4685  *
 4686  * @return 0 on success and -1 on failure.
 4687  */
 4688 int
 4689 recursive_rmdir(const char *delete_path)
 4690 {
 4691     int ret = -1;
 4692     char path[PATH_MAX] = {
 4693         0,
 4694     };
 4695     struct stat st = {
 4696         0,
 4697     };
 4698     DIR *dir = NULL;
 4699     struct dirent *entry = NULL;
 4700     struct dirent scratch[2] = {
 4701         {
 4702             0,
 4703         },
 4704     };
 4705     xlator_t *this = NULL;
 4706 
 4707     this = THIS;
 4708     GF_ASSERT(this);
 4709     GF_VALIDATE_OR_GOTO(this->name, delete_path, out);
 4710 
 4711     dir = sys_opendir(delete_path);
 4712     if (!dir) {
 4713         gf_msg_debug(this->name, 0,
 4714                      "Failed to open directory %s. "
 4715                      "Reason : %s",
 4716                      delete_path, strerror(errno));
 4717         ret = 0;
 4718         goto out;
 4719     }
 4720 
 4721     GF_SKIP_IRRELEVANT_ENTRIES(entry, dir, scratch);
 4722     while (entry) {
 4723         snprintf(path, PATH_MAX, "%s/%s", delete_path, entry->d_name);
 4724         ret = sys_lstat(path, &st);
 4725         if (ret == -1) {
 4726             gf_msg_debug(this->name, 0,
 4727                          "Failed to stat entry %s :"
 4728                          " %s",
 4729                          path, strerror(errno));
 4730             (void)sys_closedir(dir);
 4731             goto out;
 4732         }
 4733 
 4734         if (S_ISDIR(st.st_mode))
 4735             ret = recursive_rmdir(path);
 4736         else
 4737             ret = sys_unlink(path);
 4738 
 4739         if (ret) {
 4740             gf_msg_debug(this->name, 0,
 4741                          " Failed to remove %s. "
 4742                          "Reason : %s",
 4743                          path, strerror(errno));
 4744         }
 4745 
 4746         gf_msg_debug(this->name, 0, "%s %s",
 4747                      ret ? "Failed to remove" : "Removed", entry->d_name);
 4748 
 4749         GF_SKIP_IRRELEVANT_ENTRIES(entry, dir, scratch);
 4750     }
 4751 
 4752     ret = sys_closedir(dir);
 4753     if (ret) {
 4754         gf_msg_debug(this->name, 0,
 4755                      "Failed to close dir %s. Reason :"
 4756                      " %s",
 4757                      delete_path, strerror(errno));
 4758     }
 4759 
 4760     ret = sys_rmdir(delete_path);
 4761     if (ret) {
 4762         gf_msg_debug(this->name, 0, "Failed to rmdir: %s,err: %s", delete_path,
 4763                      strerror(errno));
 4764     }
 4765 
 4766 out:
 4767     return ret;
 4768 }
 4769 /*
 4770  * Input: Array of strings 'array' terminating in NULL
 4771  *        string 'elem' to be searched in the array
 4772  *
 4773  * Output: Index of the element in the array if found, '-1' otherwise
 4774  */
 4775 int
 4776 gf_get_index_by_elem(char **array, char *elem)
 4777 {
 4778     int i = 0;
 4779 
 4780     for (i = 0; array[i]; i++) {
 4781         if (strcmp(elem, array[i]) == 0)
 4782             return i;
 4783     }
 4784 
 4785     return -1;
 4786 }
 4787 
 4788 static int
 4789 get_pathinfo_host(char *pathinfo, char *hostname, size_t size)
 4790 {
 4791     char *start = NULL;
 4792     char *end = NULL;
 4793     int ret = -1;
 4794     int i = 0;
 4795 
 4796     if (!pathinfo)
 4797         goto out;
 4798 
 4799     start = strchr(pathinfo, ':');
 4800     if (!start)
 4801         goto out;
 4802 
 4803     end = strrchr(pathinfo, ':');
 4804     if (start == end)
 4805         goto out;
 4806 
 4807     memset(hostname, 0, size);
 4808     i = 0;
 4809     while (++start != end)
 4810         hostname[i++] = *start;
 4811     ret = 0;
 4812 out:
 4813     return ret;
 4814 }
 4815 
 4816 /*Note: 'pathinfo' should be gathered only from one brick*/
 4817 int
 4818 glusterfs_is_local_pathinfo(char *pathinfo, gf_boolean_t *is_local)
 4819 {
 4820     int ret = 0;
 4821     char pathinfohost[1024] = {0};
 4822     char localhost[1024] = {0};
 4823 
 4824     *is_local = _gf_false;
 4825     ret = get_pathinfo_host(pathinfo, pathinfohost, sizeof(pathinfohost));
 4826     if (ret)
 4827         goto out;
 4828 
 4829     ret = gethostname(localhost, sizeof(localhost));
 4830     if (ret)
 4831         goto out;
 4832 
 4833     if (!strcmp(localhost, pathinfohost))
 4834         *is_local = _gf_true;
 4835 out:
 4836     return ret;
 4837 }
 4838 
 4839 ssize_t
 4840 gf_nread(int fd, void *buf, size_t count)
 4841 {
 4842     ssize_t ret = 0;
 4843     ssize_t read_bytes = 0;
 4844 
 4845     for (read_bytes = 0; read_bytes < count; read_bytes += ret) {
 4846         ret = sys_read(fd, buf + read_bytes, count - read_bytes);
 4847         if (ret == 0) {
 4848             break;
 4849         } else if (ret < 0) {
 4850             if (errno == EINTR)
 4851                 ret = 0;
 4852             else
 4853                 goto out;
 4854         }
 4855     }
 4856 
 4857     ret = read_bytes;
 4858 out:
 4859     return ret;
 4860 }
 4861 
 4862 ssize_t
 4863 gf_nwrite(int fd, const void *buf, size_t count)
 4864 {
 4865     ssize_t ret = 0;
 4866     ssize_t written = 0;
 4867 
 4868     for (written = 0; written != count; written += ret) {
 4869         ret = sys_write(fd, buf + written, count - written);
 4870         if (ret < 0) {
 4871             if (errno == EINTR)
 4872                 ret = 0;
 4873             else
 4874                 goto out;
 4875         }
 4876     }
 4877 
 4878     ret = written;
 4879 out:
 4880     return ret;
 4881 }
 4882 
 4883 void
 4884 gf_free_mig_locks(lock_migration_info_t *locks)
 4885 {
 4886     lock_migration_info_t *current = NULL;
 4887     lock_migration_info_t *temp = NULL;
 4888 
 4889     if (!locks)
 4890         return;
 4891 
 4892     if (list_empty(&locks->list))
 4893         return;
 4894 
 4895     list_for_each_entry_safe(current, temp, &locks->list, list)
 4896     {
 4897         list_del_init(&current->list);
 4898         GF_FREE(current->client_uid);
 4899         GF_FREE(current);
 4900     }
 4901 }
 4902 
 4903 void
 4904 _mask_cancellation(void)
 4905 {
 4906     (void)pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
 4907 }
 4908 
 4909 void
 4910 _unmask_cancellation(void)
 4911 {
 4912     (void)pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
 4913 }
 4914 
 4915 /* This is a wrapper function to add a pointer to a list,
 4916  * which doesn't contain list member
 4917  */
 4918 struct list_node *
 4919 _list_node_add(void *ptr, struct list_head *list,
 4920                int (*compare)(struct list_head *, struct list_head *))
 4921 {
 4922     struct list_node *node = NULL;
 4923 
 4924     if (ptr == NULL || list == NULL)
 4925         goto out;
 4926 
 4927     node = GF_CALLOC(1, sizeof(struct list_node), gf_common_list_node);
 4928 
 4929     if (node == NULL)
 4930         goto out;
 4931 
 4932     node->ptr = ptr;
 4933     if (compare)
 4934         list_add_order(&node->list, list, compare);
 4935     else
 4936         list_add_tail(&node->list, list);
 4937 out:
 4938     return node;
 4939 }
 4940 
 4941 struct list_node *
 4942 list_node_add(void *ptr, struct list_head *list)
 4943 {
 4944     return _list_node_add(ptr, list, NULL);
 4945 }
 4946 
 4947 struct list_node *
 4948 list_node_add_order(void *ptr, struct list_head *list,
 4949                     int (*compare)(struct list_head *, struct list_head *))
 4950 {
 4951     return _list_node_add(ptr, list, compare);
 4952 }
 4953 
 4954 void
 4955 list_node_del(struct list_node *node)
 4956 {
 4957     if (node == NULL)
 4958         return;
 4959 
 4960     list_del_init(&node->list);
 4961     GF_FREE(node);
 4962 }
 4963 
 4964 const char *
 4965 fop_enum_to_pri_string(glusterfs_fop_t fop)
 4966 {
 4967     switch (fop) {
 4968         case GF_FOP_OPEN:
 4969         case GF_FOP_STAT:
 4970         case GF_FOP_FSTAT:
 4971         case GF_FOP_LOOKUP:
 4972         case GF_FOP_ACCESS:
 4973         case GF_FOP_READLINK:
 4974         case GF_FOP_OPENDIR:
 4975         case GF_FOP_STATFS:
 4976         case GF_FOP_READDIR:
 4977         case GF_FOP_READDIRP:
 4978         case GF_FOP_GETACTIVELK:
 4979         case GF_FOP_SETACTIVELK:
 4980         case GF_FOP_ICREATE:
 4981         case GF_FOP_NAMELINK:
 4982             return "HIGH";
 4983 
 4984         case GF_FOP_CREATE:
 4985         case GF_FOP_FLUSH:
 4986         case GF_FOP_LK:
 4987         case GF_FOP_INODELK:
 4988         case GF_FOP_FINODELK:
 4989         case GF_FOP_ENTRYLK:
 4990         case GF_FOP_FENTRYLK:
 4991         case GF_FOP_UNLINK:
 4992         case GF_FOP_SETATTR:
 4993         case GF_FOP_FSETATTR:
 4994         case GF_FOP_MKNOD:
 4995         case GF_FOP_MKDIR:
 4996         case GF_FOP_RMDIR:
 4997         case GF_FOP_SYMLINK:
 4998         case GF_FOP_RENAME:
 4999         case GF_FOP_LINK:
 5000         case GF_FOP_SETXATTR:
 5001         case GF_FOP_GETXATTR:
 5002         case GF_FOP_FGETXATTR:
 5003         case GF_FOP_FSETXATTR:
 5004         case GF_FOP_REMOVEXATTR:
 5005         case GF_FOP_FREMOVEXATTR:
 5006         case GF_FOP_IPC:
 5007         case GF_FOP_LEASE:
 5008             return "NORMAL";
 5009 
 5010         case GF_FOP_READ:
 5011         case GF_FOP_WRITE:
 5012         case GF_FOP_FSYNC:
 5013         case GF_FOP_TRUNCATE:
 5014         case GF_FOP_FTRUNCATE:
 5015         case GF_FOP_FSYNCDIR:
 5016         case GF_FOP_XATTROP:
 5017         case GF_FOP_FXATTROP:
 5018         case GF_FOP_RCHECKSUM:
 5019         case GF_FOP_ZEROFILL:
 5020         case GF_FOP_FALLOCATE:
 5021         case GF_FOP_SEEK:
 5022             return "LOW";
 5023 
 5024         case GF_FOP_NULL:
 5025         case GF_FOP_FORGET:
 5026         case GF_FOP_RELEASE:
 5027         case GF_FOP_RELEASEDIR:
 5028         case GF_FOP_GETSPEC:
 5029         case GF_FOP_MAXVALUE:
 5030         case GF_FOP_DISCARD:
 5031             return "LEAST";
 5032         default:
 5033             return "UNKNOWN";
 5034     }
 5035 }
 5036 
 5037 const char *
 5038 gf_inode_type_to_str(ia_type_t type)
 5039 {
 5040     static const char *const str_ia_type[] = {
 5041         "UNKNOWN",      "REGULAR FILE",     "DIRECTORY", "LINK",
 5042         "BLOCK DEVICE", "CHARACTER DEVICE", "PIPE",      "SOCKET"};
 5043     return str_ia_type[type];
 5044 }
 5045 
 5046 gf_boolean_t
 5047 gf_is_zero_filled_stat(struct iatt *buf)
 5048 {
 5049     if (!buf)
 5050         return 1;
 5051 
 5052     /* Do not use st_dev because it is transformed to store the xlator id
 5053      * in place of the device number. Do not use st_ino because by this time
 5054      * we've already mapped the root ino to 1 so it is not guaranteed to be
 5055      * 0.
 5056      */
 5057     if ((buf->ia_nlink == 0) && (buf->ia_ctime == 0))
 5058         return 1;
 5059 
 5060     return 0;
 5061 }
 5062 
 5063 void
 5064 gf_zero_fill_stat(struct iatt *buf)
 5065 {
 5066     buf->ia_nlink = 0;
 5067     buf->ia_ctime = 0;
 5068 }
 5069 
 5070 gf_boolean_t
 5071 gf_is_valid_xattr_namespace(char *key)
 5072 {
 5073     static char *xattr_namespaces[] = {"trusted.", "system.", "user.",
 5074                                        "security.", NULL};
 5075     int i = 0;
 5076 
 5077     for (i = 0; xattr_namespaces[i]; i++) {
 5078         if (strncmp(key, xattr_namespaces[i], strlen(xattr_namespaces[i])) == 0)
 5079             return _gf_true;
 5080     }
 5081 
 5082     return _gf_false;
 5083 }
 5084 
 5085 ino_t
 5086 gfid_to_ino(uuid_t gfid)
 5087 {
 5088     ino_t ino = 0;
 5089     int32_t i;
 5090 
 5091     for (i = 8; i < 16; i++) {
 5092         ino <<= 8;
 5093         ino += (uint8_t)gfid[i];
 5094     }
 5095 
 5096     return ino;
 5097 }
 5098 
 5099 int
 5100 gf_bits_count(uint64_t n)
 5101 {
 5102     int val = 0;
 5103 #if defined(__GNUC__) || defined(__clang__)
 5104     val = __builtin_popcountll(n);
 5105 #else
 5106     n -= (n >> 1) & 0x5555555555555555ULL;
 5107     n = ((n >> 2) & 0x3333333333333333ULL) + (n & 0x3333333333333333ULL);
 5108     n = (n + (n >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
 5109     n += n >> 8;
 5110     n += n >> 16;
 5111     n += n >> 32;
 5112     val = n & 0xFF;
 5113 #endif
 5114     return val;
 5115 }
 5116 
 5117 int
 5118 gf_bits_index(uint64_t n)
 5119 {
 5120 #if defined(__GNUC__) || defined(__clang__)
 5121     return __builtin_ffsll(n) - 1;
 5122 #else
 5123     return ffsll(n) - 1;
 5124 #endif
 5125 }
 5126 
 5127 const char *
 5128 gf_fop_string(glusterfs_fop_t fop)
 5129 {
 5130     if ((fop > GF_FOP_NULL) && (fop < GF_FOP_MAXVALUE))
 5131         return gf_fop_list[fop];
 5132     return "INVALID";
 5133 }
 5134 
 5135 int
 5136 gf_fop_int(char *fop)
 5137 {
 5138     int i = 0;
 5139 
 5140     for (i = GF_FOP_NULL + 1; i < GF_FOP_MAXVALUE; i++) {
 5141         if (strcasecmp(fop, gf_fop_list[i]) == 0)
 5142             return i;
 5143     }
 5144     return -1;
 5145 }
 5146 
 5147 int
 5148 close_fds_except(int *fdv, size_t count)
 5149 {
 5150     int i = 0;
 5151     size_t j = 0;
 5152     gf_boolean_t should_close = _gf_true;
 5153 #ifdef GF_LINUX_HOST_OS
 5154     DIR *d = NULL;
 5155     struct dirent *de = NULL;
 5156     struct dirent scratch[2] = {
 5157         {
 5158             0,
 5159         },
 5160     };
 5161     char *e = NULL;
 5162 
 5163     d = sys_opendir("/proc/self/fd");
 5164     if (!d)
 5165         return -1;
 5166 
 5167     for (;;) {
 5168         should_close = _gf_true;
 5169 
 5170         errno = 0;
 5171         de = sys_readdir(d, scratch);
 5172         if (!de || errno != 0)
 5173             break;
 5174         i = strtoul(de->d_name, &e, 10);
 5175         if (*e != '\0' || i == dirfd(d))
 5176             continue;
 5177 
 5178         for (j = 0; j < count; j++) {
 5179             if (i == fdv[j]) {
 5180                 should_close = _gf_false;
 5181                 break;
 5182             }
 5183         }
 5184         if (should_close)
 5185             sys_close(i);
 5186     }
 5187     sys_closedir(d);
 5188 #else  /* !GF_LINUX_HOST_OS */
 5189     struct rlimit rl;
 5190     int ret = -1;
 5191 
 5192     ret = getrlimit(RLIMIT_NOFILE, &rl);
 5193     if (ret)
 5194         return ret;
 5195 
 5196     for (i = 0; i < rl.rlim_cur; i++) {
 5197         should_close = _gf_true;
 5198         for (j = 0; j < count; j++) {
 5199             if (i == fdv[j]) {
 5200                 should_close = _gf_false;
 5201                 break;
 5202             }
 5203         }
 5204         if (should_close)
 5205             sys_close(i);
 5206     }
 5207 #endif /* !GF_LINUX_HOST_OS */
 5208     return 0;
 5209 }
 5210 
 5211 /**
 5212  * gf_getgrouplist - get list of groups to which a user belongs
 5213  *
 5214  * A convenience wrapper for getgrouplist(3).
 5215  *
 5216  * @param user - same as in getgrouplist(3)
 5217  * @param group - same as in getgrouplist(3)
 5218  * @param groups - pointer to a gid_t pointer
 5219  *
 5220  * gf_getgrouplist allocates a gid_t buffer which is big enough to
 5221  * hold the list of auxiliary group ids for user, up to the GF_MAX_AUX_GROUPS
 5222  * threshold. Upon successful invocation groups will be pointed to that buffer.
 5223  *
 5224  * @return success: the number of auxiliary group ids retrieved
 5225  *         failure: -1
 5226  */
 5227 int
 5228 gf_getgrouplist(const char *user, gid_t group, gid_t **groups)
 5229 {
 5230     int ret = -1;
 5231     int ngroups = SMALL_GROUP_COUNT;
 5232 
 5233     *groups = GF_CALLOC(sizeof(gid_t), ngroups, gf_common_mt_groups_t);
 5234     if (!*groups)
 5235         return -1;
 5236 
 5237     /*
 5238      * We are running getgrouplist() in a loop until we succeed (or hit
 5239      * certain exit conditions, see the comments below). This is because
 5240      * the indicated number of auxiliary groups that we obtain in case of
 5241      * the failure of the first invocation is not guaranteed to keep its
 5242      * validity upon the next invocation with a gid buffer of that size.
 5243      */
 5244     for (;;) {
 5245         int ngroups_old = ngroups;
 5246         ret = getgrouplist(user, group, *groups, &ngroups);
 5247         if (ret != -1)
 5248             break;
 5249 
 5250         if (ngroups >= GF_MAX_AUX_GROUPS) {
 5251             /*
 5252              * This should not happen as GF_MAX_AUX_GROUPS is set
 5253              * to the max value of number of supported auxiliary
 5254              * groups across all platforms supported by GlusterFS.
 5255              * However, if it still happened some way, we wouldn't
 5256              * care about the incompleteness of the result, we'd
 5257              * just go on with what we got.
 5258              */
 5259             return GF_MAX_AUX_GROUPS;
 5260         } else if (ngroups <= ngroups_old) {
 5261             /*
 5262              * There is an edge case that getgrouplist() fails but
 5263              * ngroups remains the same. This is actually not
 5264              * specified in getgrouplist(3), but implementations
 5265              * can do this upon internal failure[1]. To avoid
 5266              * falling into an infinite loop when this happens, we
 5267              * break the loop if the getgrouplist call failed
 5268              * without an increase in the indicated group number.
 5269              *
 5270              * [1]
 5271              * https://sourceware.org/git/?p=glibc.git;a=blob;f=grp/initgroups.c;hb=refs/heads/release/2.25/master#l168
 5272              */
 5273             GF_FREE(*groups);
 5274             return -1;
 5275         }
 5276 
 5277         *groups = GF_REALLOC(*groups, ngroups * sizeof(gid_t));
 5278         if (!*groups)
 5279             return -1;
 5280     }
 5281     return ret;
 5282 }
 5283 
 5284 int
 5285 glusterfs_compute_sha256(const unsigned char *content, size_t size,
 5286                          char *sha256_hash)
 5287 {
 5288     SHA256_CTX sha256;
 5289 
 5290     SHA256_Init(&sha256);
 5291     SHA256_Update(&sha256, (const unsigned char *)(content), size);
 5292     SHA256_Final((unsigned char *)sha256_hash, &sha256);
 5293 
 5294     return 0;
 5295 }
 5296 
 5297 /* * Safe wrapper function for strncpy.
 5298  * This wrapper makes sure that when there is no null byte among the first n in
 5299  * source srting for strncpy function call, the string placed in dest will be
 5300  * null-terminated.
 5301  */
 5302 
 5303 char *
 5304 gf_strncpy(char *dest, const char *src, const size_t dest_size)
 5305 {
 5306     strncpy(dest, src, dest_size - 1);
 5307     dest[dest_size - 1] = '\0';
 5308     return dest;
 5309 }
 5310 
 5311 int
 5312 gf_replace_old_iatt_in_dict(dict_t *xdata)
 5313 {
 5314     int ret;
 5315     struct old_iatt *o_iatt; /* old iatt structure */
 5316     struct iatt *c_iatt;     /* current iatt */
 5317 
 5318     if (!xdata) {
 5319         return 0;
 5320     }
 5321 
 5322     ret = dict_get_bin(xdata, DHT_IATT_IN_XDATA_KEY, (void **)&c_iatt);
 5323     if (ret < 0) {
 5324         return 0;
 5325     }
 5326 
 5327     o_iatt = GF_CALLOC(1, sizeof(struct old_iatt), gf_common_mt_char);
 5328     if (!o_iatt) {
 5329         return -1;
 5330     }
 5331 
 5332     oldiatt_from_iatt(o_iatt, c_iatt);
 5333 
 5334     ret = dict_set_bin(xdata, DHT_IATT_IN_XDATA_KEY, o_iatt,
 5335                        sizeof(struct old_iatt));
 5336     if (ret) {
 5337         GF_FREE(o_iatt);
 5338     }
 5339 
 5340     return ret;
 5341 }
 5342 
 5343 int
 5344 gf_replace_new_iatt_in_dict(dict_t *xdata)
 5345 {
 5346     int ret;
 5347     struct old_iatt *o_iatt; /* old iatt structure */
 5348     struct iatt *c_iatt;     /* new iatt */
 5349 
 5350     if (!xdata) {
 5351         return 0;
 5352     }
 5353 
 5354     ret = dict_get_bin(xdata, DHT_IATT_IN_XDATA_KEY, (void **)&o_iatt);
 5355     if (ret < 0) {
 5356         return 0;
 5357     }
 5358 
 5359     c_iatt = GF_CALLOC(1, sizeof(struct iatt), gf_common_mt_char);
 5360     if (!c_iatt) {
 5361         return -1;
 5362     }
 5363 
 5364     iatt_from_oldiatt(c_iatt, o_iatt);
 5365 
 5366     ret = dict_set_bin(xdata, DHT_IATT_IN_XDATA_KEY, c_iatt,
 5367                        sizeof(struct iatt));
 5368     if (ret) {
 5369         GF_FREE(c_iatt);
 5370     }
 5371 
 5372     return ret;
 5373 }
 5374 
 5375 xlator_cmdline_option_t *
 5376 find_xlator_option_in_cmd_args_t(const char *option_name, cmd_args_t *args)
 5377 {
 5378     xlator_cmdline_option_t *pos = NULL;
 5379     xlator_cmdline_option_t *tmp = NULL;
 5380 
 5381     list_for_each_entry_safe(pos, tmp, &args->xlator_options, cmd_args)
 5382     {
 5383         if (strcmp(pos->key, option_name) == 0)
 5384             return pos;
 5385     }
 5386     return NULL;
 5387 }
 5388 
 5389 int
 5390 gf_d_type_from_ia_type(ia_type_t type)
 5391 {
 5392     switch (type) {
 5393         case IA_IFDIR:
 5394             return DT_DIR;
 5395         case IA_IFCHR:
 5396             return DT_CHR;
 5397         case IA_IFBLK:
 5398             return DT_BLK;
 5399         case IA_IFIFO:
 5400             return DT_FIFO;
 5401         case IA_IFLNK:
 5402             return DT_LNK;
 5403         case IA_IFREG:
 5404             return DT_REG;
 5405         case IA_IFSOCK:
 5406             return DT_SOCK;
 5407         default:
 5408             return DT_UNKNOWN;
 5409     }
 5410 }
 5411 
 5412 int
 5413 gf_nanosleep(uint64_t nsec)
 5414 {
 5415     struct timespec req;
 5416     struct timespec rem;
 5417     int ret = -1;
 5418 
 5419     req.tv_sec = nsec / GF_SEC_IN_NS;
 5420     req.tv_nsec = nsec % GF_SEC_IN_NS;
 5421 
 5422     do {
 5423         ret = nanosleep(&req, &rem);
 5424         req = rem;
 5425     } while (ret == -1 && errno == EINTR);
 5426 
 5427     return ret;
 5428 }