~ubuntu-branches/ubuntu/precise/autofs5/precise

« back to all changes in this revision

Viewing changes to .pc/autofs-5.0.5-fix-remount-locking.patch/modules/lookup_nisplus.c

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short
  • Date: 2011-07-03 14:35:46 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110703143546-nej26krjij0rf792
Tags: 5.0.6-0ubuntu1
* New upstream release:
  - Dropped upstream patches 
  - Refreshed debian/patches/17ld.patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * lookup_nisplus.c
3
 
 *
4
 
 * Module for Linux automountd to access a NIS+ automount map
5
 
 */
6
 
 
7
 
#include <stdio.h>
8
 
#include <malloc.h>
9
 
#include <sys/param.h>
10
 
#include <sys/types.h>
11
 
#include <signal.h>
12
 
#include <sys/stat.h>
13
 
#include <rpc/rpc.h>
14
 
#include <rpc/xdr.h>
15
 
#include <rpcsvc/nis.h>
16
 
 
17
 
#define MODULE_LOOKUP
18
 
#include "automount.h"
19
 
#include "nsswitch.h"
20
 
 
21
 
#define MAPFMT_DEFAULT "sun"
22
 
 
23
 
#define MODPREFIX "lookup(nisplus): "
24
 
 
25
 
struct lookup_context {
26
 
        const char *domainname;
27
 
        const char *mapname;
28
 
        struct parse_mod *parse;
29
 
};
30
 
 
31
 
int lookup_version = AUTOFS_LOOKUP_VERSION;     /* Required by protocol */
32
 
 
33
 
int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **context)
34
 
{
35
 
        struct lookup_context *ctxt;
36
 
        char buf[MAX_ERR_BUF];
37
 
 
38
 
        *context = NULL;
39
 
 
40
 
        ctxt = malloc(sizeof(struct lookup_context));
41
 
        if (!ctxt) {
42
 
                char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
43
 
                logerr(MODPREFIX "%s", estr);
44
 
                return 1;
45
 
        }
46
 
 
47
 
        if (argc < 1) {
48
 
                free(ctxt);
49
 
                logmsg(MODPREFIX "No map name");
50
 
                return 1;
51
 
        }
52
 
        ctxt->mapname = argv[0];
53
 
 
54
 
        /* 
55
 
         * nis_local_directory () returns a pointer to a static buffer.
56
 
         * We don't need to copy or free it.
57
 
         */
58
 
        ctxt->domainname = nis_local_directory();
59
 
        if (!ctxt->domainname) {
60
 
                free(ctxt);
61
 
                logmsg(MODPREFIX "NIS+ domain not set");
62
 
                return 1;
63
 
        }
64
 
 
65
 
        if (!mapfmt)
66
 
                mapfmt = MAPFMT_DEFAULT;
67
 
 
68
 
        ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1);
69
 
        if (!ctxt->parse) {
70
 
                free(ctxt);
71
 
                logerr(MODPREFIX "failed to open parse context");
72
 
                return 1;
73
 
        }
74
 
        *context = ctxt;
75
 
 
76
 
        return 0;
77
 
}
78
 
 
79
 
int lookup_read_master(struct master *master, time_t age, void *context)
80
 
{
81
 
        struct lookup_context *ctxt = (struct lookup_context *) context;
82
 
        unsigned int timeout = master->default_timeout;
83
 
        unsigned int logging = master->default_logging;
84
 
        unsigned int logopt =  master->logopt;
85
 
        char *tablename;
86
 
        nis_result *result;
87
 
        nis_object *this;
88
 
        unsigned int current, result_count;
89
 
        char *path, *ent;
90
 
        char *buffer;
91
 
        char buf[MAX_ERR_BUF];
92
 
        int cur_state, len;
93
 
 
94
 
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
95
 
        tablename = malloc(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
96
 
        if (!tablename) {
97
 
                char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
98
 
                logerr(MODPREFIX "malloc: %s", estr);
99
 
                pthread_setcancelstate(cur_state, NULL);
100
 
                return NSS_STATUS_UNAVAIL;
101
 
        }
102
 
        sprintf(tablename, "%s.org_dir.%s", ctxt->mapname, ctxt->domainname);
103
 
 
104
 
        /* check that the table exists */
105
 
        result = nis_lookup(tablename, FOLLOW_PATH | FOLLOW_LINKS);
106
 
        if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) {
107
 
                nis_freeresult(result);
108
 
                crit(logopt,
109
 
                     MODPREFIX "couldn't locate nis+ table %s", ctxt->mapname);
110
 
                free(tablename);
111
 
                pthread_setcancelstate(cur_state, NULL);
112
 
                return NSS_STATUS_NOTFOUND;
113
 
        }
114
 
 
115
 
        sprintf(tablename, "[],%s.org_dir.%s", ctxt->mapname, ctxt->domainname);
116
 
 
117
 
        result = nis_list(tablename, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
118
 
        if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) {
119
 
                nis_freeresult(result);
120
 
                crit(logopt,
121
 
                     MODPREFIX "couldn't enumrate nis+ map %s", ctxt->mapname);
122
 
                free(tablename);
123
 
                pthread_setcancelstate(cur_state, NULL);
124
 
                return NSS_STATUS_UNAVAIL;
125
 
        }
126
 
 
127
 
        current = 0;
128
 
        result_count = NIS_RES_NUMOBJ(result);
129
 
 
130
 
        while (result_count--) {
131
 
                this = &result->objects.objects_val[current++];
132
 
                path = ENTRY_VAL(this, 0);
133
 
                /*
134
 
                 * Ignore keys beginning with '+' as plus map
135
 
                 * inclusion is only valid in file maps.
136
 
                 */
137
 
                if (*path == '+')
138
 
                        continue;
139
 
 
140
 
                ent = ENTRY_VAL(this, 1);
141
 
 
142
 
                len = ENTRY_LEN(this, 0) + 1 + ENTRY_LEN(this, 1) + 2;
143
 
                buffer = malloc(len);
144
 
                if (!buffer) {
145
 
                        logerr(MODPREFIX "could not malloc parse buffer");
146
 
                        continue;
147
 
                }
148
 
                memset(buffer, 0, len);
149
 
 
150
 
                strcat(buffer, path);
151
 
                strcat(buffer, " ");
152
 
                strcat(buffer, ent);
153
 
 
154
 
                master_parse_entry(buffer, timeout, logging, age);
155
 
 
156
 
                free(buffer);
157
 
        }
158
 
 
159
 
        nis_freeresult(result);
160
 
        free(tablename);
161
 
        pthread_setcancelstate(cur_state, NULL);
162
 
 
163
 
        return NSS_STATUS_SUCCESS;
164
 
}
165
 
 
166
 
int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
167
 
{
168
 
        struct lookup_context *ctxt = (struct lookup_context *) context;
169
 
        struct map_source *source;
170
 
        struct mapent_cache *mc;
171
 
        char *tablename;
172
 
        nis_result *result;
173
 
        nis_object *this;
174
 
        unsigned int current, result_count;
175
 
        char *key, *mapent;
176
 
        char buf[MAX_ERR_BUF];
177
 
        int cur_state;
178
 
 
179
 
        source = ap->entry->current;
180
 
        ap->entry->current = NULL;
181
 
        master_source_current_signal(ap->entry);
182
 
 
183
 
        /*
184
 
         * If we don't need to create directories then there's no use
185
 
         * reading the map. We always need to read the whole map for
186
 
         * direct mounts in order to mount the triggers.
187
 
         */
188
 
        if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT)
189
 
                return NSS_STATUS_SUCCESS;
190
 
 
191
 
        mc = source->mc;
192
 
 
193
 
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
194
 
        tablename = malloc(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
195
 
        if (!tablename) {
196
 
                char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
197
 
                logerr(MODPREFIX "malloc: %s", estr);
198
 
                pthread_setcancelstate(cur_state, NULL);
199
 
                return NSS_STATUS_UNAVAIL;
200
 
        }
201
 
        sprintf(tablename, "%s.org_dir.%s", ctxt->mapname, ctxt->domainname);
202
 
 
203
 
        /* check that the table exists */
204
 
        result = nis_lookup(tablename, FOLLOW_PATH | FOLLOW_LINKS);
205
 
        if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) {
206
 
                nis_freeresult(result);
207
 
                crit(ap->logopt,
208
 
                     MODPREFIX "couldn't locate nis+ table %s", ctxt->mapname);
209
 
                free(tablename);
210
 
                pthread_setcancelstate(cur_state, NULL);
211
 
                return NSS_STATUS_NOTFOUND;
212
 
        }
213
 
 
214
 
        sprintf(tablename, "[],%s.org_dir.%s", ctxt->mapname, ctxt->domainname);
215
 
 
216
 
        result = nis_list(tablename, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
217
 
        if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) {
218
 
                nis_freeresult(result);
219
 
                crit(ap->logopt,
220
 
                     MODPREFIX "couldn't enumrate nis+ map %s", ctxt->mapname);
221
 
                free(tablename);
222
 
                pthread_setcancelstate(cur_state, NULL);
223
 
                return NSS_STATUS_UNAVAIL;
224
 
        }
225
 
 
226
 
        current = 0;
227
 
        result_count = NIS_RES_NUMOBJ(result);
228
 
 
229
 
        while (result_count--) {
230
 
                char *s_key;
231
 
                size_t len;
232
 
 
233
 
                this = &result->objects.objects_val[current++];
234
 
                key = ENTRY_VAL(this, 0);
235
 
                len = ENTRY_LEN(this, 0);
236
 
 
237
 
                /*
238
 
                 * Ignore keys beginning with '+' as plus map
239
 
                 * inclusion is only valid in file maps.
240
 
                 */
241
 
                if (*key == '+')
242
 
                        continue;
243
 
 
244
 
                s_key = sanitize_path(key, len, ap->type, ap->logopt);
245
 
                if (!s_key)
246
 
                        continue;
247
 
 
248
 
                mapent = ENTRY_VAL(this, 1);
249
 
 
250
 
                cache_writelock(mc);
251
 
                cache_update(mc, source, s_key, mapent, age);
252
 
                cache_unlock(mc);
253
 
 
254
 
                free(s_key);
255
 
        }
256
 
 
257
 
        nis_freeresult(result);
258
 
 
259
 
        source->age = age;
260
 
 
261
 
        free(tablename);
262
 
        pthread_setcancelstate(cur_state, NULL);
263
 
 
264
 
        return NSS_STATUS_SUCCESS;
265
 
}
266
 
 
267
 
static int lookup_one(struct autofs_point *ap,
268
 
                      const char *key, int key_len,
269
 
                      struct lookup_context *ctxt)
270
 
{
271
 
        struct map_source *source;
272
 
        struct mapent_cache *mc;
273
 
        char *tablename;
274
 
        nis_result *result;
275
 
        nis_object *this;
276
 
        char *mapent;
277
 
        time_t age = time(NULL);
278
 
        int ret, cur_state;
279
 
        char buf[MAX_ERR_BUF];
280
 
 
281
 
        source = ap->entry->current;
282
 
        ap->entry->current = NULL;
283
 
        master_source_current_signal(ap->entry);
284
 
 
285
 
        mc = source->mc;
286
 
 
287
 
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
288
 
        tablename = malloc(strlen(key) + strlen(ctxt->mapname) +
289
 
                           strlen(ctxt->domainname) + 20);
290
 
        if (!tablename) {
291
 
                char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
292
 
                logerr(MODPREFIX "malloc: %s", estr);
293
 
                pthread_setcancelstate(cur_state, NULL);
294
 
                return -1;
295
 
        }
296
 
        sprintf(tablename, "[key=%s],%s.org_dir.%s", key, ctxt->mapname,
297
 
                ctxt->domainname);
298
 
 
299
 
        result = nis_list(tablename, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
300
 
        if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) {
301
 
                nis_error rs = result->status;
302
 
                nis_freeresult(result);
303
 
                free(tablename);
304
 
                pthread_setcancelstate(cur_state, NULL);
305
 
                if (rs == NIS_NOTFOUND ||
306
 
                    rs == NIS_S_NOTFOUND ||
307
 
                    rs == NIS_PARTIAL)
308
 
                        return CHE_MISSING;
309
 
 
310
 
                return -rs;
311
 
        }
312
 
 
313
 
        
314
 
        this = NIS_RES_OBJECT(result);
315
 
        mapent = ENTRY_VAL(this, 1);
316
 
        cache_writelock(mc);
317
 
        ret = cache_update(mc, source, key, mapent, age);
318
 
        cache_unlock(mc);
319
 
 
320
 
        nis_freeresult(result);
321
 
        free(tablename);
322
 
        pthread_setcancelstate(cur_state, NULL);
323
 
 
324
 
        return ret;
325
 
}
326
 
 
327
 
static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt)
328
 
{
329
 
        struct map_source *source;
330
 
        struct mapent_cache *mc;
331
 
        char *tablename;
332
 
        nis_result *result;
333
 
        nis_object *this;
334
 
        char *mapent;
335
 
        time_t age = time(NULL);
336
 
        int ret, cur_state;
337
 
        char buf[MAX_ERR_BUF];
338
 
 
339
 
        source = ap->entry->current;
340
 
        ap->entry->current = NULL;
341
 
        master_source_current_signal(ap->entry);
342
 
 
343
 
        mc = source->mc;
344
 
 
345
 
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
346
 
        tablename = malloc(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
347
 
        if (!tablename) {
348
 
                char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
349
 
                logerr(MODPREFIX "malloc: %s", estr);
350
 
                pthread_setcancelstate(cur_state, NULL);
351
 
                return -1;
352
 
        }
353
 
        sprintf(tablename, "[key=*],%s.org_dir.%s", ctxt->mapname,
354
 
                ctxt->domainname);
355
 
 
356
 
        result = nis_list(tablename, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
357
 
        if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) {
358
 
                nis_error rs = result->status;
359
 
                nis_freeresult(result);
360
 
                free(tablename);
361
 
                pthread_setcancelstate(cur_state, NULL);
362
 
                if (rs == NIS_NOTFOUND ||
363
 
                    rs == NIS_S_NOTFOUND ||
364
 
                    rs == NIS_PARTIAL)
365
 
                        return CHE_MISSING;
366
 
 
367
 
                return -rs;
368
 
        }
369
 
 
370
 
        this = NIS_RES_OBJECT(result);
371
 
        mapent = ENTRY_VAL(this, 1);
372
 
        cache_writelock(mc);
373
 
        ret = cache_update(mc, source, "*", mapent, age);
374
 
        cache_unlock(mc);
375
 
 
376
 
        nis_freeresult(result);
377
 
        free(tablename);
378
 
        pthread_setcancelstate(cur_state, NULL);
379
 
 
380
 
        return ret;
381
 
}
382
 
 
383
 
static int check_map_indirect(struct autofs_point *ap,
384
 
                              char *key, int key_len,
385
 
                              struct lookup_context *ctxt)
386
 
{
387
 
        struct map_source *source;
388
 
        struct mapent_cache *mc;
389
 
        struct mapent *me, *exists;
390
 
        time_t now = time(NULL);
391
 
        time_t t_last_read;
392
 
        int ret = 0;
393
 
 
394
 
        source = ap->entry->current;
395
 
        ap->entry->current = NULL;
396
 
        master_source_current_signal(ap->entry);
397
 
 
398
 
        mc = source->mc;
399
 
 
400
 
        master_source_current_wait(ap->entry);
401
 
        ap->entry->current = source;
402
 
 
403
 
        /* check map and if change is detected re-read map */
404
 
        ret = lookup_one(ap, key, key_len, ctxt);
405
 
        if (ret == CHE_FAIL)
406
 
                return NSS_STATUS_NOTFOUND;
407
 
 
408
 
        if (ret < 0) {
409
 
                /*
410
 
                 * If the server is down and the entry exists in the cache
411
 
                 * and belongs to this map return success and use the entry.
412
 
                 */
413
 
                exists = cache_lookup(mc, key);
414
 
                if (exists && exists->source == source)
415
 
                        return NSS_STATUS_SUCCESS;
416
 
 
417
 
                warn(ap->logopt,
418
 
                     MODPREFIX "lookup for %s failed: %s",
419
 
                     key, nis_sperrno(-ret));
420
 
 
421
 
                return NSS_STATUS_UNAVAIL;
422
 
        }
423
 
 
424
 
        pthread_cleanup_push(cache_lock_cleanup, mc);
425
 
        cache_writelock(mc);
426
 
        t_last_read = ap->exp_runfreq + 1;
427
 
        me = cache_lookup_first(mc);
428
 
        while (me) {
429
 
                if (me->source == source) {
430
 
                        t_last_read = now - me->age;
431
 
                        break;
432
 
                }
433
 
                me = cache_lookup_next(mc, me);
434
 
        }
435
 
        exists = cache_lookup_distinct(mc, key);
436
 
        /* Not found in the map but found in the cache */
437
 
        if (exists && exists->source == source && ret & CHE_MISSING) {
438
 
                if (exists->mapent) {
439
 
                        free(exists->mapent);
440
 
                        exists->mapent = NULL;
441
 
                        source->stale = 1;
442
 
                        exists->status = 0;
443
 
                }
444
 
        }
445
 
        pthread_cleanup_pop(1);
446
 
        
447
 
        if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED)
448
 
                source->stale = 1;
449
 
 
450
 
        if (ret == CHE_MISSING) {
451
 
                int wild = CHE_MISSING;
452
 
                struct mapent *we;
453
 
 
454
 
                master_source_current_wait(ap->entry);
455
 
                ap->entry->current = source;
456
 
 
457
 
                wild = lookup_wild(ap, ctxt);
458
 
                /*
459
 
                 * Check for map change and update as needed for
460
 
                 * following cache lookup.
461
 
                */
462
 
                pthread_cleanup_push(cache_lock_cleanup, mc);
463
 
                cache_writelock(mc);
464
 
                we = cache_lookup_distinct(mc, "*");
465
 
                if (we) {
466
 
                        /* Wildcard entry existed and is now gone */
467
 
                        if (we->source == source && wild & CHE_MISSING) {
468
 
                                cache_delete(mc, "*");
469
 
                                source->stale = 1;
470
 
                        }
471
 
                } else {
472
 
                        /* Wildcard not in map but now is */
473
 
                        if (wild & (CHE_OK | CHE_UPDATED))
474
 
                                source->stale = 1;
475
 
                }
476
 
                pthread_cleanup_pop(1);
477
 
 
478
 
                if (wild & (CHE_UPDATED | CHE_OK))
479
 
                        return NSS_STATUS_SUCCESS;
480
 
        }
481
 
 
482
 
        if (ret == CHE_MISSING)
483
 
                return NSS_STATUS_NOTFOUND;
484
 
 
485
 
        return NSS_STATUS_SUCCESS;
486
 
}
487
 
 
488
 
int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context)
489
 
{
490
 
        struct lookup_context *ctxt = (struct lookup_context *) context;
491
 
        struct map_source *source;
492
 
        struct mapent_cache *mc;
493
 
        char key[KEY_MAX_LEN + 1];
494
 
        int key_len;
495
 
        char *mapent = NULL;
496
 
        int mapent_len;
497
 
        struct mapent *me;
498
 
        int status;
499
 
        int ret = 1;
500
 
 
501
 
        source = ap->entry->current;
502
 
        ap->entry->current = NULL;
503
 
        master_source_current_signal(ap->entry);
504
 
 
505
 
        mc = source->mc;
506
 
 
507
 
        debug(ap->logopt, MODPREFIX "looking up %s", name);
508
 
 
509
 
        key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name);
510
 
        if (key_len > KEY_MAX_LEN)
511
 
                return NSS_STATUS_NOTFOUND;
512
 
 
513
 
        /* Check if we recorded a mount fail for this key anywhere */
514
 
        me = lookup_source_mapent(ap, key, LKP_DISTINCT);
515
 
        if (me) {
516
 
                if (me->status >= time(NULL)) {
517
 
                        cache_unlock(me->mc);
518
 
                        return NSS_STATUS_NOTFOUND;
519
 
                }
520
 
 
521
 
                /* Negative timeout expired for non-existent entry. */
522
 
                if (!me->mapent)
523
 
                        cache_delete(me->mc, key);
524
 
 
525
 
                cache_unlock(me->mc);
526
 
        }
527
 
 
528
 
        /*
529
 
         * We can't check the direct mount map as if it's not in
530
 
         * the map cache already we never get a mount lookup, so
531
 
         * we never know about it.
532
 
         */
533
 
        if (ap->type == LKP_INDIRECT && *key != '/') {
534
 
                char *lkp_key;
535
 
 
536
 
                cache_readlock(mc);
537
 
                me = cache_lookup_distinct(mc, key);
538
 
                if (me && me->multi)
539
 
                        lkp_key = strdup(me->multi->key);
540
 
                else
541
 
                        lkp_key = strdup(key);
542
 
                cache_unlock(mc);
543
 
 
544
 
                if (!lkp_key)
545
 
                        return NSS_STATUS_UNKNOWN;
546
 
 
547
 
                master_source_current_wait(ap->entry);
548
 
                ap->entry->current = source;
549
 
 
550
 
                status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt);
551
 
                if (status)
552
 
                        return status;
553
 
        }
554
 
 
555
 
        cache_readlock(mc);
556
 
        me = cache_lookup(mc, key);
557
 
        /* Stale mapent => check for entry in alternate source or wildcard */
558
 
        if (me && !me->mapent) {
559
 
                while ((me = cache_lookup_key_next(me)))
560
 
                        if (me->source == source)
561
 
                                break;
562
 
                if (!me)
563
 
                        me = cache_lookup_distinct(mc, "*");
564
 
        }
565
 
        if (me && (me->source == source || *me->key == '/')) {
566
 
                mapent_len = strlen(me->mapent);
567
 
                mapent = malloc(mapent_len + 1);
568
 
                strcpy(mapent, me->mapent);
569
 
        }
570
 
        cache_unlock(mc);
571
 
 
572
 
        if (!mapent)
573
 
                return NSS_STATUS_TRYAGAIN;
574
 
 
575
 
        master_source_current_wait(ap->entry);
576
 
        ap->entry->current = source;
577
 
 
578
 
        debug(ap->logopt, MODPREFIX "%s -> %s", key, mapent);
579
 
        ret = ctxt->parse->parse_mount(ap, key, key_len,
580
 
                                       mapent, ctxt->parse->context);
581
 
        if (ret) {
582
 
                time_t now = time(NULL);
583
 
                int rv = CHE_OK;
584
 
 
585
 
                cache_writelock(mc);
586
 
                me = cache_lookup_distinct(mc, key);
587
 
                if (!me)
588
 
                        rv = cache_update(mc, source, key, NULL, now);
589
 
                if (rv != CHE_FAIL) {
590
 
                        me = cache_lookup_distinct(mc, key);
591
 
                        me->status = time(NULL) + ap->negative_timeout;
592
 
                }
593
 
                cache_unlock(mc);
594
 
                free(mapent);
595
 
                return NSS_STATUS_TRYAGAIN;
596
 
        }
597
 
        free(mapent);
598
 
 
599
 
        return NSS_STATUS_SUCCESS;
600
 
}
601
 
 
602
 
int lookup_done(void *context)
603
 
{
604
 
        struct lookup_context *ctxt = (struct lookup_context *) context;
605
 
        int rv = close_parse(ctxt->parse);
606
 
        free(ctxt);
607
 
        return rv;
608
 
}