]>
git.cameronkatri.com Git - pw-darwin.git/blob - libutil/gr_util.c
2 * Copyright (c) 2008 Sean C. Farley <scf@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification, immediately at the beginning of the file.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
40 struct group_storage
{
45 static const char group_line_format
[] = "%s:%s:%ju:";
48 * Compares two struct group's.
51 gr_equal(const struct group
*gr1
, const struct group
*gr2
)
57 /* Check that the non-member information is the same. */
58 if (gr1
->gr_name
== NULL
|| gr2
->gr_name
== NULL
) {
59 if (gr1
->gr_name
!= gr2
->gr_name
)
61 } else if (strcmp(gr1
->gr_name
, gr2
->gr_name
) != 0)
63 if (gr1
->gr_passwd
== NULL
|| gr2
->gr_passwd
== NULL
) {
64 if (gr1
->gr_passwd
!= gr2
->gr_passwd
)
66 } else if (strcmp(gr1
->gr_passwd
, gr2
->gr_passwd
) != 0)
68 if (gr1
->gr_gid
!= gr2
->gr_gid
)
71 /* Check all members in both groups. */
72 if (gr1
->gr_mem
== NULL
|| gr2
->gr_mem
== NULL
) {
73 if (gr1
->gr_mem
!= gr2
->gr_mem
)
76 for (found
= false, gr1_ndx
= 0; gr1
->gr_mem
[gr1_ndx
] != NULL
;
78 for (gr2_ndx
= 0; gr2
->gr_mem
[gr2_ndx
] != NULL
;
80 if (strcmp(gr1
->gr_mem
[gr1_ndx
],
81 gr2
->gr_mem
[gr2_ndx
]) == 0) {
89 /* Check that group2 does not have more members than group1. */
90 if (gr2
->gr_mem
[gr1_ndx
] != NULL
)
98 * Make a group line out of a struct group.
101 gr_make(const struct group
*gr
)
107 /* Calculate the length of the group line. */
108 line_size
= snprintf(NULL
, 0, group_line_format
, gr
->gr_name
,
109 gr
->gr_passwd
, (uintmax_t)gr
->gr_gid
) + 1;
110 if (gr
->gr_mem
!= NULL
) {
111 for (ndx
= 0; gr
->gr_mem
[ndx
] != NULL
; ndx
++)
112 line_size
+= strlen(gr
->gr_mem
[ndx
]) + 1;
117 /* Create the group line and fill it. */
118 if ((line
= malloc(line_size
)) == NULL
)
120 snprintf(line
, line_size
, group_line_format
, gr
->gr_name
, gr
->gr_passwd
,
121 (uintmax_t)gr
->gr_gid
);
122 if (gr
->gr_mem
!= NULL
)
123 for (ndx
= 0; gr
->gr_mem
[ndx
] != NULL
; ndx
++) {
124 strcat(line
, gr
->gr_mem
[ndx
]);
125 if (gr
->gr_mem
[ndx
+ 1] != NULL
)
133 * Duplicate a struct group.
136 gr_dup(const struct group
*gr
)
140 struct group_storage
*gs
;
144 /* Calculate size of the group. */
146 if (gr
->gr_name
!= NULL
)
147 len
+= strlen(gr
->gr_name
) + 1;
148 if (gr
->gr_passwd
!= NULL
)
149 len
+= strlen(gr
->gr_passwd
) + 1;
150 if (gr
->gr_mem
!= NULL
) {
151 for (num_mem
= 0; gr
->gr_mem
[num_mem
] != NULL
; num_mem
++)
152 len
+= strlen(gr
->gr_mem
[num_mem
]) + 1;
153 len
+= (num_mem
+ 1) * sizeof(*gr
->gr_mem
);
157 /* Create new group and copy old group into it. */
158 if ((gs
= calloc(1, len
)) == NULL
)
160 dst
= (char *)&gs
->members
[num_mem
+ 1];
161 if (gr
->gr_name
!= NULL
) {
162 gs
->gr
.gr_name
= dst
;
163 dst
= stpcpy(gs
->gr
.gr_name
, gr
->gr_name
) + 1;
165 if (gr
->gr_passwd
!= NULL
) {
166 gs
->gr
.gr_passwd
= dst
;
167 dst
= stpcpy(gs
->gr
.gr_passwd
, gr
->gr_passwd
) + 1;
169 gs
->gr
.gr_gid
= gr
->gr_gid
;
170 if (gr
->gr_mem
!= NULL
) {
171 gs
->gr
.gr_mem
= gs
->members
;
172 for (ndx
= 0; ndx
< num_mem
; ndx
++) {
173 gs
->gr
.gr_mem
[ndx
] = dst
;
174 dst
= stpcpy(gs
->gr
.gr_mem
[ndx
], gr
->gr_mem
[ndx
]) + 1;
176 gs
->gr
.gr_mem
[ndx
] = NULL
;
183 * Scan a line and place it into a group structure.
186 __gr_scan(char *line
, struct group
*gr
)
191 /* Assign non-member information to structure. */
193 if ((loc
= strchr(line
, ':')) == NULL
)
196 gr
->gr_passwd
= loc
+ 1;
197 if (*gr
->gr_passwd
== ':')
198 *gr
->gr_passwd
= '\0';
200 if ((loc
= strchr(loc
+ 1, ':')) == NULL
)
204 if (sscanf(loc
+ 1, "%u", &gr
->gr_gid
) != 1)
207 /* Assign member information to structure. */
208 if ((loc
= strchr(loc
+ 1, ':')) == NULL
)
214 gr
->gr_mem
= reallocf(gr
->gr_mem
, sizeof(*gr
->gr_mem
) *
216 if (gr
->gr_mem
== NULL
)
219 /* Skip locations without members (i.e., empty string). */
221 gr
->gr_mem
[ndx
] = strsep(&line
, ",");
222 } while (gr
->gr_mem
[ndx
] != NULL
&& *gr
->gr_mem
[ndx
] == '\0');
223 } while (gr
->gr_mem
[ndx
++] != NULL
);
229 * Create a struct group from a line.
232 gr_scan(const char *line
)
236 struct group
*new_gr
;
238 if ((line_copy
= strdup(line
)) == NULL
)
240 if (!__gr_scan(line_copy
, &gr
)) {
244 new_gr
= gr_dup(&gr
);
246 if (gr
.gr_mem
!= NULL
)