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
26#pragma ident	"%Z%%M%	%I%	%E% SMI"
27
28#include <sys/types.h>
29#include <project.h>
30#include <string.h>
31#include <stdlib.h>
32#include "files_common.h"
33
34static uint_t
35hash_projname(nss_XbyY_args_t *argp, int keyhash, const char *line,
36		int linelen) {
37
38	const char	*name;
39	int		namelen, i;
40	uint_t		hash = 0;
41
42	if (keyhash) {
43		name = argp->key.name;
44		namelen = strlen(name);
45	} else {
46		name = line;
47		namelen = 0;
48		while (linelen-- && *line++ != ':')
49			namelen++;
50	}
51
52	for (i = 0; i < namelen; i++)
53		hash = hash * 15 + name[i];
54	return (hash);
55}
56
57static uint_t
58hash_projid(nss_XbyY_args_t *argp, int keyhash, const char *line,
59		int linelen) {
60
61	uint_t		id;
62	const char	*linep, *limit, *end;
63
64	linep = line;
65	limit = line + linelen;
66
67	if (keyhash)
68		return ((uint_t)argp->key.projid);
69
70	/* skip projname */
71	while (linep < limit && *linep++ != ':');
72	if (linep == limit)
73		return (0);
74
75	/* projid */
76	end = linep;
77	id = (uint_t)strtol(linep, (char **)&end, 10);
78	if (linep == end)
79		return (0);
80
81	return (id);
82}
83
84static files_hash_func hash_proj[2] = {
85	hash_projname,
86	hash_projid
87};
88
89static files_hash_t hashinfo = {
90	DEFAULTMUTEX,
91	sizeof (struct project),
92	NSS_BUFLEN_PROJECT,
93	2,
94	hash_proj
95};
96
97static int
98check_projid(nss_XbyY_args_t *argp, const char *line, int linelen) {
99	projid_t	projid;
100	const char	*linep, *limit, *end;
101
102	linep = line;
103	limit = line + linelen;
104
105	/* skip projname */
106	while (linep < limit && *linep++ != ':');
107
108	/* empty projname not allowed */
109	if (linep == limit || linep == line + 1)
110		return (0);
111
112	/* projid */
113	end = linep;
114	projid = (projid_t)strtol(linep, (char **)&end, 10);
115
116	/* empty projid is not valid */
117	if (linep == end)
118		return (0);
119
120	return (projid == argp->key.projid);
121}
122
123static nss_status_t
124getbyname(files_backend_ptr_t be, void *a) {
125	return (_nss_files_XY_hash(be, a, 0, &hashinfo, 0,
126			_nss_files_check_name_colon));
127}
128
129static nss_status_t
130getbyprojid(files_backend_ptr_t be, void *a) {
131	return (_nss_files_XY_hash(be, a, 0, &hashinfo, 1, check_projid));
132}
133
134static files_backend_op_t project_ops[] = {
135	_nss_files_destr,
136	_nss_files_endent,
137	_nss_files_setent,
138	_nss_files_getent_rigid,
139	getbyname,
140	getbyprojid
141};
142
143/*ARGSUSED*/
144nss_backend_t *
145_nss_files_project_constr(dummy1, dummy2, dummy3)
146	const char *dummy1, *dummy2, *dummy3;
147{
148	return (_nss_files_constr(project_ops,
149		    sizeof (project_ops) / sizeof (project_ops[0]),
150		    PROJF_PATH,
151		    NSS_LINELEN_PROJECT,
152		    &hashinfo));
153}
154