getgrent.c revision 2830:5228d1267a01
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 *
25 * files/getgrent.c -- "files" backend for nsswitch "group" database
26 */
27
28#pragma ident	"%Z%%M%	%I%	%E% SMI"
29
30#include <grp.h>
31#include <unistd.h>		/* for GF_PATH */
32#include <stdlib.h>		/* for GF_PATH */
33#include "files_common.h"
34#include <strings.h>
35
36static uint_t
37hash_grname(nss_XbyY_args_t *argp, int keyhash, const char *line,
38	int linelen)
39{
40	const char 	*name;
41	int		namelen, i;
42	uint_t		hash = 0;
43
44	if (keyhash) {
45		name = argp->key.name;
46		namelen = strlen(name);
47	} else {
48		name = line;
49		namelen = 0;
50		while (linelen-- && *line++ != ':')
51			namelen++;
52	}
53
54	for (i = 0; i < namelen; i++)
55		hash = hash * 15 + name[i];
56	return (hash);
57}
58
59static uint_t
60hash_grgid(nss_XbyY_args_t *argp, int keyhash, const char *line,
61	int linelen)
62{
63	uint_t		id;
64	const char	*linep, *limit, *end;
65
66	linep = line;
67	limit = line + linelen;
68
69	if (keyhash)
70		return ((uint_t)argp->key.gid);
71
72	/* skip groupname */
73	while (linep < limit && *linep++ != ':');
74	/* skip password */
75	while (linep < limit && *linep++ != ':');
76	if (linep == limit)
77		return (GID_NOBODY);
78
79	/* gid */
80	end = linep;
81	id = (uint_t)strtol(linep, (char **)&end, 10);
82	/* empty gid */
83	if (linep == end)
84		return (GID_NOBODY);
85
86	return (id);
87}
88
89static files_hash_func hash_gr[2] = { hash_grname, hash_grgid };
90
91static files_hash_t hashinfo = {
92	DEFAULTMUTEX,
93	sizeof (struct group),
94	NSS_BUFLEN_GROUP,
95	2,
96	hash_gr
97};
98
99static int
100check_grname(nss_XbyY_args_t *argp, const char *line, int linelen)
101{
102	const char *linep, *limit;
103	const char *keyp = argp->key.name;
104
105	linep = line;
106	limit = line + linelen;
107
108	/* +/- entries valid for compat source only */
109	if (linelen == 0 || *line == '+' || *line == '-')
110		return (0);
111	while (*keyp && linep < limit && *keyp == *linep) {
112		keyp++;
113		linep++;
114	}
115	return (linep < limit && *keyp == '\0' && *linep == ':');
116}
117
118static nss_status_t
119getbyname(be, a)
120	files_backend_ptr_t	be;
121	void			*a;
122{
123	return (_nss_files_XY_hash(be, a, 0, &hashinfo, 0, check_grname));
124}
125
126static int
127check_grgid(nss_XbyY_args_t *argp, const char *line, int linelen)
128{
129	const char	*linep, *limit, *end;
130	gid_t		gr_gid;
131
132	linep = line;
133	limit = line + linelen;
134
135	/* +/- entries valid for compat source only */
136	if (linelen == 0 || *line == '+' || *line == '-')
137		return (0);
138
139	/* skip username */
140	while (linep < limit && *linep++ != ':');
141	/* skip password */
142	while (linep < limit && *linep++ != ':');
143	if (linep == limit)
144		return (0);
145
146	/* uid */
147	end = linep;
148	gr_gid = (gid_t)strtol(linep, (char **)&end, 10);
149
150	/* empty gid is not valid */
151	if (linep == end)
152		return (0);
153
154	return (gr_gid == argp->key.gid);
155}
156
157static nss_status_t
158getbygid(be, a)
159	files_backend_ptr_t	be;
160	void			*a;
161{
162	return (_nss_files_XY_hash(be, a, 0, &hashinfo, 1, check_grgid));
163}
164
165static nss_status_t
166getbymember(be, a)
167	files_backend_ptr_t	be;
168	void			*a;
169{
170	struct nss_groupsbymem	*argp = (struct nss_groupsbymem *)a;
171
172	return (_nss_files_do_all(be, argp, argp->username,
173				(files_do_all_func_t)argp->process_cstr));
174}
175
176static files_backend_op_t group_ops[] = {
177	_nss_files_destr,
178	_nss_files_endent,
179	_nss_files_setent,
180	_nss_files_getent_rigid,
181	getbyname,
182	getbygid,
183	getbymember
184};
185
186/*ARGSUSED*/
187nss_backend_t *
188_nss_files_group_constr(dummy1, dummy2, dummy3)
189	const char	*dummy1, *dummy2, *dummy3;
190{
191	return (_nss_files_constr(group_ops,
192				sizeof (group_ops) / sizeof (group_ops[0]),
193				GF_PATH,
194				NSS_LINELEN_GROUP,
195				&hashinfo));
196}
197