Print this page
5910 libnisdb won't build with modern GCC
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libnisdb/yptol/update.c
+++ new/usr/src/lib/libnisdb/yptol/update.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 + * Copyright 2015 Gary Mills
23 24 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 25 * Use is subject to license terms.
25 26 */
26 27
27 -#pragma ident "%Z%%M% %I% %E% SMI"
28 -
29 28 /*
30 29 * DESCRIPTION: Contains the map update thread and related code.
31 30 */
32 31
33 32 #include <unistd.h>
34 33 #include <syslog.h>
35 34 #include <ndbm.h>
36 35 #include <thread.h>
37 36 #include <unistd.h>
38 37 #include <strings.h>
39 38 #include "ypsym.h"
40 39 #include "ypdefs.h"
41 40 #include "shim.h"
42 41 #include "yptol.h"
43 42 #include "../ldap_util.h"
44 43
45 44 /* Enable standard YP code features defined in ypdefs.h */
46 45 USE_YP_PREFIX
47 46 USE_YP_MASTER_NAME
48 47 USE_YP_LAST_MODIFIED
49 48 USE_YP_INPUT_FILE
50 49 USE_YP_OUTPUT_NAME
51 50 USE_YP_DOMAIN_NAME
52 51 USE_YP_SECURE
53 52 USE_YP_INTERDOMAIN
54 53
55 54 /*
56 55 * Decs
57 56 */
58 57 suc_code update_from_dit(map_ctrl *, datum *);
59 58 void * update_thread(void *);
60 59
61 60 /*
62 61 * Globals
63 62 */
64 63 extern pid_t parent_pid;
65 64
66 65 /*
67 66 * FUNCTION: update_entry_if_required()
68 67 *
69 68 * DESCRIPTION: Determines if an entry is to be updated and if it is does the
70 69 * update.
71 70 *
72 71 * GIVEN : Pointer to the open map ctrl
73 72 * Pointer to the entry key
74 73 *
75 74 * RETURNS : SUCCESS = Entry is in a state to be returned to the client
76 75 * i.e. either got updated, did not need to be updated or we are
77 76 * in a mode where it is acceptable to return out of date
78 77 * information.
79 78 * FAILURE = Entry need an update but it could not be done.
80 79 */
81 80 suc_code
82 81 update_entry_if_required(map_ctrl *map, datum *key)
83 82 {
84 83
85 84 /* Only update individual entries if entire map is */
86 85 /* not being updated */
87 86 if (is_map_updating(map))
88 87 return (SUCCESS);
89 88
90 89 /*
91 90 * If we are being asked for the order then need to check if
92 91 * the map is in need of an update. If it is then fake a
93 92 * recent order. The client will then read the map, using
94 93 * dbm_firstkey and this will do the update.
95 94 */
96 95 if (0 == strncmp(key->dptr, yp_last_modified, yp_last_modified_sz)) {
97 96 if (has_map_expired(map))
98 97 update_timestamp(map->entries);
99 98 return (SUCCESS);
100 99 }
101 100
102 101 /* Never update special keys. Have no TTLs */
103 102 if (is_special_key(key))
104 103 return (SUCCESS);
105 104
106 105 if (!has_entry_expired(map, key))
107 106 /* Didn't need an update */
108 107 return (SUCCESS);
109 108
110 109 /* Do the update */
111 110 return (update_from_dit(map, key));
112 111 }
113 112
114 113 /*
115 114 * FUNCTION: update_from_dit()
116 115 *
117 116 * DESCRIPTION: Called to update an entry from the DIT
118 117 *
119 118 * INPUTS: Map control structure for an open map
120 119 * Entry key
121 120 *
122 121 * OUTPUTS: SUCCESS = Update complete or we are in a mode where it is
123 122 * acceptable to return out of date information.
124 123 * FAILURE = Update failed
125 124 *
126 125 */
127 126 suc_code
128 127 update_from_dit(map_ctrl *map, datum *key)
129 128 {
130 129 datum dat;
131 130 int ret;
132 131 suc_code res;
133 132
134 133 /*
135 134 * Netgroup maps are a special case we cannot update just one entry so
136 135 * update the entire map instead.
137 136 */
138 137 if ((0 == strcmp(map->map_name, NETGROUP_BYHOST)) ||
139 138 (0 == strcmp(map->map_name, NETGROUP_BYUSER))) {
140 139 return (update_map_if_required(map, FALSE));
141 140 }
142 141
143 142 /* Read entry from the DIT */
144 143 ret = read_from_dit(map->map_name, map->domain, key, &dat);
145 144
146 145 /* Check that we got something */
147 146 if (NULL == dat.dptr) {
148 147 if (0 == ret) {
149 148 /*
150 149 * In a mode where it is acceptable to return out of
151 150 * date information.
152 151 */
153 152 logmsg(MSG_NOTIMECHECK, LOG_INFO,
154 153 "LDAP inaccessible returning old information");
155 154 return (SUCCESS);
156 155 } else {
157 156 /*
158 157 * In a mode where it is not acceptable to return out
159 158 * of date information.
160 159 *
161 160 * If the error positviely indicates that there is no
162 161 * such entry delete it. For errors where object may
163 162 * still exist in the DIT leave it.
164 163 */
165 164 if (MAP_NO_MATCHING_KEY == ret) {
166 165 /*
167 166 * Don't log errors. If the entry was not
168 167 * already present then no problem. The user
169 168 * just asked us for a non existant entry.
170 169 */
171 170 dbm_delete(map->entries, *key);
172 171 dbm_delete(map->ttl, *key);
173 172 }
174 173 return (FAILURE);
175 174 }
176 175 }
177 176
178 177 /* Write it to DBM */
179 178 res = dbm_store(map->entries, *key, dat, DBM_REPLACE);
180 179 sfree(dat.dptr);
181 180
182 181 if (SUCCESS != res)
183 182 return (FAILURE);
184 183
185 184 /* Update TTL */
186 185 update_entry_ttl(map, key, TTL_RUNNING);
187 186
188 187 return (SUCCESS);
189 188 }
190 189
191 190 /*
192 191 * FUNCTION: update_map_if_required()
193 192 *
194 193 * DESCRIPTION: Called to update an entire map if it is out of date. Map ctrl
195 194 * must be locked before this is called. This handles checking if
196 195 * the map is already being updated. It is important that this is
197 196 * done atomically with obtaining the maps update lock.
198 197 *
199 198 * INPUTS: Map control structure for an open map
200 199 * Flag indication if we should wait for completion
201 200 *
202 201 * OUTPUTS: SUCCESS = Map update initiated
203 202 * FAILURE = Map update not initiated
204 203 */
205 204 suc_code
206 205 update_map_if_required(map_ctrl *map, bool_t wait)
207 206 {
208 207 thread_t tid;
209 208 map_ctrl *new_map;
210 209 suc_code res;
211 210 long flags;
212 211
213 212 if (wait) {
214 213 /*
215 214 * Actually get the lock
216 215 *
217 216 * May block so unlock map_ctrl while it is done
218 217 */
219 218 unlock_map_ctrl(map);
220 219 res = lock_map_update(map);
221 220 lock_map_ctrl(map);
222 221 if (SUCCESS != res) {
223 222 logmsg(MSG_NOTIMECHECK, LOG_ERR,
224 223 "Could not lock map %s for update",
225 224 map->map_name);
226 225 return (FAILURE);
227 226 }
228 227 } else {
229 228 /* If not waiting try to get the lock */
230 229 switch (try_lock_map_update(map)) {
231 230 case 0:
232 231 /*
233 232 * We got the lock. Continue to start an update.
234 233 */
235 234 break;
236 235
237 236 case EBUSY:
238 237 /*
239 238 * Some one else got the lock. OK they are
240 239 * doing the update so we can just return.
241 240 */
242 241 return (SUCCESS);
243 242
244 243 default:
245 244 /*
246 245 * Some serious problem with lock.
247 246 */
248 247 return (FAILURE);
249 248 }
250 249 }
251 250
252 251 /*
253 252 * If we get here are holding the update lock. Make a final check that
254 253 * nobody beat us to the map update while we were getting it.
255 254 */
256 255 if (!has_map_expired(map)) {
257 256 /* A big waste of time. Somebody else did the update */
258 257 unlock_map_update(map);
259 258 return (SUCCESS);
260 259 }
261 260
262 261 /*
263 262 * We got the lock and nobody beat us to doing the update. Start our
264 263 * own update.
265 264 *
266 265 * Thread will free the update lock when update is complete.
267 266 */
268 267
269 268
270 269 /*
271 270 * Make a copy of the map_ctrl structure so the update thread has an
272 271 * independent version to work with. Note: Must not be on stack.
273 272 *
274 273 * On exit the update thread must free this.
275 274 */
276 275 new_map = dup_map_ctrl(map);
277 276 if (NULL == new_map) {
278 277 unlock_map_update(map);
279 278 return (FAILURE);
280 279 }
281 280
282 281 /*
283 282 * While thread is running unlock map so other processes can
284 283 * execute non update related accesses
285 284 */
286 285 unlock_map_ctrl(map);
287 286
288 287 flags = THR_BOUND | THR_NEW_LWP;
289 288
290 289 /*
291 290 * If we are not going to thr_join then need to create detached.
292 291 * This prevents a zombie being left when nobody joins us.
293 292 */
294 293 if (!wait && (getpid() == parent_pid))
295 294 flags |= THR_DETACHED;
296 295
297 296 /* Kick off update thread */
298 297 if (0 != thr_create(NULL, NULL, update_thread, new_map,
299 298 flags, &tid)) {
300 299 logmsg(MSG_NOTIMECHECK, LOG_ERR,
301 300 "Could not create NIS update thread");
302 301 free_map_ctrl(new_map);
303 302 unlock_map_update(map);
304 303 if (SUCCESS != lock_map_ctrl(map))
305 304 logmsg(MSG_NOTIMECHECK, LOG_ERR,
306 305 "Could not acquire update lock for %s", map->map_name);
307 306 return (FAILURE);
308 307 }
309 308
310 309 if (wait) {
311 310 /* May block but no problem map_ctrl is already unlocked. */
312 311 thr_join(tid, NULL, NULL);
313 312 }
314 313
315 314 /* Re acquire lock */
316 315 if (1 != lock_map_ctrl(map)) {
317 316 logmsg(MSG_NOTIMECHECK, LOG_ERR,
318 317 "Could not re-acquire lock for %s", map->map_name);
319 318 return (FAILURE);
320 319 }
321 320
322 321 return (SUCCESS);
323 322 }
324 323
325 324 /*
326 325 * FUNCTION: update_thread()
327 326 *
328 327 * DESCRIPTION: The update thread this is called to update an entire NIS map.
329 328 * if several NIS maps are found to be out of date several
330 329 * instances of this may be running at the same time.
331 330 *
332 331 * Since we are using a duplicate map_ctrl we do not have to lock
333 332 * it. If we did would end up using the same mutex as the parent
334 333 * map ctrl an possibly deadlocking.
335 334 *
336 335 * INPUTS: Map handle (because we need access to name and lock)
337 336 *
338 337 * OUTPUTS: None exits when finished.
339 338 */
340 339
341 340 void *
342 341 update_thread(void *arg)
343 342 {
344 343 void *ret = (void *)-1;
345 344 map_ctrl *map;
346 345
347 346 /* Cast argument pointer to correct type */
348 347 map = (map_ctrl *)arg;
349 348
350 349 /* Actually do the work */
↓ open down ↓ |
312 lines elided |
↑ open up ↑ |
351 350 if (SUCCESS == update_map_from_dit(map, FALSE))
352 351 ret = 0;
353 352
354 353 /* Update complete or failed */
355 354 unlock_map_update(map);
356 355
357 356 /* Free up duplicate copy of the map_ctrl */
358 357 free_map_ctrl(map);
359 358
360 359 thr_exit(ret);
360 +
361 + return (NULL);
361 362 }
362 363
363 364 /*
364 365 * FUNCTION : is_special_key()
365 366 *
366 367 * DESCRIPTION: Works out if a given key is one of the special ones. We just
367 368 * check for the "YP_" prefix. This is not 100% safe but if
368 369 * valid keys with a "YP_" prefix exist in the DIT then a lot of
369 370 * other parts of NIS wont work.
370 371 */
371 372 bool_t
372 373 is_special_key(datum *key)
373 374 {
374 375 if (0 == strncmp(key->dptr, yp_prefix, yp_prefix_sz))
375 376 return (TRUE);
376 377
377 378 return (FALSE);
378 379 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX