Updated to fedora-glibc-20080612T1619
[glibc.git] / nscd / nscd_helper.c
blob9828a46df03cf7a5764039955d208cb021d26cb6
1 /* Copyright (C) 1998-2007, 2008 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
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, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
20 #include <assert.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <stdbool.h>
24 #include <string.h>
25 #include <time.h>
26 #include <unistd.h>
27 #include <sys/mman.h>
28 #include <sys/poll.h>
29 #include <sys/socket.h>
30 #include <sys/stat.h>
31 #include <sys/time.h>
32 #include <sys/uio.h>
33 #include <sys/un.h>
34 #include <not-cancel.h>
35 #include <nis/rpcsvc/nis.h>
37 #include "nscd-client.h"
40 /* Extra time we wait if the socket is still receiving data. This
41 value is in milliseconds. Note that the other side is nscd on the
42 local machine and it is already transmitting data. So the wait
43 time need not be long. */
44 #define EXTRA_RECEIVE_TIME 200
47 static int
48 wait_on_socket (int sock, long int usectmo)
50 struct pollfd fds[1];
51 fds[0].fd = sock;
52 fds[0].events = POLLIN | POLLERR | POLLHUP;
53 int n = __poll (fds, 1, usectmo);
54 if (n == -1 && __builtin_expect (errno == EINTR, 0))
56 /* Handle the case where the poll() call is interrupted by a
57 signal. We cannot just use TEMP_FAILURE_RETRY since it might
58 lead to infinite loops. */
59 struct timeval now;
60 (void) __gettimeofday (&now, NULL);
61 long int end = now.tv_sec * 1000 + usectmo + (now.tv_usec + 500) / 1000;
62 long int timeout = usectmo;
63 while (1)
65 n = __poll (fds, 1, timeout);
66 if (n != -1 || errno != EINTR)
67 break;
69 /* Recompute the timeout time. */
70 (void) __gettimeofday (&now, NULL);
71 timeout = end - (now.tv_sec * 1000 + (now.tv_usec + 500) / 1000);
75 return n;
79 ssize_t
80 __readall (int fd, void *buf, size_t len)
82 size_t n = len;
83 ssize_t ret;
86 again:
87 ret = TEMP_FAILURE_RETRY (__read (fd, buf, n));
88 if (ret <= 0)
90 if (__builtin_expect (ret < 0 && errno == EAGAIN, 0)
91 /* The socket is still receiving data. Wait a bit more. */
92 && wait_on_socket (fd, EXTRA_RECEIVE_TIME) > 0)
93 goto again;
95 break;
97 buf = (char *) buf + ret;
98 n -= ret;
100 while (n > 0);
101 return ret < 0 ? ret : len - n;
105 ssize_t
106 __readvall (int fd, const struct iovec *iov, int iovcnt)
108 ssize_t ret = TEMP_FAILURE_RETRY (__readv (fd, iov, iovcnt));
109 if (ret <= 0)
111 if (__builtin_expect (ret == 0 || errno != EAGAIN, 1))
112 /* A genuine error or no data to read. */
113 return ret;
115 /* The data has not all yet been received. Do as if we have not
116 read anything yet. */
117 ret = 0;
120 size_t total = 0;
121 for (int i = 0; i < iovcnt; ++i)
122 total += iov[i].iov_len;
124 if (ret < total)
126 struct iovec iov_buf[iovcnt];
127 ssize_t r = ret;
129 struct iovec *iovp = memcpy (iov_buf, iov, iovcnt * sizeof (*iov));
132 while (iovp->iov_len <= r)
134 r -= iovp->iov_len;
135 --iovcnt;
136 ++iovp;
138 iovp->iov_base = (char *) iovp->iov_base + r;
139 iovp->iov_len -= r;
140 again:
141 r = TEMP_FAILURE_RETRY (__readv (fd, iovp, iovcnt));
142 if (r <= 0)
144 if (__builtin_expect (r < 0 && errno == EAGAIN, 0)
145 /* The socket is still receiving data. Wait a bit more. */
146 && wait_on_socket (fd, EXTRA_RECEIVE_TIME) > 0)
147 goto again;
149 break;
151 ret += r;
153 while (ret < total);
154 if (r < 0)
155 ret = r;
157 return ret;
161 static int
162 open_socket (request_type type, const char *key, size_t keylen)
164 int sock = __socket (PF_UNIX, SOCK_STREAM, 0);
165 if (sock < 0)
166 return -1;
168 struct
170 request_header req;
171 char key[keylen];
172 } reqdata;
173 size_t real_sizeof_reqdata = sizeof (request_header) + keylen;
175 /* Make socket non-blocking. */
176 __fcntl (sock, F_SETFL, O_RDWR | O_NONBLOCK);
178 struct sockaddr_un sun;
179 sun.sun_family = AF_UNIX;
180 strcpy (sun.sun_path, _PATH_NSCDSOCKET);
181 if (__connect (sock, (struct sockaddr *) &sun, sizeof (sun)) < 0
182 && errno != EINPROGRESS)
183 goto out;
185 reqdata.req.version = NSCD_VERSION;
186 reqdata.req.type = type;
187 reqdata.req.key_len = keylen;
189 memcpy (reqdata.key, key, keylen);
191 bool first_try = true;
192 struct timeval tvend;
193 /* Fake initializing tvend. */
194 asm ("" : "=m" (tvend));
195 while (1)
197 #ifndef MSG_NOSIGNAL
198 # define MSG_NOSIGNAL 0
199 #endif
200 ssize_t wres = TEMP_FAILURE_RETRY (__send (sock, &reqdata,
201 real_sizeof_reqdata,
202 MSG_NOSIGNAL));
203 if (__builtin_expect (wres == (ssize_t) real_sizeof_reqdata, 1))
204 /* We managed to send the request. */
205 return sock;
207 if (wres != -1 || errno != EAGAIN)
208 /* Something is really wrong, no chance to continue. */
209 break;
211 /* The daemon is busy wait for it. */
212 int to;
213 struct timeval now;
214 (void) __gettimeofday (&now, NULL);
215 if (first_try)
217 tvend.tv_usec = now.tv_usec;
218 tvend.tv_sec = now.tv_sec + 5;
219 to = 5 * 1000;
220 first_try = false;
222 else
223 to = ((tvend.tv_sec - now.tv_sec) * 1000
224 + (tvend.tv_usec - now.tv_usec) / 1000);
226 struct pollfd fds[1];
227 fds[0].fd = sock;
228 fds[0].events = POLLOUT | POLLERR | POLLHUP;
229 if (__poll (fds, 1, to) <= 0)
230 /* The connection timed out or broke down. */
231 break;
233 /* We try to write again. */
236 out:
237 close_not_cancel_no_status (sock);
239 return -1;
243 void
244 __nscd_unmap (struct mapped_database *mapped)
246 assert (mapped->counter == 0);
247 __munmap ((void *) mapped->head, mapped->mapsize);
248 free (mapped);
252 /* Try to get a file descriptor for the shared meory segment
253 containing the database. */
254 static struct mapped_database *
255 get_mapping (request_type type, const char *key,
256 struct mapped_database **mappedp)
258 struct mapped_database *result = NO_MAPPING;
259 #ifdef SCM_RIGHTS
260 const size_t keylen = strlen (key) + 1;
261 int saved_errno = errno;
263 int mapfd = -1;
264 char resdata[keylen];
266 /* Open a socket and send the request. */
267 int sock = open_socket (type, key, keylen);
268 if (sock < 0)
269 goto out;
271 /* Room for the data sent along with the file descriptor. We expect
272 the key name back. */
273 uint64_t mapsize;
274 struct iovec iov[2];
275 iov[0].iov_base = resdata;
276 iov[0].iov_len = keylen;
277 iov[1].iov_base = &mapsize;
278 iov[1].iov_len = sizeof (mapsize);
280 union
282 struct cmsghdr hdr;
283 char bytes[CMSG_SPACE (sizeof (int))];
284 } buf;
285 struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 2,
286 .msg_control = buf.bytes,
287 .msg_controllen = sizeof (buf) };
288 struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
290 cmsg->cmsg_level = SOL_SOCKET;
291 cmsg->cmsg_type = SCM_RIGHTS;
292 cmsg->cmsg_len = CMSG_LEN (sizeof (int));
294 /* This access is well-aligned since BUF is correctly aligned for an
295 int and CMSG_DATA preserves this alignment. */
296 *(int *) CMSG_DATA (cmsg) = -1;
298 msg.msg_controllen = cmsg->cmsg_len;
300 if (wait_on_socket (sock, 5 * 1000) <= 0)
301 goto out_close2;
303 # ifndef MSG_CMSG_CLOEXEC
304 # define MSG_CMSG_CLOEXEC 0
305 # endif
306 ssize_t n = TEMP_FAILURE_RETRY (__recvmsg (sock, &msg, MSG_CMSG_CLOEXEC));
308 if (__builtin_expect (CMSG_FIRSTHDR (&msg) == NULL
309 || (CMSG_FIRSTHDR (&msg)->cmsg_len
310 != CMSG_LEN (sizeof (int))), 0))
311 goto out_close2;
313 mapfd = *(int *) CMSG_DATA (cmsg);
315 if (__builtin_expect (n != keylen && n != keylen + sizeof (mapsize), 0))
316 goto out_close;
318 if (__builtin_expect (strcmp (resdata, key) != 0, 0))
319 goto out_close;
321 if (__builtin_expect (n == keylen, 0))
323 struct stat64 st;
324 if (__builtin_expect (fstat64 (mapfd, &st) != 0, 0)
325 || __builtin_expect (st.st_size < sizeof (struct database_pers_head),
327 goto out_close;
329 mapsize = st.st_size;
332 /* The file is large enough, map it now. */
333 void *mapping = __mmap (NULL, mapsize, PROT_READ, MAP_SHARED, mapfd, 0);
334 if (__builtin_expect (mapping != MAP_FAILED, 1))
336 /* Check whether the database is correct and up-to-date. */
337 struct database_pers_head *head = mapping;
339 if (__builtin_expect (head->version != DB_VERSION, 0)
340 || __builtin_expect (head->header_size != sizeof (*head), 0)
341 /* Catch some misconfiguration. The server should catch
342 them now but some older versions did not. */
343 || __builtin_expect (head->module == 0, 0)
344 /* This really should not happen but who knows, maybe the update
345 thread got stuck. */
346 || __builtin_expect (! head->nscd_certainly_running
347 && (head->timestamp + MAPPING_TIMEOUT
348 < time (NULL)), 0))
350 out_unmap:
351 __munmap (mapping, mapsize);
352 goto out_close;
355 size_t size = (sizeof (*head) + roundup (head->module * sizeof (ref_t),
356 ALIGN)
357 + head->data_size);
359 if (__builtin_expect (mapsize < size, 0))
360 goto out_unmap;
362 /* Allocate a record for the mapping. */
363 struct mapped_database *newp = malloc (sizeof (*newp));
364 if (newp == NULL)
365 /* Ugh, after all we went through the memory allocation failed. */
366 goto out_unmap;
368 newp->head = mapping;
369 newp->data = ((char *) mapping + head->header_size
370 + roundup (head->module * sizeof (ref_t), ALIGN));
371 newp->mapsize = size;
372 newp->datasize = head->data_size;
373 /* Set counter to 1 to show it is usable. */
374 newp->counter = 1;
376 result = newp;
379 out_close:
380 __close (mapfd);
381 out_close2:
382 __close (sock);
383 out:
384 __set_errno (saved_errno);
385 #endif /* SCM_RIGHTS */
387 struct mapped_database *oldval = *mappedp;
388 *mappedp = result;
390 if (oldval != NULL && atomic_decrement_val (&oldval->counter) == 0)
391 __nscd_unmap (oldval);
393 return result;
397 struct mapped_database *
398 __nscd_get_map_ref (request_type type, const char *name,
399 volatile struct locked_map_ptr *mapptr, int *gc_cyclep)
401 struct mapped_database *cur = mapptr->mapped;
402 if (cur == NO_MAPPING)
403 return cur;
405 int cnt = 0;
406 while (__builtin_expect (atomic_compare_and_exchange_val_acq (&mapptr->lock,
407 1, 0) != 0, 0))
409 // XXX Best number of rounds?
410 if (__builtin_expect (++cnt > 5, 0))
411 return NO_MAPPING;
413 atomic_delay ();
416 cur = mapptr->mapped;
418 if (__builtin_expect (cur != NO_MAPPING, 1))
420 /* If not mapped or timestamp not updated, request new map. */
421 if (cur == NULL
422 || (cur->head->nscd_certainly_running == 0
423 && cur->head->timestamp + MAPPING_TIMEOUT < time (NULL))
424 || cur->head->data_size > cur->datasize)
425 cur = get_mapping (type, name,
426 (struct mapped_database **) &mapptr->mapped);
428 if (__builtin_expect (cur != NO_MAPPING, 1))
430 if (__builtin_expect (((*gc_cyclep = cur->head->gc_cycle) & 1) != 0,
432 cur = NO_MAPPING;
433 else
434 atomic_increment (&cur->counter);
438 mapptr->lock = 0;
440 return cur;
444 /* Don't return const struct datahead *, as eventhough the record
445 is normally constant, it can change arbitrarily during nscd
446 garbage collection. */
447 struct datahead *
448 __nscd_cache_search (request_type type, const char *key, size_t keylen,
449 const struct mapped_database *mapped)
451 unsigned long int hash = __nis_hash (key, keylen) % mapped->head->module;
452 size_t datasize = mapped->datasize;
454 ref_t trail = mapped->head->array[hash];
455 ref_t work = trail;
456 int tick = 0;
458 while (work != ENDREF && work + sizeof (struct hashentry) <= datasize)
460 struct hashentry *here = (struct hashentry *) (mapped->data + work);
462 #ifndef _STRING_ARCH_unaligned
463 /* Although during garbage collection when moving struct hashentry
464 records around we first copy from old to new location and then
465 adjust pointer from previous hashentry to it, there is no barrier
466 between those memory writes. It is very unlikely to hit it,
467 so check alignment only if a misaligned load can crash the
468 application. */
469 if ((uintptr_t) here & (__alignof__ (*here) - 1))
470 return NULL;
471 #endif
473 if (type == here->type
474 && keylen == here->len
475 && here->key + keylen <= datasize
476 && memcmp (key, mapped->data + here->key, keylen) == 0
477 && here->packet + sizeof (struct datahead) <= datasize)
479 /* We found the entry. Increment the appropriate counter. */
480 struct datahead *dh
481 = (struct datahead *) (mapped->data + here->packet);
483 #ifndef _STRING_ARCH_unaligned
484 if ((uintptr_t) dh & (__alignof__ (*dh) - 1))
485 return NULL;
486 #endif
488 /* See whether we must ignore the entry or whether something
489 is wrong because garbage collection is in progress. */
490 if (dh->usable && here->packet + dh->allocsize <= datasize)
491 return dh;
494 work = here->next;
495 /* Prevent endless loops. This should never happen but perhaps
496 the database got corrupted, accidentally or deliberately. */
497 if (work == trail)
498 break;
499 if (tick)
501 struct hashentry *trailelem;
502 trailelem = (struct hashentry *) (mapped->data + trail);
504 #ifndef _STRING_ARCH_unaligned
505 /* We have to redo the checks. Maybe the data changed. */
506 if ((uintptr_t) trailelem & (__alignof__ (*trailelem) - 1))
507 return NULL;
508 #endif
509 trail = trailelem->next;
511 tick = 1 - tick;
514 return NULL;
518 /* Create a socket connected to a name. */
520 __nscd_open_socket (const char *key, size_t keylen, request_type type,
521 void *response, size_t responselen)
523 /* This should never happen and it is something the nscd daemon
524 enforces, too. He it helps to limit the amount of stack
525 used. */
526 if (keylen > MAXKEYLEN)
527 return -1;
529 int saved_errno = errno;
531 int sock = open_socket (type, key, keylen);
532 if (sock >= 0)
534 /* Wait for data. */
535 if (wait_on_socket (sock, 5 * 1000) > 0)
537 ssize_t nbytes = TEMP_FAILURE_RETRY (__read (sock, response,
538 responselen));
539 if (nbytes == (ssize_t) responselen)
540 return sock;
543 close_not_cancel_no_status (sock);
546 __set_errno (saved_errno);
548 return -1;