Project

General

Profile

Bug #3691 » testgroups4.c

Demonstration of reverse sorted GID values (fails on OpenIndiana, but not our NAS) - Andrew Bartlett, 2013-04-09 06:06 AM

 
1
#define NGROUPS_MAX 1000
2

    
3
#include <stdio.h>
4
#include <unistd.h>
5
#include <stdlib.h>
6
#include <errno.h>
7

    
8
#include <sys/types.h>
9
#include <string.h>
10
#include <grp.h>
11
#include <pwd.h>
12
#include <err.h>
13
#include <sys/stat.h>
14

    
15
/*
16
  This is a *much* faster way of getting the list of groups for a user
17
  without changing the current supplemenrary group list. The old
18
  method user getgrent() which could take 20 minutes on a really big
19
  network with hundeds of thousands of groups and users. The new method
20
  takes a couple of seconds. (tridge@samba.org)
21

    
22
  unfortunately it only works if we are root!
23
  */
24
int
25
testgroups(int test_num_groups, int gid_base)
26
{
27
	gid_t gids_found[NGROUPS_MAX + 1];
28
	gid_t gids_saved[NGROUPS_MAX + 1];
29
	gid_t gids[NGROUPS_MAX + 1];
30
	int ret, ngrp_saved, ngrp_found;
31
	int i, j, num_groups = 0;
32
	const int gid = gid_base + test_num_groups;
33
	const int uid = gid_base;
34
	
35
	ngrp_saved = getgroups(NGROUPS_MAX, gids_saved);
36
	if (ngrp_saved == -1) {
37
		return -1;
38
	}
39

    
40
	umask(002);
41

    
42
	ret = mkdir("test", 0775);
43
	if (ret != 0) {
44
		err(1, "failed to mkdir test");
45
	}
46
		
47
	for (i=test_num_groups -1; i >=0; i--) {
48
		gids[num_groups] = i+gid_base;
49
		num_groups++;
50
	}
51

    
52
	for (i=0; i < (test_num_groups); i++) {
53
		char dirname[20];
54
		char dirname2[20];
55
		snprintf(dirname, sizeof(dirname), "test/%d", gids[i]);
56
		snprintf(dirname2, sizeof(dirname), "test/%d/test", gids[i]);
57
		
58
		ret = mkdir(dirname, 0770);
59
		if (ret != 0) {
60
			err(1, "failed to mkdir %s", dirname);
61
		}
62
		
63
		ret = mkdir(dirname2, 0750);
64
		if (ret != 0) {
65
			err(1, "failed to mkdir %s", dirname2);
66
		}
67
		ret = chown(dirname, 0, gids[i]);
68
		if (ret != 0) {
69
			err(1, "failed to chown %s", dirname);
70
		}
71
		ret = chown(dirname2, 0, gids[i]);
72
		if (ret != 0) {
73
			err(1, "failed to chown %s", dirname2);
74
		}
75
	}
76

    
77
	ret = setgroups(test_num_groups, gids);
78
	if (ret != 0) {
79
		err(1, "failed to setgroups %d groups", test_num_groups);
80
	}
81
	ret = setregid(gid, gid);
82
	if (ret != 0) {
83
		err(1, "failed to setregid to %d", gid);
84
	}
85
	ret = setreuid(uid, uid);
86
	if (ret != 0) {
87
		err(1, "failed to setreuid to %d", uid);
88
	}
89
		
90
	ret = getgroups(NGROUPS_MAX, gids_found);
91
	if (ret >= 0) {
92
		ngrp_found = ret;
93
	} else {
94
		err(1, "failed to getgroups");
95
	}
96

    
97
	printf("Got %d groups\n", ngrp_found);
98
	for (i=0;i<ngrp_found;i++) {
99
		printf("%u ", (unsigned)gids_found[i]);
100
	}
101
	printf("\n");
102
	
103
	if (ngrp_found != test_num_groups) {
104
		err(1, "getgroups returned the wrong number of groups");
105
	}
106

    
107
	for (j=0; j<test_num_groups; j++) {
108
		if (gids_found[j] != gids[j]) {
109
			printf("got gid %d, expected %d at idx %d\n", gids_found[j], gids[j], j);
110
		}
111
	}
112

    
113
	for (j=0; j<test_num_groups; j++) {
114
		struct stat st;
115
		char dirname[20];
116
		char dirname2[20];
117
		char shell_dirname2[20];
118
		snprintf(dirname2, sizeof(dirname), "test/%d/test", gids[j]);
119
		ret = stat(dirname2, &st);
120
		if (ret != 0) {
121
			err(1, "failed to stat %s", dirname2);
122
		}
123
		ret = rmdir(dirname2);
124
		if (ret != 0) {
125
			err(1,"failed to rmdir %s: %s\n", dirname2);
126
		}
127
	}
128

    
129
	return ret;
130
}
131

    
132
int main(int argc, char *argv[])
133
{
134
	int ret;
135
	
136
	int test_num_groups = atoi(argv[1]);
137
	int gid_base = 65500;
138
	if (argc >= 3) {
139
		gid_base = atoi(argv[2]);
140
	}
141

    
142
	ret = testgroups(test_num_groups, gid_base);
143

    
144
	return 0;
145
}
(5-5/7)