summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/async_req/async_sock.c40
-rw-r--r--lib/async_req/async_sock.h20
-rw-r--r--lib/async_req/config.mk1
-rw-r--r--lib/crypto/sha256.c2
-rw-r--r--lib/nss_wrapper/nss_wrapper.c84
-rw-r--r--lib/nss_wrapper/nss_wrapper.h6
-rw-r--r--lib/nss_wrapper/testsuite.c332
-rw-r--r--lib/replace/system/config.m41
-rw-r--r--lib/util/config.mk3
-rw-r--r--lib/util/tevent_unix.c20
-rw-r--r--lib/util/tevent_unix.h20
-rw-r--r--lib/util/util.h12
-rw-r--r--lib/util/util_id.c88
13 files changed, 593 insertions, 36 deletions
diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c
index fe71b29117..d88edb177a 100644
--- a/lib/async_req/async_sock.c
+++ b/lib/async_req/async_sock.c
@@ -3,17 +3,21 @@
async socket syscalls
Copyright (C) Volker Lendecke 2008
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
+ ** NOTE! The following LGPL license applies to the async_sock
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
- This program is distributed in the hope that it will be useful,
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -77,6 +81,10 @@ static void async_send_handler(struct tevent_context *ev,
tevent_req_data(req, struct async_send_state);
state->sent = send(state->fd, state->buf, state->len, state->flags);
+ if ((state->sent == -1) && (errno == EINTR)) {
+ /* retry */
+ return;
+ }
if (state->sent == -1) {
tevent_req_error(req, errno);
return;
@@ -144,6 +152,10 @@ static void async_recv_handler(struct tevent_context *ev,
state->received = recv(state->fd, state->buf, state->len,
state->flags);
+ if ((state->received == -1) && (errno == EINTR)) {
+ /* retry */
+ return;
+ }
if (state->received == -1) {
tevent_req_error(req, errno);
return;
@@ -422,7 +434,11 @@ static void writev_handler(struct tevent_context *ev, struct tevent_fd *fde,
to_write += state->iov[i].iov_len;
}
- written = sys_writev(state->fd, state->iov, state->count);
+ written = writev(state->fd, state->iov, state->count);
+ if ((written == -1) && (errno = EINTR)) {
+ /* retry */
+ return;
+ }
if (written == -1) {
tevent_req_error(req, errno);
return;
@@ -530,6 +546,10 @@ static void read_packet_handler(struct tevent_context *ev,
nread = recv(state->fd, state->buf+state->nread, total-state->nread,
0);
+ if ((nread == -1) && (errno == EINTR)) {
+ /* retry */
+ return;
+ }
if (nread == -1) {
tevent_req_error(req, errno);
return;
@@ -566,7 +586,7 @@ static void read_packet_handler(struct tevent_context *ev,
return;
}
- tmp = TALLOC_REALLOC_ARRAY(state, state->buf, uint8_t, total+more);
+ tmp = talloc_realloc(state, state->buf, uint8_t, total+more);
if (tevent_req_nomem(tmp, req)) {
return;
}
diff --git a/lib/async_req/async_sock.h b/lib/async_req/async_sock.h
index a50e93238a..d47be30589 100644
--- a/lib/async_req/async_sock.h
+++ b/lib/async_req/async_sock.h
@@ -3,17 +3,21 @@
async socket operations
Copyright (C) Volker Lendecke 2008
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
+ ** NOTE! The following LGPL license applies to the async_sock
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
- This program is distributed in the hope that it will be useful,
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
diff --git a/lib/async_req/config.mk b/lib/async_req/config.mk
index bf0fd6a2db..1f4b557ce4 100644
--- a/lib/async_req/config.mk
+++ b/lib/async_req/config.mk
@@ -1,3 +1,4 @@
[SUBSYSTEM::LIBASYNC_REQ]
+PUBLIC_DEPENDENCIES = LIBREPLACE_NETWORK
LIBASYNC_REQ_OBJ_FILES = $(addprefix ../lib/async_req/, async_sock.o)
diff --git a/lib/crypto/sha256.c b/lib/crypto/sha256.c
index a2def25814..233abe23f8 100644
--- a/lib/crypto/sha256.c
+++ b/lib/crypto/sha256.c
@@ -189,7 +189,7 @@ struct x32{
void
SHA256_Update (SHA256_CTX *m, const void *v, size_t len)
{
- const unsigned char *p = v;
+ const unsigned char *p = (const unsigned char *)v;
size_t old_sz = m->sz[0];
size_t offset;
diff --git a/lib/nss_wrapper/nss_wrapper.c b/lib/nss_wrapper/nss_wrapper.c
index 1875dc3e4f..d7f7b0ba56 100644
--- a/lib/nss_wrapper/nss_wrapper.c
+++ b/lib/nss_wrapper/nss_wrapper.c
@@ -68,6 +68,11 @@
#define getgrent_r(grdst, buf, buflen, grdstp) ENOSYS
#endif
+/* not all systems have getgrouplist */
+#ifndef HAVE_GETGROUPLIST
+#define getgrouplist(user, group, groups, ngroups) 0
+#endif
+
/* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
* for now */
#define REWRITE_CALLS
@@ -90,6 +95,7 @@
#define real_initgroups_dyn initgroups_dyn
*/
#define real_initgroups initgroups
+#define real_getgrouplist getgrouplist
#define real_getgrnam getgrnam
#define real_getgrnam_r getgrnam_r
@@ -1222,3 +1228,81 @@ _PUBLIC_ void nwrap_endgrent(void)
nwrap_files_endgrent();
}
+
+static int nwrap_files_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
+{
+ struct group *grp;
+ gid_t *groups_tmp;
+ int count = 1;
+ const char *name_of_group = NULL;
+
+ NWRAP_DEBUG(("%s: getgrouplist called for %s\n", __location__, user));
+
+ groups_tmp = (gid_t *)malloc(count * sizeof(gid_t));
+ if (!groups_tmp) {
+ NWRAP_ERROR(("%s:calloc failed\n",__location__));
+ errno = ENOMEM;
+ return -1;
+ }
+
+ memcpy(groups_tmp, &group, sizeof(gid_t));
+
+ grp = nwrap_getgrgid(group);
+ if (grp) {
+ name_of_group = grp->gr_name;
+ }
+
+ nwrap_files_setgrent();
+ while ((grp = nwrap_files_getgrent()) != NULL) {
+ int i = 0;
+
+ NWRAP_VERBOSE(("%s: inspecting %s for group membership\n",
+ __location__, grp->gr_name));
+
+ for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
+
+ if ((strcmp(user, grp->gr_mem[i]) == 0) &&
+ (strcmp(name_of_group, grp->gr_name) != 0)) {
+
+ NWRAP_DEBUG(("%s: %s is member of %s\n",
+ __location__, user, grp->gr_name));
+
+ groups_tmp = (gid_t *)realloc(groups_tmp, (count + 1) * sizeof(gid_t));
+ if (!groups_tmp) {
+ NWRAP_ERROR(("%s:calloc failed\n",__location__));
+ errno = ENOMEM;
+ return -1;
+ }
+
+ memcpy(&groups_tmp[count], &grp->gr_gid, sizeof(gid_t));
+ count++;
+ }
+ }
+ }
+ nwrap_files_endgrent();
+
+ NWRAP_VERBOSE(("%s: %s is member of %d groups: %d\n",
+ __location__, user, *ngroups));
+
+ if (*ngroups < count) {
+ *ngroups = count;
+ free(groups_tmp);
+ return -1;
+ }
+
+ *ngroups = count;
+ memcpy(groups, groups_tmp, count * sizeof(gid_t));
+ free(groups_tmp);
+
+ return count;
+}
+
+_PUBLIC_ int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
+{
+ if (!nwrap_enabled()) {
+ return real_getgrouplist(user, group, groups, ngroups);
+ }
+
+ return nwrap_files_getgrouplist(user, group, groups, ngroups);
+}
+
diff --git a/lib/nss_wrapper/nss_wrapper.h b/lib/nss_wrapper/nss_wrapper.h
index 35a47348a8..5bcd42ead4 100644
--- a/lib/nss_wrapper/nss_wrapper.h
+++ b/lib/nss_wrapper/nss_wrapper.h
@@ -46,6 +46,7 @@ int nwrap_getpwent_r(struct passwd *pwbuf, char *buf,
size_t buflen, struct passwd **pwbufp);
void nwrap_endpwent(void);
int nwrap_initgroups(const char *user, gid_t group);
+int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups);
struct group *nwrap_getgrnam(const char *name);
int nwrap_getgrnam_r(const char *name, struct group *gbuf,
char *buf, size_t buflen, struct group **gbufp);
@@ -120,6 +121,11 @@ void nwrap_endgrent(void);
#endif
#define initgroups nwrap_initgroups
+#ifdef getgrouplist
+#undef getgrouplist
+#endif
+#define getgrouplist nwrap_getgrouplist
+
#ifdef getgrnam
#undef getgrnam
#endif
diff --git a/lib/nss_wrapper/testsuite.c b/lib/nss_wrapper/testsuite.c
new file mode 100644
index 0000000000..4f37354e12
--- /dev/null
+++ b/lib/nss_wrapper/testsuite.c
@@ -0,0 +1,332 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ local testing of the nss wrapper
+
+ Copyright (C) Guenther Deschner 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "torture/torture.h"
+#include "lib/replace/system/passwd.h"
+#include "lib/nss_wrapper/nss_wrapper.h"
+
+static void print_passwd(struct passwd *pwd)
+{
+ printf("%s:%s:%lu:%lu:%s:%s:%s\n",
+ pwd->pw_name,
+ pwd->pw_passwd,
+ (unsigned long)pwd->pw_uid,
+ (unsigned long)pwd->pw_gid,
+ pwd->pw_gecos,
+ pwd->pw_dir,
+ pwd->pw_shell);
+}
+
+
+static bool test_nwrap_getpwnam(struct torture_context *tctx,
+ const char *name)
+{
+ struct passwd *pwd;
+
+ torture_comment(tctx, "Testing getpwnam: %s\n", name);
+
+ pwd = getpwnam(name);
+ if (pwd) {
+ print_passwd(pwd);
+ }
+
+ return pwd ? true : false;
+}
+
+static bool test_nwrap_getpwuid(struct torture_context *tctx,
+ uid_t uid)
+{
+ struct passwd *pwd;
+
+ torture_comment(tctx, "Testing getpwuid: %lu\n", (unsigned long)uid);
+
+ pwd = getpwuid(uid);
+ if (pwd) {
+ print_passwd(pwd);
+ }
+
+ return pwd ? true : false;
+}
+
+static void print_group(struct group *grp)
+{
+ int i;
+ printf("%s:%s:%lu:",
+ grp->gr_name,
+ grp->gr_passwd,
+ (unsigned long)grp->gr_gid);
+
+ if (!grp->gr_mem[0]) {
+ printf("\n");
+ return;
+ }
+
+ for (i=0; grp->gr_mem[i+1]; i++) {
+ printf("%s,", grp->gr_mem[i]);
+ }
+ printf("%s\n", grp->gr_mem[i]);
+}
+
+static bool test_nwrap_getgrnam(struct torture_context *tctx,
+ const char *name)
+{
+ struct group *grp;
+
+ torture_comment(tctx, "Testing getgrnam: %s\n", name);
+
+ grp = getgrnam(name);
+ if (grp) {
+ print_group(grp);
+ }
+
+ return grp ? true : false;
+}
+
+static bool test_nwrap_getgrgid(struct torture_context *tctx,
+ gid_t gid)
+{
+ struct group *grp;
+
+ torture_comment(tctx, "Testing getgrgid: %lu\n", (unsigned long)gid);
+
+ grp = getgrgid(gid);
+ if (grp) {
+ print_group(grp);
+ }
+
+ return grp ? true : false;
+}
+
+static bool test_nwrap_enum_passwd(struct torture_context *tctx,
+ struct passwd **pwd_array_p,
+ size_t *num_pwd_p)
+{
+ struct passwd *pwd;
+ struct passwd *pwd_array = NULL;
+ size_t num_pwd = 0;
+
+ torture_comment(tctx, "Testing setpwent\n");
+ setpwent();
+
+ while ((pwd = getpwent()) != NULL) {
+ torture_comment(tctx, "Testing getpwent\n");
+
+ print_passwd(pwd);
+ if (pwd_array_p && num_pwd_p) {
+ pwd_array = talloc_realloc(tctx, pwd_array, struct passwd, num_pwd+1);
+ torture_assert(tctx, pwd_array, "out of memory");
+ pwd_array[num_pwd].pw_name = talloc_strdup(tctx, pwd->pw_name);
+ pwd_array[num_pwd].pw_uid = pwd->pw_uid;
+ pwd_array[num_pwd].pw_gid = pwd->pw_gid;
+ num_pwd++;
+ }
+ }
+
+ torture_comment(tctx, "Testing endpwent\n");
+ endpwent();
+
+ if (pwd_array_p) {
+ *pwd_array_p = pwd_array;
+ }
+ if (num_pwd_p) {
+ *num_pwd_p = num_pwd;
+ }
+
+ return true;
+}
+
+static bool test_nwrap_passwd(struct torture_context *tctx)
+{
+ int i;
+ struct passwd *pwd;
+ size_t num_pwd;
+
+ torture_assert(tctx, test_nwrap_enum_passwd(tctx, &pwd, &num_pwd),
+ "failed to enumerate passwd");
+
+ for (i=0; i < num_pwd; i++) {
+ torture_assert(tctx, test_nwrap_getpwnam(tctx, pwd[i].pw_name),
+ "failed to call getpwnam for enumerated user");
+ torture_assert(tctx, test_nwrap_getpwuid(tctx, pwd[i].pw_uid),
+ "failed to call getpwuid for enumerated user");
+ }
+
+ return true;
+}
+
+static bool test_nwrap_enum_group(struct torture_context *tctx,
+ struct group **grp_array_p,
+ size_t *num_grp_p)
+{
+ struct group *grp;
+ struct group *grp_array = NULL;
+ size_t num_grp = 0;
+
+ torture_comment(tctx, "Testing setgrent\n");
+ setgrent();
+
+ while ((grp = getgrent()) != NULL) {
+ torture_comment(tctx, "Testing getgrent\n");
+
+ print_group(grp);
+ if (grp_array_p && num_grp_p) {
+ grp_array = talloc_realloc(tctx, grp_array, struct group, num_grp+1);
+ torture_assert(tctx, grp_array, "out of memory");
+ grp_array[num_grp].gr_name = talloc_strdup(tctx, grp->gr_name);
+ grp_array[num_grp].gr_gid = grp->gr_gid;
+ num_grp++;
+ }
+ }
+
+ torture_comment(tctx, "Testing endgrent\n");
+ endgrent();
+
+ if (grp_array_p) {
+ *grp_array_p = grp_array;
+ }
+ if (num_grp_p) {
+ *num_grp_p = num_grp;
+ }
+
+
+ return true;
+}
+
+static bool test_nwrap_group(struct torture_context *tctx)
+{
+ int i;
+ struct group *grp;
+ size_t num_grp;
+
+ torture_assert(tctx, test_nwrap_enum_group(tctx, &grp, &num_grp),
+ "failed to enumerate group");
+
+ for (i=0; i < num_grp; i++) {
+ torture_assert(tctx, test_nwrap_getgrnam(tctx, grp[i].gr_name),
+ "failed to call getgrnam for enumerated user");
+ torture_assert(tctx, test_nwrap_getgrgid(tctx, grp[i].gr_gid),
+ "failed to call getgrgid for enumerated user");
+ }
+
+ return true;
+}
+
+static bool test_nwrap_getgrouplist(struct torture_context *tctx,
+ const char *user,
+ gid_t gid,
+ gid_t **gids_p,
+ int *num_gids_p)
+{
+ int ret;
+ int num_groups = 0;
+ gid_t *groups = NULL;
+
+ torture_comment(tctx, "Testing getgrouplist: %s\n", user);
+
+ ret = getgrouplist(user, gid, NULL, &num_groups);
+ if (ret == -1 || num_groups != 0) {
+
+ groups = talloc_array(tctx, gid_t, num_groups);
+ torture_assert(tctx, groups, "out of memory\n");
+
+ ret = getgrouplist(user, gid, groups, &num_groups);
+ }
+
+ torture_assert(tctx, (ret != -1), "failed to call getgrouplist");
+
+ torture_comment(tctx, "%s is member in %d groups\n", user, num_groups);
+
+ if (gids_p) {
+ *gids_p = groups;
+ }
+ if (num_gids_p) {
+ *num_gids_p = num_groups;
+ }
+
+ return true;
+}
+
+static bool test_nwrap_membership(struct torture_context *tctx)
+{
+ const char *old_pwd = getenv("NSS_WRAPPER_PASSWD");
+ const char *old_group = getenv("NSS_WRAPPER_GROUP");
+ struct passwd *pwd;
+ size_t num_pwd;
+ int i;
+
+ if (!old_pwd || !old_group) {
+ torture_skip(tctx, "nothing to test\n");
+ return true;
+ }
+
+ torture_assert(tctx, test_nwrap_enum_passwd(tctx, &pwd, &num_pwd),
+ "failed to enumerate passwd");
+
+ for (i=0; i < num_pwd; i++) {
+
+ int num_user_groups = 0;
+ gid_t *user_groups = NULL;
+ int g;
+
+ torture_assert(tctx, test_nwrap_getgrouplist(tctx,
+ pwd[i].pw_name,
+ pwd[i].pw_gid,
+ &user_groups,
+ &num_user_groups),
+ "failed to test getgrouplist");
+
+ for (g=0; g < num_user_groups; g++) {
+ torture_assert(tctx, test_nwrap_getgrgid(tctx, user_groups[g]),
+ "failed to find the group the user is a member of");
+ }
+ }
+
+ return true;
+}
+
+static bool test_nwrap_env(struct torture_context *tctx)
+{
+ const char *old_pwd = getenv("NSS_WRAPPER_PASSWD");
+ const char *old_group = getenv("NSS_WRAPPER_GROUP");
+
+ if (!old_pwd || !old_group) {
+ torture_skip(tctx, "nothing to test\n");
+ return true;
+ }
+
+ torture_assert(tctx, test_nwrap_passwd(tctx),
+ "failed to test users");
+ torture_assert(tctx, test_nwrap_group(tctx),
+ "failed to test groups");
+
+ return true;
+}
+
+struct torture_suite *torture_local_nss_wrapper(TALLOC_CTX *mem_ctx)
+{
+ struct torture_suite *suite = torture_suite_create(mem_ctx, "NSS-WRAPPER");
+
+ torture_suite_add_simple_test(suite, "env", test_nwrap_env);
+ torture_suite_add_simple_test(suite, "membership", test_nwrap_membership);
+
+ return suite;
+}
diff --git a/lib/replace/system/config.m4 b/lib/replace/system/config.m4
index 5c9b53d5c5..e2196586ad 100644
--- a/lib/replace/system/config.m4
+++ b/lib/replace/system/config.m4
@@ -116,6 +116,7 @@ AC_VERIFY_C_PROTOTYPE([struct group *getgrent_r(struct group *src, char *buf, si
#include <unistd.h>
#include <grp.h>
])
+AC_CHECK_FUNCS(getgrouplist)
# locale
AC_CHECK_HEADERS(ctype.h locale.h)
diff --git a/lib/util/config.mk b/lib/util/config.mk
index 1b620d1464..3ae8a22780 100644
--- a/lib/util/config.mk
+++ b/lib/util/config.mk
@@ -28,7 +28,8 @@ LIBSAMBA-UTIL_OBJ_FILES = $(addprefix $(libutilsrcdir)/, \
rbtree.o \
talloc_stack.o \
smb_threads.o \
- params.o)
+ params.o \
+ util_id.o)
PUBLIC_HEADERS += $(addprefix $(libutilsrcdir)/, util.h \
dlinklist.h \
diff --git a/lib/util/tevent_unix.c b/lib/util/tevent_unix.c
index b89d5cd4d4..0a8c4c6b30 100644
--- a/lib/util/tevent_unix.c
+++ b/lib/util/tevent_unix.c
@@ -3,17 +3,21 @@
Wrap unix errno around tevent_req
Copyright (C) Volker Lendecke 2009
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
+ ** NOTE! The following LGPL license applies to the tevent_unix
+ ** helper library. This does NOT imply that all of Samba is released
+ ** under the LGPL
- This program is distributed in the hope that it will be useful,
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
diff --git a/lib/util/tevent_unix.h b/lib/util/tevent_unix.h
index dc3ffaef33..bc2cea9199 100644
--- a/lib/util/tevent_unix.h
+++ b/lib/util/tevent_unix.h
@@ -3,17 +3,21 @@
Wrap unix errno around tevent_req
Copyright (C) Volker Lendecke 2009
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
+ ** NOTE! The following LGPL license applies to the tevent_unix
+ ** helper library. This does NOT imply that all of Samba is released
+ ** under the LGPL
- This program is distributed in the hope that it will be useful,
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library 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.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
diff --git a/lib/util/util.h b/lib/util/util.h
index dab5ff9360..20050d2f0a 100644
--- a/lib/util/util.h
+++ b/lib/util/util.h
@@ -817,4 +817,16 @@ bool unmap_file(void *start, size_t size);
void print_asc(int level, const uint8_t *buf,int len);
+/**
+ * Add an id to an array of ids.
+ *
+ * num should be a pointer to an integer that holds the current
+ * number of elements in ids. It will be updated by this function.
+ */
+
+bool add_uid_to_array_unique(TALLOC_CTX *mem_ctx, uid_t uid,
+ uid_t **uids, size_t *num_uids);
+bool add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid,
+ gid_t **gids, size_t *num_gids);
+
#endif /* _SAMBA_UTIL_H_ */
diff --git a/lib/util/util_id.c b/lib/util/util_id.c
new file mode 100644
index 0000000000..8744ce4e4e
--- /dev/null
+++ b/lib/util/util_id.c
@@ -0,0 +1,88 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Helper routines for uid and gid arrays
+
+ Copyright (C) Guenther Deschner 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+
+/****************************************************************************
+ Add a gid to an array of gids if it's not already there.
+****************************************************************************/
+
+bool add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid,
+ gid_t **gids, size_t *num_gids)
+{
+ int i;
+
+ if ((*num_gids != 0) && (*gids == NULL)) {
+ /*
+ * A former call to this routine has failed to allocate memory
+ */
+ return false;
+ }
+
+ for (i=0; i<*num_gids; i++) {
+ if ((*gids)[i] == gid) {
+ return true;
+ }
+ }
+
+ *gids = talloc_realloc(mem_ctx, *gids, gid_t, *num_gids+1);
+ if (*gids == NULL) {
+ *num_gids = 0;
+ return false;
+ }
+
+ (*gids)[*num_gids] = gid;
+ *num_gids += 1;
+ return true;
+}
+
+/****************************************************************************
+ Add a uid to an array of uids if it's not already there.
+****************************************************************************/
+
+bool add_uid_to_array_unique(TALLOC_CTX *mem_ctx, uid_t uid,
+ uid_t **uids, size_t *num_uids)
+{
+ int i;
+
+ if ((*num_uids != 0) && (*uids == NULL)) {
+ /*
+ * A former call to this routine has failed to allocate memory
+ */
+ return false;
+ }
+
+ for (i=0; i<*num_uids; i++) {
+ if ((*uids)[i] == uid) {
+ return true;
+ }
+ }
+
+ *uids = talloc_realloc(mem_ctx, *uids, uid_t, *num_uids+1);
+ if (*uids == NULL) {
+ *num_uids = 0;
+ return false;
+ }
+
+ (*uids)[*num_uids] = uid;
+ *num_uids += 1;
+ return true;
+}