X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libatalk%2Fcnid%2Fdbd%2Fcnid_dbd.c;h=0d105ea920810801f99ce8d5bfa41c4717bd8197;hb=b0bcb8f6b0571592a50ce039882c9319e012a270;hp=01c984062543317ea6bfb65f1f3c2206af05fe47;hpb=e83a5199e4f35ceea335dc3075b23e8d983e7642;p=netatalk.git diff --git a/libatalk/cnid/dbd/cnid_dbd.c b/libatalk/cnid/dbd/cnid_dbd.c index 01c98406..0d105ea9 100644 --- a/libatalk/cnid/dbd/cnid_dbd.c +++ b/libatalk/cnid/dbd/cnid_dbd.c @@ -1,5 +1,6 @@ /* * Copyright (C) Joerg Lenneis 2003 + * Copyright (C) Frank Lahm 2010 * All Rights Reserved. See COPYING. */ @@ -10,15 +11,8 @@ #ifdef CNID_BACKEND_DBD #include -#ifdef HAVE_SYS_STAT_H #include -#endif /* HAVE_SYS_STAT_H */ -#ifdef HAVE_SYS_UIO_H #include -#endif /* HAVE_SYS_UIO_H */ -#ifdef HAVE_STRINGS_H -#include -#endif #include #include #include @@ -32,8 +26,8 @@ #include #include #include +#include -#include #include #include #include @@ -47,7 +41,8 @@ #endif /* ! SOL_TCP */ /* Wait MAX_DELAY seconds before a request to the CNID server times out */ -#define MAX_DELAY 10 +#define MAX_DELAY 20 +#define ONE_DELAY 5 static void RQST_RESET(struct cnid_dbd_rqst *r) { @@ -102,7 +97,7 @@ static int tsock_getfd(const char *host, const char *port) } if (setnonblock(sock, 1) != 0) { - LOG(log_error, logtype_cnid, "getfd: setnonblock: %s", strerror(err)); + LOG(log_error, logtype_cnid, "getfd: setnonblock: %s", strerror(errno)); close(sock); sock = -1; return -1; @@ -205,7 +200,7 @@ static int write_vec(int fd, struct iovec *iov, ssize_t towrite, int vecs) continue; if ((! slept) && len == -1 && errno == EAGAIN) { - sleepsecs = 5; + sleepsecs = 2; while ((sleepsecs = sleep(sleepsecs))); slept = 1; continue; @@ -215,7 +210,7 @@ static int write_vec(int fd, struct iovec *iov, ssize_t towrite, int vecs) break; if (len == -1) - LOG(log_error, logtype_cnid, "write_vec: short write: %s", strerror(errno)); + LOG(log_error, logtype_cnid, "write_vec: %s", strerror(errno)); else LOG(log_error, logtype_cnid, "write_vec: short write: %d", len); return len; @@ -271,7 +266,7 @@ static int send_packet(CNID_private *db, struct cnid_dbd_rqst *rqst) vecs = 1; if (rqst->namelen) { - iov[1].iov_base = rqst->name; + iov[1].iov_base = (char *)rqst->name; iov[1].iov_len = rqst->namelen; towrite += rqst->namelen; vecs++; @@ -310,60 +305,6 @@ static int dbd_reply_stamp(struct cnid_dbd_rply *rply) return 0; } -/*! - * Non-blocking read "length" bytes within 1 second using select - * - * @param socket (r) must be nonblocking ! - * @param data (rw) buffer for the read data - * @param lenght (r) how many bytes to read - * - * @returns number of bytes actually read or -1 on fatal error - */ -static ssize_t read_packet(int socket, void *data, const size_t length) -{ - size_t stored; - ssize_t len; - struct timeval tv; - fd_set rfds; - int ret; - - stored = 0; - - while (stored < length) { - len = readt(socket, (u_int8_t *) data + stored, length - stored, 0, 5); - if (len == -1) { - switch (errno) { - case EINTR: - continue; - case EAGAIN: - tv.tv_usec = 0; - tv.tv_sec = 1; - - FD_ZERO(&rfds); - FD_SET(socket, &rfds); - while ((ret = select(socket + 1, &rfds, NULL, NULL, &tv)) < 1) { - switch (ret) { - case 0: - LOG(log_warning, logtype_cnid, "select timeout 1s"); - return stored; - default: /* -1 */ - LOG(log_error, logtype_cnid, "select: %s", strerror(errno)); - return -1; - } - } - continue; - } - LOG(log_error, logtype_cnid, "read: %s", strerror(errno)); - return -1; - } - else if (len > 0) - stored += len; - else - break; - } - return stored; -} - /* --------------------- * send a request and get reply * assume send is non blocking @@ -381,11 +322,11 @@ static int dbd_rpc(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd len = rply->namelen; nametmp = rply->name; - ret = read_packet(db->fd, rply, sizeof(struct cnid_dbd_rply)); + ret = readt(db->fd, rply, sizeof(struct cnid_dbd_rply), 0, ONE_DELAY); if (ret != sizeof(struct cnid_dbd_rply)) { - LOG(log_error, logtype_cnid, "dbd_rpc: Error reading header from fd (db_dir %s): %s", - db->db_dir, ret == -1?strerror(errno):"closed"); + LOG(log_debug, logtype_cnid, "dbd_rpc: Error reading header from fd (db_dir %s): %s", + db->db_dir, ret == -1 ? strerror(errno) : "closed"); rply->name = nametmp; return -1; } @@ -396,7 +337,7 @@ static int dbd_rpc(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd db->db_dir, rply->name, rply->namelen, len); return -1; } - if (rply->namelen && (ret = read_packet(db->fd, rply->name, rply->namelen)) != (ssize_t)rply->namelen) { + if (rply->namelen && (ret = readt(db->fd, rply->name, rply->namelen, 0, ONE_DELAY)) != (ssize_t)rply->namelen) { LOG(log_error, logtype_cnid, "dbd_rpc: Error reading name from fd (db_dir %s): %s", db->db_dir, ret == -1?strerror(errno):"closed"); return -1; @@ -506,6 +447,7 @@ static struct _cnid_db *cnid_dbd_new(const char *volpath) cdb->cnid_delete = cnid_dbd_delete; cdb->cnid_get = cnid_dbd_get; cdb->cnid_lookup = cnid_dbd_lookup; + cdb->cnid_find = cnid_dbd_find; cdb->cnid_nextid = NULL; cdb->cnid_resolve = cnid_dbd_resolve; cdb->cnid_getstamp = cnid_dbd_getstamp; @@ -589,8 +531,7 @@ void cnid_dbd_close(struct _cnid_db *cdb) /* ---------------------- */ cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st, - const cnid_t did, char *name, const size_t len, - cnid_t hint) + cnid_t did, const char *name, size_t len, cnid_t hint) { CNID_private *db; struct cnid_dbd_rqst rqst; @@ -654,7 +595,7 @@ cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st, } /* ---------------------- */ -cnid_t cnid_dbd_get(struct _cnid_db *cdb, const cnid_t did, char *name, const size_t len) +cnid_t cnid_dbd_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t len) { CNID_private *db; struct cnid_dbd_rqst rqst; @@ -731,11 +672,9 @@ char *cnid_dbd_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t le rqst.op = CNID_DBD_OP_RESOLVE; rqst.cnid = *id; - /* This mimicks the behaviour of the "regular" cnid_resolve. So far, - nobody uses the content of buffer. It only provides space for the - name in the caller. */ - rply.name = (char *)buffer + CNID_HEADER_LEN; - rply.namelen = len - CNID_HEADER_LEN; + /* Pass buffer to transmit so it can stuff the reply data there */ + rply.name = (char *)buffer; + rply.namelen = len; if (transmit(db, &rqst, &rply) < 0) { errno = CNID_ERR_DB; @@ -746,7 +685,7 @@ char *cnid_dbd_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t le switch (rply.result) { case CNID_DBD_RES_OK: *id = rply.did; - name = rply.name; + name = rply.name + CNID_NAME_OFS; LOG(log_debug, logtype_cnid, "cnid_dbd_resolve: resolved did: %u, name: '%s'", ntohl(*id), name); break; case CNID_DBD_RES_NOTFOUND: @@ -782,8 +721,8 @@ int cnid_dbd_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len) } /* ---------------------- */ -cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, - char *name, const size_t len) +cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did, + const char *name, size_t len) { CNID_private *db; struct cnid_dbd_rqst rqst; @@ -844,8 +783,63 @@ cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t } /* ---------------------- */ -int cnid_dbd_update(struct _cnid_db *cdb, const cnid_t id, const struct stat *st, - const cnid_t did, char *name, const size_t len) +int cnid_dbd_find(struct _cnid_db *cdb, const char *name, size_t namelen, void *buffer, size_t buflen) +{ + CNID_private *db; + struct cnid_dbd_rqst rqst; + struct cnid_dbd_rply rply; + int count; + + if (!cdb || !(db = cdb->_private) || !name) { + LOG(log_error, logtype_cnid, "cnid_find: Parameter error"); + errno = CNID_ERR_PARAM; + return CNID_INVALID; + } + + if (namelen > MAXPATHLEN) { + LOG(log_error, logtype_cnid, "cnid_find: Path name is too long"); + errno = CNID_ERR_PATH; + return CNID_INVALID; + } + + LOG(log_debug, logtype_cnid, "cnid_find(\"%s\")", name); + + RQST_RESET(&rqst); + rqst.op = CNID_DBD_OP_SEARCH; + + rqst.name = name; + rqst.namelen = namelen; + + rply.name = buffer; + rply.namelen = buflen; + + if (transmit(db, &rqst, &rply) < 0) { + errno = CNID_ERR_DB; + return CNID_INVALID; + } + + switch (rply.result) { + case CNID_DBD_RES_OK: + count = rply.namelen / sizeof(cnid_t); + LOG(log_debug, logtype_cnid, "cnid_find: got %d matches", count); + break; + case CNID_DBD_RES_NOTFOUND: + count = 0; + break; + case CNID_DBD_RES_ERR_DB: + errno = CNID_ERR_DB; + count = -1; + break; + default: + abort(); + } + + return count; +} + +/* ---------------------- */ +int cnid_dbd_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, + cnid_t did, const char *name, size_t len) { CNID_private *db; struct cnid_dbd_rqst rqst; @@ -899,8 +893,7 @@ int cnid_dbd_update(struct _cnid_db *cdb, const cnid_t id, const struct stat *st /* ---------------------- */ cnid_t cnid_dbd_rebuild_add(struct _cnid_db *cdb, const struct stat *st, - const cnid_t did, char *name, const size_t len, - cnid_t hint) + cnid_t did, const char *name, size_t len, cnid_t hint) { CNID_private *db; struct cnid_dbd_rqst rqst;