Commit ab1e8383 authored by Robin Sonnabend's avatar Robin Sonnabend

Update adcli patches

parent 46954fe7
From 213116ea8a16a10f4def750d92095c250b51def7 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 7 Oct 2016 13:57:44 +0200
Subject: [PATCH 01/30] Handle empty string in client site name
Subject: [PATCH 01/55] Handle empty string in client site name
parse_disco_string() returns an empty string if there is no client site
name in the NetLogon reply. Later in the code only a NULL check is used
......
From 85146804c219b2d4a62f315a0988536af7a53911 Mon Sep 17 00:00:00 2001
From: Joakim Tjernlund <joakim.tjernlund@infinera.com>
Date: Thu, 30 Mar 2017 12:50:33 +0200
Subject: [PATCH 02/30] Move the empty client site check
Subject: [PATCH 02/55] Move the empty client site check
Currently this check will SEGV(NULL ptr access) if the parsing
of Netlogon discovery data fails. Move the empty check to where the
......
From 7c95c61a86c5801d551d1042900b0e2e671891ce Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 24 Aug 2016 15:37:41 +0200
Subject: [PATCH 03/30] Remove upper-case only check when looking for the
Subject: [PATCH 03/55] Remove upper-case only check when looking for the
NetBIOS name
It is a convention to use only upper-case letters for NetBIOS names but
......
From 90c1e96cf3eea8718aa97a6fb97aa2029ef64670 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 24 Aug 2016 16:19:36 +0200
Subject: [PATCH 04/30] Use strdup() if offsets are used
Subject: [PATCH 04/55] Use strdup() if offsets are used
Strings with an offset to the original starting point must be copied
because otherwise they cannot be properly freed later.
......
From 99b2d00ea848db46898ae111a10739f9a9c7bf3e Mon Sep 17 00:00:00 2001
From: Striker Leggette <striker@redhat.com>
Date: Wed, 1 Nov 2017 11:16:39 +0100
Subject: [PATCH 05/30] correct spelling of 'adcli_tool_computer_delete'
Subject: [PATCH 05/55] correct spelling of 'adcli_tool_computer_delete'
description
---
......
From 8bfeba525a104f39c9ede7601035d934cd062437 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 1 Nov 2017 12:01:18 +0100
Subject: [PATCH 06/30] doc: explain that all credential cache types are
Subject: [PATCH 06/55] doc: explain that all credential cache types are
supported
---
......
From d9721f64ca3bb3467898c06aa8470aec73a0d0d8 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 1 Nov 2017 16:29:19 +0100
Subject: [PATCH 07/30] library: add adcli_conn_is_writeable()
Subject: [PATCH 07/55] library: add adcli_conn_is_writeable()
---
library/adconn.c | 11 +++++++++++
......
From 4edc04768f6b28312404312e7012c700661a4ee3 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 1 Nov 2017 17:14:05 +0100
Subject: [PATCH 08/30] Handle kvno increment for RODCs
Subject: [PATCH 08/55] Handle kvno increment for RODCs
Since the actual password change does not happen on the read-only domain
controller (RODC) the kvno change has to be replicated back which might
......
From 2f08e7992d484563c29a1db979e2a95691dbb170 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 30 Jan 2018 14:37:05 +0100
Subject: [PATCH 09/30] library: add _adcli_bin_sid_to_str()
Subject: [PATCH 09/55] library: add _adcli_bin_sid_to_str()
Convert a binary SID to the string representation.
......
From e25c49fc8be4df614e74a98e0d5dfecbf0af6020 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 30 Jan 2018 14:39:17 +0100
Subject: [PATCH 10/30] library: add _adcli_call_external_program()
Subject: [PATCH 10/55] library: add _adcli_call_external_program()
Allow adcli to call an external program given by an absolute path name
and an array of options. stdin and stdout can be used if needed.
......
From 64fb4f01d38c0f01554bc35e949ba4838247c72e Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 30 Jan 2018 14:44:45 +0100
Subject: [PATCH 11/30] library: add _adcli_ldap_parse_sid()
Subject: [PATCH 11/55] library: add _adcli_ldap_parse_sid()
Get a binary SID from a LDAP message and return it in the string
representation.
......
From d00590ada9094c47ed39e4e3a4e1d80bff126f8f Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 30 Jan 2018 14:40:46 +0100
Subject: [PATCH 12/30] library: add lookup_domain_sid()
Subject: [PATCH 12/55] library: add lookup_domain_sid()
Read the domain SID from the default naming context AD object and store
it in adcli_conn.
......
From 839ab7f8248aea897ae95b20d8bb79222c4bf21e Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 30 Jan 2018 18:23:03 +0100
Subject: [PATCH 13/30] library: add adcli_conn_get_domain_sid()
Subject: [PATCH 13/55] library: add adcli_conn_get_domain_sid()
https://bugs.freedesktop.org/show_bug.cgi?id=100118
https://gitlab.freedesktop.org/realmd/adcli/issues/6
......
From 9e2be6f374d6d9107a34acfcd6fa551190d756d5 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 30 Jan 2018 14:46:00 +0100
Subject: [PATCH 14/30] tools: add option --add-samba-data
Subject: [PATCH 14/55] tools: add option --add-samba-data
https://bugs.freedesktop.org/show_bug.cgi?id=100118
https://gitlab.freedesktop.org/realmd/adcli/issues/6
......
From a79e03c5a559389c5c9c0e9d72831e5fe5c62f54 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 30 Jan 2018 18:24:15 +0100
Subject: [PATCH 15/30] tools: store Samba data if requested
Subject: [PATCH 15/55] tools: store Samba data if requested
Use Samba's net utility to add the machine account password and the
domain SID to the Samba configuration.
......
From 9fa4b8d2bd98525212a019bfa62c2f132614faba Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Thu, 1 Feb 2018 14:26:22 +0100
Subject: [PATCH 16/30] make Samba data tool configurable
Subject: [PATCH 16/55] make Samba data tool configurable
Allow to specify an alternative path to Samba's net utility at configure
time and at run time.
......@@ -11,6 +11,7 @@ https://gitlab.freedesktop.org/realmd/adcli/issues/6
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
.gitignore | 1 +
configure.ac | 13 ++++++++++++
doc/adcli.xml | 21 ++++++++++++++++++-
doc/samba_data_tool_path.xml.in | 1 +
......@@ -20,6 +21,18 @@ Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
7 files changed, 95 insertions(+), 8 deletions(-)
create mode 100644 doc/samba_data_tool_path.xml.in
diff --git a/.gitignore b/.gitignore
index b49a065..c64f4e7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,6 +46,7 @@ Makefile.in
/doc/adcli.8
/doc/html/
/doc/version.xml
+/doc/samba_data_tool_path.xml
/po/POTFILES
/po/stamp-po
diff --git a/configure.ac b/configure.ac
index fe86638..68877c7 100644
--- a/configure.ac
......
From 1b31d18c574e820d50c80e6973e8d6031a305410 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 30 Jan 2018 14:39:46 +0100
Subject: [PATCH 17/30] Fix memory leak in test_check_nt_time_string_lifetime
Subject: [PATCH 17/55] Fix memory leak in test_check_nt_time_string_lifetime
The test added with 650e5d33ef31437a049fb454ad3dc5457c56abe7 introduced
a small memory leak.
......
From 12e13aaea8ab999540ad62e91829fc3d1815fac1 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 8 Aug 2018 12:03:01 +0200
Subject: [PATCH 18/30] fix typo in flag value
Subject: [PATCH 18/55] fix typo in flag value
---
library/adenroll.h | 2 +-
......
From b1da8a2fbe739cc8754de712711d84956848a7ea Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Thu, 31 May 2018 18:27:37 +0200
Subject: [PATCH 19/30] Add trusted-for-delegation option
Subject: [PATCH 19/55] Add trusted-for-delegation option
Resolves https://bugzilla.redhat.com/show_bug.cgi?id=1538730
---
......
From 32d8f994120cbb9b5b8b4bb1f7e80798bf82da20 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 1 Jun 2018 21:26:47 +0200
Subject: [PATCH 20/30] Only update attributes given on the command line
Subject: [PATCH 20/55] Only update attributes given on the command line
When updating attributes of the LDAP computer object we only want to
update attributes which are related to options given on the command
......
From 8396b9bca05fec8022758c6930f1e594252ae296 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 4 Jun 2018 10:49:33 +0200
Subject: [PATCH 21/30] update: allow to add service names
Subject: [PATCH 21/55] update: allow to add service names
Related to https://bugzilla.redhat.com/show_bug.cgi?id=1547013
https://bugzilla.redhat.com/show_bug.cgi?id=1545568
......
From 19c56937a7e2a1e2fd184c131587377bc2d24fbb Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 6 Jun 2018 16:31:32 +0200
Subject: [PATCH 22/30] Calculate enctypes in a separate function
Subject: [PATCH 22/55] Calculate enctypes in a separate function
Related to https://bugzilla.redhat.com/show_bug.cgi?id=1542354
---
......
From 6ea7637f75c3ec74f2ee196f2f599643b34b3c14 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 11 Jun 2018 09:44:49 +0200
Subject: [PATCH 23/30] join: add all attributes while creating computer object
Subject: [PATCH 23/55] join: add all attributes while creating computer object
It is possible to create special accounts which can only join a computer
to a domain but is not allowed to do any further operations which the
......
From 163730cf8c91fc8dc4f44eb1eca45daa3abf3ed8 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Thu, 14 Jun 2018 16:48:22 +0200
Subject: [PATCH 24/30] util: add _adcli_strv_remove_unsorted
Subject: [PATCH 24/55] util: add _adcli_strv_remove_unsorted
Related to https://bugzilla.redhat.com/show_bug.cgi?id=1547014
---
......
From bb828f22f76d5281c6bb3724fbdee3916e178407 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Thu, 14 Jun 2018 16:49:26 +0200
Subject: [PATCH 25/30] Add add-service-principal and remove-service-principal
Subject: [PATCH 25/55] Add add-service-principal and remove-service-principal
options
Currently it is only possible to specific a service name for service
......
From f448aeaebb39efa300f05ef3c2bb8b2e8f18fb82 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 13 Aug 2018 17:32:24 +0200
Subject: [PATCH 26/30] Do not add service principals twice
Subject: [PATCH 26/55] Do not add service principals twice
---
library/adenroll.c | 23 +++++++++++++++++++----
......
From 1143163c367b8473dc3d0ea696eed3c30ccd634b Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Thu, 5 Jul 2018 13:06:26 +0200
Subject: [PATCH 27/30] doc: fix typos in the adcli man page
Subject: [PATCH 27/55] doc: fix typos in the adcli man page
Resolves https://bugzilla.redhat.com/show_bug.cgi?id=1440533
---
......
From 185a8b7378665d1d0ef7dd4d5a78438459bad9e0 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Wed, 8 Aug 2018 12:17:18 +0200
Subject: [PATCH 28/30] _adcli_call_external_program: silence noisy debug
Subject: [PATCH 28/55] _adcli_call_external_program: silence noisy debug
message
---
......
From 6686c72985bc14adecf9e7db6c5fea891b7a5ef5 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 13 Aug 2018 18:24:58 +0200
Subject: [PATCH 29/30] Do not depend on default_realm in krb5.conf
Subject: [PATCH 29/55] Do not depend on default_realm in krb5.conf
---
library/adenroll.c | 4 +++-
......
From 3c93c96eb6ea2abd3869921ee4c89e1a4d9e4c44 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 14 Aug 2018 13:08:52 +0200
Subject: [PATCH 30/30] Fix for issues found by Coverity
Subject: [PATCH 30/55] Fix for issues found by Coverity
---
library/adenroll.c | 12 ++++++------
......
From 0a0d0f66409eb83e06b7dc50543c2f6c15a36bc4 Mon Sep 17 00:00:00 2001
From: Alexey A Nikitin <nikitin@amazon.com>
Date: Mon, 29 Oct 2018 20:40:36 -0700
Subject: [PATCH 31/55] Make 'adcli info' DC location mechanism more compliant
with [MS-ADTS] and [MS-NRPC]
AD specifications say that DC locator must attempt to find a suitable DC for the client. That means going through all of the DCs in SRV RRs one by one until one of them answers.
The problem with adcli's original behavior is that it queries only five DCs from SRV, ever. This becomes a problem if for any reason there is a large number of DCs in the domain from which the client cannot get a CLDAP response.
---
library/addisco.c | 146 +++++++++++++++++++++++++++++++++++-------------------
1 file changed, 94 insertions(+), 52 deletions(-)
diff --git a/library/addisco.c b/library/addisco.c
index 8cc5bf0..6e73ead 100644
--- a/library/addisco.c
+++ b/library/addisco.c
@@ -41,8 +41,10 @@
#include <string.h>
#include <time.h>
-/* Number of servers to do discovery against */
-#define DISCO_COUNT 5
+/* Number of servers to do discovery against.
+ * For AD DS maximum number of DCs is 1200.
+ */
+#define DISCO_COUNT 1200
/* The time period in which to do rapid requests */
#define DISCO_FEVER 1
@@ -454,6 +456,51 @@ parse_disco (LDAP *ldap,
}
static int
+ldap_disco_poller (LDAP **ldap,
+ LDAPMessage **message,
+ adcli_disco **results,
+ const char **addrs)
+{
+ int found = ADCLI_DISCO_UNUSABLE;
+ int close_ldap;
+ int parsed;
+ int ret = 0;
+ struct timeval tvpoll = { 0, 0 };
+
+ switch (ldap_result (*ldap, LDAP_RES_ANY, 1, &tvpoll, message)) {
+ case LDAP_RES_SEARCH_ENTRY:
+ case LDAP_RES_SEARCH_RESULT:
+ parsed = parse_disco (*ldap, *addrs, *message, results);
+ if (parsed > found)
+ found = parsed;
+ ldap_msgfree (*message);
+ close_ldap = 1;
+ break;
+ case -1:
+ ldap_get_option (*ldap, LDAP_OPT_RESULT_CODE, &ret);
+ close_ldap = 1;
+ break;
+ default:
+ ldap_msgfree (*message);
+ close_ldap = 0;
+ break;
+ }
+
+ if (ret != LDAP_SUCCESS) {
+ _adcli_ldap_handle_failure (*ldap, ADCLI_ERR_CONFIG,
+ "Couldn't perform discovery search");
+ }
+
+ /* Done with this connection */
+ if (close_ldap) {
+ ldap_unbind_ext_s (*ldap, NULL, NULL);
+ *ldap = NULL;
+ }
+
+ return found;
+}
+
+static int
ldap_disco (const char *domain,
srvinfo *srv,
adcli_disco **results)
@@ -477,6 +524,7 @@ ldap_disco (const char *domain,
int num, i;
int ret;
int have_any = 0;
+ struct timeval interval;
if (domain) {
value = _adcli_ldap_escape_filter (domain);
@@ -540,7 +588,6 @@ ldap_disco (const char *domain,
version = LDAP_VERSION3;
ldap_set_option (ldap[num], LDAP_OPT_PROTOCOL_VERSION, &version);
ldap_set_option (ldap[num], LDAP_OPT_REFERRALS , 0);
- _adcli_info ("Sending netlogon pings to domain controller: %s", url);
addrs[num] = srv->hostname;
have_any = 1;
num++;
@@ -555,70 +602,65 @@ ldap_disco (const char *domain,
freeaddrinfo (res);
}
- /* Wait for the first response. Poor mans fd watch */
- for (started = now = time (NULL);
- have_any && found != ADCLI_DISCO_USABLE && now < started + DISCO_TIME;
- now = time (NULL)) {
+ /* Initial send and short time wait */
+ interval.tv_sec = 0;
+ for (i = 0; ADCLI_DISCO_UNUSABLE == found && i < num; ++i) {
+ int parsed;
+
+ if (NULL == ldap[i])
+ continue;
- struct timeval tvpoll = { 0, 0 };
- struct timeval interval;
+ have_any = 1;
+ _adcli_info ("Sending NetLogon ping to domain controller: %s", addrs[i]);
- /* If in the initial period, send feverishly */
- if (now < started + DISCO_FEVER) {
- interval.tv_sec = 0;
- interval.tv_usec = 100 * 1000;
+ ret = ldap_search_ext (ldap[i], "", LDAP_SCOPE_BASE,
+ filter, attrs, 0, NULL, NULL, NULL,
+ -1, &msgidp);
+
+ if (ret != LDAP_SUCCESS) {
+ _adcli_ldap_handle_failure (ldap[i], ADCLI_ERR_CONFIG,
+ "Couldn't perform discovery search");
+ ldap_unbind_ext_s (ldap[i], NULL, NULL);
+ ldap[i] = NULL;
+ }
+
+ /* From https://msdn.microsoft.com/en-us/library/ff718294.aspx first
+ * five DCs are given 0.4 seconds timeout, next five are given 0.2
+ * seconds, and the rest are given 0.1 seconds
+ */
+ if (i < 5) {
+ interval.tv_usec = 400000;
+ } else if (i < 10) {
+ interval.tv_usec = 200000;
} else {
- interval.tv_sec = 1;
- interval.tv_usec = 0;
+ interval.tv_usec = 100000;
}
+ select (0, NULL, NULL, NULL, &interval);
+
+ parsed = ldap_disco_poller (&(ldap[i]), &message, results, &(addrs[i]));
+ if (parsed > found)
+ found = parsed;
+ }
+
+ /* Wait some more until LDAP timeout (DISCO_TIME) */
+ for (started = now = time (NULL);
+ have_any && ADCLI_DISCO_UNUSABLE == found && now < started + DISCO_TIME;
+ now = time (NULL)) {
select (0, NULL, NULL, NULL, &interval);
have_any = 0;
- for (i = 0; found != ADCLI_DISCO_USABLE && i < num; i++) {
- int close_ldap;
+ for (i = 0; ADCLI_DISCO_UNUSABLE == found && i < num; ++i) {
int parsed;
if (ldap[i] == NULL)
continue;
- ret = 0;
have_any = 1;
- switch (ldap_result (ldap[i], LDAP_RES_ANY, 1, &tvpoll, &message)) {
- case LDAP_RES_SEARCH_ENTRY:
- case LDAP_RES_SEARCH_RESULT:
- parsed = parse_disco (ldap[i], addrs[i], message, results);
- if (parsed > found)
- found = parsed;
- ldap_msgfree (message);
- close_ldap = 1;
- break;
- case 0:
- ret = ldap_search_ext (ldap[i], "", LDAP_SCOPE_BASE,
- filter, attrs, 0, NULL, NULL, NULL,
- -1, &msgidp);
- close_ldap = (ret != 0);
- break;
- case -1:
- ldap_get_option (ldap[i], LDAP_OPT_RESULT_CODE, &ret);
- close_ldap = 1;
- break;
- default:
- ldap_msgfree (message);
- close_ldap = 0;
- break;
- }
-
- if (ret != LDAP_SUCCESS) {
- _adcli_ldap_handle_failure (ldap[i], ADCLI_ERR_CONFIG,
- "Couldn't perform discovery search");
- }
- /* Done with this connection */
- if (close_ldap) {
- ldap_unbind_ext_s (ldap[i], NULL, NULL);
- ldap[i] = NULL;
- }
+ parsed = ldap_disco_poller (&(ldap[i]), &message, results, &(addrs[i]));
+ if (parsed > found)
+ found = parsed;
}
}
--
2.11.0
From 4bc96c69fbb93eb1fe9fcef6c6d942c296852e03 Mon Sep 17 00:00:00 2001
From: George Hartzell <ghartzell@audentestx.com>
Date: Mon, 14 Jan 2019 17:40:42 -0800
Subject: [PATCH 32/55] samba-data-tool needs to take an argument
See https://gitlab.freedesktop.org/realmd/adcli/issues/15
---
tools/computer.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/computer.c b/tools/computer.c
index 377d449..3813f0a 100644
--- a/tools/computer.c
+++ b/tools/computer.c
@@ -367,7 +367,7 @@ adcli_tool_computer_join (adcli_conn *conn,
{ "show-details", no_argument, NULL, opt_show_details },
{ "show-password", no_argument, NULL, opt_show_password },
{ "add-samba-data", no_argument, NULL, opt_add_samba_data },
- { "samba-data-tool", no_argument, NULL, opt_samba_data_tool },
+ { "samba-data-tool", required_argument, 0, opt_samba_data_tool },
{ "verbose", no_argument, NULL, opt_verbose },
{ "help", no_argument, NULL, 'h' },
{ 0 },
@@ -474,7 +474,7 @@ adcli_tool_computer_update (adcli_conn *conn,
{ "show-details", no_argument, NULL, opt_show_details },
{ "show-password", no_argument, NULL, opt_show_password },
{ "add-samba-data", no_argument, NULL, opt_add_samba_data },
- { "samba-data-tool", no_argument, NULL, opt_samba_data_tool },
+ { "samba-data-tool", required_argument, 0, opt_samba_data_tool },
{ "verbose", no_argument, NULL, opt_verbose },
{ "help", no_argument, NULL, 'h' },
{ 0 },
--
2.11.0
From 85d127fd52a8469f9f3ce0d1130fe17e756fdd75 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Fri, 16 Nov 2018 13:32:33 +0100
Subject: [PATCH 33/55] adutil: add _adcli_strv_add_unique
_adcli_strv_add_unique checks is the new value already exists in the
strv before adding it. Check can be done case-sensitive or not.
Related to https://gitlab.freedesktop.org/realmd/adcli/issues/16
---
library/adprivate.h | 5 +++++
library/adutil.c | 65 +++++++++++++++++++++++++++++++++++++++++++++--------
2 files changed, 61 insertions(+), 9 deletions(-)
diff --git a/library/adprivate.h b/library/adprivate.h
index bc9df6d..0806430 100644
--- a/library/adprivate.h
+++ b/library/adprivate.h
@@ -111,6 +111,11 @@ char ** _adcli_strv_add (char **strv,
char *string,
int *length) GNUC_WARN_UNUSED;
+char ** _adcli_strv_add_unique (char **strv,
+ char *string,
+ int *length,
+ bool case_sensitive) GNUC_WARN_UNUSED;
+
void _adcli_strv_remove_unsorted (char **strv,
const char *string,
int *length);
diff --git a/library/adutil.c b/library/adutil.c
index 17d2caa..76ea158 100644
--- a/library/adutil.c
+++ b/library/adutil.c
@@ -221,6 +221,34 @@ _adcli_strv_add (char **strv,
return seq_push (strv, length, string);
}
+static int
+_adcli_strv_has_ex (char **strv,
+ const char *str,
+ int (* compare) (const char *match, const char*value))
+{
+ int i;
+
+ for (i = 0; strv && strv[i] != NULL; i++) {
+ if (compare (strv[i], str) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+char **
+_adcli_strv_add_unique (char **strv,
+ char *string,
+ int *length,
+ bool case_sensitive)
+{
+ if (_adcli_strv_has_ex (strv, string, case_sensitive ? strcmp : strcasecmp) == 1) {
+ return strv;
+ }
+
+ return _adcli_strv_add (strv, string, length);
+}
+
#define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
void
@@ -241,19 +269,11 @@ _adcli_strv_remove_unsorted (char **strv,
(seq_compar)strcasecmp, free);
}
-
int
_adcli_strv_has (char **strv,
const char *str)
{
- int i;
-
- for (i = 0; strv && strv[i] != NULL; i++) {
- if (strcmp (strv[i], str) == 0)
- return 1;
- }
-
- return 0;
+ return _adcli_strv_has_ex (strv, str, strcmp);
}
void
@@ -705,6 +725,32 @@ test_strv_add_free (void)
}
static void
+test_strv_add_unique_free (void)
+{
+ char **strv = NULL;
+
+ strv = _adcli_strv_add_unique (strv, strdup ("one"), NULL, false);
+ strv = _adcli_strv_add_unique (strv, strdup ("one"), NULL, false);
+ strv = _adcli_strv_add_unique (strv, strdup ("two"), NULL, false);
+ strv = _adcli_strv_add_unique (strv, strdup ("two"), NULL, false);
+ strv = _adcli_strv_add_unique (strv, strdup ("tWo"), NULL, false);
+ strv = _adcli_strv_add_unique (strv, strdup ("three"), NULL, false);
+ strv = _adcli_strv_add_unique (strv, strdup ("three"), NULL, false);
+ strv = _adcli_strv_add_unique (strv, strdup ("TWO"), NULL, true);
+
+ assert_num_eq (_adcli_strv_len (strv), 4);
+
+ assert_str_eq (strv[0], "one");
+ assert_str_eq (strv[1], "two");
+ assert_str_eq (strv[2], "three");
+ assert_str_eq (strv[3], "TWO");
+ assert (strv[4] == NULL);
+
+ _adcli_strv_free (strv);
+}
+
+
+static void
test_strv_dup (void)
{
char *values[] = { "one", "two", "three", NULL };