~ubuntu-branches/debian/wheezy/netatalk/wheezy

« back to all changes in this revision

Viewing changes to libatalk/cnid/dbd/cnid_dbd.c

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2011-06-05 21:04:21 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20110605210421-19gag2srevj0ocxh
Tags: 2.2~beta4-1
* New upstream release.
  + Fixes "Internal Error" after ad_open on sparc.
    Closes: bug#606005. Thanks to Alfredo Sola.
* Adjust references to unofficial packages in README.Debian.
* Use dversionmangle (not uversionmangle) in watch file. Fix add
  leading dash (-) to upstream version in mangling.
* Update patches:
  + Drop patches 107 and 294 (Zeroconf support): Implemented
    (differently) upstream now.
  + Drop patches 109 and 112 (avoid broken XFS linkage) obsolete.
  + Drop patch 200 (hostname resolving): adopted upstream.
  + Refresh patch 205.
* Rewrite copyright file using draft 174 of DEP-5 format.
* Build-depend on and recommend unversioned (i.e. default) BerkeleyDB
  packages.
  Closes: bug#621413. Thanks to Ondřej Surý.
  Simplify suggestions on older versioned BerkeleyDB packages.
* Stop installing some documentation dropped upstream, and let CDBS
  automagically handle some of the remains.
* Update control file:
  + Bump policy compliance to standards-version 3.9.2.
  + Shorten Vcs-* URLs.
* Add patches 115 and (for automade file) 214 to avoid installing
  unneeded /default dir.
  Closes: bug#628119. Thanks to Russell Muetzelfeldt and Luk Claes.
* Don't ship .la files. Closes: bug#621849. Thanks to Andreas Metzler
  and Luk Claes.
* Stop renaming afile and achfile, dropped upstream.
* Explicitly enable DDP (AppleTalk), now disabled by default.
* Enable Zeroconf, should be stable now.
* Simplify package relations:
  + Drop (build-)dependency fallback unneeded even for oldstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * $Id: cnid_dbd.c,v 1.17 2010-03-31 09:47:32 franklahm Exp $
3
 
 *
4
2
 * Copyright (C) Joerg Lenneis 2003
 
3
 * Copyright (C) Frank Lahm 2010
5
4
 * All Rights Reserved.  See COPYING.
6
5
 */
7
6
 
39
38
#include <atalk/logger.h>
40
39
#include <atalk/adouble.h>
41
40
#include <atalk/cnid.h>
 
41
#include <atalk/cnid_dbd_private.h>
 
42
#include <atalk/util.h>
 
43
 
42
44
#include "cnid_dbd.h"
43
 
#include <atalk/cnid_dbd_private.h>
44
45
 
45
46
#ifndef SOL_TCP
46
47
#define SOL_TCP IPPROTO_TCP
47
48
#endif /* ! SOL_TCP */
48
49
 
 
50
/* Wait MAX_DELAY seconds before a request to the CNID server times out */
 
51
#define MAX_DELAY 20
 
52
#define ONE_DELAY 5
 
53
 
49
54
static void RQST_RESET(struct cnid_dbd_rqst  *r)
50
55
{
51
56
    memset(r, 0, sizeof(struct cnid_dbd_rqst ));
52
57
}
53
58
 
54
 
/* ----------- */
55
 
#define MAX_DELAY 10
56
 
 
57
 
/* *MUST* be < afp tickle or it's never triggered (got EINTR first) */
58
 
#define SOCK_DELAY 11
59
 
 
60
59
static void delay(int sec)
61
60
{
62
61
    struct timeval tv;
69
68
static int tsock_getfd(const char *host, const char *port)
70
69
{
71
70
    int sock = -1;
72
 
    struct timeval tv;
73
71
    int attr;
74
72
    int err;
75
73
    struct addrinfo hints, *servinfo, *p;
 
74
    int optval;
 
75
    socklen_t optlen = sizeof(optval);
76
76
 
77
77
    /* Prepare hint for getaddrinfo */
78
78
    memset(&hints, 0, sizeof hints);
81
81
    hints.ai_flags = AI_NUMERICSERV;
82
82
 
83
83
    if ((err = getaddrinfo(host, port, &hints, &servinfo)) != 0) {
84
 
        LOG(log_error, logtype_default, "tsock_getfd: getaddrinfo: CNID server %s:%s : %s\n", host, port, gai_strerror(err));
 
84
        LOG(log_error, logtype_default, "tsock_getfd: getaddrinfo: CNID server %s:%s : %s\n",
 
85
            host, port, gai_strerror(err));
85
86
        return -1;
86
87
    }
87
88
 
88
89
    /* loop through all the results and bind to the first we can */
89
90
    for (p = servinfo; p != NULL; p = p->ai_next) {
90
91
        if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
91
 
            LOG(log_info, logtype_default, "tsock_getfd: socket CNID server %s:: %s", host, strerror(errno));
92
 
                continue;
 
92
            LOG(log_info, logtype_default, "tsock_getfd: socket CNID server %s:: %s",
 
93
                host, strerror(errno));
 
94
            continue;
93
95
        }
94
96
 
95
97
        attr = 1;
96
98
        if (setsockopt(sock, SOL_TCP, TCP_NODELAY, &attr, sizeof(attr)) == -1) {
97
 
            LOG(log_error, logtype_cnid, "getfd: set TCP_NODELAY CNID server %s: %s", host, strerror(errno));
98
 
            close(sock);
99
 
            continue;
100
 
        }
101
 
        
102
 
        tv.tv_sec = SOCK_DELAY;
103
 
        tv.tv_usec = 0;
104
 
        if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) {
105
 
            LOG(log_error, logtype_cnid, "getfd: set SO_RCVTIMEO CNID server %s: %s", host, strerror(errno));
106
 
            close(sock);
107
 
            continue;
108
 
        }
109
 
 
110
 
        tv.tv_sec = SOCK_DELAY;
111
 
        tv.tv_usec = 0;
112
 
        if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) {
113
 
            LOG(log_error, logtype_cnid, "getfd: set SO_SNDTIMEO CNID server %s: %s", host, strerror(errno));
114
 
            close(sock);
115
 
            continue;
116
 
        }
117
 
        
 
99
            LOG(log_error, logtype_cnid, "getfd: set TCP_NODELAY CNID server %s: %s",
 
100
                host, strerror(errno));
 
101
            close(sock);
 
102
            sock = -1;
 
103
            return -1;
 
104
        }
 
105
 
 
106
        if (setnonblock(sock, 1) != 0) {
 
107
            LOG(log_error, logtype_cnid, "getfd: setnonblock: %s", strerror(err));
 
108
            close(sock);
 
109
            sock = -1;
 
110
            return -1;
 
111
        }
 
112
 
118
113
        if (connect(sock, p->ai_addr, p->ai_addrlen) == -1) {
119
 
            err = errno;
120
 
            close(sock);
121
 
            sock=-1;
122
 
            LOG(log_error, logtype_cnid, "getfd: connect CNID server %s: %s", host, strerror(err));
123
 
            continue;
 
114
            if (errno == EINPROGRESS) {
 
115
                struct timeval tv;
 
116
                tv.tv_usec = 0;
 
117
                tv.tv_sec  = 5; /* give it five seconds ... */
 
118
                fd_set wfds;
 
119
                FD_ZERO(&wfds);
 
120
                FD_SET(sock, &wfds);
 
121
 
 
122
                if ((err = select(sock + 1, NULL, &wfds, NULL, &tv)) == 0) {
 
123
                    /* timeout */
 
124
                    LOG(log_error, logtype_cnid, "getfd: select timed out for CNID server %s",
 
125
                        host);
 
126
                    close(sock);
 
127
                    sock = -1;
 
128
                    continue;
 
129
                }
 
130
                if (err == -1) {
 
131
                    /* select failed */
 
132
                    LOG(log_error, logtype_cnid, "getfd: select failed for CNID server %s",
 
133
                        host);
 
134
                    close(sock);
 
135
                    sock = -1;
 
136
                    continue;
 
137
                }
 
138
 
 
139
                if ( ! FD_ISSET(sock, &wfds)) {
 
140
                    /* give up */
 
141
                    LOG(log_error, logtype_cnid, "getfd: socket not ready connecting to %s",
 
142
                        host);
 
143
                    close(sock);
 
144
                    sock = -1;
 
145
                    continue;
 
146
                }
 
147
 
 
148
                if ((err = getsockopt(sock, SOL_SOCKET, SO_ERROR, &optval, &optlen)) != 0 || optval != 0) {
 
149
                    if (err != 0) {
 
150
                        /* somethings very wrong */
 
151
                        LOG(log_error, logtype_cnid, "getfd: getsockopt error with CNID server %s: %s",
 
152
                            host, strerror(errno));
 
153
                    } else {
 
154
                        errno = optval;
 
155
                        LOG(log_error, logtype_cnid, "getfd: getsockopt says: %s",
 
156
                            strerror(errno));
 
157
                    }
 
158
                    close(sock);
 
159
                    sock = -1;
 
160
                    continue;
 
161
                }
 
162
            } else {
 
163
                LOG(log_error, logtype_cnid, "getfd: connect CNID server %s: %s",
 
164
                    host, strerror(errno));
 
165
                close(sock);
 
166
                sock = -1;
 
167
                continue;
 
168
            }
124
169
        }
125
 
        
 
170
 
126
171
        /* We've got a socket */
127
172
        break;
128
173
    }
130
175
    freeaddrinfo(servinfo);
131
176
 
132
177
    if (p == NULL) {
133
 
        LOG(log_error, logtype_cnid, "tsock_getfd: no suitable network config from CNID server %s:%s", host, port);
 
178
        errno = optval;
 
179
        LOG(log_error, logtype_cnid, "tsock_getfd: no suitable network config from CNID server (%s:%s): %s",
 
180
            host, port, strerror(errno));
134
181
        return -1;
135
182
    }
136
183
 
137
184
    return(sock);
138
185
}
139
186
 
140
 
/* --------------------- */
141
 
static int write_vec(int fd, struct iovec *iov, size_t towrite)
 
187
/*!
 
188
 * Write "towrite" bytes using writev on non-blocking fd
 
189
 *
 
190
 * Every short write is considered an error, transmit can handle that.
 
191
 *
 
192
 * @param fd      (r) socket fd which must be non-blocking
 
193
 * @param iov     (r) iovec for writev
 
194
 * @param towrite (r) number of bytes in all iovec elements
 
195
 * @param vecs    (r) number of iovecs in array
 
196
 *
 
197
 * @returns "towrite" bytes written or -1 on error
 
198
 */
 
199
static int write_vec(int fd, struct iovec *iov, ssize_t towrite, int vecs)
142
200
{
143
201
    ssize_t len;
144
 
    size_t len1;
145
 
 
146
 
    LOG(log_maxdebug, logtype_cnid, "write_vec: request to write %d bytes", towrite);
147
 
 
148
 
    len1 =  iov[1].iov_len;
149
 
    while (towrite > 0) {
150
 
        if (((len = writev(fd, iov, 2)) == -1 && errno == EINTR) || !len)
151
 
            continue;
152
 
 
153
 
        if ((size_t)len == towrite) /* wrote everything out */
 
202
    int slept = 0;
 
203
    int sleepsecs;
 
204
 
 
205
    while (1) {
 
206
        if (((len = writev(fd, iov, vecs)) == -1 && errno == EINTR))
 
207
            continue;
 
208
 
 
209
        if ((! slept) && len == -1 && errno == EAGAIN) {
 
210
            sleepsecs = 2;
 
211
            while ((sleepsecs = sleep(sleepsecs)));
 
212
            slept = 1;
 
213
            continue;
 
214
        }
 
215
 
 
216
        if (len == towrite) /* wrote everything out */
154
217
            break;
155
 
        else if (len < 0) { /* error */
156
 
            return -1;
157
 
        }
158
218
 
159
 
        towrite -= len;
160
 
        if (towrite > len1) { /* skip part of header */
161
 
            iov[0].iov_base = (char *) iov[0].iov_base + len;
162
 
            iov[0].iov_len -= len;
163
 
        } else { /* skip to data */
164
 
            if (iov[0].iov_len) {
165
 
                len -= iov[0].iov_len;
166
 
                iov[0].iov_len = 0;
167
 
            }
168
 
            iov[1].iov_base = (char *) iov[1].iov_base + len;
169
 
            iov[1].iov_len -= len;
170
 
        }
 
219
        if (len == -1)
 
220
            LOG(log_error, logtype_cnid, "write_vec: %s", strerror(errno));
 
221
        else
 
222
            LOG(log_error, logtype_cnid, "write_vec: short write: %d", len);
 
223
        return len;
171
224
    }
172
225
 
173
 
    LOG(log_maxdebug, logtype_cnid, "write_vec: wrote %d bytes", towrite);
 
226
    LOG(log_maxdebug, logtype_cnid, "write_vec: wrote %d bytes", len);
174
227
 
175
 
    return 0;
 
228
    return len;
176
229
}
177
230
 
178
231
/* --------------------- */
182
235
    int len;
183
236
    struct iovec iov[2];
184
237
 
185
 
    LOG(log_debug, logtype_cnid, "init_tsock: BEGIN. Opening volume '%s', CNID Server: %s/%s", 
 
238
    LOG(log_debug, logtype_cnid, "init_tsock: BEGIN. Opening volume '%s', CNID Server: %s/%s",
186
239
        db->db_dir, db->cnidserver, db->cnidport);
187
240
 
188
241
    if ((fd = tsock_getfd(db->cnidserver, db->cnidport)) < 0)
196
249
    iov[1].iov_base = db->db_dir;
197
250
    iov[1].iov_len  = len;
198
251
 
199
 
    if (write_vec(fd, iov, len + sizeof(int)) < 0) {
 
252
    if (write_vec(fd, iov, len + sizeof(int), 2) != len + sizeof(int)) {
200
253
        LOG(log_error, logtype_cnid, "init_tsock: Error/short write: %s", strerror(errno));
201
254
        close(fd);
202
255
        return -1;
212
265
{
213
266
    struct iovec iov[2];
214
267
    size_t towrite;
215
 
 
216
 
    LOG(log_maxdebug, logtype_cnid, "send_packet: BEGIN");
217
 
 
218
 
    if (!rqst->namelen) {
219
 
        if (write(db->fd, rqst, sizeof(struct cnid_dbd_rqst)) != sizeof(struct cnid_dbd_rqst)) {
220
 
            LOG(log_warning, logtype_cnid, "send_packet: Error/short write rqst (db_dir %s): %s",
221
 
                db->db_dir, strerror(errno));
222
 
            return -1;
223
 
        }
224
 
        LOG(log_maxdebug, logtype_cnid, "send_packet: OK");
225
 
        return 0;
226
 
    }
 
268
    int vecs;
227
269
 
228
270
    iov[0].iov_base = rqst;
229
271
    iov[0].iov_len  = sizeof(struct cnid_dbd_rqst);
230
 
 
231
 
    iov[1].iov_base = rqst->name;
232
 
    iov[1].iov_len  = rqst->namelen;
233
 
 
234
 
    towrite = sizeof(struct cnid_dbd_rqst) +rqst->namelen;
235
 
 
236
 
    if (write_vec(db->fd, iov, towrite) < 0) {
 
272
    towrite = sizeof(struct cnid_dbd_rqst);
 
273
    vecs = 1;
 
274
 
 
275
    if (rqst->namelen) {
 
276
        iov[1].iov_base = rqst->name;
 
277
        iov[1].iov_len  = rqst->namelen;
 
278
        towrite += rqst->namelen;
 
279
        vecs++;
 
280
    }
 
281
 
 
282
    if (write_vec(db->fd, iov, towrite, vecs) != towrite) {
237
283
        LOG(log_warning, logtype_cnid, "send_packet: Error writev rqst (db_dir %s): %s",
238
284
            db->db_dir, strerror(errno));
239
285
        return -1;
240
286
    }
241
 
    
242
 
    LOG(log_maxdebug, logtype_cnid, "send_packet: OK");
 
287
 
 
288
    LOG(log_maxdebug, logtype_cnid, "send_packet: {done}");
243
289
    return 0;
244
290
}
245
291
 
266
312
    return 0;
267
313
}
268
314
 
269
 
/* ------------------- */
270
 
static ssize_t dbd_read(int socket, void *data, const size_t length)
271
 
{
272
 
    size_t stored;
273
 
    ssize_t len;
274
 
  
275
 
    stored = 0;
276
 
    while (stored < length) {
277
 
        len = read(socket, (u_int8_t *) data + stored, length - stored);
278
 
        if (len == -1) {
279
 
            if (errno == EINTR)
280
 
                continue;
281
 
            return -1;
282
 
        }
283
 
        else if (len > 0)
284
 
            stored += len;
285
 
        else
286
 
            break;
287
 
    }
288
 
    return stored;
289
 
}
290
 
 
291
315
/* ---------------------
292
316
 * send a request and get reply
293
317
 * assume send is non blocking
299
323
    char *nametmp;
300
324
    size_t len;
301
325
 
302
 
    LOG(log_maxdebug, logtype_cnid, "dbd_rpc: BEGIN");
303
 
 
304
326
    if (send_packet(db, rqst) < 0) {
305
327
        return -1;
306
328
    }
307
329
    len = rply->namelen;
308
330
    nametmp = rply->name;
309
331
 
310
 
    ret = dbd_read(db->fd, rply, sizeof(struct cnid_dbd_rply));
 
332
    ret = readt(db->fd, rply, sizeof(struct cnid_dbd_rply), 0, ONE_DELAY);
311
333
 
312
334
    if (ret != sizeof(struct cnid_dbd_rply)) {
313
335
        LOG(log_error, logtype_cnid, "dbd_rpc: Error reading header from fd (db_dir %s): %s",
314
 
            db->db_dir, ret == -1?strerror(errno):"closed");
 
336
            db->db_dir, ret == -1 ? strerror(errno) : "closed");
315
337
        rply->name = nametmp;
316
338
        return -1;
317
339
    }
322
344
            db->db_dir, rply->name, rply->namelen, len);
323
345
        return -1;
324
346
    }
325
 
    if (rply->namelen && (ret = dbd_read(db->fd, rply->name, rply->namelen)) != (ssize_t)rply->namelen) {
 
347
    if (rply->namelen && (ret = readt(db->fd, rply->name, rply->namelen, 0, ONE_DELAY)) != (ssize_t)rply->namelen) {
326
348
        LOG(log_error, logtype_cnid, "dbd_rpc: Error reading name from fd (db_dir %s): %s",
327
349
            db->db_dir, ret == -1?strerror(errno):"closed");
328
350
        return -1;
329
351
    }
330
352
 
331
 
    LOG(log_maxdebug, logtype_cnid, "dbd_rpc: END");
 
353
    LOG(log_maxdebug, logtype_cnid, "dbd_rpc: {done}");
332
354
 
333
355
    return 0;
334
356
}
339
361
    time_t orig, t;
340
362
    int clean = 1; /* no errors so far - to prevent sleep on first try */
341
363
 
342
 
    LOG(log_debug7, logtype_cnid, "transmit: BEGIN");
343
 
 
344
364
    if (db->changed) {
345
365
        /* volume and db don't have the same timestamp
346
366
         */
352
372
            struct cnid_dbd_rply rply_stamp;
353
373
            char  stamp[ADEDLEN_PRIVSYN];
354
374
 
355
 
            LOG(log_debug, logtype_cnid, "transmit: connecting to cnid_dbd ...");
 
375
            LOG(log_maxdebug, logtype_cnid, "transmit: connecting to cnid_dbd ...");
356
376
            if ((db->fd = init_tsock(db)) < 0) {
357
377
                goto transmit_fail;
358
378
            }
374
394
                    return -1;
375
395
                }
376
396
                LOG(log_debug7, logtype_cnid, "transmit: ... OK.");
377
 
            }
378
 
            else {
 
397
            } else { /* db->notfirst == 0 */
379
398
                db->notfirst = 1;
380
399
                if (db->client_stamp)
381
400
                    memcpy(db->client_stamp, stamp, ADEDLEN_PRIVSYN);
382
401
                memcpy(db->stamp, stamp, ADEDLEN_PRIVSYN);
383
402
            }
384
 
            LOG(log_debug, logtype_cnid, "transmit: succesfully attached to cnid_dbd for volume '%s' with stamp '%08lx'.", 
 
403
            LOG(log_debug, logtype_cnid, "transmit: attached to '%s', stamp: '%08lx'.",
385
404
                db->db_dir, *(uint64_t *)stamp);
386
405
        }
387
406
        if (!dbd_rpc(db, rqst, rply)) {
388
 
            LOG(log_debug7, logtype_cnid, "transmit: END OK");
 
407
            LOG(log_maxdebug, logtype_cnid, "transmit: {done}");
389
408
            return 0;
390
409
        }
391
410
    transmit_fail:
394
413
            db->fd = -1; /* FD not valid... will need to reconnect */
395
414
        }
396
415
 
 
416
        if (errno == ECONNREFUSED) { /* errno carefully injected in tsock_getfd */
 
417
            /* give up */
 
418
            LOG(log_error, logtype_cnid, "transmit: connection refused (db_dir %s)", db->db_dir);
 
419
            return -1;
 
420
        }
 
421
 
397
422
        if (!clean) { /* don't sleep if just got disconnected by cnid server */
398
423
            time(&t);
399
424
            if (t - orig > MAX_DELAY) {
401
426
                return -1;
402
427
            }
403
428
            /* sleep a little before retry */
404
 
            delay(2);
 
429
            delay(1);
405
430
        } else {
406
431
            clean = 0; /* false... next time sleep */
407
432
            time(&orig);
429
454
    cdb->cnid_delete = cnid_dbd_delete;
430
455
    cdb->cnid_get = cnid_dbd_get;
431
456
    cdb->cnid_lookup = cnid_dbd_lookup;
 
457
    cdb->cnid_find = cnid_dbd_find;
432
458
    cdb->cnid_nextid = NULL;
433
459
    cdb->cnid_resolve = cnid_dbd_resolve;
434
460
    cdb->cnid_getstamp = cnid_dbd_getstamp;
654
680
    rqst.op = CNID_DBD_OP_RESOLVE;
655
681
    rqst.cnid = *id;
656
682
 
657
 
    /* This mimicks the behaviour of the "regular" cnid_resolve. So far,
658
 
       nobody uses the content of buffer. It only provides space for the
659
 
       name in the caller. */
660
 
    rply.name = (char *)buffer + CNID_HEADER_LEN;
661
 
    rply.namelen = len - CNID_HEADER_LEN;
 
683
    /* Pass buffer to transmit so it can stuff the reply data there */
 
684
    rply.name = (char *)buffer;
 
685
    rply.namelen = len;
662
686
 
663
687
    if (transmit(db, &rqst, &rply) < 0) {
664
688
        errno = CNID_ERR_DB;
669
693
    switch (rply.result) {
670
694
    case CNID_DBD_RES_OK:
671
695
        *id = rply.did;
672
 
        name = rply.name;
 
696
        name = rply.name + CNID_NAME_OFS;
673
697
        LOG(log_debug, logtype_cnid, "cnid_dbd_resolve: resolved did: %u, name: '%s'", ntohl(*id), name);
674
698
        break;
675
699
    case CNID_DBD_RES_NOTFOUND:
767
791
}
768
792
 
769
793
/* ---------------------- */
 
794
int cnid_dbd_find(struct _cnid_db *cdb, char *name, size_t namelen, void *buffer, size_t buflen)
 
795
{
 
796
    CNID_private *db;
 
797
    struct cnid_dbd_rqst rqst;
 
798
    struct cnid_dbd_rply rply;
 
799
    int count;
 
800
 
 
801
    if (!cdb || !(db = cdb->_private) || !name) {
 
802
        LOG(log_error, logtype_cnid, "cnid_find: Parameter error");
 
803
        errno = CNID_ERR_PARAM;
 
804
        return CNID_INVALID;
 
805
    }
 
806
 
 
807
    if (namelen > MAXPATHLEN) {
 
808
        LOG(log_error, logtype_cnid, "cnid_find: Path name is too long");
 
809
        errno = CNID_ERR_PATH;
 
810
        return CNID_INVALID;
 
811
    }
 
812
 
 
813
    LOG(log_debug, logtype_cnid, "cnid_find(\"%s\")", name);
 
814
 
 
815
    RQST_RESET(&rqst);
 
816
    rqst.op = CNID_DBD_OP_SEARCH;
 
817
 
 
818
    rqst.name = name;
 
819
    rqst.namelen = namelen;
 
820
 
 
821
    rply.name = buffer;
 
822
    rply.namelen = buflen;
 
823
 
 
824
    if (transmit(db, &rqst, &rply) < 0) {
 
825
        errno = CNID_ERR_DB;
 
826
        return CNID_INVALID;
 
827
    }
 
828
 
 
829
    switch (rply.result) {
 
830
    case CNID_DBD_RES_OK:
 
831
        count = rply.namelen / sizeof(cnid_t);
 
832
        LOG(log_debug, logtype_cnid, "cnid_find: got %d matches", count);
 
833
        break;
 
834
    case CNID_DBD_RES_NOTFOUND:
 
835
        count = 0;
 
836
        break;
 
837
    case CNID_DBD_RES_ERR_DB:
 
838
        errno = CNID_ERR_DB;
 
839
        count = -1;
 
840
        break;
 
841
    default:
 
842
        abort();
 
843
    }
 
844
 
 
845
    return count;
 
846
}
 
847
 
 
848
/* ---------------------- */
770
849
int cnid_dbd_update(struct _cnid_db *cdb, const cnid_t id, const struct stat *st,
771
850
                    const cnid_t did, char *name, const size_t len)
772
851
{