diff options
author | Andrew Tridgell <tridge@samba.org> | 2009-06-01 10:39:30 +1000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2009-06-01 10:39:30 +1000 |
commit | ba95882155db4f8c10725f47f70ae482d5343f9a (patch) | |
tree | 52c65ddfbcd81f3dcbb3b91183ae043b9c51acd5 /lib | |
parent | 67b83d2489788f1899c253fdab554d0998f9c044 (diff) | |
parent | 14c13620345dfd9f1e18761f103aa66138bf8907 (diff) | |
download | samba-ba95882155db4f8c10725f47f70ae482d5343f9a.tar.gz samba-ba95882155db4f8c10725f47f70ae482d5343f9a.tar.bz2 samba-ba95882155db4f8c10725f47f70ae482d5343f9a.zip |
Merge branch 'master' of ssh://git.samba.org/data/git/samba
Diffstat (limited to 'lib')
-rw-r--r-- | lib/async_req/async_sock.c | 40 | ||||
-rw-r--r-- | lib/async_req/async_sock.h | 20 | ||||
-rw-r--r-- | lib/async_req/config.mk | 1 | ||||
-rw-r--r-- | lib/crypto/sha256.c | 2 | ||||
-rw-r--r-- | lib/nss_wrapper/nss_wrapper.c | 84 | ||||
-rw-r--r-- | lib/nss_wrapper/nss_wrapper.h | 6 | ||||
-rw-r--r-- | lib/nss_wrapper/testsuite.c | 332 | ||||
-rw-r--r-- | lib/replace/system/config.m4 | 1 | ||||
-rw-r--r-- | lib/util/config.mk | 3 | ||||
-rw-r--r-- | lib/util/tevent_unix.c | 20 | ||||
-rw-r--r-- | lib/util/tevent_unix.h | 20 | ||||
-rw-r--r-- | lib/util/util.h | 12 | ||||
-rw-r--r-- | lib/util/util_id.c | 88 |
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; +} |