gr_util.c revision 184831
1178431Sscf/*- 2178431Sscf * Copyright (c) 2008 Sean C. Farley <scf@FreeBSD.org> 3178431Sscf * All rights reserved. 4178431Sscf * 5178431Sscf * Redistribution and use in source and binary forms, with or without 6178431Sscf * modification, are permitted provided that the following conditions 7178431Sscf * are met: 8178431Sscf * 1. Redistributions of source code must retain the above copyright 9178431Sscf * notice, this list of conditions and the following disclaimer, 10178431Sscf * without modification, immediately at the beginning of the file. 11178431Sscf * 2. Redistributions in binary form must reproduce the above copyright 12178431Sscf * notice, this list of conditions and the following disclaimer in the 13178431Sscf * documentation and/or other materials provided with the distribution. 14178431Sscf * 15178431Sscf * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16178431Sscf * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17178431Sscf * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18178431Sscf * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19178431Sscf * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20178431Sscf * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21178431Sscf * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22178431Sscf * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23178431Sscf * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24178431Sscf * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25178431Sscf */ 26178431Sscf 27178431Sscf#include <sys/cdefs.h> 28178431Sscf__FBSDID("$FreeBSD: head/lib/libutil/gr_util.c 184831 2008-11-11 00:32:55Z scf $"); 29178431Sscf 30178431Sscf#include <sys/param.h> 31184831Sscf 32178431Sscf#include <grp.h> 33178431Sscf#include <inttypes.h> 34184831Sscf#include <libutil.h> 35178431Sscf#include <stdbool.h> 36178431Sscf#include <stdio.h> 37178431Sscf#include <stdlib.h> 38178431Sscf#include <string.h> 39178431Sscf 40178431Sscfstatic const char GroupLineFormat[] = "%s:%s:%ju:"; 41178431Sscf 42178431Sscf/* 43178431Sscf * Compares two struct group's. 44178431Sscf */ 45178431Sscfint 46178431Sscfgr_equal(const struct group *gr1, const struct group *gr2) 47178431Sscf{ 48178431Sscf int gr1Ndx; 49178431Sscf int gr2Ndx; 50184831Sscf bool equal; 51184831Sscf bool found; 52178431Sscf 53178431Sscf /* Check that the non-member information is the same. */ 54178431Sscf equal = strcmp(gr1->gr_name, gr2->gr_name) == 0 && 55178431Sscf strcmp(gr1->gr_passwd, gr2->gr_passwd) == 0 && 56178431Sscf gr1->gr_gid == gr2->gr_gid; 57178431Sscf 58178431Sscf /* Check all members in both groups. */ 59178431Sscf if (equal) { 60178431Sscf for (found = false, gr1Ndx = 0; gr1->gr_mem[gr1Ndx] != NULL; 61178431Sscf gr1Ndx++) { 62178431Sscf for (gr2Ndx = 0; gr2->gr_mem[gr2Ndx] != NULL; gr2Ndx++) 63178431Sscf if (strcmp(gr1->gr_mem[gr1Ndx], 64178431Sscf gr2->gr_mem[gr2Ndx]) == 0) { 65178431Sscf found = true; 66178431Sscf break; 67178431Sscf } 68178431Sscf if (! found) { 69178431Sscf equal = false; 70178431Sscf break; 71178431Sscf } 72178431Sscf } 73178431Sscf 74178431Sscf /* Check that group2 does not have more members than group1. */ 75178431Sscf if (gr2->gr_mem[gr1Ndx] != NULL) 76178431Sscf equal = false; 77178431Sscf } 78178431Sscf 79178431Sscf return (equal); 80178431Sscf} 81178431Sscf 82178431Sscf/* 83178431Sscf * Make a group line out of a struct group. 84178431Sscf */ 85178431Sscfchar * 86178431Sscfgr_make(const struct group *gr) 87178431Sscf{ 88178431Sscf char *line; 89184831Sscf size_t lineSize; 90178431Sscf int ndx; 91178431Sscf 92178431Sscf /* Calculate the length of the group line. */ 93178431Sscf lineSize = snprintf(NULL, 0, GroupLineFormat, gr->gr_name, 94178431Sscf gr->gr_passwd, (uintmax_t)gr->gr_gid) + 1; 95178431Sscf for (ndx = 0; gr->gr_mem[ndx] != NULL; ndx++) 96178431Sscf lineSize += strlen(gr->gr_mem[ndx]) + 1; 97178431Sscf if (ndx > 0) 98178431Sscf lineSize--; 99178431Sscf 100178431Sscf /* Create the group line and fill it. */ 101178431Sscf if ((line = malloc(lineSize)) == NULL) 102178431Sscf return (NULL); 103178431Sscf lineSize = snprintf(line, lineSize, GroupLineFormat, gr->gr_name, 104178431Sscf gr->gr_passwd, (uintmax_t)gr->gr_gid); 105178431Sscf for (ndx = 0; gr->gr_mem[ndx] != NULL; ndx++) { 106178431Sscf strcat(line, gr->gr_mem[ndx]); 107178431Sscf if (gr->gr_mem[ndx + 1] != NULL) 108178431Sscf strcat(line, ","); 109178431Sscf } 110178431Sscf 111178431Sscf return (line); 112178431Sscf} 113178431Sscf 114178431Sscf/* 115178431Sscf * Duplicate a struct group. 116178431Sscf */ 117178431Sscfstruct group * 118178431Sscfgr_dup(const struct group *gr) 119178431Sscf{ 120184831Sscf size_t len; 121184831Sscf struct group *ngr; 122178431Sscf int ndx; 123178431Sscf int numMem; 124178431Sscf 125178431Sscf /* Calculate size of group. */ 126178431Sscf len = sizeof(*gr) + 127178431Sscf (gr->gr_name != NULL ? strlen(gr->gr_name) + 1 : 0) + 128178431Sscf (gr->gr_passwd != NULL ? strlen(gr->gr_passwd) + 1 : 0); 129178431Sscf numMem = 0; 130178431Sscf if (gr->gr_mem != NULL) { 131178431Sscf for (; gr->gr_mem[numMem] != NULL; numMem++) 132178431Sscf len += strlen(gr->gr_mem[numMem]) + 1; 133184831Sscf len += (numMem + 1) * sizeof(*gr->gr_mem); 134178431Sscf } 135178431Sscf 136178431Sscf /* Create new group and copy old group into it. */ 137178431Sscf if ((ngr = calloc(1, len)) == NULL) 138178431Sscf return (NULL); 139178431Sscf len = sizeof(*ngr); 140178431Sscf ngr->gr_gid = gr->gr_gid; 141178431Sscf if (gr->gr_name != NULL) { 142178431Sscf ngr->gr_name = (char *)ngr + len; 143178431Sscf len += sprintf(ngr->gr_name, "%s", gr->gr_name) + 1; 144178431Sscf } 145178431Sscf if (gr->gr_passwd != NULL) { 146178431Sscf ngr->gr_passwd = (char *)ngr + len; 147178431Sscf len += sprintf(ngr->gr_passwd, "%s", gr->gr_passwd) + 1; 148178431Sscf } 149178431Sscf if (gr->gr_mem != NULL) { 150178431Sscf ngr->gr_mem = (char **)((char *)ngr + len); 151184831Sscf len += (numMem + 1) * sizeof(*ngr->gr_mem); 152178431Sscf for (ndx = 0; gr->gr_mem[ndx] != NULL; ndx++) { 153178431Sscf ngr->gr_mem[ndx] = (char *)ngr + len; 154178431Sscf len += sprintf(ngr->gr_mem[ndx], "%s", 155178431Sscf gr->gr_mem[ndx]) + 1; 156178431Sscf } 157178431Sscf ngr->gr_mem[ndx] = NULL; 158178431Sscf } 159178431Sscf 160178431Sscf return (ngr); 161178431Sscf} 162178431Sscf 163178431Sscf/* 164178431Sscf * Scan a line and place it into a group structure. 165178431Sscf */ 166178431Sscfstatic bool 167178431Sscf__gr_scan(char *line, struct group *gr) 168178431Sscf{ 169178431Sscf char *loc; 170178431Sscf int ndx; 171178431Sscf 172178431Sscf /* Assign non-member information to structure. */ 173178431Sscf gr->gr_name = line; 174178431Sscf if ((loc = strchr(line, ':')) == NULL) 175178431Sscf return (false); 176178431Sscf *loc = '\0'; 177178431Sscf gr->gr_passwd = loc + 1; 178184831Sscf if (*gr->gr_passwd == ':') 179184831Sscf *gr->gr_passwd = '\0'; 180178431Sscf else { 181178431Sscf if ((loc = strchr(loc + 1, ':')) == NULL) 182178431Sscf return (false); 183178431Sscf *loc = '\0'; 184178431Sscf } 185184831Sscf if (sscanf(loc + 1, "%u", &gr->gr_gid) != 1) 186178431Sscf return (false); 187178431Sscf 188178431Sscf /* Assign member information to structure. */ 189178431Sscf if ((loc = strchr(loc + 1, ':')) == NULL) 190178431Sscf return (false); 191178431Sscf line = loc + 1; 192178431Sscf gr->gr_mem = NULL; 193178431Sscf if (*line != '\0') { 194178431Sscf ndx = 0; 195178431Sscf do { 196178431Sscf if ((gr->gr_mem = reallocf(gr->gr_mem, 197184831Sscf sizeof(*gr->gr_mem) * (ndx + 1))) == NULL) 198178431Sscf return (false); 199178431Sscf gr->gr_mem[ndx] = strsep(&line, ","); 200178431Sscf } while (gr->gr_mem[ndx++] != NULL); 201178431Sscf } 202178431Sscf 203178431Sscf return (true); 204178431Sscf} 205178431Sscf 206178431Sscf/* 207178431Sscf * Create a struct group from a line. 208178431Sscf */ 209178431Sscfstruct group * 210178431Sscfgr_scan(const char *line) 211178431Sscf{ 212184831Sscf struct group gr; 213178431Sscf char *lineCopy; 214178431Sscf struct group *newGr; 215178431Sscf 216178431Sscf if ((lineCopy = strdup(line)) == NULL) 217178431Sscf return (NULL); 218178431Sscf if (!__gr_scan(lineCopy, &gr)) { 219178431Sscf free(lineCopy); 220178431Sscf return (NULL); 221178431Sscf } 222178431Sscf newGr = gr_dup(&gr); 223178431Sscf free(lineCopy); 224178431Sscf if (gr.gr_mem != NULL) 225178431Sscf free(gr.gr_mem); 226178431Sscf 227178431Sscf return (newGr); 228178431Sscf} 229