1
/* Common code for file-based databases in nss_files module.
2
Copyright (C) 1996-2014 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/>. */
23
#include <bits/libc-lock.h>
26
#include <kernel-features.h>
28
/* These symbols are defined by the including source file:
30
ENTNAME -- database name of the structure and functions (hostent, pwent).
31
STRUCTURE -- struct name, define only if not ENTNAME (passwd, group).
32
DATABASE -- string of the database file's name ("hosts", "passwd").
34
NEED_H_ERRNO - defined iff an arg `int *herrnop' is used.
36
Also see files-parse.c.
39
#define ENTNAME_r CONCAT(ENTNAME,_r)
41
#define DATAFILE "/etc/" DATABASE
45
# define H_ERRNO_PROTO , int *herrnop
46
# define H_ERRNO_ARG , herrnop
47
# define H_ERRNO_SET(val) (*herrnop = (val))
49
# define H_ERRNO_PROTO
51
# define H_ERRNO_SET(val) ((void) 0)
56
# define EXTRA_ARGS_DECL
57
# define EXTRA_ARGS_VALUE
60
/* Locks the static variables in this file. */
61
__libc_lock_define_initialized (static, lock)
63
/* Maintenance of the stream open on the database file. For getXXent
64
operations the stream needs to be held open across calls, the other
65
getXXbyYY operations all use their own stream. */
69
/* Open database file if not already opened. */
70
static enum nss_status
71
internal_setent (FILE **stream)
73
enum nss_status status = NSS_STATUS_SUCCESS;
77
*stream = fopen (DATAFILE, "rce");
80
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
83
#if !defined O_CLOEXEC || !defined __ASSUME_O_CLOEXEC
85
if (__have_o_cloexec <= 0)
88
/* We have to make sure the file is `closed on exec'. */
92
result = flags = fcntl (fileno (*stream), F_GETFD, 0);
96
if (__have_o_cloexec == 0)
97
__have_o_cloexec = (flags & FD_CLOEXEC) == 0 ? -1 : 1;
98
if (__have_o_cloexec < 0)
102
result = fcntl (fileno (*stream), F_SETFD, flags);
107
/* Something went wrong. Close the stream and return a
111
status = NSS_STATUS_UNAVAIL;
124
/* Thread-safe, exported version of that. */
126
CONCAT(_nss_files_set,ENTNAME) (int stayopen)
128
enum nss_status status;
130
__libc_lock_lock (lock);
132
status = internal_setent (&stream);
134
__libc_lock_unlock (lock);
140
/* Close the database file. */
142
internal_endent (FILE **stream)
152
/* Thread-safe, exported version of that. */
154
CONCAT(_nss_files_end,ENTNAME) (void)
156
__libc_lock_lock (lock);
158
internal_endent (&stream);
160
__libc_lock_unlock (lock);
162
return NSS_STATUS_SUCCESS;
173
/* Hack around the fact that fgets only accepts int sizes. */
174
static get_contents_ret
175
get_contents (char *linebuf, size_t len, FILE *stream)
177
size_t remaining_len = len;
178
char *curbuf = linebuf;
182
int curlen = ((remaining_len > (size_t) INT_MAX) ? INT_MAX
184
char *p = fgets_unlocked (curbuf, curlen, stream);
186
((unsigned char *) curbuf)[curlen - 1] = 0xff;
188
/* EOF or read error. */
192
/* Done reading in the line. */
193
if (((unsigned char *) curbuf)[curlen - 1] == 0xff)
196
/* Drop the terminating '\0'. */
197
remaining_len -= curlen - 1;
198
curbuf += curlen - 1;
200
/* fgets copies one less than the input length. Our last iteration is of
201
REMAINING_LEN and once that is done, REMAINING_LEN is decremented by
202
REMAINING_LEN - 1, leaving the result as 1. */
203
while (remaining_len > 1);
205
/* This means that the current buffer was not large enough. */
209
/* Parsing the database file into `struct STRUCTURE' data structures. */
210
static enum nss_status
211
internal_getent (FILE *stream, struct STRUCTURE *result,
212
char *buffer, size_t buflen, int *errnop H_ERRNO_PROTO
216
struct parser_data *data = (void *) buffer;
217
size_t linebuflen = buffer + buflen - data->linebuffer;
220
if (buflen < sizeof *data + 2)
223
H_ERRNO_SET (NETDB_INTERNAL);
224
return NSS_STATUS_TRYAGAIN;
229
get_contents_ret r = get_contents (data->linebuffer, linebuflen, stream);
233
/* End of file or read error. */
234
H_ERRNO_SET (HOST_NOT_FOUND);
235
return NSS_STATUS_NOTFOUND;
238
if (r == gcr_overflow)
240
/* The line is too long. Give the user the opportunity to
241
enlarge the buffer. */
243
H_ERRNO_SET (NETDB_INTERNAL);
244
return NSS_STATUS_TRYAGAIN;
247
/* Everything OK. Now skip leading blanks. */
248
p = data->linebuffer;
252
while (*p == '\0' || *p == '#' /* Ignore empty and comment lines. */
253
/* Parse the line. If it is invalid, loop to get the next
254
line of the file to parse. */
255
|| ! (parse_result = parse_line (p, result, data, buflen, errnop
258
if (__builtin_expect (parse_result == -1, 0))
260
H_ERRNO_SET (NETDB_INTERNAL);
261
return NSS_STATUS_TRYAGAIN;
264
/* Filled in RESULT with the next entry from the database file. */
265
return NSS_STATUS_SUCCESS;
269
/* Return the next entry from the database file, doing locking. */
271
CONCAT(_nss_files_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer,
272
size_t buflen, int *errnop H_ERRNO_PROTO)
274
/* Return next entry in host file. */
275
enum nss_status status = NSS_STATUS_SUCCESS;
277
__libc_lock_lock (lock);
279
/* Be prepared that the set*ent function was not called before. */
282
int save_errno = errno;
284
status = internal_setent (&stream);
286
__set_errno (save_errno);
289
if (status == NSS_STATUS_SUCCESS)
290
status = internal_getent (stream, result, buffer, buflen, errnop
291
H_ERRNO_ARG EXTRA_ARGS_VALUE);
293
__libc_lock_unlock (lock);
298
/* Macro for defining lookup functions for this file-based database.
300
NAME is the name of the lookup; e.g. `hostbyname'.
302
DB_CHAR, KEYPATTERN, KEYSIZE are ignored here but used by db-XXX.c
303
e.g. `1 + sizeof (id) * 4'.
305
PROTO is the potentially empty list of other parameters.
307
BREAK_IF_MATCH is a block of code which compares `struct STRUCTURE *result'
308
to the lookup key arguments and does `break;' if they match. */
310
#define DB_LOOKUP(name, db_char, keysize, keypattern, break_if_match, proto...)\
312
_nss_files_get##name##_r (proto, \
313
struct STRUCTURE *result, char *buffer, \
314
size_t buflen, int *errnop H_ERRNO_PROTO) \
316
enum nss_status status; \
317
FILE *stream = NULL; \
320
status = internal_setent (&stream); \
322
if (status == NSS_STATUS_SUCCESS) \
324
while ((status = internal_getent (stream, result, buffer, buflen, errnop \
325
H_ERRNO_ARG EXTRA_ARGS_VALUE)) \
326
== NSS_STATUS_SUCCESS) \
329
internal_endent (&stream); \