]> git.ipfire.org Git - thirdparty/glibc.git/blame - nscd/grpcache.c
Update.
[thirdparty/glibc.git] / nscd / grpcache.c
CommitLineData
67479a70 1/* Cache handling for group lookup.
5512461f 2 Copyright (C) 1998, 1999 Free Software Foundation, Inc.
d67281a7 3 This file is part of the GNU C Library.
67479a70 4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
d67281a7
UD
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
67479a70 19 Boston, MA 02111-1307, USA. */
d67281a7
UD
20
21#include <errno.h>
67479a70 22#include <error.h>
d67281a7 23#include <grp.h>
67479a70
UD
24#include <stddef.h>
25#include <stdio.h>
da2d1bc5 26#include <stdlib.h>
d67281a7 27#include <string.h>
ba9234d9 28#include <unistd.h>
d67281a7 29
d67281a7 30#include "nscd.h"
67479a70 31#include "dbg_log.h"
d67281a7 32
67479a70
UD
33/* This is the standard reply in case the service is disabled. */
34static const gr_response_header disabled =
d67281a7 35{
67479a70
UD
36 version: NSCD_VERSION,
37 found: -1,
38 gr_name_len: 0,
39 gr_passwd_len: 0,
40 gr_gid: -1,
41 gr_mem_cnt: 0,
d67281a7 42};
d67281a7 43
67479a70
UD
44/* This is the struct describing how to write this record. */
45const struct iovec grp_iov_disabled =
d67281a7 46{
67479a70
UD
47 iov_base: (void *) &disabled,
48 iov_len: sizeof (disabled)
d67281a7 49};
d67281a7 50
67479a70
UD
51
52/* This is the standard reply in case we haven't found the dataset. */
53static const gr_response_header notfound =
d67281a7 54{
67479a70
UD
55 version: NSCD_VERSION,
56 found: 0,
57 gr_name_len: 0,
58 gr_passwd_len: 0,
59 gr_gid: -1,
60 gr_mem_cnt: 0,
d67281a7 61};
d67281a7 62
67479a70
UD
63/* This is the struct describing how to write this record. */
64static const struct iovec iov_notfound =
d67281a7 65{
67479a70
UD
66 iov_base: (void *) &notfound,
67 iov_len: sizeof (notfound)
68};
d67281a7 69
d67281a7 70
67479a70 71struct groupdata
d67281a7 72{
67479a70
UD
73 gr_response_header resp;
74 char strdata[0];
75};
d67281a7 76
d67281a7 77
67479a70
UD
78static void
79cache_addgr (struct database *db, int fd, request_header *req, void *key,
80 struct group *grp)
d67281a7 81{
67479a70
UD
82 ssize_t total;
83 ssize_t written;
84 time_t t = time (NULL);
d67281a7 85
67479a70 86 if (grp == NULL)
d67281a7 87 {
67479a70
UD
88 /* We have no data. This means we send the standard reply for this
89 case. */
90 void *copy;
d67281a7 91
67479a70 92 total = sizeof (notfound);
d67281a7 93
67479a70 94 written = writev (fd, &iov_notfound, 1);
d67281a7 95
67479a70
UD
96 copy = malloc (req->key_len);
97 if (copy == NULL)
98 error (EXIT_FAILURE, errno, _("while allocating key copy"));
99 memcpy (copy, key, req->key_len);
d67281a7 100
67479a70
UD
101 /* Compute the timeout time. */
102 t += db->negtimeout;
14e9dd67 103
67479a70
UD
104 /* Now get the lock to safely insert the records. */
105 pthread_rwlock_rdlock (&db->lock);
d67281a7 106
67479a70
UD
107 cache_add (req->type, copy, req->key_len, &iov_notfound,
108 sizeof (notfound), (void *) -1, 0, t, db);
d67281a7 109
67479a70 110 pthread_rwlock_unlock (&db->lock);
d67281a7 111 }
ba9234d9
UD
112 else
113 {
67479a70
UD
114 /* Determine the I/O structure. */
115 struct groupdata *data;
116 size_t gr_name_len = strlen (grp->gr_name) + 1;
117 size_t gr_passwd_len = strlen (grp->gr_passwd) + 1;
118 size_t gr_mem_cnt = 0;
119 size_t *gr_mem_len;
120 size_t gr_mem_len_total = 0;
121 char *gr_name;
122 char *cp;
123 char buf[12];
124 ssize_t n;
125 size_t cnt;
126
127 /* We need this to insert the `bygid' entry. */
128 n = snprintf (buf, sizeof (buf), "%d", grp->gr_gid) + 1;
129
130 /* Determine the length of all members. */
131 while (grp->gr_mem[gr_mem_cnt])
132 ++gr_mem_cnt;
133 gr_mem_len = (size_t *) alloca (gr_mem_cnt * sizeof (size_t));
134 for (gr_mem_cnt = 0; grp->gr_mem[gr_mem_cnt]; ++gr_mem_cnt)
135 {
136 gr_mem_len[gr_mem_cnt] = strlen (grp->gr_mem[gr_mem_cnt]) + 1;
137 gr_mem_len_total += gr_mem_len[gr_mem_cnt];
138 }
ba9234d9 139
67479a70
UD
140 /* We allocate all data in one memory block: the iov vector,
141 the response header and the dataset itself. */
142 total = (sizeof (struct groupdata)
143 + gr_mem_cnt * sizeof (size_t)
144 + gr_name_len + gr_passwd_len + gr_mem_len_total);
145 data = (struct groupdata *) malloc (total + n);
146 if (data == NULL)
147 /* There is no reason to go on. */
148 error (EXIT_FAILURE, errno, _("while allocating cache entry"));
d67281a7 149
67479a70
UD
150 data->resp.found = 1;
151 data->resp.gr_name_len = gr_name_len;
152 data->resp.gr_passwd_len = gr_passwd_len;
153 data->resp.gr_gid = grp->gr_gid;
154 data->resp.gr_mem_cnt = gr_mem_cnt;
d67281a7 155
67479a70 156 cp = data->strdata;
d67281a7 157
67479a70
UD
158 /* This is the member string length array. */
159 cp = mempcpy (cp, gr_mem_len, gr_mem_cnt * sizeof (size_t));
160 gr_name = cp = mempcpy (cp, grp->gr_name, gr_name_len);
161 cp = mempcpy (cp, grp->gr_passwd, gr_passwd_len);
d67281a7 162
67479a70
UD
163 for (cnt = 0; cnt < gr_mem_cnt; ++cnt)
164 cp = mempcpy (cp, grp->gr_mem[cnt], gr_mem_len[cnt]);
d67281a7 165
67479a70
UD
166 /* Finally the stringified GID value. */
167 memcpy (cp, buf, n);
d67281a7 168
67479a70
UD
169 /* Write the result. */
170 written = write (fd, &data->resp, total);
d67281a7 171
67479a70
UD
172 /* Compute the timeout time. */
173 t += db->postimeout;
d67281a7 174
67479a70
UD
175 /* Now get the lock to safely insert the records. */
176 pthread_rwlock_rdlock (&db->lock);
14e9dd67 177
67479a70
UD
178 /* We have to add the value for both, byname and byuid. */
179 cache_add (GETGRBYNAME, gr_name, gr_name_len, data,
180 total, data, 0, t, db);
d67281a7 181
67479a70 182 cache_add (GETGRBYGID, cp, n, data, total, data, 1, t, db);
d67281a7 183
67479a70 184 pthread_rwlock_unlock (&db->lock);
d67281a7
UD
185 }
186
67479a70 187 if (written != total)
d67281a7 188 {
67479a70
UD
189 char buf[256];
190 dbg_log (_("short write in %s: %s"), __FUNCTION__,
191 strerror_r (errno, buf, sizeof (buf)));
d67281a7 192 }
d67281a7
UD
193}
194
d67281a7 195
67479a70
UD
196void
197addgrbyname (struct database *db, int fd, request_header *req, void *key)
198{
199 /* Search for the entry matching the key. Please note that we don't
200 look again in the table whether the dataset is now available. We
201 simply insert it. It does not matter if it is in there twice. The
202 pruning function only will look at the timestamp. */
203 int buflen = 256;
204 char *buffer = alloca (buflen);
205 struct group resultbuf;
206 struct group *grp;
d67281a7 207
67479a70
UD
208 if (debug_level > 0)
209 dbg_log (_("Haven't found \"%s\" in group cache!"), key);
d67281a7 210
67479a70
UD
211 while (getgrnam_r (key, &resultbuf, buffer, buflen, &grp) != 0
212 && errno == ERANGE)
d67281a7 213 {
67479a70
UD
214 errno = 0;
215 buflen += 256;
216 buffer = alloca (buflen);
d67281a7 217 }
d67281a7 218
67479a70 219 cache_addgr (db, fd, req, key, grp);
d67281a7
UD
220}
221
d67281a7 222
67479a70
UD
223void
224addgrbygid (struct database *db, int fd, request_header *req, void *key)
225{
226 /* Search for the entry matching the key. Please note that we don't
227 look again in the table whether the dataset is now available. We
228 simply insert it. It does not matter if it is in there twice. The
229 pruning function only will look at the timestamp. */
230 int buflen = 256;
231 char *buffer = alloca (buflen);
232 struct group resultbuf;
233 struct group *grp;
234 gid_t gid = atol (key);
d67281a7 235
67479a70
UD
236 if (debug_level > 0)
237 dbg_log (_("Haven't found \"%d\" in group cache!"), gid);
d67281a7 238
67479a70
UD
239 while (getgrgid_r (gid, &resultbuf, buffer, buflen, &grp) != 0
240 && errno == ERANGE)
d67281a7 241 {
67479a70
UD
242 errno = 0;
243 buflen += 256;
244 buffer = alloca (buflen);
d67281a7 245 }
d67281a7 246
67479a70 247 cache_addgr (db, fd, req, key, grp);
d67281a7 248}