xref: /openbsd/regress/lib/libpthread/group/group.c (revision d0774bb2)
1*d0774bb2Sfgsch /*	$OpenBSD: group.c,v 1.6 2005/10/30 23:59:43 fgsch Exp $	*/
2f2ecab7dSfgsch 
3b2ea75c1Sfgsch /* David Leonard <d@openbsd.org>, 2001. Public Domain. */
4b2ea75c1Sfgsch 
5b2ea75c1Sfgsch /*
6b2ea75c1Sfgsch  * Test getgrgid_r() across multiple threads to see if the members list changes.
7b2ea75c1Sfgsch  */
8b2ea75c1Sfgsch 
9f2ecab7dSfgsch #include <sys/types.h>
10f2ecab7dSfgsch #include <grp.h>
11b2ea75c1Sfgsch #include <pthread.h>
12b2ea75c1Sfgsch #include <unistd.h>
13b2ea75c1Sfgsch #include <stdio.h>
14f2ecab7dSfgsch #include <stdlib.h>
15b2ea75c1Sfgsch #include "test.h"
16b2ea75c1Sfgsch 
17f2ecab7dSfgsch int	getgrgid_r(gid_t, struct group *, char *, size_t, struct group **);
18b2ea75c1Sfgsch 
19b2ea75c1Sfgsch char fail[] = "fail";
20b2ea75c1Sfgsch 
21b2ea75c1Sfgsch pthread_cond_t done;
22b2ea75c1Sfgsch volatile int done_count;
23b2ea75c1Sfgsch 
24b2ea75c1Sfgsch pthread_mutex_t display;
25b2ea75c1Sfgsch pthread_mutex_t display2;
26b2ea75c1Sfgsch 
27db3296cfSderaadt static void *
test(void * arg)28b2ea75c1Sfgsch test(void *arg)
29b2ea75c1Sfgsch {
302badd5e3Sfgsch 	gid_t gid = *(gid_t *)arg;
31b2ea75c1Sfgsch 	gid_t ogid;
32b2ea75c1Sfgsch 	struct group grpbuf;
33b2ea75c1Sfgsch 	struct group *grp;
34b2ea75c1Sfgsch 	char **p;
35f2ecab7dSfgsch 	char buffer[5000];
36b2ea75c1Sfgsch 	char buf[2048];
37b2ea75c1Sfgsch 	char *cpy[128];
38b2ea75c1Sfgsch 	int i;
39b2ea75c1Sfgsch 	int count1, count2;
40b2ea75c1Sfgsch 	char *s;
41b2ea75c1Sfgsch 	char *oname;
42b2ea75c1Sfgsch 	char *opasswd;
43*d0774bb2Sfgsch 	size_t len;
44b2ea75c1Sfgsch 
45b2ea75c1Sfgsch 	/* Acquire lock for running first part. */
46b2ea75c1Sfgsch 	CHECKr(pthread_mutex_lock(&display));
47b2ea75c1Sfgsch 
48b2ea75c1Sfgsch 	/* Store magic name to test for non-alteration */
49b2ea75c1Sfgsch 	grpbuf.gr_name = fail;
50b2ea75c1Sfgsch 
51b2ea75c1Sfgsch 	/* Call getgrgid_r() */
52b2ea75c1Sfgsch 	printf("gid %d\n", gid);
53f2ecab7dSfgsch 	CHECKr(getgrgid_r(gid, &grpbuf, buffer, sizeof(buffer), &grp));
54b2ea75c1Sfgsch 
55b2ea75c1Sfgsch 	/* Test for non-alteration of group structure */
56b2ea75c1Sfgsch 	ASSERT(grp->gr_name != fail);
57b2ea75c1Sfgsch 
58b2ea75c1Sfgsch 	/* We must get the right group */
59b2ea75c1Sfgsch 	ASSERT(grp->gr_gid == gid);
60b2ea75c1Sfgsch 
61b2ea75c1Sfgsch 	s = buf;	/* Keep our private buffer on the stack */
62*d0774bb2Sfgsch 	len = sizeof(buf);
63b2ea75c1Sfgsch 
64b2ea75c1Sfgsch 	/* copy gr_name */
65*d0774bb2Sfgsch 	strlcpy(oname = s, grp->gr_name, len);
66*d0774bb2Sfgsch 	len -= 1 + strlen(s);
67b2ea75c1Sfgsch 	s += 1 + strlen(s);
68b2ea75c1Sfgsch 
69b2ea75c1Sfgsch 	/* copy gr_passwd */
70*d0774bb2Sfgsch 	strlcpy(opasswd = s, grp->gr_passwd, len);
71*d0774bb2Sfgsch 	len -= 1 + strlen(s);
72b2ea75c1Sfgsch 	s += 1 + strlen(s);
73b2ea75c1Sfgsch 
74b2ea75c1Sfgsch 	/* copy gr_gid */
75b2ea75c1Sfgsch 	ogid = grp->gr_gid;
76b2ea75c1Sfgsch 
77b2ea75c1Sfgsch 	/* copy gr_mem */
78b2ea75c1Sfgsch 	for (i = 0, p = grp->gr_mem; *p; p++) {
79*d0774bb2Sfgsch 		strlcpy(cpy[i] = s, *p, len);
80*d0774bb2Sfgsch 		i++;
81*d0774bb2Sfgsch 		len -= 1 + strlen(s);
82b2ea75c1Sfgsch 		s += 1 + strlen(s);
83b2ea75c1Sfgsch 	}
84b2ea75c1Sfgsch 	cpy[i] = NULL;
85b2ea75c1Sfgsch 
86b2ea75c1Sfgsch #if 0
87b2ea75c1Sfgsch 	printf("now:    %s:%s:%d:", grp->gr_name, grp->gr_passwd, grp->gr_gid);
88b2ea75c1Sfgsch 	for (p = grp->gr_mem; *p; p++)
89b2ea75c1Sfgsch 		printf("%s%s", *p, *(p+1) == NULL ? "": ",");
90b2ea75c1Sfgsch 	printf("\n");
91b2ea75c1Sfgsch #endif
92b2ea75c1Sfgsch 
93b2ea75c1Sfgsch #ifdef DEBUG /* debugging this program */
94b2ea75c1Sfgsch 	printf("buf = \"");
95b2ea75c1Sfgsch 	for (i = 0; i < s - buf; i++)
96b2ea75c1Sfgsch 		if (buf[i] == '\0')	printf("\\0");
97b2ea75c1Sfgsch 		else printf("%c", buf[i]);
98b2ea75c1Sfgsch 	printf("\"\n");
99b2ea75c1Sfgsch #endif
100b2ea75c1Sfgsch 
101b2ea75c1Sfgsch 	/* Inform main that we have finished */
102b2ea75c1Sfgsch 	done_count++;
103b2ea75c1Sfgsch 	CHECKr(pthread_cond_signal(&done));
104b2ea75c1Sfgsch 
105b2ea75c1Sfgsch 	/* Allow other threads to run first part */
106b2ea75c1Sfgsch 	CHECKr(pthread_mutex_unlock(&display));
107b2ea75c1Sfgsch 
108b2ea75c1Sfgsch 	/* Acquire lock for the second part */
109b2ea75c1Sfgsch 	CHECKr(pthread_mutex_lock(&display2));
110b2ea75c1Sfgsch 
111b2ea75c1Sfgsch 	count1 = 0;
112b2ea75c1Sfgsch 	printf("before: %s:%s:%d:", oname, opasswd, ogid);
113b2ea75c1Sfgsch 	for (p = cpy; *p; p++)  {
114b2ea75c1Sfgsch 		count1++;
115b2ea75c1Sfgsch 		printf("%s%s", *p, *(p+1) == NULL ? "": ",");
116b2ea75c1Sfgsch 	}
117b2ea75c1Sfgsch 	printf("\n");
118b2ea75c1Sfgsch 
119b2ea75c1Sfgsch 	count2 = 0;
120b2ea75c1Sfgsch 	printf("after:  %s:%s:%d:", grp->gr_name, grp->gr_passwd, grp->gr_gid);
121b2ea75c1Sfgsch 	for (p = grp->gr_mem; *p; p++)  {
122b2ea75c1Sfgsch 		count2++;
123b2ea75c1Sfgsch 		printf("%s%s", *p, *(p+1) == NULL ? "": ",");
124b2ea75c1Sfgsch 	}
125b2ea75c1Sfgsch 	printf("\n");
126b2ea75c1Sfgsch 
127b2ea75c1Sfgsch 	CHECKr(pthread_mutex_unlock(&display2));
128b2ea75c1Sfgsch 
129b2ea75c1Sfgsch 	if (count1 != count2)
130b2ea75c1Sfgsch 		return "gr_mem length changed";
131b2ea75c1Sfgsch 	for (i = 0; i < count1; i++)
132b2ea75c1Sfgsch 		if (strcmp(cpy[i], grp->gr_mem[i]) != 0)
133b2ea75c1Sfgsch 			return "gr_mem list changed";
134b2ea75c1Sfgsch 	if (strcmp(grp->gr_name, oname) != 0)
135b2ea75c1Sfgsch 		return "gr_name changed";
136b2ea75c1Sfgsch 	if (strcmp(grp->gr_passwd, opasswd) != 0)
137b2ea75c1Sfgsch 		return "gr_passwd changed";
138b2ea75c1Sfgsch 	if (grp->gr_gid != ogid)
139b2ea75c1Sfgsch 		return "gr_gid changed";
140b2ea75c1Sfgsch 	return NULL;
141b2ea75c1Sfgsch }
142b2ea75c1Sfgsch 
143b2ea75c1Sfgsch 
144b2ea75c1Sfgsch #define NGRPS	5
145b2ea75c1Sfgsch int
main(int argc,char * argv[])146db3296cfSderaadt main(int argc, char *argv[])
147b2ea75c1Sfgsch {
148b2ea75c1Sfgsch 	pthread_t thread[NGRPS];
149b2ea75c1Sfgsch 	int gid;
150b2ea75c1Sfgsch 	int failed;
151b2ea75c1Sfgsch 	void *result;
152b2ea75c1Sfgsch 
153b2ea75c1Sfgsch 	CHECKr(pthread_mutex_init(&display, NULL));
154b2ea75c1Sfgsch 	CHECKr(pthread_mutex_init(&display2, NULL));
155b2ea75c1Sfgsch 
156b2ea75c1Sfgsch 	CHECKr(pthread_cond_init(&done, NULL));
157b2ea75c1Sfgsch 	done_count = 0;
158b2ea75c1Sfgsch 
159b2ea75c1Sfgsch 	pthread_mutex_lock(&display);
160b2ea75c1Sfgsch 	pthread_mutex_lock(&display2);
161b2ea75c1Sfgsch 
162b2ea75c1Sfgsch 	/* Get separate threads to do a group open separately */
163b2ea75c1Sfgsch 	for (gid = 0; gid < NGRPS; gid++) {
164f2ecab7dSfgsch 		int *n = (int *)malloc(sizeof(int));
165f2ecab7dSfgsch 		*n = gid;
166f2ecab7dSfgsch 
167f2ecab7dSfgsch 		CHECKr(pthread_create(&thread[gid], NULL, test, (void *)n));
168b2ea75c1Sfgsch 	}
169b2ea75c1Sfgsch 
170b2ea75c1Sfgsch 	/* Allow all threads to run their first part */
171b2ea75c1Sfgsch 	while (done_count < NGRPS)
172b2ea75c1Sfgsch 		pthread_cond_wait(&done, &display);
173b2ea75c1Sfgsch 
174b2ea75c1Sfgsch 	/* Allow each thread to run the 2nd part of its test */
175b2ea75c1Sfgsch 	CHECKr(pthread_mutex_unlock(&display2));
176b2ea75c1Sfgsch 
177b2ea75c1Sfgsch 	/* Wait for each thread to terminate, collecting results. */
178b2ea75c1Sfgsch 	failed = 0;
179b2ea75c1Sfgsch 	for (gid = 0; gid < NGRPS; gid++) {
180b2ea75c1Sfgsch 		CHECKr(pthread_join(thread[gid], &result));
181b2ea75c1Sfgsch 		if (result != NULL) {
182b2ea75c1Sfgsch 			fprintf(stderr, "gid %d: %s\n", gid, (char *)result);
183b2ea75c1Sfgsch 			failed++;
184b2ea75c1Sfgsch 		}
185b2ea75c1Sfgsch 	}
186b2ea75c1Sfgsch 
187b2ea75c1Sfgsch 	if (!failed) {
188b2ea75c1Sfgsch 		SUCCEED;
189b2ea75c1Sfgsch 	} else {
190b2ea75c1Sfgsch 		exit(1);
191b2ea75c1Sfgsch 	}
192b2ea75c1Sfgsch }
193