diff options
author | scf <scf@FreeBSD.org> | 2008-04-23 00:49:13 +0000 |
---|---|---|
committer | scf <scf@FreeBSD.org> | 2008-04-23 00:49:13 +0000 |
commit | cab3742f107c2ffe5e778a8fc08b3070278fe4ac (patch) | |
tree | e4b13bb34526bfc901f80321dd423bf46c41e1a0 /lib/libutil | |
parent | e3c15650b08e098db24738aa1cd64372ffcb7d45 (diff) | |
download | FreeBSD-src-cab3742f107c2ffe5e778a8fc08b3070278fe4ac.zip FreeBSD-src-cab3742f107c2ffe5e778a8fc08b3070278fe4ac.tar.gz |
Add four utility functions related to struct grp processing modeled in-part
after similar calls related to struct pwd in libutil/pw_util.c:
- gr_equal()
Perform a deep comparison of two struct grp's. It does a thorough, yet
unoptimized comparison of all the members regardless of order.
- gr_make()
Create a string (see group(5)) from a struct grp.
- gr_dup()
Duplicate a struct grp. Returns a value that is a single contiguous
block of memory.
- gr_scan()
Create a struct grp from a string (as produced by gr_make()).
MFC after: 3 weeks
Diffstat (limited to 'lib/libutil')
-rw-r--r-- | lib/libutil/Makefile | 2 | ||||
-rw-r--r-- | lib/libutil/gr_util.c | 234 | ||||
-rw-r--r-- | lib/libutil/libutil.h | 7 |
3 files changed, 242 insertions, 1 deletions
diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile index 773dd74..4860292 100644 --- a/lib/libutil/Makefile +++ b/lib/libutil/Makefile @@ -8,7 +8,7 @@ SHLIBDIR?= /lib LIB= util SHLIB_MAJOR= 7 -SRCS= _secure_path.c auth.c expand_number.c flopen.c fparseln.c \ +SRCS= _secure_path.c auth.c gr_util.c expand_number.c flopen.c fparseln.c \ humanize_number.c kld.c login.c login_auth.c login_cap.c login_class.c \ login_crypt.c login_ok.c login_times.c login_tty.c logout.c \ logwtmp.c pidfile.c property.c pty.c pw_util.c realhostname.c \ diff --git a/lib/libutil/gr_util.c b/lib/libutil/gr_util.c new file mode 100644 index 0000000..89f5fa3 --- /dev/null +++ b/lib/libutil/gr_util.c @@ -0,0 +1,234 @@ +/*- + * Copyright (c) 2008 Sean C. Farley <scf@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <grp.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <libutil.h> + + +static const char GroupLineFormat[] = "%s:%s:%ju:"; + + +/* + * Compares two struct group's. + */ +int +gr_equal(const struct group *gr1, const struct group *gr2) +{ + bool found; + bool equal; + int gr1Ndx; + int gr2Ndx; + + /* Check that the non-member information is the same. */ + equal = strcmp(gr1->gr_name, gr2->gr_name) == 0 && + strcmp(gr1->gr_passwd, gr2->gr_passwd) == 0 && + gr1->gr_gid == gr2->gr_gid; + + /* Check all members in both groups. */ + if (equal) { + for (found = false, gr1Ndx = 0; gr1->gr_mem[gr1Ndx] != NULL; + gr1Ndx++) { + for (gr2Ndx = 0; gr2->gr_mem[gr2Ndx] != NULL; gr2Ndx++) + if (strcmp(gr1->gr_mem[gr1Ndx], + gr2->gr_mem[gr2Ndx]) == 0) { + found = true; + break; + } + if (! found) { + equal = false; + break; + } + } + + /* Check that group2 does not have more members than group1. */ + if (gr2->gr_mem[gr1Ndx] != NULL) + equal = false; + } + + return (equal); +} + + +/* + * Make a group line out of a struct group. + */ +char * +gr_make(const struct group *gr) +{ + char *line; + int ndx; + size_t lineSize; + + /* Calculate the length of the group line. */ + lineSize = snprintf(NULL, 0, GroupLineFormat, gr->gr_name, + gr->gr_passwd, (uintmax_t)gr->gr_gid) + 1; + for (ndx = 0; gr->gr_mem[ndx] != NULL; ndx++) + lineSize += strlen(gr->gr_mem[ndx]) + 1; + if (ndx > 0) + lineSize--; + + /* Create the group line and fill it. */ + if ((line = malloc(lineSize)) == NULL) + return (NULL); + lineSize = snprintf(line, lineSize, GroupLineFormat, gr->gr_name, + gr->gr_passwd, (uintmax_t)gr->gr_gid); + for (ndx = 0; gr->gr_mem[ndx] != NULL; ndx++) { + strcat(line, gr->gr_mem[ndx]); + if (gr->gr_mem[ndx + 1] != NULL) + strcat(line, ","); + } + + return (line); +} + + +/* + * Duplicate a struct group. + */ +struct group * +gr_dup(const struct group *gr) +{ + int ndx; + int numMem; + size_t len; + struct group *ngr; + + /* Calculate size of group. */ + len = sizeof(*gr) + + (gr->gr_name != NULL ? strlen(gr->gr_name) + 1 : 0) + + (gr->gr_passwd != NULL ? strlen(gr->gr_passwd) + 1 : 0); + numMem = 0; + if (gr->gr_mem != NULL) { + for (; gr->gr_mem[numMem] != NULL; numMem++) + len += strlen(gr->gr_mem[numMem]) + 1; + len += (numMem + 1) * sizeof(*(gr->gr_mem)); + } + + /* Create new group and copy old group into it. */ + if ((ngr = calloc(1, len)) == NULL) + return (NULL); + len = sizeof(*ngr); + ngr->gr_gid = gr->gr_gid; + if (gr->gr_name != NULL) { + ngr->gr_name = (char *)ngr + len; + len += sprintf(ngr->gr_name, "%s", gr->gr_name) + 1; + } + if (gr->gr_passwd != NULL) { + ngr->gr_passwd = (char *)ngr + len; + len += sprintf(ngr->gr_passwd, "%s", gr->gr_passwd) + 1; + } + if (gr->gr_mem != NULL) { + ngr->gr_mem = (char **)((char *)ngr + len); + len += (numMem + 1) * sizeof(*(ngr->gr_mem)); + for (ndx = 0; gr->gr_mem[ndx] != NULL; ndx++) { + ngr->gr_mem[ndx] = (char *)ngr + len; + len += sprintf(ngr->gr_mem[ndx], "%s", + gr->gr_mem[ndx]) + 1; + } + ngr->gr_mem[ndx] = NULL; + } + + return (ngr); +} + + +/* + * Scan a line and place it into a group structure. + */ +static bool +__gr_scan(char *line, struct group *gr) +{ + char *loc; + int ndx; + + /* Assign non-member information to structure. */ + gr->gr_name = line; + if ((loc = strchr(line, ':')) == NULL) + return (false); + *loc = '\0'; + gr->gr_passwd = loc + 1; + if (*(gr->gr_passwd) == ':') + *(gr->gr_passwd) = '\0'; + else { + if ((loc = strchr(loc + 1, ':')) == NULL) + return (false); + *loc = '\0'; + } + if (sscanf(loc + 1, "%u", &(gr->gr_gid)) != 1) + return (false); + + /* Assign member information to structure. */ + if ((loc = strchr(loc + 1, ':')) == NULL) + return (false); + line = loc + 1; + gr->gr_mem = NULL; + if (*line != '\0') { + ndx = 0; + do { + if ((gr->gr_mem = reallocf(gr->gr_mem, + sizeof(*(gr->gr_mem)) * (ndx + 1))) == NULL) + return (false); + gr->gr_mem[ndx] = strsep(&line, ","); + } while (gr->gr_mem[ndx++] != NULL); + } + + return (true); +} + + +/* + * Create a struct group from a line. + */ +struct group * +gr_scan(const char *line) +{ + char *lineCopy; + struct group *newGr; + struct group gr; + + if ((lineCopy = strdup(line)) == NULL) + return (NULL); + if (!__gr_scan(lineCopy, &gr)) { + free(lineCopy); + return (NULL); + } + newGr = gr_dup(&gr); + free(lineCopy); + if (gr.gr_mem != NULL) + free(gr.gr_mem); + + return (newGr); +} diff --git a/lib/libutil/libutil.h b/lib/libutil/libutil.h index aa663a7..8fafe9b 100644 --- a/lib/libutil/libutil.h +++ b/lib/libutil/libutil.h @@ -119,6 +119,13 @@ const char *pw_tempname(void); int pw_tmp(int _mfd); #endif +#ifdef _GRP_H_ +int gr_equal(const struct group *gr1, const struct group *gr2); +char *gr_make(const struct group *gr); +struct group *gr_dup(const struct group *gr); +struct group *gr_scan(const char *line); +#endif + #ifdef _SYS_PARAM_H_ struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr); int pidfile_write(struct pidfh *pfh); |