Fix: unchecked return value of cds_lfht_destroy()
[lttng-tools.git] / src / bin / lttng-sessiond / tracker.c
index af527b4fd03b5f7a2fd441b71c225ad1f1df8495..302971767742a41f792f907484e2e91bc10e9c7f 100644 (file)
@@ -1,18 +1,8 @@
 /*
- * Copyright (C) 2018 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2018 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2 only,
- * as published by the Free Software Foundation.
+ * SPDX-License-Identifier: GPL-2.0-only
  *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #define _LGPL_SOURCE
@@ -27,6 +17,7 @@
 #include <common/hashtable/hashtable.h>
 #include <common/hashtable/utils.h>
 #include <lttng/lttng-error.h>
+#include <lttng/tracker-internal.h>
 
 #define FALLBACK_USER_BUFLEN 16384
 #define FALLBACK_GROUP_BUFLEN 16384
@@ -60,53 +51,42 @@ static int match_tracker_key(struct cds_lfht_node *node, const void *key)
 
        tracker_node = caa_container_of(
                        node, struct lttng_tracker_list_node, ht_node);
-       if (tracker_node->id.type != tracker_key->type) {
-               return 0;
-       }
-       switch (tracker_node->id.type) {
-       case LTTNG_ID_ALL:
-               return 1;
-       case LTTNG_ID_VALUE:
-               if (tracker_node->id.value != tracker_key->value) {
-                       return 0;
-               }
-               break;
-       case LTTNG_ID_STRING:
-               if (strcmp(tracker_node->id.string, tracker_key->string) != 0) {
-                       return 0;
-               }
-               break;
-       default:
-               return 0;
-       }
-       return 1;
+
+       return lttng_tracker_id_is_equal(tracker_node->id, tracker_key);
 }
 
 static unsigned long hash_tracker_key(
                const struct lttng_tracker_id *tracker_key)
 {
        unsigned long key_hash = 0;
+       int value;
+       const char *string;
+       enum lttng_tracker_id_type type;
+
+       /* We do not care for invalid state during hash computation */
+       type = lttng_tracker_id_get_type(tracker_key);
+       (void) lttng_tracker_id_get_value(tracker_key, &value);
+       (void) lttng_tracker_id_get_string(tracker_key, &string);
 
-       switch (tracker_key->type) {
+       switch (type) {
        case LTTNG_ID_ALL:
                break;
        case LTTNG_ID_VALUE:
                key_hash ^= hash_key_ulong(
-                               (void *) (unsigned long) tracker_key->value,
-                               lttng_ht_seed);
+                               (void *) (unsigned long) value, lttng_ht_seed);
                break;
        case LTTNG_ID_STRING:
-               key_hash ^= hash_key_str(tracker_key->string, lttng_ht_seed);
+               key_hash ^= hash_key_str(string, lttng_ht_seed);
                break;
        case LTTNG_ID_UNKNOWN:
                break;
        }
-       key_hash ^= hash_key_ulong((void *) (unsigned long) tracker_key->type,
-                       lttng_ht_seed);
+       key_hash ^= hash_key_ulong(
+                       (void *) (unsigned long) type, lttng_ht_seed);
        return key_hash;
 }
 
-static struct lttng_tracker_id *lttng_tracker_list_lookup(
+static struct lttng_tracker_id **lttng_tracker_list_lookup(
                const struct lttng_tracker_list *tracker_list,
                const struct lttng_tracker_id *key)
 {
@@ -130,7 +110,7 @@ static void destroy_list_node_rcu(struct rcu_head *head)
        struct lttng_tracker_list_node *n = caa_container_of(
                        head, struct lttng_tracker_list_node, rcu_head);
 
-       free(n->id.string);
+       lttng_tracker_id_destroy(n->id);
        free(n);
 }
 
@@ -161,14 +141,15 @@ static void lttng_tracker_list_reset(struct lttng_tracker_list *tracker_list)
 int lttng_tracker_list_add(struct lttng_tracker_list *tracker_list,
                const struct lttng_tracker_id *_id)
 {
-       struct lttng_tracker_id *id;
-       struct lttng_tracker_list_node *n;
+       struct lttng_tracker_id **id;
+       struct lttng_tracker_list_node *n = NULL;
        int ret;
 
-       if (_id->type == LTTNG_ID_ALL) {
+       if (lttng_tracker_id_get_type(_id) == LTTNG_ID_ALL) {
                /* Track all, so remove each individual item. */
                lttng_tracker_list_reset(tracker_list);
-               return LTTNG_OK;
+               ret = LTTNG_OK;
+               goto error;
        }
        rcu_read_lock();
        id = lttng_tracker_list_lookup(tracker_list, _id);
@@ -178,28 +159,26 @@ int lttng_tracker_list_add(struct lttng_tracker_list *tracker_list,
         */
        rcu_read_unlock();
        if (id) {
-               return LTTNG_ERR_ID_TRACKED;
+               ret = LTTNG_ERR_ID_TRACKED;
+               goto error;
        }
        n = zmalloc(sizeof(*n));
        if (!n) {
-               return LTTNG_ERR_NOMEM;
+               ret = LTTNG_ERR_NOMEM;
+               goto error;
        }
-       n->id = *_id;
-       if (_id->type == LTTNG_ID_STRING) {
-               n->id.string = strdup(_id->string);
-               if (!n->id.string) {
-                       ret = LTTNG_ERR_NOMEM;
-                       goto error;
-               }
-       } else {
-               n->id.string = NULL;
+
+       n->id = lttng_tracker_id_duplicate(_id);
+       if (!n->id) {
+               ret = LTTNG_ERR_NOMEM;
+               goto error;
        }
 
        cds_list_add_tail(&n->list_node, &tracker_list->list_head);
        tracker_list->state = LTTNG_TRACK_LIST;
 
        rcu_read_lock();
-       cds_lfht_add(tracker_list->ht, hash_tracker_key(&n->id), &n->ht_node);
+       cds_lfht_add(tracker_list->ht, hash_tracker_key(n->id), &n->ht_node);
        rcu_read_unlock();
 
        return LTTNG_OK;
@@ -217,10 +196,10 @@ int lttng_tracker_list_remove(struct lttng_tracker_list *tracker_list,
                const struct lttng_tracker_id *_id)
 {
        enum lttng_error_code ret = LTTNG_OK;
-       struct lttng_tracker_id *id;
+       struct lttng_tracker_id **id;
        struct lttng_tracker_list_node *n;
 
-       if (_id->type == LTTNG_ID_ALL) {
+       if (lttng_tracker_id_get_type(_id) == LTTNG_ID_ALL) {
                /* Untrack all. */
                lttng_tracker_list_reset(tracker_list);
                /* Set state to "track none". */
@@ -246,11 +225,14 @@ end:
 
 void lttng_tracker_list_destroy(struct lttng_tracker_list *tracker_list)
 {
+       int ret;
+
        if (!tracker_list) {
                return;
        }
        lttng_tracker_list_reset(tracker_list);
-       cds_lfht_destroy(tracker_list->ht, NULL);
+       ret = cds_lfht_destroy(tracker_list->ht, NULL);
+       assert(!ret);
        free(tracker_list);
 }
 
@@ -380,14 +362,26 @@ int lttng_tracker_id_lookup_string(enum lttng_tracker_type tracker_type,
                const struct lttng_tracker_id *id,
                int *result)
 {
-       switch (id->type) {
+       enum lttng_tracker_id_status status;
+       int value;
+       const char *string;
+
+       switch (lttng_tracker_id_get_type(id)) {
        case LTTNG_ID_ALL:
                *result = -1;
                return LTTNG_OK;
        case LTTNG_ID_VALUE:
+               status = lttng_tracker_id_get_value(id, &value);
+               if (status != LTTNG_TRACKER_ID_STATUS_OK) {
+                       return LTTNG_ERR_INVALID;
+               }
                *result = id->value;
                return LTTNG_OK;
        case LTTNG_ID_STRING:
+               status = lttng_tracker_id_get_string(id, &string);
+               if (status != LTTNG_TRACKER_ID_STATUS_OK) {
+                       return LTTNG_ERR_INVALID;
+               }
                switch (tracker_type) {
                case LTTNG_TRACKER_PID:
                case LTTNG_TRACKER_VPID:
@@ -396,11 +390,11 @@ int lttng_tracker_id_lookup_string(enum lttng_tracker_type tracker_type,
                case LTTNG_TRACKER_UID:
                case LTTNG_TRACKER_VUID:
                        DBG("Lookup of tracker UID/VUID by name.");
-                       return lttng_lookup_user(id->string, result);
+                       return lttng_lookup_user(string, result);
                case LTTNG_TRACKER_GID:
                case LTTNG_TRACKER_VGID:
                        DBG("Lookup of tracker GID/VGID by name.");
-                       return lttng_lookup_group(id->string, result);
+                       return lttng_lookup_group(string, result);
                default:
                        return LTTNG_ERR_INVALID;
                }
@@ -412,14 +406,17 @@ int lttng_tracker_id_lookup_string(enum lttng_tracker_type tracker_type,
 
 /*
  * Protected by session mutex held by caller.
- * On success, _ids and the strings it contains must be freed by caller.
+ * On success, _ids and the ids it contains must be freed by the caller.
  */
-ssize_t lttng_tracker_id_get_list(const struct lttng_tracker_list *tracker_list,
-               struct lttng_tracker_id **_ids)
+int lttng_tracker_id_get_list(const struct lttng_tracker_list *tracker_list,
+               struct lttng_tracker_ids **_ids)
 {
+       int retval = LTTNG_OK, ret;
        struct lttng_tracker_list_node *n;
-       ssize_t count = 0, i = 0, retval = 0;
-       struct lttng_tracker_id *ids;
+       ssize_t count = 0, i = 0;
+       struct lttng_tracker_ids *ids = NULL;
+       struct lttng_tracker_id *id;
+       enum lttng_tracker_id_status status;
 
        switch (tracker_list->state) {
        case LTTNG_TRACK_LIST:
@@ -427,7 +424,7 @@ ssize_t lttng_tracker_id_get_list(const struct lttng_tracker_list *tracker_list,
                                n, &tracker_list->list_head, list_node) {
                        count++;
                }
-               ids = zmalloc(sizeof(*ids) * count);
+               ids = lttng_tracker_ids_create(count);
                if (ids == NULL) {
                        PERROR("Failed to allocate tracked ID list");
                        retval = -LTTNG_ERR_NOMEM;
@@ -435,67 +432,91 @@ ssize_t lttng_tracker_id_get_list(const struct lttng_tracker_list *tracker_list,
                }
                cds_list_for_each_entry (
                                n, &tracker_list->list_head, list_node) {
-                       ids[i].type = n->id.type;
-                       ids[i].value = n->id.value;
-                       if (ids[i].type == LTTNG_ID_STRING) {
-                               ids[i].string = strdup(n->id.string);
-                               if (!ids[i].string) {
-                                       retval = -LTTNG_ERR_NOMEM;
-                                       goto error;
-                               }
+                       id = lttng_tracker_ids_get_pointer_of_index(ids, i);
+                       if (!id) {
+                               retval = -LTTNG_ERR_INVALID;
+                               goto error;
+                       }
+
+                       ret = lttng_tracker_id_copy(id, n->id);
+                       if (ret) {
+                               retval = -LTTNG_ERR_NOMEM;
+                               goto error;
                        }
                        i++;
                }
-               *_ids = ids;
-               retval = count;
                break;
        case LTTNG_TRACK_ALL:
-               ids = zmalloc(sizeof(*ids));
+
+               ids = lttng_tracker_ids_create(1);
                if (ids == NULL) {
                        PERROR("Failed to allocate tracked ID list");
                        retval = -LTTNG_ERR_NOMEM;
                        goto end;
                }
-               ids->type = LTTNG_TRACK_ALL;
-               *_ids = ids;
-               retval = 1;
+
+               id = lttng_tracker_ids_get_pointer_of_index(ids, 0);
+               status = lttng_tracker_id_set_all(id);
+               if (status != LTTNG_TRACKER_ID_STATUS_OK) {
+                       ERR("Invalid tracker id for track all");
+                       retval = -LTTNG_ERR_INVALID;
+                       goto error;
+               }
                break;
        case LTTNG_TRACK_NONE:
-               /* No ids track, so we return 0 element. */
-               *_ids = NULL;
+               /* No ids track, so we return 0 element collection. */
+               ids = lttng_tracker_ids_create(0);
+               if (ids == NULL) {
+                       PERROR("alloc list ids");
+                       retval = -LTTNG_ERR_NOMEM;
+                       goto end;
+               }
                break;
        }
+       *_ids = ids;
+
 end:
        return retval;
 
 error:
-       for (i = 0; i < count; i++) {
-               free(ids[i].string);
-       }
-       free(ids);
+       lttng_tracker_ids_destroy(ids);
        return retval;
 }
 
 int lttng_tracker_id_set_list(struct lttng_tracker_list *tracker_list,
-               struct lttng_tracker_id *_ids,
-               size_t count)
+               const struct lttng_tracker_ids *ids)
 {
-       size_t i;
+       unsigned int i, count;
+       const struct lttng_tracker_id *id;
+       enum lttng_tracker_id_status status;
+
+       assert(tracker_list);
+       assert(ids);
 
        lttng_tracker_list_reset(tracker_list);
-       if (count == 1 && _ids[0].type == LTTNG_ID_ALL) {
-               /* Track all. */
-               return LTTNG_OK;
+
+       status = lttng_tracker_ids_get_count(ids, &count);
+       if (status != LTTNG_TRACKER_ID_STATUS_OK) {
+               return LTTNG_ERR_INVALID;
        }
+
        if (count == 0) {
                /* Set state to "track none". */
                tracker_list->state = LTTNG_TRACK_NONE;
                return LTTNG_OK;
        }
+
+       if (count == 1) {
+               id = lttng_tracker_ids_get_at_index(ids, 0);
+               if (lttng_tracker_id_get_type(id) == LTTNG_ID_ALL) {
+                       /* Track all. */
+                       return LTTNG_OK;
+               }
+       }
+
        for (i = 0; i < count; i++) {
-               struct lttng_tracker_id *id = &_ids[i];
                int ret;
-
+               id = lttng_tracker_ids_get_at_index(ids, i);
                ret = lttng_tracker_list_add(tracker_list, id);
                if (ret != LTTNG_OK) {
                        return ret;
This page took 0.029343 seconds and 4 git commands to generate.