Use binutils 2.40 branch in build-many-glibcs.py
[glibc.git] / nss / nss_files_data.c
blob4da1a2d904b6ab29c154908051b30955881f2963
1 /* Returns a pointer to the global nss_files data structure.
2 Copyright (C) 2021-2023 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 <https://www.gnu.org/licenses/>. */
19 #include <nss_files.h>
21 #include <allocate_once.h>
22 #include <errno.h>
23 #include <netdb.h>
24 #include <nss.h>
25 #include <stdlib.h>
27 /* This collects all per file-data. */
28 struct nss_files_data
30 struct nss_files_per_file_data files[nss_file_count];
33 /* For use with allocate_once. */
34 static void *nss_files_global;
35 static void *
36 nss_files_global_allocate (void *closure)
38 struct nss_files_data *result = malloc (sizeof (*result));
39 if (result != NULL)
41 for (int i = 0; i < nss_file_count; ++i)
43 result->files[i].stream = NULL;
44 __libc_lock_init (result->files[i].lock);
47 return result;
49 /* Like __nss_files_data_open, but does not perform the open call. */
50 static enum nss_status
51 __nss_files_data_get (struct nss_files_per_file_data **pdata,
52 enum nss_files_file file, int *errnop, int *herrnop)
54 struct nss_files_data *data = allocate_once (&nss_files_global,
55 nss_files_global_allocate,
56 NULL, NULL);
57 if (data == NULL)
59 if (errnop != NULL)
60 *errnop = errno;
61 if (herrnop != NULL)
63 __set_h_errno (NETDB_INTERNAL);
64 *herrnop = NETDB_INTERNAL;
66 return NSS_STATUS_TRYAGAIN;
69 *pdata = &data->files[file];
70 __libc_lock_lock ((*pdata)->lock);
71 return NSS_STATUS_SUCCESS;
74 /* Helper function for opening the backing file at PATH. */
75 static enum nss_status
76 __nss_files_data_internal_open (struct nss_files_per_file_data *data,
77 const char *path)
79 enum nss_status status = NSS_STATUS_SUCCESS;
81 if (data->stream == NULL)
83 data->stream = __nss_files_fopen (path);
85 if (data->stream == NULL)
86 status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
89 return status;
93 enum nss_status
94 __nss_files_data_open (struct nss_files_per_file_data **pdata,
95 enum nss_files_file file, const char *path,
96 int *errnop, int *herrnop)
98 enum nss_status status = __nss_files_data_get (pdata, file, errnop, herrnop);
99 if (status != NSS_STATUS_SUCCESS)
100 return status;
102 /* Be prepared that the set*ent function was not called before. */
103 if ((*pdata)->stream == NULL)
105 int saved_errno = errno;
106 status = __nss_files_data_internal_open (*pdata, path);
107 __set_errno (saved_errno);
108 if (status != NSS_STATUS_SUCCESS)
109 __nss_files_data_put (*pdata);
112 return status;
115 libc_hidden_def (__nss_files_data_open)
117 void
118 __nss_files_data_put (struct nss_files_per_file_data *data)
120 __libc_lock_unlock (data->lock);
122 libc_hidden_def (__nss_files_data_put)
124 enum nss_status
125 __nss_files_data_setent (enum nss_files_file file, const char *path)
127 struct nss_files_per_file_data *data;
128 enum nss_status status = __nss_files_data_get (&data, file, NULL, NULL);
129 if (status != NSS_STATUS_SUCCESS)
130 return status;
132 if (data->stream == NULL)
133 status = __nss_files_data_internal_open (data, path);
134 else
135 rewind (data->stream);
137 __nss_files_data_put (data);
138 return status;
140 libc_hidden_def (__nss_files_data_setent)
142 enum nss_status
143 __nss_files_data_endent (enum nss_files_file file)
145 /* No cleanup is necessary if not initialized. */
146 struct nss_files_data *data = atomic_load_acquire (&nss_files_global);
147 if (data == NULL)
148 return NSS_STATUS_SUCCESS;
150 struct nss_files_per_file_data *fdata = &data->files[file];
151 __libc_lock_lock (fdata->lock);
152 if (fdata->stream != NULL)
154 fclose (fdata->stream);
155 fdata->stream = NULL;
157 __libc_lock_unlock (fdata->lock);
159 return NSS_STATUS_SUCCESS;
161 libc_hidden_def (__nss_files_data_endent)