X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=libatalk%2Fcnid%2Fdbd%2Fcnid_dbd.c;h=09cf9ead2ed4f4cc10cf6f4458b8e85545afb7b8;hp=c96a22596163659fc87be4a6b3a60f3eafc6e321;hb=refs%2Fheads%2Fv3.1.3-alex;hpb=53aafa98097fa39b62fd0c7914db291a393aa01b diff --git a/libatalk/cnid/dbd/cnid_dbd.c b/libatalk/cnid/dbd/cnid_dbd.c index c96a2259..09cf9ead 100644 --- a/libatalk/cnid/dbd/cnid_dbd.c +++ b/libatalk/cnid/dbd/cnid_dbd.c @@ -31,8 +31,9 @@ #include #include #include -#include +#include #include +#include #include "cnid_dbd.h" @@ -224,27 +225,49 @@ static int write_vec(int fd, struct iovec *iov, ssize_t towrite, int vecs) } /* --------------------- */ -static int init_tsock(CNID_private *db) +static int init_tsock(CNID_bdb_private *db) { int fd; - int len; - struct iovec iov[2]; + int len[DBD_NUM_OPEN_ARGS]; + int iovecs; + struct iovec iov[DBD_NUM_OPEN_ARGS + 1] = {{0}}; + struct vol *vol = db->vol; + ssize_t iovlen; - LOG(log_debug, logtype_cnid, "init_tsock: BEGIN. Opening volume '%s', CNID Server: %s/%s", - db->db_dir, db->cnidserver, db->cnidport); + LOG(log_debug, logtype_cnid, "connecting to CNID server: %s:%s", + vol->v_cnidserver, vol->v_cnidport); - if ((fd = tsock_getfd(db->cnidserver, db->cnidport)) < 0) + if ((fd = tsock_getfd(vol->v_cnidserver, vol->v_cnidport)) < 0) return -1; - len = strlen(db->db_dir); + LOG(log_debug, logtype_cnid, "connecting volume '%s', path: %s, user: %s", + vol->v_configname, vol->v_path, vol->v_obj->username[0] ? vol->v_obj->username : "-"); + + iovecs = 1 + DBD_NUM_OPEN_ARGS - 1; + + len[0] = strlen(vol->v_configname) + 1; + len[1] = strlen(vol->v_path) + 1; + len[2] = strlen(vol->v_obj->username); + + iov[0].iov_base = &len[0]; + iov[0].iov_len = DBD_NUM_OPEN_ARGS * sizeof(int); - iov[0].iov_base = &len; - iov[0].iov_len = sizeof(int); + iov[1].iov_base = vol->v_configname; + iov[1].iov_len = len[0]; - iov[1].iov_base = db->db_dir; - iov[1].iov_len = len; + iov[2].iov_base = vol->v_path; + iov[2].iov_len = len[1]; - if (write_vec(fd, iov, len + sizeof(int), 2) != len + sizeof(int)) { + if (len[2] > 0) { + len[2] += 1; + iovecs++; + iov[3].iov_base = vol->v_obj->username; + iov[3].iov_len = len[2]; + } + + iovlen = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len + iov[3].iov_len; + + if (write_vec(fd, iov, iovlen, iovecs) != iovlen) { LOG(log_error, logtype_cnid, "init_tsock: Error/short write: %s", strerror(errno)); close(fd); return -1; @@ -256,7 +279,7 @@ static int init_tsock(CNID_private *db) } /* --------------------- */ -static int send_packet(CNID_private *db, struct cnid_dbd_rqst *rqst) +static int send_packet(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst) { struct iovec iov[2]; size_t towrite; @@ -275,8 +298,8 @@ static int send_packet(CNID_private *db, struct cnid_dbd_rqst *rqst) } if (write_vec(db->fd, iov, towrite, vecs) != towrite) { - LOG(log_warning, logtype_cnid, "send_packet: Error writev rqst (db_dir %s): %s", - db->db_dir, strerror(errno)); + LOG(log_warning, logtype_cnid, "send_packet: Error writev rqst (volume %s): %s", + db->vol->v_localname, strerror(errno)); return -1; } @@ -312,7 +335,7 @@ static int dbd_reply_stamp(struct cnid_dbd_rply *rply) * assume send is non blocking * if no answer after sometime (at least MAX_DELAY secondes) return an error */ -static int dbd_rpc(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) +static int dbd_rpc(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) { ssize_t ret; char *nametmp; @@ -327,21 +350,21 @@ static int dbd_rpc(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd ret = readt(db->fd, rply, sizeof(struct cnid_dbd_rply), 0, ONE_DELAY); if (ret != sizeof(struct cnid_dbd_rply)) { - LOG(log_debug, 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 (volume %s): %s", + db->vol->v_localname, ret == -1 ? strerror(errno) : "closed"); rply->name = nametmp; return -1; } rply->name = nametmp; if (rply->namelen && rply->namelen > len) { LOG(log_error, logtype_cnid, - "dbd_rpc: Error reading name (db_dir %s): %s name too long: %d. only wanted %d, garbage?", - db->db_dir, rply->name, rply->namelen, len); + "dbd_rpc: Error reading name (volume %s): %s name too long: %d. only wanted %d, garbage?", + db->vol->v_localname, rply->name, rply->namelen, len); return -1; } 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"); + LOG(log_error, logtype_cnid, "dbd_rpc: Error reading name from fd (volume %s): %s", + db->vol->v_localname, ret == -1?strerror(errno):"closed"); return -1; } @@ -351,52 +374,23 @@ static int dbd_rpc(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd } /* -------------------- */ -static int transmit(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) +static int transmit(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) { time_t orig, t; int clean = 1; /* no errors so far - to prevent sleep on first try */ - if (db->changed) { - /* volume and db don't have the same timestamp - */ - return -1; - } while (1) { if (db->fd == -1) { - struct cnid_dbd_rqst rqst_stamp; - struct cnid_dbd_rply rply_stamp; - char stamp[ADEDLEN_PRIVSYN]; - LOG(log_maxdebug, logtype_cnid, "transmit: connecting to cnid_dbd ..."); if ((db->fd = init_tsock(db)) < 0) { goto transmit_fail; } - dbd_initstamp(&rqst_stamp); - memset(stamp, 0, ADEDLEN_PRIVSYN); - rply_stamp.name = stamp; - rply_stamp.namelen = ADEDLEN_PRIVSYN; - - if (dbd_rpc(db, &rqst_stamp, &rply_stamp) < 0) - goto transmit_fail; - if (dbd_reply_stamp(&rply_stamp ) < 0) - goto transmit_fail; - if (db->notfirst) { - LOG(log_debug7, logtype_cnid, "transmit: reconnected to cnid_dbd, comparing database stamps..."); - if (memcmp(stamp, db->stamp, ADEDLEN_PRIVSYN)) { - LOG(log_error, logtype_cnid, "transmit: ... not the same db!"); - db->changed = 1; - return -1; - } - LOG(log_debug7, logtype_cnid, "transmit: ... OK."); + LOG(log_debug7, logtype_cnid, "transmit: reconnected to cnid_dbd"); } else { /* db->notfirst == 0 */ db->notfirst = 1; - if (db->client_stamp) - memcpy(db->client_stamp, stamp, ADEDLEN_PRIVSYN); - memcpy(db->stamp, stamp, ADEDLEN_PRIVSYN); } - LOG(log_debug, logtype_cnid, "transmit: attached to '%s', stamp: '%08lx'.", - db->db_dir, *(uint64_t *)stamp); + LOG(log_debug, logtype_cnid, "transmit: attached to '%s'", db->vol->v_localname); } if (!dbd_rpc(db, rqst, rply)) { LOG(log_maxdebug, logtype_cnid, "transmit: {done}"); @@ -410,14 +404,14 @@ static int transmit(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_db if (errno == ECONNREFUSED) { /* errno carefully injected in tsock_getfd */ /* give up */ - LOG(log_error, logtype_cnid, "transmit: connection refused (db_dir %s)", db->db_dir); + LOG(log_error, logtype_cnid, "transmit: connection refused (volume %s)", db->vol->v_localname); return -1; } if (!clean) { /* don't sleep if just got disconnected by cnid server */ time(&t); if (t - orig > MAX_DELAY) { - LOG(log_error, logtype_cnid, "transmit: Request to dbd daemon (db_dir %s) timed out.", db->db_dir); + LOG(log_error, logtype_cnid, "transmit: Request to dbd daemon (volume %s) timed out.", db->vol->v_localname); return -1; } /* sleep a little before retry */ @@ -431,20 +425,15 @@ static int transmit(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_db } /* ---------------------- */ -static struct _cnid_db *cnid_dbd_new(const char *volpath) +static struct _cnid_db *cnid_dbd_new(struct vol *vol) { struct _cnid_db *cdb; if ((cdb = (struct _cnid_db *)calloc(1, sizeof(struct _cnid_db))) == NULL) return NULL; - if ((cdb->volpath = strdup(volpath)) == NULL) { - free(cdb); - return NULL; - } - - cdb->flags = CNID_FLAG_PERSISTENT | CNID_FLAG_LAZY_INIT; - + cdb->cnid_db_vol = vol; + cdb->cnid_db_flags = CNID_FLAG_PERSISTENT | CNID_FLAG_LAZY_INIT; cdb->cnid_add = cnid_dbd_add; cdb->cnid_delete = cnid_dbd_delete; cdb->cnid_get = cnid_dbd_get; @@ -456,51 +445,39 @@ static struct _cnid_db *cnid_dbd_new(const char *volpath) cdb->cnid_update = cnid_dbd_update; cdb->cnid_rebuild_add = cnid_dbd_rebuild_add; cdb->cnid_close = cnid_dbd_close; - + cdb->cnid_wipe = cnid_dbd_wipe; return cdb; } /* ---------------------- */ struct _cnid_db *cnid_dbd_open(struct cnid_open_args *args) { - CNID_private *db = NULL; + CNID_bdb_private *db = NULL; struct _cnid_db *cdb = NULL; - if (!args->dir) { - return NULL; - } - - if ((cdb = cnid_dbd_new(args->dir)) == NULL) { + if ((cdb = cnid_dbd_new(args->cnid_args_vol)) == NULL) { LOG(log_error, logtype_cnid, "cnid_open: Unable to allocate memory for database"); return NULL; } - if ((db = (CNID_private *)calloc(1, sizeof(CNID_private))) == NULL) { + if ((db = (CNID_bdb_private *)calloc(1, sizeof(CNID_bdb_private))) == NULL) { LOG(log_error, logtype_cnid, "cnid_open: Unable to allocate memory for database"); goto cnid_dbd_open_fail; } - cdb->_private = db; + cdb->cnid_db_private = db; - /* We keep a copy of the directory in the db structure so that we can - transparently reconnect later. */ - strcpy(db->db_dir, args->dir); - db->magic = CNID_DB_MAGIC; db->fd = -1; - db->cnidserver = strdup(args->cnidserver); - db->cnidport = strdup(args->cnidport); + db->vol = args->cnid_args_vol; - LOG(log_debug, logtype_cnid, "cnid_dbd_open: Finished initializing cnid dbd module for volume '%s'", db->db_dir); + LOG(log_debug, logtype_cnid, "Finished initializing CNID dbd module for volume '%s'", + args->cnid_args_vol->v_localname); return cdb; cnid_dbd_open_fail: - if (cdb != NULL) { - if (cdb->volpath != NULL) { - free(cdb->volpath); - } + if (cdb != NULL) free(cdb); - } if (db != NULL) free(db); @@ -510,37 +487,62 @@ cnid_dbd_open_fail: /* ---------------------- */ void cnid_dbd_close(struct _cnid_db *cdb) { - CNID_private *db; + CNID_bdb_private *db; if (!cdb) { LOG(log_error, logtype_cnid, "cnid_close called with NULL argument!"); return; } - if ((db = cdb->_private) != NULL) { - LOG(log_debug, logtype_cnid, "closing database connection for volume '%s'", db->db_dir); + if ((db = cdb->cnid_db_private) != NULL) { + LOG(log_debug, logtype_cnid, "closing database connection for volume '%s'", db->vol->v_localname); if (db->fd >= 0) close(db->fd); free(db); } - free(cdb->volpath); free(cdb); return; } +/** + * Get the db stamp + **/ +static int cnid_dbd_stamp(CNID_bdb_private *db) +{ + struct cnid_dbd_rqst rqst_stamp; + struct cnid_dbd_rply rply_stamp; + char stamp[ADEDLEN_PRIVSYN]; + + dbd_initstamp(&rqst_stamp); + memset(stamp, 0, ADEDLEN_PRIVSYN); + rply_stamp.name = stamp; + rply_stamp.namelen = ADEDLEN_PRIVSYN; + + if (transmit(db, &rqst_stamp, &rply_stamp) < 0) + return -1; + if (dbd_reply_stamp(&rply_stamp ) < 0) + return -1; + + if (db->client_stamp) + memcpy(db->client_stamp, stamp, ADEDLEN_PRIVSYN); + memcpy(db->stamp, stamp, ADEDLEN_PRIVSYN); + + return 0; +} + /* ---------------------- */ cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st, cnid_t did, const char *name, size_t len, cnid_t hint) { - CNID_private *db; + CNID_bdb_private *db; struct cnid_dbd_rqst rqst; struct cnid_dbd_rply rply; cnid_t id; - if (!cdb || !(db = cdb->_private) || !st || !name) { + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) { LOG(log_error, logtype_cnid, "cnid_add: Parameter error"); errno = CNID_ERR_PARAM; return CNID_INVALID; @@ -555,7 +557,7 @@ cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st, RQST_RESET(&rqst); rqst.op = CNID_DBD_OP_ADD; - if (!(cdb->flags & CNID_FLAG_NODEV)) { + if (!(cdb->cnid_db_flags & CNID_FLAG_NODEV)) { rqst.dev = st->st_dev; } @@ -566,8 +568,8 @@ cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st, rqst.name = name; rqst.namelen = len; - LOG(log_debug, logtype_cnid, "cnid_dbd_add: CNID: %u, name: '%s', inode: 0x%llx, type: %d (0=file, 1=dir)", - ntohl(did), name, (long long)st->st_ino, rqst.type); + LOG(log_debug, logtype_cnid, "cnid_dbd_add: CNID: %u, name: '%s', dev: 0x%llx, inode: 0x%llx, type: %s", + ntohl(did), name, (long long)rqst.dev, (long long)st->st_ino, rqst.type ? "dir" : "file"); rply.namelen = 0; if (transmit(db, &rqst, &rply) < 0) { @@ -599,12 +601,12 @@ cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st, /* ---------------------- */ cnid_t cnid_dbd_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t len) { - CNID_private *db; + CNID_bdb_private *db; struct cnid_dbd_rqst rqst; struct cnid_dbd_rply rply; cnid_t id; - if (!cdb || !(db = cdb->_private) || !name) { + if (!cdb || !(db = cdb->cnid_db_private) || !name) { LOG(log_error, logtype_cnid, "cnid_dbd_get: Parameter error"); errno = CNID_ERR_PARAM; return CNID_INVALID; @@ -652,12 +654,12 @@ cnid_t cnid_dbd_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t l /* ---------------------- */ char *cnid_dbd_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t len) { - CNID_private *db; + CNID_bdb_private *db; struct cnid_dbd_rqst rqst; struct cnid_dbd_rply rply; char *name; - if (!cdb || !(db = cdb->_private) || !id || !(*id)) { + if (!cdb || !(db = cdb->cnid_db_private) || !id || !(*id)) { LOG(log_error, logtype_cnid, "cnid_resolve: Parameter error"); errno = CNID_ERR_PARAM; return NULL; @@ -706,32 +708,34 @@ char *cnid_dbd_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t le return name; } -/* ---------------------- */ +/** + * Caller passes buffer where we will store the db stamp + **/ int cnid_dbd_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len) { - CNID_private *db; + CNID_bdb_private *db; - if (!cdb || !(db = cdb->_private) || len != ADEDLEN_PRIVSYN) { + if (!cdb || !(db = cdb->cnid_db_private) || len != ADEDLEN_PRIVSYN) { LOG(log_error, logtype_cnid, "cnid_getstamp: Parameter error"); errno = CNID_ERR_PARAM; return -1; } db->client_stamp = buffer; db->stamp_size = len; - memset(buffer,0, len); - return 0; + + return cnid_dbd_stamp(db); } /* ---------------------- */ 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; + CNID_bdb_private *db; struct cnid_dbd_rqst rqst; struct cnid_dbd_rply rply; cnid_t id; - if (!cdb || !(db = cdb->_private) || !st || !name) { + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) { LOG(log_error, logtype_cnid, "cnid_lookup: Parameter error"); errno = CNID_ERR_PARAM; return CNID_INVALID; @@ -746,7 +750,7 @@ cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did, RQST_RESET(&rqst); rqst.op = CNID_DBD_OP_LOOKUP; - if (!(cdb->flags & CNID_FLAG_NODEV)) { + if (!(cdb->cnid_db_flags & CNID_FLAG_NODEV)) { rqst.dev = st->st_dev; } @@ -787,12 +791,12 @@ cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did, /* ---------------------- */ int cnid_dbd_find(struct _cnid_db *cdb, const char *name, size_t namelen, void *buffer, size_t buflen) { - CNID_private *db; + CNID_bdb_private *db; struct cnid_dbd_rqst rqst; struct cnid_dbd_rply rply; int count; - if (!cdb || !(db = cdb->_private) || !name) { + if (!cdb || !(db = cdb->cnid_db_private) || !name) { LOG(log_error, logtype_cnid, "cnid_find: Parameter error"); errno = CNID_ERR_PARAM; return CNID_INVALID; @@ -843,11 +847,11 @@ int cnid_dbd_find(struct _cnid_db *cdb, const char *name, size_t namelen, void * 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; + CNID_bdb_private *db; struct cnid_dbd_rqst rqst; struct cnid_dbd_rply rply; - if (!cdb || !(db = cdb->_private) || !id || !st || !name) { + if (!cdb || !(db = cdb->cnid_db_private) || !id || !st || !name) { LOG(log_error, logtype_cnid, "cnid_update: Parameter error"); errno = CNID_ERR_PARAM; return -1; @@ -862,7 +866,7 @@ int cnid_dbd_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, RQST_RESET(&rqst); rqst.op = CNID_DBD_OP_UPDATE; rqst.cnid = id; - if (!(cdb->flags & CNID_FLAG_NODEV)) { + if (!(cdb->cnid_db_flags & CNID_FLAG_NODEV)) { rqst.dev = st->st_dev; } rqst.ino = st->st_ino; @@ -897,12 +901,12 @@ int cnid_dbd_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, cnid_t cnid_dbd_rebuild_add(struct _cnid_db *cdb, const struct stat *st, cnid_t did, const char *name, size_t len, cnid_t hint) { - CNID_private *db; + CNID_bdb_private *db; struct cnid_dbd_rqst rqst; struct cnid_dbd_rply rply; cnid_t id; - if (!cdb || !(db = cdb->_private) || !st || !name || hint == CNID_INVALID) { + if (!cdb || !(db = cdb->cnid_db_private) || !st || !name || hint == CNID_INVALID) { LOG(log_error, logtype_cnid, "cnid_rebuild_add: Parameter error"); errno = CNID_ERR_PARAM; return CNID_INVALID; @@ -917,7 +921,7 @@ cnid_t cnid_dbd_rebuild_add(struct _cnid_db *cdb, const struct stat *st, RQST_RESET(&rqst); rqst.op = CNID_DBD_OP_REBUILD_ADD; - if (!(cdb->flags & CNID_FLAG_NODEV)) { + if (!(cdb->cnid_db_flags & CNID_FLAG_NODEV)) { rqst.dev = st->st_dev; } @@ -959,11 +963,11 @@ cnid_t cnid_dbd_rebuild_add(struct _cnid_db *cdb, const struct stat *st, /* ---------------------- */ int cnid_dbd_delete(struct _cnid_db *cdb, const cnid_t id) { - CNID_private *db; + CNID_bdb_private *db; struct cnid_dbd_rqst rqst; struct cnid_dbd_rply rply; - if (!cdb || !(db = cdb->_private) || !id) { + if (!cdb || !(db = cdb->cnid_db_private) || !id) { LOG(log_error, logtype_cnid, "cnid_delete: Parameter error"); errno = CNID_ERR_PARAM; return -1; @@ -994,6 +998,39 @@ int cnid_dbd_delete(struct _cnid_db *cdb, const cnid_t id) } } +int cnid_dbd_wipe(struct _cnid_db *cdb) +{ + CNID_bdb_private *db; + struct cnid_dbd_rqst rqst; + struct cnid_dbd_rply rply; + + if (!cdb || !(db = cdb->cnid_db_private)) { + LOG(log_error, logtype_cnid, "cnid_wipe: Parameter error"); + errno = CNID_ERR_PARAM; + return -1; + } + + LOG(log_debug, logtype_cnid, "cnid_dbd_wipe"); + + RQST_RESET(&rqst); + rqst.op = CNID_DBD_OP_WIPE; + rqst.cnid = 0; + + rply.namelen = 0; + if (transmit(db, &rqst, &rply) < 0) { + errno = CNID_ERR_DB; + return -1; + } + + if (rply.result != CNID_DBD_RES_OK) { + errno = CNID_ERR_DB; + return -1; + } + LOG(log_debug, logtype_cnid, "cnid_dbd_wipe: ok"); + + return cnid_dbd_stamp(db); +} + struct _cnid_module cnid_dbd_module = { "dbd",