]> git.ipfire.org Git - thirdparty/glibc.git/blame - nss/nss_files/files-XXX.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / nss / nss_files / files-XXX.c
CommitLineData
5f0e6fc7 1/* Common code for file-based databases in nss_files module.
d614a753 2 Copyright (C) 1996-2020 Free Software Foundation, Inc.
2303f5fd 3 This file is part of the GNU C Library.
5f0e6fc7 4
2303f5fd 5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
5f0e6fc7 9
2303f5fd
UD
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
41bdb6e2 13 Lesser General Public License for more details.
5f0e6fc7 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
5f0e6fc7
RM
18
19#include <stdio.h>
20#include <ctype.h>
26761c28 21#include <errno.h>
3996f34b 22#include <fcntl.h>
ec999b8e 23#include <libc-lock.h>
5f0e6fc7
RM
24#include "nsswitch.h"
25
aa132749
UD
26#include <kernel-features.h>
27
5f0e6fc7
RM
28/* These symbols are defined by the including source file:
29
30 ENTNAME -- database name of the structure and functions (hostent, pwent).
31 STRUCTURE -- struct name, define only if not ENTNAME (passwd, group).
96bda0ea 32 DATABASE -- string of the database file's name ("hosts", "passwd").
5f0e6fc7
RM
33
34 NEED_H_ERRNO - defined iff an arg `int *herrnop' is used.
adc6ff7f
RM
35
36 Also see files-parse.c.
5f0e6fc7
RM
37*/
38
96bda0ea
RM
39#define ENTNAME_r CONCAT(ENTNAME,_r)
40
41#define DATAFILE "/etc/" DATABASE
5f0e6fc7
RM
42
43#ifdef NEED_H_ERRNO
47707456 44# include <netdb.h>
26761c28
UD
45# define H_ERRNO_PROTO , int *herrnop
46# define H_ERRNO_ARG , herrnop
47# define H_ERRNO_SET(val) (*herrnop = (val))
5f0e6fc7 48#else
26761c28
UD
49# define H_ERRNO_PROTO
50# define H_ERRNO_ARG
51# define H_ERRNO_SET(val) ((void) 0)
5f0e6fc7
RM
52#endif
53
71d3bda9
UD
54#ifndef EXTRA_ARGS
55# define EXTRA_ARGS
56# define EXTRA_ARGS_DECL
57# define EXTRA_ARGS_VALUE
58#endif
59
5f0e6fc7 60/* Locks the static variables in this file. */
1e16111c 61__libc_lock_define_initialized (static, lock)
5f0e6fc7 62\f
b13b96ca
AS
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. */
5f0e6fc7
RM
66
67static FILE *stream;
5f0e6fc7
RM
68
69/* Open database file if not already opened. */
26761c28 70static enum nss_status
b13b96ca 71internal_setent (FILE **stream)
5f0e6fc7 72{
26761c28 73 enum nss_status status = NSS_STATUS_SUCCESS;
5f0e6fc7 74
b13b96ca 75 if (*stream == NULL)
5f0e6fc7 76 {
b13b96ca 77 *stream = fopen (DATAFILE, "rce");
5f0e6fc7 78
b13b96ca 79 if (*stream == NULL)
0413b54c 80 status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
5f0e6fc7
RM
81 }
82 else
b13b96ca 83 rewind (*stream);
5f0e6fc7
RM
84
85 return status;
86}
87
88
89/* Thread-safe, exported version of that. */
26761c28 90enum nss_status
5f0e6fc7
RM
91CONCAT(_nss_files_set,ENTNAME) (int stayopen)
92{
26761c28 93 enum nss_status status;
5f0e6fc7
RM
94
95 __libc_lock_lock (lock);
96
b13b96ca 97 status = internal_setent (&stream);
2303f5fd 98
5f0e6fc7
RM
99 __libc_lock_unlock (lock);
100
101 return status;
102}
103
104
105/* Close the database file. */
106static void
b13b96ca 107internal_endent (FILE **stream)
5f0e6fc7 108{
b13b96ca 109 if (*stream != NULL)
5f0e6fc7 110 {
b13b96ca
AS
111 fclose (*stream);
112 *stream = NULL;
5f0e6fc7 113 }
5f0e6fc7
RM
114}
115
116
117/* Thread-safe, exported version of that. */
26761c28 118enum nss_status
5f0e6fc7
RM
119CONCAT(_nss_files_end,ENTNAME) (void)
120{
121 __libc_lock_lock (lock);
122
b13b96ca 123 internal_endent (&stream);
6dbe2837 124
5f0e6fc7
RM
125 __libc_lock_unlock (lock);
126
127 return NSS_STATUS_SUCCESS;
128}
129\f
5f0e6fc7 130
977f4b31 131/* Parsing the database file into `struct STRUCTURE' data structures. */
5f0e6fc7 132static enum nss_status
b13b96ca 133internal_getent (FILE *stream, struct STRUCTURE *result,
71d3bda9
UD
134 char *buffer, size_t buflen, int *errnop H_ERRNO_PROTO
135 EXTRA_ARGS_DECL)
5f0e6fc7
RM
136{
137 char *p;
138 struct parser_data *data = (void *) buffer;
977f4b31 139 size_t linebuflen = buffer + buflen - data->linebuffer;
22d57dd3 140 int parse_result;
5f0e6fc7 141
4caef86c 142 if (buflen < sizeof *data + 2)
5f0e6fc7 143 {
d71b808a 144 *errnop = ERANGE;
47707456 145 H_ERRNO_SET (NETDB_INTERNAL);
ffee1316 146 return NSS_STATUS_TRYAGAIN;
5f0e6fc7
RM
147 }
148
916124ed 149 while (true)
5f0e6fc7 150 {
916124ed
FW
151 ssize_t r = __libc_readline_unlocked
152 (stream, data->linebuffer, linebuflen);
153 if (r < 0)
154 {
155 *errnop = errno;
156 H_ERRNO_SET (NETDB_INTERNAL);
157 if (*errnop == ERANGE)
158 /* Request larger buffer. */
159 return NSS_STATUS_TRYAGAIN;
160 else
161 /* Other read failure. */
162 return NSS_STATUS_UNAVAIL;
163 }
164 else if (r == 0)
5f0e6fc7 165 {
916124ed 166 /* End of file. */
5f0e6fc7
RM
167 H_ERRNO_SET (HOST_NOT_FOUND);
168 return NSS_STATUS_NOTFOUND;
169 }
977f4b31 170
916124ed
FW
171 /* Everything OK. Now skip leading blanks. */
172 p = data->linebuffer;
173 while (isspace (*p))
174 ++p;
175
176 /* Ignore empty and comment lines. */
177 if (*p == '\0' || *p == '#')
178 continue;
179
180 /* Parse the line. */
181 *errnop = EINVAL;
182 parse_result = parse_line (p, result, data, buflen, errnop EXTRA_ARGS);
183
184 if (parse_result == -1)
26761c28 185 {
916124ed
FW
186 if (*errnop == ERANGE)
187 {
188 /* Return to the original file position at the beginning
189 of the line, so that the next call can read it again
190 if necessary. */
191 if (__fseeko64 (stream, -r, SEEK_CUR) != 0)
192 {
193 if (errno == ERANGE)
194 *errnop = EINVAL;
195 else
196 *errnop = errno;
197 H_ERRNO_SET (NETDB_INTERNAL);
198 return NSS_STATUS_UNAVAIL;
199 }
200 }
26761c28
UD
201 H_ERRNO_SET (NETDB_INTERNAL);
202 return NSS_STATUS_TRYAGAIN;
203 }
6dbe2837 204
916124ed
FW
205 /* Return the data if parsed successfully. */
206 if (parse_result != 0)
207 return NSS_STATUS_SUCCESS;
5f0e6fc7 208
916124ed
FW
209 /* If it is invalid, loop to get the next line of the file to
210 parse. */
405521b5 211 }
5f0e6fc7
RM
212}
213
214
215/* Return the next entry from the database file, doing locking. */
26761c28 216enum nss_status
d71b808a
UD
217CONCAT(_nss_files_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer,
218 size_t buflen, int *errnop H_ERRNO_PROTO)
5f0e6fc7
RM
219{
220 /* Return next entry in host file. */
26761c28 221 enum nss_status status = NSS_STATUS_SUCCESS;
5f0e6fc7
RM
222
223 __libc_lock_lock (lock);
224
26761c28
UD
225 /* Be prepared that the set*ent function was not called before. */
226 if (stream == NULL)
d47aac39 227 {
0facd3df
UD
228 int save_errno = errno;
229
b13b96ca 230 status = internal_setent (&stream);
d47aac39 231
9aef35a5 232 __set_errno (save_errno);
d47aac39 233 }
2303f5fd 234
54d79e99 235 if (status == NSS_STATUS_SUCCESS)
b13b96ca
AS
236 status = internal_getent (stream, result, buffer, buflen, errnop
237 H_ERRNO_ARG EXTRA_ARGS_VALUE);
5f0e6fc7
RM
238
239 __libc_lock_unlock (lock);
240
241 return status;
242}
243\f
244/* Macro for defining lookup functions for this file-based database.
245
246 NAME is the name of the lookup; e.g. `hostbyname'.
247
2666d441
UD
248 DB_CHAR, KEYPATTERN, KEYSIZE are ignored here but used by db-XXX.c
249 e.g. `1 + sizeof (id) * 4'.
96bda0ea 250
2666d441 251 PROTO is the potentially empty list of other parameters.
5f0e6fc7
RM
252
253 BREAK_IF_MATCH is a block of code which compares `struct STRUCTURE *result'
254 to the lookup key arguments and does `break;' if they match. */
255
2666d441 256#define DB_LOOKUP(name, db_char, keysize, keypattern, break_if_match, proto...)\
5f0e6fc7
RM
257enum nss_status \
258_nss_files_get##name##_r (proto, \
d71b808a
UD
259 struct STRUCTURE *result, char *buffer, \
260 size_t buflen, int *errnop H_ERRNO_PROTO) \
5f0e6fc7
RM
261{ \
262 enum nss_status status; \
b13b96ca 263 FILE *stream = NULL; \
5f0e6fc7 264 \
b13b96ca
AS
265 /* Open file. */ \
266 status = internal_setent (&stream); \
5f0e6fc7 267 \
26761c28
UD
268 if (status == NSS_STATUS_SUCCESS) \
269 { \
b13b96ca 270 while ((status = internal_getent (stream, result, buffer, buflen, errnop \
71d3bda9 271 H_ERRNO_ARG EXTRA_ARGS_VALUE)) \
26761c28
UD
272 == NSS_STATUS_SUCCESS) \
273 { break_if_match } \
5f0e6fc7 274 \
b13b96ca 275 internal_endent (&stream); \
26761c28 276 } \
5f0e6fc7 277 \
5f0e6fc7
RM
278 return status; \
279}