Improve performance of memmem
[glibc.git] / nss / nss_test1.c
blobd5b99641d5c4dd3363341012d0ef6405aa928cfd
1 /* Template generic NSS service provider. See nss_test.h for usage.
2 Copyright (C) 2017-2019 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 #include <errno.h>
20 #include <nss.h>
21 #include <pthread.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <alloc_buffer.h>
27 /* We need to be able to handle NULLs "properly" within the testsuite,
28 to test known bad data. */
29 #define alloc_buffer_maybe_copy_string(b,s) s ? alloc_buffer_copy_string (b, s) : NULL;
31 /* This file is the master template. Other instances of this test
32 module should define NAME(x) to have their name instead of "test1",
33 then include this file.
35 #define NAME_(x,n) _nss_##n##_##x
36 #ifndef NAME
37 #define NAME(x) NAME_(x,test1)
38 #endif
39 #define NAMESTR__(x) #x
40 #define NAMESTR_(x) NAMESTR__(x)
41 #define NAMESTR(x) NAMESTR_(NAME(x))
43 #include "nss_test.h"
45 /* -------------------------------------------------- */
46 /* Default Data. */
48 static struct passwd default_pwd_data[] =
50 #define PWD(u) \
51 { .pw_name = (char *) "name" #u, .pw_passwd = (char *) "*", .pw_uid = u, \
52 .pw_gid = 100, .pw_gecos = (char *) "*", .pw_dir = (char *) "*", \
53 .pw_shell = (char *) "*" }
54 PWD (30),
55 PWD (100),
56 PWD (200),
57 PWD (60),
58 PWD (20000)
60 #define default_npwd_data \
61 (sizeof (default_pwd_data) / sizeof (default_pwd_data[0]))
63 static struct passwd *pwd_data = default_pwd_data;
64 static int npwd_data = default_npwd_data;
66 static struct group *grp_data = NULL;
67 static int ngrp_data = 0;
69 /* This function will get called, and once per session, look back into
70 the test case's executable for an init hook function, and call
71 it. */
73 static int initted = 0;
74 static void
75 init(void)
77 test_tables t;
78 int i;
80 if (initted)
81 return;
82 if (NAME(init_hook))
84 memset (&t, 0, sizeof (t));
85 NAME(init_hook)(&t);
87 if (t.pwd_table)
89 pwd_data = t.pwd_table;
90 for (i=0; ! PWD_ISLAST(& pwd_data[i]); i++)
92 npwd_data = i;
95 if (t.grp_table)
97 grp_data = t.grp_table;
98 for (i=0; ! GRP_ISLAST(& grp_data[i]); i++)
100 ngrp_data = i;
103 initted = 1;
106 /* -------------------------------------------------- */
107 /* Password handling. */
109 static size_t pwd_iter;
110 #define CURPWD pwd_data[pwd_iter]
112 static pthread_mutex_t pwd_lock = PTHREAD_MUTEX_INITIALIZER;
114 enum nss_status
115 NAME(setpwent) (int stayopen)
117 init();
118 pwd_iter = 0;
119 return NSS_STATUS_SUCCESS;
123 enum nss_status
124 NAME(endpwent) (void)
126 init();
127 return NSS_STATUS_SUCCESS;
130 static enum nss_status
131 copy_passwd (struct passwd *result, struct passwd *local,
132 char *buffer, size_t buflen, int *errnop)
134 struct alloc_buffer buf = alloc_buffer_create (buffer, buflen);
136 result->pw_name = alloc_buffer_maybe_copy_string (&buf, local->pw_name);
137 result->pw_passwd = alloc_buffer_maybe_copy_string (&buf, local->pw_passwd);
138 result->pw_uid = local->pw_uid;
139 result->pw_gid = local->pw_gid;
140 result->pw_gecos = alloc_buffer_maybe_copy_string (&buf, local->pw_gecos);
141 result->pw_dir = alloc_buffer_maybe_copy_string (&buf, local->pw_dir);
142 result->pw_shell = alloc_buffer_maybe_copy_string (&buf, local->pw_shell);
144 if (alloc_buffer_has_failed (&buf))
146 *errnop = ERANGE;
147 return NSS_STATUS_TRYAGAIN;
150 return NSS_STATUS_SUCCESS;
153 enum nss_status
154 NAME(getpwent_r) (struct passwd *result, char *buffer, size_t buflen,
155 int *errnop)
157 int res = NSS_STATUS_SUCCESS;
159 init();
160 pthread_mutex_lock (&pwd_lock);
162 if (pwd_iter >= npwd_data)
163 res = NSS_STATUS_NOTFOUND;
164 else
166 res = copy_passwd (result, &CURPWD, buffer, buflen, errnop);
167 ++pwd_iter;
170 pthread_mutex_unlock (&pwd_lock);
172 return res;
176 enum nss_status
177 NAME(getpwuid_r) (uid_t uid, struct passwd *result, char *buffer,
178 size_t buflen, int *errnop)
180 init();
181 for (size_t idx = 0; idx < npwd_data; ++idx)
182 if (pwd_data[idx].pw_uid == uid)
183 return copy_passwd (result, &pwd_data[idx], buffer, buflen, errnop);
185 return NSS_STATUS_NOTFOUND;
189 enum nss_status
190 NAME(getpwnam_r) (const char *name, struct passwd *result, char *buffer,
191 size_t buflen, int *errnop)
193 init();
194 for (size_t idx = 0; idx < npwd_data; ++idx)
195 if (strcmp (pwd_data[idx].pw_name, name) == 0)
196 return copy_passwd (result, &pwd_data[idx], buffer, buflen, errnop);
198 return NSS_STATUS_NOTFOUND;
201 /* -------------------------------------------------- */
202 /* Group handling. */
204 static size_t grp_iter;
205 #define CURGRP grp_data[grp_iter]
207 static pthread_mutex_t grp_lock = PTHREAD_MUTEX_INITIALIZER;
209 enum nss_status
210 NAME(setgrent) (int stayopen)
212 init();
213 grp_iter = 0;
214 return NSS_STATUS_SUCCESS;
218 enum nss_status
219 NAME(endgrent) (void)
221 init();
222 return NSS_STATUS_SUCCESS;
225 static enum nss_status
226 copy_group (struct group *result, struct group *local,
227 char *buffer, size_t buflen, int *errnop)
229 struct alloc_buffer buf = alloc_buffer_create (buffer, buflen);
230 char **memlist;
231 int i;
233 if (local->gr_mem)
235 i = 0;
236 while (local->gr_mem[i])
237 ++i;
239 memlist = alloc_buffer_alloc_array (&buf, char *, i + 1);
241 if (memlist) {
242 for (i = 0; local->gr_mem[i]; ++i)
243 memlist[i] = alloc_buffer_maybe_copy_string (&buf, local->gr_mem[i]);
244 memlist[i] = NULL;
247 result->gr_mem = memlist;
249 else
250 result->gr_mem = NULL;
252 result->gr_name = alloc_buffer_maybe_copy_string (&buf, local->gr_name);
253 result->gr_passwd = alloc_buffer_maybe_copy_string (&buf, local->gr_passwd);
254 result->gr_gid = local->gr_gid;
256 if (alloc_buffer_has_failed (&buf))
258 *errnop = ERANGE;
259 return NSS_STATUS_TRYAGAIN;
262 return NSS_STATUS_SUCCESS;
266 enum nss_status
267 NAME(getgrent_r) (struct group *result, char *buffer, size_t buflen,
268 int *errnop)
270 int res = NSS_STATUS_SUCCESS;
272 init();
273 pthread_mutex_lock (&grp_lock);
275 if (grp_iter >= ngrp_data)
276 res = NSS_STATUS_NOTFOUND;
277 else
279 res = copy_group (result, &CURGRP, buffer, buflen, errnop);
280 ++grp_iter;
283 pthread_mutex_unlock (&pwd_lock);
285 return res;
289 enum nss_status
290 NAME(getgrgid_r) (gid_t gid, struct group *result, char *buffer,
291 size_t buflen, int *errnop)
293 init();
294 for (size_t idx = 0; idx < ngrp_data; ++idx)
295 if (grp_data[idx].gr_gid == gid)
296 return copy_group (result, &grp_data[idx], buffer, buflen, errnop);
298 return NSS_STATUS_NOTFOUND;
302 enum nss_status
303 NAME(getgrnam_r) (const char *name, struct group *result, char *buffer,
304 size_t buflen, int *errnop)
306 init();
307 for (size_t idx = 0; idx < ngrp_data; ++idx)
308 if (strcmp (pwd_data[idx].pw_name, name) == 0)
310 return copy_group (result, &grp_data[idx], buffer, buflen, errnop);
313 return NSS_STATUS_NOTFOUND;