[Pkg-freeipa-devel] [Git][freeipa-team/slapi-nis][master] 29 commits: support transition from libtirpc to libnsl in Fedora 28

Timo Aaltonen gitlab at salsa.debian.org
Tue Mar 24 09:14:08 GMT 2020



Timo Aaltonen pushed to branch master at FreeIPA packaging / slapi-nis


Commits:
062c1570 by Alexander Bokovoy at 2018-05-02T09:34:18+03:00
support transition from libtirpc to libnsl in Fedora 28

libnsl2-devel in Fedora 28 depends on libtirpc-devel internally
so we can also reduce the dependency in spec

- - - - -
8b10ea48 by Thierry Bordaz at 2018-11-30T16:47:12+01:00
Bug 1435663: deadlock between write and search operation in schema-compat plugin

Problem description:
    Schema compat is a betxn pre/post op plugin managing maps.
    The maps are protected by a RW lock.
    A typical deadlock scenario is when a read thread (SRCH) holding
    the map lock needs a ressource (DB page) acquired by an
    write thread (MOD/ADD/DEL..) and that write thread needs to update
    the map and so acquire the map lock.

    So far we have been able to reduce the frequency of those scenarios
    (but not eliminate them) by restricting the scope of operations
    that need to acquire the lock.

    But scoping is not systematically possible like described in
    https://bugzilla.redhat.com/show_bug.cgi?id=1435663#c16

Fix description:
    The fix implements a plugin RW reentrant lock 'plugin_lock'.
    To do this it uses a thread private variables (thread_plugin_lock_status and
    thread_plugin_lock_count to remember the current status of the lock
    (free, read_acquired, write_acquired).

    Then for write operations (even if it is out of the scope of SC), the lock is acquired in write
    in the BE_preop operation (note not in BETXN_preop) and only released
    in the BE_postop (postop/bepostop).
    So a write operation acquires (exclusive) the maps lock before acquiring DB pages.
    So read and write operation will acquire locks in the same order.

    Design is https://www.freeipa.org/page/V4_slapi_nis_locking

Signed-off-by: Thierry Bordaz <tbordaz at redhat.com>

- - - - -
4110b730 by Alexander Bokovoy at 2019-04-09T16:14:32+03:00
Update spec file to what is in Fedora rawhide

Signed-off-by: Alexander Bokovoy <abokovoy at redhat.com>

- - - - -
5d8783a9 by Alexander Bokovoy at 2019-04-09T16:14:45+03:00
Add COPR makefile and target to use 'make srpm' in COPR

Signed-off-by: Alexander Bokovoy <abokovoy at redhat.com>

- - - - -
8a277197 by Alexander Bokovoy at 2019-04-09T17:14:12+03:00
Install packages required to create a source rpm

Signed-off-by: Alexander Bokovoy <abokovoy at redhat.com>

- - - - -
8bdbd7a6 by Alexander Bokovoy at 2019-04-09T17:26:09+03:00
COPR: Update the list of installed packages for build

Signed-off-by: Alexander Bokovoy <abokovoy at redhat.com>

- - - - -
a67cfa15 by Alexander Bokovoy at 2019-04-10T17:47:03+03:00
Test with azure pipelines

Add pipeline definition that can be used to run build and test jobs in
dev.azure.com environment.

- - - - -
1ccbfe23 by Thierry Bordaz at 2019-04-18T09:37:36+02:00
Bug 1694263: Fix thread private variable initialization

Fix description:
	The initialization of the thread private variable was buggy.
	The private variable required an allocated struct (per thread).
	The struct is allocated on demand (during get/set) when the
	retrieved (PR_GetThreadPrivate) struct is NULL.

Signed-off-by: Thierry Bordaz <tbordaz at redhat.com>

- - - - -
5e6953c1 by Thierry Bordaz at 2019-04-18T09:37:36+02:00
Bug 1694263: improve debug msg to match pstack threadId

Description:

	A pstack is showing threadId that differs from the
	the thread pointer. To match logs with pstack
	better to display the threadId

https://bugzilla.redhat.com/show_bug.cgi?id=1694263
Signed-off-by: Thierry Bordaz <tbordaz at redhat.com>

- - - - -
52fd1595 by Thierry Bordaz at 2019-04-18T09:37:36+02:00
Bug 1694263: On some 'cn=config' updates bepost_op are not called that leads to lock leak

Description:
	The true cause of the hang was that some updates on 'cn=config'
	can skip the BEPOST phase. (in this bug it was the maxbersize setting).
	The consequence is that the slapi-nis map lock was acquired but not released.
	The fix consist to ignore (not lock slapi-nis map) write operation done
	on 'cn=config' and 'cn=schema'

https://bugzilla.redhat.com/show_bug.cgi?id=1694263
Signed-off-by: Thierry Bordaz <tbordaz at redhat.com>

- - - - -
c44f9ca8 by Alexander Bokovoy at 2019-04-23T09:39:08+03:00
Cast callbacks passed to xdrrec_create to a right type

With newer compilers there are stricter checks on callback type
validation. As result, we need to cast the callback signatures even
though it makes no practical difference in our test case.

- - - - -
a4f645e0 by Alexander Bokovoy at 2019-04-23T09:40:59+03:00
Define send_ldap_result as an external function prototype

389-ds does not expose send_ldap_result() as a public API. However,
we depend on it because slapi_send_ldap_result() is not usable for
the specific use case of the schema compatibility plugin.

- - - - -
dc3c95cf by Alexander Bokovoy at 2019-04-23T09:42:41+03:00
Declare transaction-aware callbacks for schema compat plugin

Schema compatibility plugin provides two transaction-aware
callbacks. The functions need to be declared as they are defined and
used in different compilation units.

- - - - -
1d9e7955 by Alexander Bokovoy at 2019-04-23T09:44:48+03:00
Use portable definitions for printing PRUint32 values

Also include proper headers for NSPR thread-local variable handling.
Fixes covscan warnings.

- - - - -
89485c7a by Alexander Bokovoy at 2019-06-05T13:05:54+03:00
Release 0.56.3

- - - - -
a8881e4c by Stanislav Levin at 2019-06-14T16:10:24+03:00
Fix some of compiler warnings

Signed-off-by: Stanislav Levin <slev at altlinux.org>

- - - - -
e34a1220 by Thierry Bordaz at 2019-08-01T18:28:16+02:00
Bug 1725845: slapi-nis crashes when returning an entry with invalid DN

Bug Description:
	On a search on compat tree, slapi-nis prepared the set of entries to return.
	It stores the entries into a hashtable, using the normalized DN as a key..
	If the entry contains an invalid DN, the key is invalid and triggers
	a crash while adding the entry in the hashtable

https://bugzilla.redhat.com/show_bug.cgi?id=1725845

- - - - -
d8237d43 by Thierry Bordaz at 2019-10-08T10:34:04+02:00
Bug 1746830: Memory leak during search of idview overrides

During a search on a idview with override attributes, the valueset used to retrieve the original
values of the original attribute needs to be freed once added to the overridden entry

An other leak also related to idview override is when idview_replace_target_dn
replaces the target DN. It does not free the previous target DN.

- - - - -
891138a3 by Thierry Bordaz at 2019-10-08T09:49:24+00:00
Bug 1750893: Memory leak when slapi-nis return entries retrieved from nsswitch

When slapi-nis retrieves the entries added by nsswitch search
it fills 'staged' structures.
Those structures should be freed once the entries have been returned

https://bugzilla.redhat.com/show_bug.cgi?id=1750893

- - - - -
43db38c5 by Thierry Bordaz at 2019-10-08T09:50:09+00:00
Bug 1751295: When sync-repl is enabled, slapi-nis can deadlock during retrochanglog trimming

Bug Description:
	When sync-repl is enabled, it enables retroCL that can lead to the following deadlock scenario.

	Since 1435663, slapi-nis lock is acquired from be_preop to be_postop.
	So during a write operation on domain, retroCL is updated and being a BE_TXN_POST it holds slapi-nis lock when it tries to acquire retroCL backend lock.
	If at the same time an operation on the retroCL (like retroCL trimming) acquire retroCL backend lock then during its BE_TXN_POST it tries to acquire slapi-nis lock.

	This is a common scenario, when there are updates on several backends, there is a chance
	that two updates are acquiring the backends lock in the opposite order.
	Here the backends are slapi-nis and retroCL.

Fix Description:

	Slapi-nis does nothing when an update happens on retroCL, so this suffix
	can be ignored. It will prevent retroCL trimming to try to acquire slapi-nis lock.

https://bugzilla.redhat.com/show_bug.cgi?id=1751295

- - - - -
9b46b7ef by Alexander Bokovoy at 2020-02-07T09:15:07+02:00
ignored containers are part of a shared backend code

ignored_containers_sdn is defined in src/back-shr.c and referenced in
src/back-shr.h for the actual backends to use. Header file, however, has
to use 'external' or it would be defining the variable at each
inclusion.

Fixes: RHBZ#1800097
Signed-off-by: Alexander Bokovoy <abokovoy at redhat.com>

- - - - -
165708d2 by Alexander Bokovoy at 2020-02-07T09:18:22+02:00
Streamline error message when no user information is available

- - - - -
3dd5f7c2 by Alexander Bokovoy at 2020-02-07T09:38:09+02:00
Release 0.56.4

- - - - -
4d91ad30 by Timo Aaltonen at 2020-03-24T10:49:29+02:00
Merge branch 'upstream'

- - - - -
8c056444 by Timo Aaltonen at 2020-03-24T10:50:46+02:00
bump the version

- - - - -
576b31e4 by Timo Aaltonen at 2020-03-24T11:02:21+02:00
control: Use debhelper-compat, bump to 12.

- - - - -
06f4a469 by Timo Aaltonen at 2020-03-24T11:04:17+02:00
control: Bump policy to 4.5.0.

- - - - -
06db332d by Timo Aaltonen at 2020-03-24T11:11:25+02:00
source/options: Ignore some diff.

- - - - -
275b6de5 by Timo Aaltonen at 2020-03-24T11:13:10+02:00
releasing package slapi-nis version 0.56.4-1

- - - - -


26 changed files:

- + .copr/Makefile
- NEWS
- configure.ac
- debian/changelog
- − debian/compat
- debian/control
- + debian/source/options
- slapi-nis.spec
- src/back-nis.c
- src/back-sch-idview.c
- src/back-sch-pam.c
- src/back-sch.c
- src/back-shr.c
- src/back-shr.h
- src/backend.h
- src/map.c
- src/map.h
- src/nis.c
- src/plug-sch.c
- src/portmap.c
- src/wrap.c
- + tests/azure/README.md
- + tests/azure/azure-pipelines.yml
- tests/clients/Makefile.am
- tests/clients/yp.c
- yp/Makefile.am


Changes:

=====================================
.copr/Makefile
=====================================
@@ -0,0 +1,26 @@
+VERSION != grep AC_INIT configure.ac|cut -d, -f2|tr -d ")"
+outdir=.
+SUDO=
+
+srpm:
+	$(SUDO) dnf -y install rpm-build autoconf automake libtool \
+		/usr/bin/rpcgen 389-ds-base-devel libnsl2-devel \
+		libsss_nss_idmap-devel nspr-devel nss-devel \
+		openldap-devel pam-devel ; \
+	./autogen.sh; \
+	./configure; \
+	tmpdir=`mktemp -d /tmp/make_archive_XXXXXX`;\
+	make dist;\
+	mv slapi-nis-$(VERSION).tar.gz $$tmpdir; \
+	touch $$tmpdir/slapi-nis-$(VERSION).tar.gz.sig;\
+	rpmbuild \
+		--define "_topdir $$tmpdir" \
+		--define "_sourcedir $$tmpdir" \
+		--define "_specdir $$tmpdir" \
+		--define "_builddir $$tmpdir" \
+		--define "_srcrpmdir $$tmpdir" \
+		--define "_rpmdir $$tmpdir" \
+		--build-in-place \
+		-ts $$tmpdir/slapi-nis-$(VERSION).tar.gz;\
+	cp -v $$tmpdir/slapi-nis-$(VERSION)-*.src.rpm $(outdir)/; \
+	rm -rf $$tmpdir


=====================================
NEWS
=====================================
@@ -1,3 +1,7 @@
+0.56.3  * Bug 1694263: On some 'cn=config' updates bepost_op are not called
+          that leads to lock leak
+	* Bug 1435663: deadlock between write and search operation in
+	  schema-compat plugin
 0.52	* Properly note in the nsslapd-pluginVersion attribute whether or
 	  not transaction support is available.
 	* Fix a pair of incorrect memcpy()-instead-of-memmove() cases which


=====================================
configure.ac
=====================================
@@ -1,4 +1,4 @@
-AC_INIT(slapi-nis,0.56.2)
+AC_INIT(slapi-nis,0.56.4)
 AC_CONFIG_MACRO_DIR([m4])
 AM_INIT_AUTOMAKE(foreign)
 LT_INIT([disable-static])
@@ -273,6 +273,12 @@ AC_ARG_WITH(tirpc,
 	    ])
 if test $use_tirpc = yes ; then
 	PKG_CHECK_MODULES(TIRPC,libtirpc)
+fi
+
+PKG_CHECK_MODULES(NSL,libnsl,[use_libnsl=yes],[use_libnsl=no])
+if test "$use_libnsl" = yes ; then
+	RPC_CFLAGS="$NSL_CFLAGS"
+	RPC_LIBS="$NSL_LIBS"
 else
 	RPC_CFLAGS=
 	RPC_LIBS=-lnsl


=====================================
debian/changelog
=====================================
@@ -1,3 +1,12 @@
+slapi-nis (0.56.4-1) unstable; urgency=medium
+
+  * New upstream release.
+  * control: Use debhelper-compat, bump to 12.
+  * control: Bump policy to 4.5.0.
+  * source/options: Ignore some diff.
+
+ -- Timo Aaltonen <tjaalton at debian.org>  Tue, 24 Mar 2020 11:11:27 +0200
+
 slapi-nis (0.56.2-1) unstable; urgency=medium
 
   * New upstream release.


=====================================
debian/compat deleted
=====================================
@@ -1 +0,0 @@
-11


=====================================
debian/control
=====================================
@@ -5,7 +5,7 @@ Maintainer: Debian FreeIPA Team <pkg-freeipa-devel at alioth-lists.debian.net>
 Uploaders: Timo Aaltonen <tjaalton at debian.org>
 Build-Depends:
  389-ds-base-dev,
- debhelper (>= 11),
+ debhelper-compat (= 12),
  libldap2-dev,
  libnspr4-dev,
  libnss3-dev,
@@ -14,7 +14,7 @@ Build-Depends:
  libtirpc-dev,
  libwrap0-dev,
  pkg-config
-Standards-Version: 4.1.4
+Standards-Version: 4.5.0
 Homepage: https://pagure.io/slapi-nis
 Vcs-Git: https://salsa.debian.org/freeipa-team/slapi-nis.git
 Vcs-Browser: https://salsa.debian.org/freeipa-team/slapi-nis


=====================================
debian/source/options
=====================================
@@ -0,0 +1 @@
+extend-diff-ignore = .copr|tests


=====================================
slapi-nis.spec
=====================================
@@ -10,15 +10,16 @@
 %endif
 
 Name:		slapi-nis
-Version:	0.56.2
+Version:	0.56.4
 Release:	1%{?dist}
 Summary:	NIS Server and Schema Compatibility plugins for Directory Server
-Group:		System Environment/Daemons
 License:	GPLv2
-URL:		http://slapi-nis.fedorahosted.org/
-Source0:	https://fedorahosted.org/releases/s/l/slapi-nis/slapi-nis-%{version}.tar.gz
-#Source1:	https://fedorahosted.org/releases/s/l/slapi-nis/slapi-nis-%{version}.tar.gz.sig
-BuildRoot:	%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+URL:		http://pagure.io/slapi-nis/
+Source0:	https://releases.pagure.org/slapi-nis/slapi-nis-%{version}.tar.gz
+Source1:	https://releases.pagure.org/slapi-nis/slapi-nis-%{version}.tar.gz.sig
+BuildRequires:  autoconf
+BuildRequires:  automake
+BuildRequires:  libtool
 BuildRequires:	389-ds-base-devel >= 1.3.5.6, %{ldap_impl}-devel
 BuildRequires:	nspr-devel, nss-devel, /usr/bin/rpcgen
 %if 0%{?fedora} > 18 || 0%{?rhel} > 6
@@ -28,16 +29,13 @@ BuildRequires:	libsss_nss_idmap-devel > 1.16.0-5
 %define sss_nss_opts %{nil}
 %endif
 BuildRequires:	pam-devel
-%if 0%{?fedora} > 6 || 0%{?rhel} > 5
-BuildRequires:	tcp_wrappers-devel
-%else
-BuildRequires:	tcp_wrappers
-%endif
-%if 0%{?fedora} > 14 || 0%{?rhel} > 6
+%if (0%{?fedora} > 14 && 0%{?fedora} < 28) || (0%{?rhel} > 6 && 0%{?rhel} < 8)
 BuildRequires:	libtirpc-devel
+%else:
+BuildRequires:  libnsl2-devel
 %endif
-%if 0%{?rhel} > 0 && 0%{?rhel} < 7
-ExclusiveArch:	x86_64 %{ix86}
+%if 0%{?fedora} > 27
+ExcludeArch: %{ix86}
 %endif
 Requires: 389-ds-base >= 1.3.5.6
 
@@ -58,7 +56,8 @@ for attributes from multiple entries in the tree.
 %setup -q
 
 %build
-%configure --disable-static --with-tcp-wrappers --with-ldap=%{ldap_impl} \
+autoconf --force
+%configure --disable-static --with-ldap=%{ldap_impl} \
 	--with-nsswitch --with-pam --with-pam-service=system-auth \
 	%{sss_nss_opts} %{betxn_opts}
 sed -i -e 's,%{_libdir}/dirsrv/plugins/,,g' -e 's,.so$,,g' doc/examples/*.ldif
@@ -75,22 +74,58 @@ rm $RPM_BUILD_ROOT/%{_libdir}/dirsrv/plugins/*.la
 make check
 %endif
 
-%clean
-rm -rf $RPM_BUILD_ROOT
-
 %files
-%defattr(-,root,root,-)
 %doc COPYING NEWS README STATUS doc/*.txt doc/examples/*.ldif doc/ipa
 %{_mandir}/man1/*
 %{_libdir}/dirsrv/plugins/*.so
 %{_sbindir}/nisserver-plugin-defs
 
 %changelog
+* Fri Feb 07 2020 Alexander Bokovoy <abokovoy at redhat.com> - 0.56.4-1
+- New upstream release
+- Fix build with newer gcc versions
+- Resolves rhbz#1800097
+
+* Wed Jun 05 2019 Alexander Bokovoy <abokovoy at redhat.com> - 0.56.3-1
+- New upstream release
+
+* Sat Feb 02 2019 Fedora Release Engineering <releng at fedoraproject.org> - 0.56.2-8
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
+
+* Sat Jul 14 2018 Fedora Release Engineering <releng at fedoraproject.org> - 0.56.2-7
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
+
+* Wed May 02 2018 Alexander Bokovoy <abokovoy at redhat.com> - 0.56.2-6
+- Force rebuild of configure
+
+* Wed May 02 2018 Alexander Bokovoy <abokovoy at redhat.com> - 0.56.2-5
+- Link with libnsl explicitly in Fedora 28 or later
+- Require libnsl2-devel for build
+- Resolves rhbz#1573636
+
+* Thu Mar 15 2018 Alexander Bokovoy <abokovoy at redhat.com> - 0.56.2-4
+- Remove tcpwrappers support as they aren't available in Fedora anymore
+
+* Thu Mar 15 2018 Alexander Bokovoy <abokovoy at redhat.com> - 0.56.2-3
+- Do not build on i686 in Fedora 28 or later as 389-ds-base is not available there anymore
+- Resolves rhbz#1556448
+- Remove outdated ExclusiveArch for RHEL6
+
+* Fri Feb 09 2018 Fedora Release Engineering <releng at fedoraproject.org> - 0.56.2-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
+
 * Fri Jan 19 2018 Alexander Bokovoy <abokovoy at redhat.com> - 0.56.2-1
 - New upstream release
+- Update links to the upstream project page and releases
 - Use extended SSSD API to signal that an entry should not be cached anymore
 - Add support for timeout-based NSS queries with libsss_nss_idmap
 
+* Thu Aug 03 2017 Fedora Release Engineering <releng at fedoraproject.org> - 0.56.1-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
+
+* Thu Jul 27 2017 Fedora Release Engineering <releng at fedoraproject.org> - 0.56.1-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
+
 * Sat Feb 11 2017 Fedora Release Engineering <releng at fedoraproject.org> - 0.56.1-2
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
 


=====================================
src/back-nis.c
=====================================
@@ -849,6 +849,8 @@ backend_update_params(Slapi_PBlock *pb, struct plugin_state *state)
 		request_set(state->request_info, RQ_DAEMON,
 			    DEFAULT_TCPWRAP_NAME);
 	}
+#else
+        (void)tmp;
 #endif
 	use_be_txns = backend_shr_get_vattr_boolean(state, our_entry,
 						    "nsslapd-pluginbetxn",


=====================================
src/back-sch-idview.c
=====================================
@@ -56,7 +56,7 @@ void
 idview_get_overrides(struct backend_search_cbdata *cbdata)
 {
 	char *dn = NULL;
-	int ret = 0, result = 0;
+	int result = 0;
 	const Slapi_DN *suffix = NULL;
 	Slapi_PBlock *pb;
 
@@ -76,7 +76,7 @@ idview_get_overrides(struct backend_search_cbdata *cbdata)
 	slapi_search_internal_set_pb(pb, dn, LDAP_SCOPE_SUBTREE,
 				     "(objectclass=ipaOverrideAnchor)", NULL, 0,
 				     NULL, NULL, cbdata->state->plugin_identity, 0);
-	ret = slapi_search_internal_pb(pb);
+	slapi_search_internal_pb(pb);
 	slapi_ch_free_string(&dn);
 	slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &result);
 
@@ -180,6 +180,7 @@ idview_process_overrides(struct backend_search_cbdata *cbdata,
 				}
 				result = slapi_attr_get_valueset(override_attr, &override_valueset);
 				result = slapi_entry_add_valueset(entry, override_type, override_valueset);
+				slapi_valueset_free(override_valueset);
 			}
 			result = slapi_entry_next_attr(override_entry, override_attr, &override_attr);
 		}
@@ -287,6 +288,7 @@ idview_replace_target_dn(char **target, char **idview)
 			new_target = slapi_ch_smprintf("%s", cnviews+10);
 		}
 		cnviews[0] = ',';
+		slapi_ch_free_string(target);
 		*target = new_target;
 	}
 }
@@ -411,8 +413,6 @@ idview_replace_filter(struct backend_search_cbdata *cbdata)
 {
 	struct backend_search_filter_config config =
 		{FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL, NULL, NULL};
-	int res = 0;
-
 	if (cbdata->idview == NULL) {
 		return;
 	}
@@ -421,7 +421,7 @@ idview_replace_filter(struct backend_search_cbdata *cbdata)
 	config.callback_data = cbdata;
 
 	/* Ignore the return code as it will always be SLAPI_FILTER_SCAN_NO_MORE */
-	res = backend_analyze_search_filter(cbdata->filter, &config);
+	(void)backend_analyze_search_filter(cbdata->filter, &config);
 
 	if (config.name != NULL) {
 		slapi_ch_free_string(&config.name);


=====================================
src/back-sch-pam.c
=====================================
@@ -168,9 +168,8 @@ map_pam_error(Slapi_PBlock *pb, const char *fn,
 		}
 	} else {
 		if (rc == PAM_SUCCESS) {
-			*errmsg = PR_smprintf("PAM %s succeeds for user \"%s\" "
-					      "(bind DN \"%s\")",
-					      fn, user, binddn);
+			*errmsg = PR_smprintf("PAM %s succeeds for bind DN \"%s\"",
+					      fn, binddn);
 		} else {
 			if (pamh != NULL) {
 				*errmsg = PR_smprintf("PAM %s error for invalid user "


=====================================
src/back-sch.c
=====================================
@@ -55,6 +55,12 @@
 #include "map.h"
 #include "back-sch.h"
 
+/*
+ * This is not a public function in 389-ds but we need to use it in backend_search_cb(),
+ * see a comment there on the difference between slapi_send_ldap_result() and send_ldap_result().
+ */
+extern void send_ldap_result(Slapi_PBlock *pb, int err, char *matched, char *text, int nentries, struct berval **urls);
+
 static int backend_passwdmod_extop(Slapi_PBlock *pb);
 backend_extop_handlers_t extop_handlers[] = {{EXTOP_PASSWD_OID, (IFP) backend_passwdmod_extop},
 					    {NULL, NULL}};
@@ -432,13 +438,8 @@ backend_set_operational_attributes(Slapi_Entry *e,
 	 * plugin want to override the values using the configuration, they
 	 * can. */
 	if (gmtime_r(&timestamp, &timestamp_tm) == &timestamp_tm) {
-		sprintf(timestamp_str, "%04d%02d%02d%02d%02d%02dZ",
-			timestamp_tm.tm_year + 1900,
-			timestamp_tm.tm_mon + 1,
-			timestamp_tm.tm_mday,
-			timestamp_tm.tm_hour,
-			timestamp_tm.tm_min,
-			timestamp_tm.tm_sec);
+		strftime(timestamp_str, sizeof(timestamp_str),
+			 "%Y%m%d%H%M%SZ", &timestamp_tm);
 		slapi_entry_add_string(e, "createTimestamp", timestamp_str);
 		slapi_entry_add_string(e, "modifyTimestamp", timestamp_str);
 	}
@@ -1524,16 +1525,17 @@ backend_entries_to_return_push(struct backend_search_cbdata *cbdata, Slapi_Entry
 	struct entries_to_send *e_to_send = NULL;
 	struct cached_entry *entry = NULL;
 	bool_t dont_cache = FALSE;
+	void *ndn_key = (void *) slapi_entry_get_ndn(e);
 	PLHashTable* ht = (PLHashTable*) cbdata->state->cached_entries;
 
-	if ((cbdata == NULL) || (e == NULL)) return;
+	if ((cbdata == NULL) || (e == NULL) || (ndn_key == NULL)) return;
 
 	e_to_send = (struct entries_to_send *) slapi_ch_calloc(1, sizeof(struct entries_to_send));
 
 	dont_cache = cbdata->state->use_entry_cache ? FALSE : TRUE;
 
 	if (!wrap_rwlock_wrlock(cbdata->state->cached_entries_lock)) {
-		entry = PL_HashTableLookup(ht, slapi_entry_get_ndn(e));
+		entry = PL_HashTableLookup(ht, ndn_key);
 		if (entry != NULL) {
 			/* There is an entry in the hash table but is it the same? */
 			char *e_modifyTimestamp = slapi_entry_attr_get_charptr(e, "modifyTimestamp");
@@ -1647,6 +1649,45 @@ backend_send_mapped_entries(struct backend_search_cbdata *cbdata)
 	cbdata->entries_tail = NULL;
 }
 
+static void
+backend_search_free_staged(struct backend_search_cbdata *cbdata)
+{
+	struct backend_staged_search *staged, *next;
+	int i;
+	int nb_entries = 0;
+	int nb_stages = 0;
+
+	if (cbdata == NULL) {
+		return;
+	}
+
+	staged = cbdata->staged;
+	while (staged != NULL) {
+		nb_stages++;
+		for (i = 0;
+				(i < staged->count) &&
+				(staged->entries != NULL) &&
+				(staged->entries[i] != NULL);
+				i++) {
+			slapi_entry_free(staged->entries[i]);
+			staged->entries[i] = NULL;
+		}
+		nb_entries += i;
+		slapi_ch_free_string(&staged->map_group);
+		slapi_ch_free_string(&staged->map_set);
+		slapi_ch_free_string(&staged->name);
+		slapi_ch_free_string(&staged->container_sdn);
+		next = staged->next;
+		free(staged);
+		staged = next;
+	}
+	slapi_log_error(SLAPI_LOG_PLUGIN,
+			cbdata->state->plugin_desc->spd_id,
+			"backend_search_free_staged freed %d stages with %d entries\n",
+			nb_stages,
+			nb_entries);
+	cbdata->staged = NULL;
+}
 static int
 backend_search_cb(Slapi_PBlock *pb)
 {
@@ -1851,6 +1892,7 @@ backend_search_cb(Slapi_PBlock *pb)
 			map_unlock();
 			/* Return newly acquired entries */
 			backend_send_mapped_entries(&cbdata);
+			backend_search_free_staged(&cbdata);
 		} else {
 			slapi_log_error(SLAPI_LOG_PLUGIN,
 					cbdata.state->plugin_desc->spd_id,
@@ -2303,6 +2345,200 @@ backend_betxn_pre_write_cb(Slapi_PBlock *pb)
 	slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
 	return state->use_be_txns ? backend_write_cb(pb, state) : 0;
 }
+static PRBool
+backend_be_write_ignore(Slapi_PBlock *pb)
+{
+    char *dn = NULL;
+    Slapi_DN *target_sdn = NULL;
+    int check;
+    int i = 0;
+    PRBool ignore = PR_FALSE;
+
+    /* Check if the target DN is a subordinates of
+     * on of the ignored containers
+     */
+    slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET, &dn);
+    target_sdn = slapi_sdn_new_dn_byval(dn);
+
+    for (i = 0; ignored_containers_sdn[i]; i++) {
+        check  = slapi_sdn_issuffix(target_sdn, ignored_containers_sdn[i]);
+        if (check != 0) {
+            /* This entry is an ignored container */
+            ignore = PR_TRUE;
+            break;
+        }
+    }
+    slapi_sdn_free(&target_sdn);
+    return ignore;
+}
+
+
+static int
+backend_be_pre_write_cb(Slapi_PBlock *pb) {
+    int ret = 0;
+    int lock_status;
+    int lock_count;
+    struct plugin_state *state;
+
+    slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
+
+    if (wrap_get_call_level() > 0) {
+        return 0;
+    }
+    if (state->ready_to_serve == 0) {
+        /* No data to serve yet */
+        return 0;
+    }
+    if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) {
+        return 0;
+    }
+    if (backend_be_write_ignore(pb)) {
+#if DEBUG_MAP_LOCK
+        slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+                "backend_be_pre_write_cb: (%p) operation is not impacting schema compat\n", PR_MyThreadId(), 1);
+#endif
+        return 0;
+    }
+
+
+
+    wrap_inc_call_level();
+
+    lock_status = get_plugin_monitor_status();
+    lock_count = get_plugin_monitor_count();
+    if (lock_status == MAP_RWLOCK_UNINIT) {
+        return 0;
+    }
+
+    if (lock_status == MAP_RWLOCK_FREE) {
+        /* This thread does not hold the map lock */
+        set_plugin_monitor_count(1);
+
+        if (plugin_wrlock() == 0) {
+            ret = 0;
+        } else {
+            slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+                    "backend_be_pre_write_cb: unable to acquire write lock\n");
+            ret = -1;
+        }
+#if DEBUG_MAP_LOCK
+        slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+                "backend_be_pre_write_cb: (%p) MAP_RWLOCK_FREE -> MAP_WLOCK_HELD  : count=%d\n", (void *) PR_MyThreadId(), 1);
+#endif
+    } else {
+        set_plugin_monitor_count(lock_count + 1);
+#if DEBUG_MAP_LOCK
+        slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                        "backend_be_pre_write_cb: (%p)  %s --> MAP_WLOCK_HELD  : count=%d\n",
+                (void *) PR_MyThreadId(),
+                (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD": "MAP_RLOCK_HELD",
+                lock_count + 1);
+#endif
+        ret = 0;
+        if (lock_status == MAP_RLOCK_HELD) {
+            /* lock is already acquired in read */
+
+#if DEBUG_MAP_LOCK
+            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+				"map backend_be_pre_write_cb: weird situation map lock is held in read and now required in write mode\n");
+#endif
+            /* First free the lock held in read */
+            ret = plugin_unlock();
+            if (ret) {
+                    slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                            "backend_be_pre_write_cb: fail to unlock plugin lock (%d)\n", ret);
+            }
+
+            /* Second acquire it in write */
+            ret = plugin_wrlock();
+            if (ret) {
+                    slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                            "backend_be_pre_write_cb: fail to write lock plugin lock (%d)\n", ret);
+            }
+        }
+    }
+
+    set_plugin_monitor_status(MAP_WLOCK_HELD);
+    wrap_dec_call_level();
+
+    return ret;
+}
+
+static int
+backend_be_post_write_cb(Slapi_PBlock *pb)
+{
+    int ret = 0;
+    int lock_status;
+    int lock_count;
+    struct plugin_state *state;
+
+    slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
+
+	if (wrap_get_call_level() > 0) {
+		return 0;
+	}
+	if (state->ready_to_serve == 0) {
+		/* No data to serve yet */
+		return 0;
+	}
+    if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) {
+        return 0;
+    }
+    if (backend_be_write_ignore(pb)) {
+#if DEBUG_MAP_LOCK
+        slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+                "backend_be_post_write_cb: (%p) operation was not impacting schema compat\n", PR_MyThreadId(), 1);
+#endif
+        return 0;
+    }
+
+	wrap_inc_call_level();
+
+    lock_status = get_plugin_monitor_status();
+    lock_count = get_plugin_monitor_count();
+    if (lock_status == MAP_RWLOCK_UNINIT) {
+        return 0;
+    }
+
+    if (lock_count == 1) {
+        set_plugin_monitor_status(MAP_RWLOCK_FREE);
+        if (plugin_unlock() == 0) {
+            ret = 0;
+        } else {
+            slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+                    "backend_be_post_write_cb: unable to release write lock\n");
+            ret = -1;
+        }
+#if DEBUG_MAP_LOCK
+        slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                "backend_be_post_write_cb: (%p)  %s --> MAP_RWLOCK_FREE  : count=%d\n",
+                (void *) PR_MyThreadId(),
+                (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
+                0);
+#endif
+    }
+    if (lock_count >= 1) {
+        set_plugin_monitor_count(lock_count - 1);
+#if DEBUG_MAP_LOCK
+        if (lock_count > 1) {
+            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                    "backend_be_post_write_cb: (%p)  keep %s : count=%d\n",
+                    (void *) PR_MyThreadId(),
+                    (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
+                    lock_count - 1);
+        } else {
+            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                    "backend_be_post_write_cb: (%p)  is now %s : count=%d\n",
+                    (void *) PR_MyThreadId(),
+                    "MAP_RWLOCK_FREE",
+                    lock_count - 1);
+        }
+#endif
+    }
+	wrap_dec_call_level();
+
+	return ret;
+}
 
 #ifdef USE_PAM
 static int
@@ -2814,6 +3050,42 @@ backend_init_betxn_preop(Slapi_PBlock *pb, struct plugin_state *state)
 	return 0;
 }
 
+int
+backend_init_be_preop(Slapi_PBlock *pb, struct plugin_state *state)
+{
+	slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+	                "hooking up bet preoperation callbacks\n");
+	/* Intercept write requests and return an insufficient-access error for
+	 * attempts to write to anything we're managing. */
+	if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_ADD_FN,
+			     backend_be_pre_write_cb) != 0) {
+		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+				"error hooking up betxn pre add callback\n");
+		return -1;
+	}
+	if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_MODIFY_FN,
+			     backend_be_pre_write_cb) != 0) {
+		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+				"error hooking up betxn pre modify callback\n");
+		return -1;
+	}
+	if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_MODRDN_FN,
+			     backend_be_pre_write_cb) != 0) {
+		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+				"error hooking up betxn pre modrdn callback\n");
+		return -1;
+	}
+	if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_DELETE_FN,
+			     backend_be_pre_write_cb) != 0) {
+		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+				"error hooking up betxn pre delete callback\n");
+		return -1;
+	}
+	/* We don't hook abandonment requests. */
+	/* We don't hook unbind requests. */
+	return 0;
+}
+
 int
 backend_init_betxn_postop(Slapi_PBlock *pb, struct plugin_state *state)
 {
@@ -2821,6 +3093,40 @@ backend_init_betxn_postop(Slapi_PBlock *pb, struct plugin_state *state)
 			"hooking up betxn postoperation callbacks\n");
 	return backend_shr_betxn_postop_init(pb, state);
 }
+
+
+int
+backend_init_be_postop(Slapi_PBlock *pb, struct plugin_state *state)
+{
+	if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_ADD_FN,
+			     backend_be_post_write_cb) != 0) {
+		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+				"error hooking up betxn post add callback\n");
+		return -1;
+	}
+	if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_MODIFY_FN,
+			     backend_be_post_write_cb) != 0) {
+		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+				"error hooking up betxn post modify "
+				"callback\n");
+		return -1;
+	}
+	if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_MODRDN_FN,
+			     backend_be_post_write_cb) != 0) {
+		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+				"error hooking up betxn post modrdn "
+				"callback\n");
+		return -1;
+	}
+	if (slapi_pblock_set(pb, SLAPI_PLUGIN_BE_POST_DELETE_FN,
+			     backend_be_post_write_cb) != 0) {
+		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+				"error hooking up betxn post delete "
+				"callback\n");
+		return -1;
+	}
+	return 0;
+}
 #endif
 
 int


=====================================
src/back-shr.c
=====================================
@@ -37,6 +37,9 @@
 #endif
 
 #include <rpc/xdr.h>
+#include <prtypes.h>
+/* NSPR private API for thread-local variables */
+#include <private/prpriv.h>
 #include "../yp/yp.h"
 
 #ifdef HAVE_TCPD_H
@@ -777,8 +780,6 @@ static void
 backend_shr_data_initialize_thread(time_t when, void *arg)
 {
 	struct backend_shr_data_init_cbdata *cbdata = (struct backend_shr_data_init_cbdata *)arg;
-	PRThread *thread = NULL;
-
 	if (slapi_is_shutting_down()) {
 		return;
 	}
@@ -2866,3 +2867,201 @@ backend_shr_internal_postop_init(Slapi_PBlock *pb, struct plugin_state *state)
 	}
 	return 0;
 }
+
+int
+PR_MyThreadId(void)
+{
+    PRThread *thr = PR_GetCurrentThread();
+    PRUint32 myself = PR_GetThreadID(thr);
+    return myself;
+}
+PRBool use_lock_status = PR_FALSE;
+static unsigned int thread_plugin_lock_status;
+PRBool use_lock_count = PR_FALSE;
+static unsigned int thread_plugin_lock_count;
+/*
+ * https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSPR/Reference/PR_NewThreadPrivateIndex
+ * It is called each time:
+ *  - PR_SetThreadPrivate is call with a not NULL private value
+ *  - on thread exit
+ */
+static void
+lock_status_free(void *ptr)
+{
+    int *lock_status = ptr;
+    if (lock_status) {
+        slapi_ch_free((void **)&lock_status);
+    }
+}
+static void
+lock_count_free(void *ptr)
+{
+    int *lock_count = ptr;
+    if (lock_count) {
+        slapi_ch_free((void **)&lock_count);
+    }
+}
+
+/* This is used to ignore some write operations
+ * if they target subordinates entry of ignored containers
+ */
+Slapi_DN **ignored_containers_sdn = NULL;
+void
+init_map_lock(void)
+{
+#if DEBUG_MAP_LOCK
+    /* The plugin lock is initialized as free */
+    slapi_log_error(SLAPI_LOG_FATAL, "init_plugin_lock",
+            "thread_id = %p\n", PR_MyThreadId());
+#endif
+    if (ignored_containers_sdn == NULL) {
+        /* allocates ignored_containers_sdn of Slapi_DN* only once
+         * It will be used later in be_pre/post_write_cb
+         */
+        int cnt;
+        char *ignored_containers[4] = { "cn=config", "cn=schema", "cn=changelog", NULL};
+
+        for (cnt = 0; ignored_containers[cnt]; cnt++);
+        ignored_containers_sdn = (Slapi_DN **) slapi_ch_calloc(cnt + 1, sizeof(Slapi_DN *));
+
+        for (cnt = 0; ignored_containers[cnt]; cnt++) {
+            ignored_containers_sdn[cnt] = slapi_sdn_new_dn_byval(ignored_containers[cnt]);
+        }
+    }
+
+    if (PR_NewThreadPrivateIndex(&thread_plugin_lock_status, lock_status_free) == PR_SUCCESS) {
+        use_lock_status = PR_TRUE;
+    }
+    if (PR_NewThreadPrivateIndex(&thread_plugin_lock_count, lock_count_free) == PR_SUCCESS) {
+        use_lock_count = PR_TRUE;
+    }
+
+#if DEBUG_MAP_LOCK
+    slapi_log_error(SLAPI_LOG_FATAL, "init_plugin_lock",
+            "thread_plugin_lock_status = %d\n", thread_plugin_lock_status);
+    slapi_log_error(SLAPI_LOG_FATAL, "init_map_lock",
+            "thread_plugin_lock_count = %d\n", thread_plugin_lock_count);
+#endif
+}
+
+int
+rw_monitor_enabled(void)
+{
+    if (use_lock_status)
+        return (int) MAP_MONITOR_ENABLED;
+    else
+        return (int) MAP_MONITOR_DISABLED;
+}
+
+int
+get_plugin_monitor_status(void)
+{
+    int ret;
+
+    if (use_lock_status) {
+        int *lock_status_p;
+        lock_status_p = (int *) PR_GetThreadPrivate(thread_plugin_lock_status);
+        if (lock_status_p == NULL) {
+            /* if it was not initialized then allocates a structure
+             * that will be private to that thread.
+             * Later when the structure is retrieved (PR_GetThreadPrivate), the
+             * content of the structure can be read/write without allocating
+             * this private structure PR_SetThreadPrivate.
+             * So this branch is processed one time per each thread
+             */
+            lock_status_p = (int *) slapi_ch_calloc(1, sizeof (int));
+            PR_SetThreadPrivate(thread_plugin_lock_status, (void *) lock_status_p);
+            *lock_status_p = MAP_RWLOCK_FREE;
+        }
+        ret = *lock_status_p;
+    } else
+        ret = (int) MAP_RWLOCK_UNINIT;
+#if DEBUG_MAP_LOCK
+    slapi_log_error(SLAPI_LOG_FATAL, "get_plugin_monitor_status",
+            "(%s) lock_status = %d (%p)\n", use_lock_status ? "TRUE" : "FALSE", ret, (void *) PR_MyThreadId());
+#endif
+    return ret;
+}
+
+void
+set_plugin_monitor_status(int lock_status)
+{
+#if DEBUG_MAP_LOCK
+    slapi_log_error(SLAPI_LOG_FATAL, "set_plugin_monitor_status",
+            "(%s) lock_status = %d --> %d (%p)\n", use_lock_status ? "TRUE" : "FALSE", get_plugin_monitor_status(), (int) lock_status, (void *) PR_MyThreadId());
+#endif
+
+    if (use_lock_status) {
+        int *lock_status_p;
+
+        lock_status_p = (int *) PR_GetThreadPrivate(thread_plugin_lock_status);
+        if (lock_status_p == NULL) {
+            /* if it was not initialized then allocates a structure
+             * that will be private to that thread.
+             * Later when the structure is retrieved (PR_GetThreadPrivate), the
+             * content of the structure can be read/write without allocating
+             * this private structure PR_SetThreadPrivate.
+             * So this branch is processed one time per each thread
+             */
+            lock_status_p = (int *) slapi_ch_calloc(1, sizeof (int));
+            PR_SetThreadPrivate(thread_plugin_lock_status, (void *) lock_status_p);
+        }
+        *lock_status_p = lock_status;
+    }
+}
+
+int
+get_plugin_monitor_count(void)
+{
+    int ret;
+
+    if (use_lock_count) {
+        int *lock_count;
+        lock_count = (int *) PR_GetThreadPrivate(thread_plugin_lock_count);
+        if (lock_count == NULL) {
+            /* if it was not initialized then allocates a structure
+             * that will be private to that thread.
+             * Later when the structure is retrieved (PR_GetThreadPrivate), the
+             * content of the structure can be read/write without allocating
+             * this private structure PR_SetThreadPrivate.
+             * So this branch is processed one time per each thread
+             */
+            lock_count = (int *) slapi_ch_calloc(1, sizeof (int));
+            PR_SetThreadPrivate(thread_plugin_lock_count, (void *) lock_count);
+            *lock_count = 0;
+        }
+        ret = *lock_count;
+    } else
+        ret = (int) MAP_RWLOCK_UNINIT;
+#if DEBUG_MAP_LOCK
+    slapi_log_error(SLAPI_LOG_FATAL, "get_plugin_monitor_count",
+            "(%s) lock_count = %d (%p)\n", use_lock_count ? "TRUE" : "FALSE", ret, (void *) PR_MyThreadId());
+#endif
+    return ret;
+}
+
+void
+set_plugin_monitor_count(int lock_count)
+{
+#if DEBUG_MAP_LOCK
+    slapi_log_error(SLAPI_LOG_FATAL, "set_plugin_monitor_count",
+            "(%s) lock_count = %d --> %d (%p)\n", use_lock_count ? "TRUE" : "FALSE", get_plugin_monitor_count(), (int) lock_count, (void *) PR_MyThreadId());
+#endif
+    if (use_lock_count) {
+        int *lock_count_p;
+
+        lock_count_p = (int *) PR_GetThreadPrivate(thread_plugin_lock_count);
+        if (lock_count_p == NULL) {
+            /* if it was not initialized then allocates a structure
+             * that will be private to that thread.
+             * Later when the structure is retrieved (PR_GetThreadPrivate), the
+             * content of the structure can be read/write without allocating
+             * this private structure PR_SetThreadPrivate.
+             * So this branch is processed one time per each thread
+             */
+            lock_count_p = (int *) slapi_ch_calloc(1, sizeof (int));
+            PR_SetThreadPrivate(thread_plugin_lock_count, (void *) lock_count_p);
+        }
+        *lock_count_p = lock_count;
+    }
+}


=====================================
src/back-shr.h
=====================================
@@ -22,6 +22,24 @@
 #ifndef back_shr_h
 #define back_shr_h
 
+#define DEBUG_MAP_LOCK 0
+#define MAP_MONITOR_DISABLED 0
+#define MAP_MONITOR_ENABLED 1
+
+#define MAP_RWLOCK_UNINIT 3
+#define MAP_WLOCK_HELD    2
+#define MAP_RLOCK_HELD    1
+#define MAP_RWLOCK_FREE   0
+int PR_MyThreadId(void);
+int  rw_monitor_enabled(void);
+int  get_plugin_monitor_status(void);
+void set_plugin_monitor_status(int lock_status);
+int  get_plugin_monitor_count(void);
+void set_plugin_monitor_count(int lock_count);
+void init_map_lock(void);
+extern Slapi_DN **ignored_containers_sdn;
+
+
 struct plugin_state;
 
 void backend_shr_free_server_name(struct plugin_state *state, char *master);


=====================================
src/backend.h
=====================================
@@ -68,6 +68,11 @@ int backend_init_postop(struct slapi_pblock *pb, struct plugin_state *state);
 int backend_init_internal_postop(struct slapi_pblock *pb,
 				 struct plugin_state *state);
 
+/* Only used for schema compatibility plugin*/
+int backend_init_be_preop(Slapi_PBlock *pb, struct plugin_state *state);
+int backend_init_be_postop(Slapi_PBlock *pb, struct plugin_state *state);
+
+
 /* Read the server's name. */
 int backend_read_master_name(struct plugin_state *state,
 			     struct slapi_pblock *pb,


=====================================
src/map.c
=====================================
@@ -23,6 +23,7 @@
 #include "config.h"
 #endif
 
+#include <inttypes.h>
 #include <sys/types.h>
 #include <search.h>
 #include <stdlib.h>
@@ -40,11 +41,15 @@
 
 #include <rpc/rpc.h>
 
+/* NSPR private API for thread-local variables */
+#include <private/prpriv.h>
+
 #include "backend.h"
 #include "disp-nis.h"
 #include "map.h"
 #include "portmap.h"
 #include "wrap.h"
+#include "back-shr.h"
 
 /* The singleton for the cache. */
 static struct {
@@ -91,6 +96,7 @@ static struct {
 	} *domains;
 	int n_domains;
 	struct wrapped_rwlock *lock;
+        struct wrapped_rwlock *plugin_lock;
 } map_data;
 
 static void *
@@ -1155,6 +1161,10 @@ map_init(struct slapi_pblock *pb, struct plugin_state *state)
 	if (map_data.lock == NULL) {
 		return -1;
 	}
+        map_data.plugin_lock = wrap_new_rwlock();
+	if (map_data.plugin_lock == NULL) {
+		return -1;
+	}
 	return 0;
 }
 
@@ -1193,6 +1203,8 @@ map_done(struct plugin_state *state)
 	}
 	wrap_free_rwlock(map_data.lock);
 	map_data.lock = NULL;
+        wrap_free_rwlock(map_data.plugin_lock);
+        map_data.plugin_lock = NULL;
 }
 
 int
@@ -1219,19 +1231,270 @@ map_data_get_map_size(struct plugin_state *state,
 }
 
 int
-map_rdlock(void)
+plugin_rdlock(void)
 {
-	return wrap_rwlock_rdlock(map_data.lock);
+	return wrap_rwlock_rdlock(map_data.plugin_lock);
 }
 
 int
-map_wrlock(void)
+plugin_wrlock(void)
 {
-	return wrap_rwlock_wrlock(map_data.lock);
+	return wrap_rwlock_wrlock(map_data.plugin_lock);
 }
 
 int
-map_unlock(void)
+plugin_unlock(void)
 {
-	return wrap_rwlock_unlock(map_data.lock);
+	return wrap_rwlock_unlock(map_data.plugin_lock);
 }
+
+int
+map_rdlock(void)
+{
+	int lock_status;
+    int lock_count;
+	int rc = 0;
+
+	if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) {
+		/* This is not initialized used the old way */
+		slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+				"map rdlock: old way MAP_MONITOR_DISABLED\n");
+		return wrap_rwlock_rdlock(map_data.lock);
+	}
+
+
+	lock_status = get_plugin_monitor_status();
+    lock_count = get_plugin_monitor_count();
+
+#if DEBUG_MAP_LOCK
+	slapi_log_error(SLAPI_LOG_FATAL, "map_rdlock",
+				"thread_id = %"PRIx32" (call level = %d)\n", PR_MyThreadId(), wrap_get_call_level());
+#endif
+	if (lock_status == MAP_RWLOCK_UNINIT) {
+		/* This is not initialized used the old way */
+		slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+				"map rdlock: old way lock_status == MAP_RWLOCK_UNINIT\n");
+		return wrap_rwlock_rdlock(map_data.lock);
+    }
+
+    if (lock_status == MAP_RWLOCK_FREE) {
+        /* The plugin lock is free, acquire it */
+#if DEBUG_MAP_LOCK
+        slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+                "map rdlock: current lock_status == MAP_RWLOCK_FREE\n");
+#endif
+        set_plugin_monitor_status(MAP_RLOCK_HELD);
+        set_plugin_monitor_count(1);
+#if DEBUG_MAP_LOCK
+        if (lock_count != 0) {
+            slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+                    "map rdlock: (%"PRIx32") ALERT !!!   count was %d -> 1\n", PR_MyThreadId(), lock_count);
+        }
+#endif
+
+        /* Acquire the slapi plugin in read */
+        rc = plugin_rdlock();
+        if (rc) {
+            slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+                    "map rdlock: (%"PRIx32") MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_MyThreadId(), rc);
+            return rc;
+        }
+#if DEBUG_MAP_LOCK
+        slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+                "map rdlock: (%"PRIx32") MAP_RWLOCK_FREE -> MAP_RLOCK_HELD  : count=%d\n", PR_MyThreadId(), 1);
+#endif
+        rc = wrap_rwlock_rdlock(map_data.lock);
+        if (rc) {
+            slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+                    "Fail to acquire map lock in read (%d)\n", rc);
+            plugin_unlock();
+            return rc;
+        }
+        return 0;
+    }
+
+#if DEBUG_MAP_LOCK
+    slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+            "map rdlock: (%x"PRIx32") was already hold %s : count=%d > %d!!!\n",
+            PR_MyThreadId(),
+            (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : "MAP_RLOCK_HELD",
+            lock_count, lock_count + 1);
+#endif
+    set_plugin_monitor_count(lock_count + 1);
+	return 0;
+ }
+
+int
+map_wrlock(void)
+{
+	int lock_status;
+    int lock_count;
+	int rc = 0;
+
+	if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) {
+		/* This is not initialized used the old way */
+		slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+				"map wrlock: old way MAP_MONITOR_DISABLED\n");
+		return wrap_rwlock_wrlock(map_data.lock);
+	}
+
+	lock_status = get_plugin_monitor_status();
+    lock_count = get_plugin_monitor_count();
+
+#if DEBUG_MAP_LOCK
+	slapi_log_error(SLAPI_LOG_FATAL, "map wrlock",
+				"thread_id = %p (call level = %d)\n", (void *) PR_MyThreadId(), wrap_get_call_level());
+#endif
+	if (lock_status == MAP_RWLOCK_UNINIT) {
+		/* This is not initialized used the old way */
+		slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+				"map wrlock: old way lock_status == MAP_LOCK_UNINIT\n");
+
+		return wrap_rwlock_wrlock(map_data.lock);
+	}
+
+	if (lock_status == MAP_RWLOCK_FREE) {
+		/* The lock is free, acquire it */
+#if DEBUG_MAP_LOCK
+		slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+				"map wrlock: current lock_status == MAP_LOCK_FREE\n");
+#endif
+
+        set_plugin_monitor_count(1);
+#if DEBUG_MAP_LOCK
+        if (lock_count != 0) {
+            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                    "map wrlock: (%"PRIx32") ALERT !!!   count was %d --> 1\n", PR_MyThreadId(), lock_count);
+        }
+#endif
+        /* Acquire the slapi plugin in write */
+        rc = plugin_wrlock();
+        if (rc) {
+            slapi_log_error(SLAPI_LOG_FATAL, "schemacompat",
+                    "map wrlock: (%"PRIx32") MAP_RWLOCK_FREE -> MAP_RLOCK_HELD: fail to read lock plugin lock (%d)\n", PR_MyThreadId(), rc);
+            return rc;
+        }
+#if DEBUG_MAP_LOCK
+        slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                "map wrlock: (%"PRIx32") MAP_RWLOCK_FREE --> MAP_WLOCK_HELD  : count=%d\n", PR_MyThreadId(), 1);
+#endif
+
+        rc = wrap_rwlock_wrlock(map_data.lock);
+        if (rc) {
+            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                    "map wrlock: (%"PRIx32") MAP_RWLOCK_FREE --> MAP_WLOCK_HELD : fail to write lock map lock (%d)\n", PR_MyThreadId(), rc);
+            plugin_unlock();
+            goto common;
+        }
+    } else {
+        set_plugin_monitor_count(lock_count + 1);
+#if DEBUG_MAP_LOCK
+        slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                "map wrlock: (%"PRIx32")  %s --> MAP_WLOCK_HELD  : count=%d\n",
+                PR_MyThreadId(),
+                (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : "MAP_RLOCK_HELD",
+                lock_count + 1);
+#endif
+
+        if (lock_status == MAP_RLOCK_HELD) {
+            /* lock is already acquired in read */
+#if DEBUG_MAP_LOCK
+            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                    "map wrlock: weird situation map lock is held in read and now required in write mode\n");
+#endif
+            /* First free the lock held in read */
+            rc = plugin_unlock();
+            if (rc) {
+                slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                        "map wrlock: fail to unlock plugin lock (%d)\n", rc);
+                goto common;
+            }
+
+            /* Second acquire it in write */
+            rc = plugin_wrlock();
+            if (rc) {
+                slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                        "map wrlock: fail to write lock plugin lock (%d)\n", rc);
+                goto common;
+            }
+        }
+    }
+
+common:
+    set_plugin_monitor_status(MAP_WLOCK_HELD);
+    return rc;
+ }
+
+int
+map_unlock(void)
+ {
+	int lock_status;
+    int lock_count;
+	int rc = 0;
+
+	if (rw_monitor_enabled() == MAP_MONITOR_DISABLED) {
+		/* This is not initialized used the old way */
+		slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+				"map_unlock: old way MAP_MONITOR_DISABLED\n");
+		return wrap_rwlock_unlock(map_data.lock);
+	}
+
+	lock_status = get_plugin_monitor_status();
+    lock_count = get_plugin_monitor_count();
+
+#if DEBUG_MAP_LOCK
+	slapi_log_error(SLAPI_LOG_FATAL, "map_unlock",
+				"thread_id = %p (call level = %d)\n", (void *) PR_MyThreadId(), wrap_get_call_level());
+#endif
+	if (lock_status == MAP_RWLOCK_UNINIT) {
+		/* This is not initialized used the old way */
+		slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+				"map_unlock: old way lock_status == MAP_RWLOCK_UNINIT\n");
+
+		return wrap_rwlock_unlock(map_data.lock);
+    }
+
+    if (lock_count == 1) {
+        set_plugin_monitor_status(MAP_RWLOCK_FREE);
+        rc = plugin_unlock();
+        if (rc) {
+            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                    "map unlock: fail to unlock plugin lock (%d)\n", rc);
+            goto common;
+        }
+#if DEBUG_MAP_LOCK
+        slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                "map_unlock: (%p)  %s --> MAP_RWLOCK_FREE  : count=%d\n",
+                (void *) PR_MyThreadId(),
+                (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
+                0);
+#endif
+        rc = wrap_rwlock_unlock(map_data.lock);
+        if (rc) {
+            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                    "map_unlock: fail to unlock map lock (%d)\n", rc);
+            goto common;
+        }
+    }
+    if (lock_count >= 1) {
+        set_plugin_monitor_count(lock_count - 1);
+#if DEBUG_MAP_LOCK
+        if (lock_count > 1) {
+            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                    "map_unlock: (%p)  keep %s : count=%d\n",
+                    (void *) PR_MyThreadId(),
+                    (lock_status == MAP_WLOCK_HELD) ? "MAP_WLOCK_HELD" : (lock_status == MAP_RLOCK_HELD) ? "MAP_RLOCK_HELD" : "MAP_RWLOCK_FREE",
+                    lock_count - 1);
+        } else {
+            slapi_log_error(SLAPI_LOG_FATAL, "schema-compat",
+                    "map_unlock: (%p)  is now %s : count=%d\n",
+                    (void *) PR_MyThreadId(),
+                    "MAP_RWLOCK_FREE",
+                    lock_count - 1);
+        }
+#endif
+    }
+
+common:
+       return rc;
+ }


=====================================
src/map.h
=====================================
@@ -115,6 +115,9 @@ int map_data_get_domain_size(struct plugin_state *state,
 			     const char *domain_name);
 int map_data_get_map_size(struct plugin_state *state,
 			  const char *domain_name, const char *map_name);
+int plugin_rdlock(void);
+int plugin_wrlock(void);
+int plugin_unlock(void);
 int map_rdlock(void);
 int map_wrlock(void);
 int map_unlock(void);


=====================================
src/nis.c
=====================================
@@ -967,7 +967,7 @@ nis_process_request(struct plugin_state *state,
 	AUTH *request_auth, *reply_auth;
 	char auth_buf[MAX_AUTH_BYTES];
 	struct rpc_msg request, reply;
-	int auth_flavor, auth_len;
+	int auth_flavor;
 	struct ypresp_val reply_val;
 	struct ypresp_key_val reply_key_val;
 	struct ypresp_all reply_all;
@@ -1057,7 +1057,7 @@ nis_process_request(struct plugin_state *state,
 	}
 	auth_marshall(reply_auth, &auth_xdrs);
 	auth_destroy(reply_auth);
-	auth_len = xdr_getpos(&auth_xdrs);
+	(void)xdr_getpos(&auth_xdrs);
 	xdr_destroy(&auth_xdrs);
 	slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
 			"built reply authenticator\n");


=====================================
src/plug-sch.c
=====================================
@@ -62,6 +62,8 @@
 #define PLUGIN_ID "schema-compat-plugin"
 #define PLUGIN_PREOP_ID PLUGIN_ID "-preop"
 #define PLUGIN_BETXN_PREOP_ID PLUGIN_ID "-betxn_preop"
+#define PLUGIN_BE_POSTOP_ID PLUGIN_ID "-be_postop"
+#define PLUGIN_BE_PREOP_ID PLUGIN_ID "-be_preop"
 #define PLUGIN_BETXN_POSTOP_ID PLUGIN_ID "-betxn_postop"
 #define PLUGIN_POSTOP_ID PLUGIN_ID "-postop"
 #define PLUGIN_INTERNAL_POSTOP_ID PLUGIN_ID "-internal-postop"
@@ -195,6 +197,13 @@ plugin_shutdown(Slapi_PBlock *pb)
 	if (state->plugin_base != NULL) {
 		slapi_ch_free((void **)&state->plugin_base);
 	}
+	if (ignored_containers_sdn) {
+		int i;
+		for (i = 0; ignored_containers_sdn[i]; i++) {
+			slapi_sdn_free(&ignored_containers_sdn[i]);
+		}
+		slapi_ch_free((void **)&ignored_containers_sdn);
+	}
 	slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
 			"plugin shutdown completed\n");
 	return 0;
@@ -258,6 +267,35 @@ schema_compat_plugin_init_betxn_postop(Slapi_PBlock *pb)
 	}
 	return 0;
 }
+static int
+schema_compat_plugin_init_bepreop(Slapi_PBlock *pb)
+{
+	slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_03);
+	slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, &plugin_description);
+	slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, global_plugin_state);
+	if (backend_init_be_preop(pb, global_plugin_state) == -1) {
+		slapi_log_error(SLAPI_LOG_PLUGIN,
+				global_plugin_state->plugin_desc->spd_id,
+				"error registering be preoperation hooks\n");
+		return -1;
+	}
+	return 0;
+}
+static int
+schema_compat_plugin_init_bepostop(Slapi_PBlock *pb)
+{
+	slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_03);
+	slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, &plugin_description);
+	slapi_pblock_set(pb, SLAPI_PLUGIN_PRIVATE, global_plugin_state);
+	if (backend_init_be_postop(pb, global_plugin_state) == -1) {
+		slapi_log_error(SLAPI_LOG_PLUGIN,
+				global_plugin_state->plugin_desc->spd_id,
+				"error registering be postoperation "
+				"hooks\n");
+		return -1;
+	}
+	return 0;
+}
 #endif
 static int
 schema_compat_plugin_init_postop(Slapi_PBlock *pb)
@@ -300,6 +338,9 @@ schema_compat_plugin_init(Slapi_PBlock *pb)
 				"error setting up plugin\n");
 		return -1;
 	}
+
+    init_map_lock();
+
 	/* Read global configuration. */
 	if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY,
 			      &plugin_entry) == 0) &&
@@ -341,6 +382,15 @@ schema_compat_plugin_init(Slapi_PBlock *pb)
 				"error registering betxn preoperation plugin\n");
 		return -1;
 	}
+        if (slapi_register_plugin("bepreoperation", TRUE,
+				  "schema_compat_plugin_init_bepreop",
+				  schema_compat_plugin_init_bepreop,
+				  PLUGIN_BE_PREOP_ID, NULL,
+				  state->plugin_identity) != 0) {
+		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+				"error registering betxn preoperation plugin\n");
+		return -1;
+	}
 #endif
 	if (slapi_register_plugin("postoperation", TRUE,
 				  "schema_compat_plugin_init_postop",
@@ -370,6 +420,15 @@ schema_compat_plugin_init(Slapi_PBlock *pb)
 				"error registering betxn postoperation plugin\n");
 		return -1;
 	}
+        if (slapi_register_plugin("bepostoperation", TRUE,
+				  "schema_compat_plugin_init_bepostop",
+				  schema_compat_plugin_init_bepostop,
+				  PLUGIN_BE_POSTOP_ID, NULL,
+				  state->plugin_identity) != 0) {
+		slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+				"error registering betxn postoperation plugin\n");
+		return -1;
+	}
 #endif
 	if (slapi_register_plugin("preextendedop", TRUE,
 				  "schema_compat_plugin_init_extop",


=====================================
src/portmap.c
=====================================
@@ -77,7 +77,8 @@ slapi_log_error(int i, char *f, char *fmt, ...)
 int
 main(int argc, char **argv)
 {
-	int s, ret, port;
+	int s, port;
+	int ret __attribute__ ((unused));
 	s = socket(PF_INET, SOCK_DGRAM, 0);
 	if (s == -1) {
 		printf("error allocating socket\n");
@@ -94,8 +95,16 @@ main(int argc, char **argv)
 		printf("error creating portmap/rpcbind client socket\n");
 		return 1;
 	}
-	setregid(2516, 2516);
-	setreuid(2510, 2510);
+	if (setregid(2516, 2516) == -1) {
+		printf("error setting real and effective group id %s\n",
+		       strerror(errno));
+		return 1;
+	}
+	if (setreuid(2510, 2510) == -1) {
+		printf("error setting real and effective user id %s\n",
+		       strerror(errno));
+		return 1;
+	}
 	sleep(60);
 	portmap_unregister("portmap", &s, port, YPPROG, YPVERS,
 			   AF_INET, IPPROTO_TCP, 0);


=====================================
src/wrap.c
=====================================
@@ -153,13 +153,14 @@ void *
 wrap_stop_thread(struct wrapped_thread *t)
 {
 	void *returned = NULL;
+	int ret __attribute__ ((unused));
 #ifdef USE_PTHREADS
-	write(t->stopfd[1], "", 1);
+	ret = write(t->stopfd[1], "", 1);
 	close(t->stopfd[1]);
 	pthread_join(t->tid, &returned);
 #endif
 #ifdef USE_NSPR_THREADS
-	write(t->stopfd[1], "", 1);
+	ret = write(t->stopfd[1], "", 1);
 	close(t->stopfd[1]);
 	PR_JoinThread(t->tid);
 	returned = t->args.result;


=====================================
tests/azure/README.md
=====================================
@@ -0,0 +1,27 @@
+Test with azure pipelines
+
+Add pipeline definition that can be used to run build and test jobs in
+dev.azure.com environment.
+
+Following needs to be done to use the Azure Pipelines definition for
+slapi-nis:
+
+- Configure Azure DevOps organization
+- Create public project there
+- Clone your Git repository for slapi-nis from pagure.io
+- On Azure side, navigate to Repos -> Files, choose your repo top
+  directory and click 'Clone'
+- The 'Clone Repository' dialog will show how to clone the repository
+  with HTTPS or SSH. Choose SSH tab and note the URL.
+- Set mirroring hook on Pagure's project site (Settings -> Hooks ->
+  Mirroring) by providing this URL
+- Return back to the hook settings in Pagure and copy public SSH key
+  from there
+- Choose 'Manage SSH keys' in the 'Clone Repository' dialog and add a
+  public SSH key there
+
+After these actions a push to pagure project will automatically be
+mirrored to Azure Repos repository.
+
+Now a pipeline can be set up in Azure by picking up azure-pipelines.yml
+file from the repo.


=====================================
tests/azure/azure-pipelines.yml
=====================================
@@ -0,0 +1,70 @@
+jobs:
+- job: Build
+  pool:
+    vmImage: 'Ubuntu-16.04'
+  variables:
+    builddir: /__w/1/s
+  container:
+    image: f30/fedora-toolbox
+    endpoint: fedora-project-registry
+  steps:
+    - script: |
+        sudo rm -rf /var/cache/dnf/*
+        cd $(builddir)
+        sudo dnf makecache || :
+        sudo dnf -y install dnf-plugins-core rpm-build autoconf automake libtool \
+                /usr/bin/rpcgen 389-ds-base-devel libnsl2-devel \
+                libsss_nss_idmap-devel nspr-devel nss-devel \
+                openldap-devel pam-devel gdb gcc annobin make
+        sudo dnf builddep -y --spec slapi-nis.spec --best --allowerasing --setopt=install_weak_deps=False
+      displayName: Prepare build environment
+    - script: |
+        mkdir -p $(builddir)/dist
+        make -f .copr/Makefile outdir=$(builddir)/dist SUDO=sudo srpm
+        rpmbuild --rebuild \
+                --define "_topdir $(builddir)/build" \
+                --define "_sourcedir $(builddir)/build" \
+                --define "_specdir $(builddir)/build" \
+                --define "_builddir $(builddir)/build" \
+                --define "_srcrpmdir $(builddir)/dist" \
+                --define "_rpmdir $(builddir)/dist" \
+                $(builddir)/dist/*.src.rpm
+      displayName: Build packages
+    - script: |
+        mv $(builddir)/dist/*/*.rpm $(builddir)/dist/
+        ls -la $(builddir)/dist
+      displayName: List packages
+    - task: PublishPipelineArtifact at 0
+      displayName: Publish packages
+      inputs:
+        artifactName: 'packages-$(Build.BuildId)-$(Agent.OS)-$(Agent.OSArchitecture)'
+        targetPath: $(Build.Repository.LocalPath)/dist
+      condition: always()
+
+- job: Install_with_FreeIPA_packages
+  dependsOn: Build
+  condition: succeeded()
+  pool:
+    vmImage: 'Ubuntu-16.04'
+  variables:
+    builddir: /__w/1/s
+  container:
+    image: f30/fedora-toolbox
+    endpoint: fedora-project-registry
+  steps:
+    - checkout: none
+    - task: DownloadPipelineArtifact at 0
+      displayName: Download pre-built packages
+      inputs:
+        artifactName: 'packages-$(Build.BuildId)-$(Agent.OS)-$(Agent.OSArchitecture)'
+        targetPath: $(Build.Repository.LocalPath)/dist
+    - script: |
+        rm -f $(builddir)/dist/*.src.rpm
+      displayName: Remove source package
+    - script: |
+        sudo rm -rf /var/cache/dnf/*
+        cd $(builddir)
+        sudo dnf makecache || :
+        sudo dnf -y install freeipa-server-dns freeipa-server $(builddir)/dist/*.rpm 
+      displayName: Attempt package installation
+


=====================================
tests/clients/Makefile.am
=====================================
@@ -12,7 +12,7 @@ yp.h: ../../yp/yp.x
 	$(RPCGEN) -h -o $@ $^
 yp_xdr.c: ../../yp/yp.x
 	$(RM) -f $@
-	$(RPCGEN) -c -o $@ $^
+	$(RPCGEN) -c -i 0 -o $@ $^
 yp_clnt.c: ../../yp/yp.x
 	$(RM) -f $@
 	$(RPCGEN) -l -o $@ $^


=====================================
tests/clients/yp.c
=====================================
@@ -34,6 +34,8 @@
 #include <rpc/rpc.h>
 #include "../../yp/yp.h"
 
+typedef int (*xdrrec_proc_t)(void *, void *, int);
+
 static struct sockaddr_in server;
 static int connected;
 
@@ -162,8 +164,7 @@ writejunk(char *fd, char *data, int size)
 static int
 all(CLIENT *client, FILE *output, int argc, char **argv)
 {
-	ypresp_all *ret;
-	int i, sock;
+	int sock;
 	ypreq_nokey nokey;
 	struct rpc_msg req, rep;
 	struct ypresp_all resp;
@@ -189,7 +190,7 @@ all(CLIENT *client, FILE *output, int argc, char **argv)
 	}
 
 	memset(&s, 0, sizeof(s));
-	xdrrec_create(&s, 0, 0, (char *) &sock, &readjunk, &writejunk);
+	xdrrec_create(&s, 0, 0, (char *) &sock, (xdrrec_proc_t) &readjunk, (xdrrec_proc_t) &writejunk);
 	s.x_op = XDR_ENCODE;
 
 	memset(&req, 0, sizeof(req));
@@ -218,7 +219,7 @@ all(CLIENT *client, FILE *output, int argc, char **argv)
 	xdr_destroy(&s);
 
 	memset(&s, 0, sizeof(s));
-	xdrrec_create(&s, 0, 0, (char *) &sock, &readjunk, &writejunk);
+	xdrrec_create(&s, 0, 0, (char *) &sock, (xdrrec_proc_t) &readjunk, (xdrrec_proc_t) &writejunk);
 	s.x_op = XDR_DECODE;
 	xdrrec_skiprecord(&s);
 


=====================================
yp/Makefile.am
=====================================
@@ -7,7 +7,7 @@ yp.h: yp.x
 	$(RPCGEN) -h -o $@ $^
 yp_xdr.c: yp.x
 	$(RM) -f $@
-	$(RPCGEN) -c -o $@ $^
+	$(RPCGEN) -c -i 0 -o $@ $^
 yp_clnt.c: yp.x
 	$(RM) -f $@
 	$(RPCGEN) -l -o $@ $^



View it on GitLab: https://salsa.debian.org/freeipa-team/slapi-nis/-/compare/85704ac0eaca00363f359ce945631627bf601381...275b6de54509a4174444718cb6cb635ea621eb7d

-- 
View it on GitLab: https://salsa.debian.org/freeipa-team/slapi-nis/-/compare/85704ac0eaca00363f359ce945631627bf601381...275b6de54509a4174444718cb6cb635ea621eb7d
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-freeipa-devel/attachments/20200324/7a9e6567/attachment-0001.html>


More information about the Pkg-freeipa-devel mailing list