powerpc: Optimize lock elision for pthread_mutex_t
[glibc.git] / nis / nss_nisplus / nisplus-parser.c
blob4ae5fcdd1effe74b63a6168bdd9745e6476be420
1 /* Copyright (C) 1997-2015 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
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/>. */
19 #include <pwd.h>
20 #include <ctype.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <rpcsvc/nis.h>
25 #include "nisplus-parser.h"
27 #define NISENTRYVAL(idx, col, res) \
28 (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
30 #define NISENTRYLEN(idx, col, res) \
31 (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
33 #define NISOBJVAL(col, obj) \
34 ((obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
36 #define NISOBJLEN(col, obj) \
37 ((obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
40 int
41 _nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw,
42 char *buffer, size_t buflen, int *errnop)
44 if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
45 || NIS_RES_NUMOBJ (result) != 1
46 || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
47 || strcmp (NIS_RES_OBJECT (result)->EN_data.en_type, "passwd_tbl") != 0
48 || NIS_RES_OBJECT (result)->EN_data.en_cols.en_cols_len < 7)
49 return 0;
51 nis_object *obj = NIS_RES_OBJECT (result);
52 char *first_unused = buffer;
53 size_t room_left = buflen;
54 size_t len;
56 if (NISOBJLEN (0, obj) >= room_left)
58 /* The line is too long for our buffer. */
59 no_more_room:
60 *errnop = ERANGE;
61 return -1;
64 strncpy (first_unused, NISOBJVAL (0, obj), NISOBJLEN (0, obj));
65 first_unused[NISOBJLEN (0, obj)] = '\0';
66 len = strlen (first_unused);
67 if (len == 0) /* No name ? Should never happen, database is corrupt */
68 return 0;
69 pw->pw_name = first_unused;
70 room_left -= len + 1;
71 first_unused += len + 1;
73 if (NISOBJLEN (1, obj) >= room_left)
74 goto no_more_room;
76 strncpy (first_unused, NISOBJVAL (1, obj), NISOBJLEN (1, obj));
77 first_unused[NISOBJLEN (1, obj)] = '\0';
78 pw->pw_passwd = first_unused;
79 len = strlen (first_unused);
80 room_left -= len + 1;
81 first_unused += len + 1;
83 char *numstr = NISOBJVAL (2, obj);
84 len = NISOBJLEN (2, obj);
85 if (len == 0 && numstr[len - 1] != '\0')
87 if (len >= room_left)
88 goto no_more_room;
90 strncpy (first_unused, numstr, len);
91 first_unused[len] = '\0';
92 numstr = first_unused;
94 if (numstr[0] == '\0')
95 /* If we don't have a uid, it's an invalid shadow entry. */
96 return 0;
97 pw->pw_uid = strtoul (numstr, NULL, 10);
99 numstr = NISOBJVAL (3, obj);
100 len = NISOBJLEN (3, obj);
101 if (len == 0 && numstr[len - 1] != '\0')
103 if (len >= room_left)
104 goto no_more_room;
106 strncpy (first_unused, numstr, len);
107 first_unused[len] = '\0';
108 numstr = first_unused;
110 if (numstr[0] == '\0')
111 /* If we don't have a gid, it's an invalid shadow entry. */
112 return 0;
113 pw->pw_gid = strtoul (numstr, NULL, 10);
115 if (NISOBJLEN(4, obj) >= room_left)
116 goto no_more_room;
118 strncpy (first_unused, NISOBJVAL (4, obj), NISOBJLEN (4, obj));
119 first_unused[NISOBJLEN (4, obj)] = '\0';
120 pw->pw_gecos = first_unused;
121 len = strlen (first_unused);
122 room_left -= len + 1;
123 first_unused += len + 1;
125 if (NISOBJLEN (5, obj) >= room_left)
126 goto no_more_room;
128 strncpy (first_unused, NISOBJVAL (5, obj), NISOBJLEN (5, obj));
129 first_unused[NISOBJLEN (5, obj)] = '\0';
130 pw->pw_dir = first_unused;
131 len = strlen (first_unused);
132 room_left -= len + 1;
133 first_unused += len + 1;
135 if (NISOBJLEN (6, obj) >= room_left)
136 goto no_more_room;
138 strncpy (first_unused, NISOBJVAL (6, obj), NISOBJLEN (6, obj));
139 first_unused[NISOBJLEN (6, obj)] = '\0';
140 pw->pw_shell = first_unused;
141 len = strlen (first_unused);
142 room_left -= len + 1;
143 first_unused += len + 1;
145 return 1;
150 _nss_nisplus_parse_grent (nis_result *result, struct group *gr,
151 char *buffer, size_t buflen, int *errnop)
153 if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
154 || __type_of(NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
155 || strcmp (NIS_RES_OBJECT (result)[0].EN_data.en_type, "group_tbl") != 0
156 || NIS_RES_OBJECT (result)[0].EN_data.en_cols.en_cols_len < 4)
157 return 0;
159 nis_object *obj = NIS_RES_OBJECT (result);
160 char *first_unused = buffer;
161 size_t room_left = buflen;
162 char *line;
163 int count;
164 size_t len;
166 if (NISOBJLEN (0, obj) >= room_left)
168 /* The line is too long for our buffer. */
169 no_more_room:
170 *errnop = ERANGE;
171 return -1;
174 strncpy (first_unused, NISOBJVAL (0, obj), NISOBJLEN (0, obj));
175 first_unused[NISOBJLEN (0, obj)] = '\0';
176 len = strlen (first_unused);
177 if (len == 0) /* group table is corrupt */
178 return 0;
179 gr->gr_name = first_unused;
180 room_left -= len + 1;
181 first_unused += len + 1;
183 if (NISOBJLEN (1, obj) >= room_left)
184 goto no_more_room;
186 strncpy (first_unused, NISOBJVAL (1, obj), NISOBJLEN (1, obj));
187 first_unused[NISOBJLEN (1, obj)] = '\0';
188 gr->gr_passwd = first_unused;
189 len = strlen (first_unused);
190 room_left -= len + 1;
191 first_unused += len + 1;
193 char *numstr = NISOBJVAL (2, obj);
194 len = NISOBJLEN (2, obj);
195 if (len == 0 || numstr[len - 1] != '\0')
197 if (len >= room_left)
198 goto no_more_room;
200 strncpy (first_unused, numstr, len);
201 first_unused[len] = '\0';
202 numstr = first_unused;
204 if (numstr[0] == '\0')
205 /* We should always have a gid. */
206 return 0;
207 gr->gr_gid = strtoul (numstr, NULL, 10);
209 if (NISOBJLEN (3, obj) >= room_left)
210 goto no_more_room;
212 strncpy (first_unused, NISOBJVAL (3, obj), NISOBJLEN (3, obj));
213 first_unused[NISOBJLEN (3, obj)] = '\0';
214 line = first_unused;
215 len = strlen (line);
216 room_left -= len + 1;
217 first_unused += len + 1;
218 /* Adjust the pointer so it is aligned for
219 storing pointers. */
220 size_t adjust = ((__alignof__ (char *)
221 - (first_unused - (char *) 0) % __alignof__ (char *))
222 % __alignof__ (char *));
223 if (room_left < adjust)
224 goto no_more_room;
225 first_unused += adjust;
226 room_left -= adjust;
227 gr->gr_mem = (char **) first_unused;
229 count = 0;
230 while (*line != '\0')
232 /* Skip leading blanks. */
233 while (isspace (*line))
234 ++line;
236 if (*line == '\0')
237 break;
239 if (room_left < sizeof (char *))
240 goto no_more_room;
241 room_left -= sizeof (char *);
242 gr->gr_mem[count++] = line;
244 while (*line != '\0' && *line != ',' && !isspace (*line))
245 ++line;
247 if (*line == ',' || isspace (*line))
249 int is = isspace (*line);
251 *line++ = '\0';
252 if (is)
253 while (*line != '\0' && (*line == ',' || isspace (*line)))
254 ++line;
257 if (room_left < sizeof (char *))
258 goto no_more_room;
259 room_left -= sizeof (char *);
260 gr->gr_mem[count] = NULL;
262 return 1;
267 _nss_nisplus_parse_spent (nis_result *result, struct spwd *sp,
268 char *buffer, size_t buflen, int *errnop)
270 char *first_unused = buffer;
271 size_t room_left = buflen;
272 size_t len;
274 if (result == NULL)
275 return 0;
277 if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
278 || NIS_RES_NUMOBJ (result) != 1
279 || __type_of(NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
280 || strcmp (NIS_RES_OBJECT (result)->EN_data.en_type, "passwd_tbl") != 0
281 || NIS_RES_OBJECT (result)->EN_data.en_cols.en_cols_len < 8)
282 return 0;
284 if (NISENTRYLEN (0, 0, result) >= room_left)
286 /* The line is too long for our buffer. */
287 no_more_room:
288 *errnop = ERANGE;
289 return -1;
292 strncpy (first_unused, NISENTRYVAL (0, 0, result),
293 NISENTRYLEN (0, 0, result));
294 first_unused[NISENTRYLEN (0, 0, result)] = '\0';
295 len = strlen (first_unused);
296 if (len == 0)
297 return 0;
298 sp->sp_namp = first_unused;
299 room_left -= len + 1;
300 first_unused += len + 1;
302 if (NISENTRYLEN (0, 1, result) >= room_left)
303 goto no_more_room;
305 strncpy (first_unused, NISENTRYVAL (0, 1, result),
306 NISENTRYLEN (0, 1, result));
307 first_unused[NISENTRYLEN (0, 1, result)] = '\0';
308 sp->sp_pwdp = first_unused;
309 len = strlen (first_unused);
310 room_left -= len + 1;
311 first_unused += len + 1;
313 sp->sp_lstchg = sp->sp_min = sp->sp_max = sp->sp_warn = sp->sp_inact =
314 sp->sp_expire = -1;
315 sp->sp_flag = ~0ul;
317 if (NISENTRYLEN (0, 7, result) > 0)
319 char *line = NISENTRYVAL (0, 7, result);
320 char *cp = strchr (line, ':');
321 if (cp == NULL)
322 return 1;
323 *cp++ = '\0';
324 if (*line)
325 sp->sp_lstchg = atol (line);
327 line = cp;
328 cp = strchr (line, ':');
329 if (cp == NULL)
330 return 1;
331 *cp++ = '\0';
332 if (*line)
333 sp->sp_min = atol (line);
335 line = cp;
336 cp = strchr (line, ':');
337 if (cp == NULL)
338 return 1;
339 *cp++ = '\0';
340 if (*line)
341 sp->sp_max = atol (line);
343 line = cp;
344 cp = strchr (line, ':');
345 if (cp == NULL)
346 return 1;
347 *cp++ = '\0';
348 if (*line)
349 sp->sp_warn = atol (line);
351 line = cp;
352 cp = strchr (line, ':');
353 if (cp == NULL)
354 return 1;
355 *cp++ = '\0';
356 if (*line)
357 sp->sp_inact = atol (line);
359 line = cp;
360 cp = strchr (line, ':');
361 if (cp == NULL)
362 return 1;
363 *cp++ = '\0';
364 if (*line)
365 sp->sp_expire = atol (line);
367 line = cp;
368 if (line == NULL)
369 return 1;
370 if (*line)
371 sp->sp_flag = atol (line);
374 return 1;