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>
27 /* This collects all per file-data. */
30 struct nss_files_per_file_data files
[nss_file_count
];
33 /* For use with allocate_once. */
34 static void *nss_files_global
;
36 nss_files_global_allocate (void *closure
)
38 struct nss_files_data
*result
= malloc (sizeof (*result
));
41 for (int i
= 0; i
< nss_file_count
; ++i
)
43 result
->files
[i
].stream
= NULL
;
44 __libc_lock_init (result
->files
[i
].lock
);
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
,
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
,
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
;
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
)
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
);
115 libc_hidden_def (__nss_files_data_open
)
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
)
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
)
132 if (data
->stream
== NULL
)
133 status
= __nss_files_data_internal_open (data
, path
);
135 rewind (data
->stream
);
137 __nss_files_data_put (data
);
140 libc_hidden_def (__nss_files_data_setent
)
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
);
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
)