/* ------------------------ */
cnid_t cnid_cdb_rebuild_add(struct _cnid_db *cdb, const struct stat *st,
                const cnid_t did, char *name, const size_t len, 
		cnid_t hint)
{
    CNID_private *db;
    DBT key, data;
    int rc;

    if (!cdb || !(db = cdb->_private) || !st || !name || hint == CNID_INVALID || hint < CNID_START) {
        errno = CNID_ERR_PARAM;
        return CNID_INVALID;
    }

#if 0
    /* FIXME: Bjoern does a lookup. Should we not overwrite unconditionally? */
    /* Do a lookup. */
    id = cnid_cdb_lookup(cdb, st, did, name, len);
    /* ... Return id if it is valid, or if Rootinfo is read-only. */
    if (id || (db->flags & CNIDFLAG_DB_RO)) {
#ifdef DEBUG
        LOG(log_debug9, logtype_default, "cnid_add: Looked up did %u, name %s as %u", ntohl(did), name, ntohl(id));
#endif
        return id;
    }
#endif

    /* Initialize our DBT data structures. */
    memset(&key, 0, sizeof(key));
    memset(&data, 0, sizeof(data));

    if ((data.data = make_cnid_data(cdb->flags, st, did, name, len)) == NULL) {
        LOG(log_error, logtype_default, "cnid_add: Path name is too long");
        errno = CNID_ERR_PATH;
        return CNID_INVALID;
    }
    data.size = CNID_HEADER_LEN + len + 1;
    
    memcpy(data.data, &hint, sizeof(hint));
    
    key.data = &hint;
    key.size = sizeof(hint);

    /* Now we need to add the CNID data to the databases. */
    if ((rc = db->db_cnid->put(db->db_cnid, tid, &key, &data, 0))) {
            LOG(log_error, logtype_default
                   , "cnid_add: Failed to add CNID for %s to database using hint %u: %s", 
                   name, ntohl(hint), db_strerror(rc));  
            errno = CNID_ERR_DB;
	    goto cleanup;
    }

    if (set_max_cnid(db, hint) == CNID_INVALID) {
	    errno = CNID_ERR_DB;
	    goto cleanup;
    }

#ifdef DEBUG
    LOG(log_debug9, logtype_default, "cnid_add: Returned CNID for did %u, name %s as %u", ntohl(did), name, ntohl(hint));
#endif

    return hint;

cleanup:
    return CNID_INVALID;
}
Пример #2
0
/* cnid_update: takes the given cnid and updates the metadata.  To
 * handle the did/name data, there are a bunch of functions to get
 * and set the various fields. */
int cnid_cdb_update(struct _cnid_db *cdb, const cnid_t id, const struct stat *st,
                const cnid_t did, char *name, const size_t len
                /*, const char *info, const int infolen*/)
{
    unsigned char *buf;
    CNID_private *db;
    DBT key, pkey, data;
    int rc;
    int notfound = 0;
    char getbuf[CNID_HEADER_LEN + MAXPATHLEN +1];

    if (!cdb || !(db = cdb->_private) || !id || !st || !name || (db->flags & CNIDFLAG_DB_RO)) {
        return -1;
    }

    memset(&key, 0, sizeof(key));
    memset(&pkey, 0, sizeof(pkey));
    memset(&data, 0, sizeof(data));

    buf = make_cnid_data(cdb->flags, st, did, name, len);

    key.data = buf +CNID_DEVINO_OFS;
    key.size = CNID_DEVINO_LEN;
    data.data = getbuf;
    data.size = CNID_HEADER_LEN + MAXPATHLEN + 1;

    if (0 != (rc = db->db_devino->pget(db->db_devino, tid, &key, &pkey, &data, 0)) ) {
#if DB_VERSION_MAJOR >= 4
        if (rc != DB_NOTFOUND && rc != DB_SECONDARY_BAD) {
#else
	if (rc != DB_NOTFOUND) {
#endif
           LOG(log_error, logtype_default, "cnid_update: Unable to get devino CNID %u, name %s: %s",
               ntohl(did), name, db_strerror(rc));
           goto fin;
        }
        notfound = 1;
    } else {
        if ((rc = db->db_cnid->del(db->db_cnid, tid, &pkey, 0))) {
            LOG(log_error, logtype_default, "cnid_update: Unable to delete CNID %u: %s",
                ntohl(id), db_strerror(rc));
	}
    }

    memset(&pkey, 0, sizeof(pkey));
    buf = make_cnid_data(cdb->flags, st, did, name, len);
    key.data = buf + CNID_DID_OFS;
    key.size = CNID_DID_LEN + len + 1;

    if (0 != (rc = db->db_didname->pget(db->db_didname, tid, &key, &pkey, &data, 0)) ) {
#if DB_VERSION_MAJOR >= 4
        if (rc != DB_NOTFOUND && rc != DB_SECONDARY_BAD) {
#else
	if (rc != DB_NOTFOUND) {
#endif
           LOG(log_error, logtype_default, "cnid_update: Unable to get didname CNID %u, name %s: %s",
               ntohl(did), name, db_strerror(rc));
           goto fin;
        }
        notfound |= 2;
    } else {
        if ((rc = db->db_cnid->del(db->db_cnid, tid, &pkey, 0))) {
            LOG(log_error, logtype_default, "cnid_update: Unable to delete CNID %u: %s",
                ntohl(id), db_strerror(rc));
	}
    }


    memset(&key, 0, sizeof(key));
    key.data = (cnid_t *)&id;
    key.size = sizeof(id);

    memset(&data, 0, sizeof(data));
    /* Make a new entry. */
    buf = make_cnid_data(cdb->flags, st, did, name, len);
    data.data = buf;
    memcpy(data.data, &id, sizeof(id));
    data.size = CNID_HEADER_LEN + len + 1;

    /* Update the old CNID with the new info. */
    if ((rc = db->db_cnid->put(db->db_cnid, tid, &key, &data, 0))) {
        LOG(log_error, logtype_default, "cnid_update: (%d) Unable to update CNID %u:%s: %s",
            notfound, ntohl(id), name, db_strerror(rc));
        goto fin;
    }

    return 0;
fin:
    return -1;
 
}
Пример #3
0
/* ------------------------ */
cnid_t cnid_cdb_add(struct _cnid_db *cdb, const struct stat *st,
                    cnid_t did, const char *name, size_t len, cnid_t hint)
{
    CNID_private *db;
    DBT key, data;
    cnid_t id;
    int rc;

    if (!cdb || !(db = cdb->_private) || !st || !name) {
        errno = CNID_ERR_PARAM;
        return CNID_INVALID;
    }

    /* Do a lookup. */
    id = cnid_cdb_lookup(cdb, st, did, name, len);
    /* ... Return id if it is valid, or if Rootinfo is read-only. */
    if (id || (db->flags & CNIDFLAG_DB_RO)) {
#ifdef DEBUG
        LOG(log_debug9, logtype_default, "cnid_add: Looked up did %u, name %s as %u", ntohl(did), name, ntohl(id));
#endif
        return id;
    }

    /* Initialize our DBT data structures. */
    memset(&key, 0, sizeof(key));
    memset(&data, 0, sizeof(data));

    if ((data.data = make_cnid_data(cdb->flags, st, did, name, len)) == NULL) {
        LOG(log_error, logtype_default, "cnid_add: Path name is too long");
        errno = CNID_ERR_PATH;
        return CNID_INVALID;
    }
    data.size = CNID_HEADER_LEN + len + 1;

    if ((hint = get_cnid(db)) == 0) {
         errno = CNID_ERR_DB;
         return CNID_INVALID;
    }
    memcpy(data.data, &hint, sizeof(hint));
    
    key.data = &hint;
    key.size = sizeof(hint);

    /* Now we need to add the CNID data to the databases. */
    if ((rc = db->db_cnid->put(db->db_cnid, tid, &key, &data, DB_NOOVERWRITE))) {
        if (rc == EINVAL) {
            /* if we have a duplicate
             * on cnid it's a fatal error.
             * on dev:inode
             *   - leftover should have been delete before.
             *   - a second process already updated the db
             *   - it's a new file eg our file is already deleted and replaced
             * on did:name leftover
            */
            if (cnid_cdb_update(cdb, hint, st, did, name, len)) {
                errno = CNID_ERR_DB;
                return CNID_INVALID;
            }
        }
        else {
            LOG(log_error, logtype_default
                   , "cnid_add: Failed to add CNID for %s to database using hint %u: %s", 
                   name, ntohl(hint), db_strerror(rc));  
            errno = CNID_ERR_DB;
            return CNID_INVALID;
        }
    }

#ifdef DEBUG
    LOG(log_debug9, logtype_default, "cnid_add: Returned CNID for did %u, name %s as %u", ntohl(did), name, ntohl(hint));
#endif

    return hint;
}
Пример #4
0
/* This returns the CNID corresponding to a particular file.  It will
 * also fix up the various databases if there's a problem. */
cnid_t cnid_cdb_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did,
                       const char *name, size_t len)
{
    unsigned char *buf;
    CNID_private *db;
    DBT key, devdata, diddata;
    char dev[CNID_DEV_LEN];
    char ino[CNID_INO_LEN];  
    int devino = 1, didname = 1; 
    u_int32_t type_devino  = (unsigned)-1;
    u_int32_t type_didname = (unsigned)-1;
    u_int32_t type;
    int update = 0;
    cnid_t id_devino, id_didname,id = 0;
    int rc;

    if (!cdb || !(db = cdb->_private) || !st || !name) {
        return 0;
    }
    
    if ((buf = make_cnid_data(cdb->flags, st, did, name, len)) == NULL) {
        LOG(log_error, logtype_default, "cnid_lookup: Pathname is too long");
        return 0;
    }

    memcpy(&type, buf +CNID_TYPE_OFS, sizeof(type));
    type = ntohl(type);

    memset(&key, 0, sizeof(key));
    memset(&diddata, 0, sizeof(diddata));
    memset(&devdata, 0, sizeof(devdata));

    /* Look for a CNID for our did/name */
    key.data = buf +CNID_DEVINO_OFS;
    key.size = CNID_DEVINO_LEN;

    memcpy(dev, buf + CNID_DEV_OFS, CNID_DEV_LEN);
    memcpy(ino, buf + CNID_INO_OFS, CNID_INO_LEN);
    
    if (0 != (rc = db->db_didname->get(db->db_devino, NULL, &key, &devdata, 0 )) ) {
        if (rc != DB_NOTFOUND) {
            LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID did 0x%x, name %s: %s",
               did, name, db_strerror(rc));
            return 0;
        }
        devino = 0;
    }
    else {
        memcpy(&id_devino, devdata.data, sizeof(cnid_t));
        memcpy(&type_devino, (char *)devdata.data +CNID_TYPE_OFS, sizeof(type_devino));
        type_devino = ntohl(type_devino);
    }

    buf = make_cnid_data(cdb->flags, st, did, name, len);
    key.data = buf +CNID_DID_OFS;
    key.size = CNID_DID_LEN + len + 1;
    
    if (0 != (rc = db->db_didname->get(db->db_didname, NULL, &key, &diddata, 0 ) ) ) {
        if (rc != DB_NOTFOUND) {
            LOG(log_error, logtype_default, "cnid_lookup: Unable to get CNID did 0x%x, name %s: %s",
               did, name, db_strerror(rc));
            return 0;
        }
        didname = 0;
    }
    else {
        memcpy(&id_didname, diddata.data, sizeof(cnid_t));
        memcpy(&type_didname, (char *)diddata.data +CNID_TYPE_OFS, sizeof(type_didname));
        type_didname = ntohl(type_didname);
    }

    if (!devino && !didname) {  
        return 0;
    }

    if (devino && didname && id_devino == id_didname && type_devino == type) {
        /* the same */
        return id_didname;
    }
 
    if (didname) {
        id = id_didname;
        /* we have a did:name 
         * if it's the same dev or not the same type
         * just delete it
        */
        if (!memcmp(dev, (char *)diddata.data + CNID_DEV_OFS, CNID_DEV_LEN) ||
                   type_didname != type) {
            if (cnid_cdb_delete(cdb, id) < 0) {
                return 0;
            }
        }
        else {
            update = 1;
        }
    }

    if (devino) {
        id = id_devino;
        if (type_devino != type) {
            /* same dev:inode but not same type one is a folder the other 
             * is a file,it's an inode reused, delete the record
            */
            if (cnid_cdb_delete(cdb, id) < 0) {
                return 0;
            }
        }
        else {
            update = 1;
        }
    }
    if (!update) {
        return 0;
    }
    /* Fix up the database. assume it was a file move and rename */
    cnid_cdb_update(cdb, id, st, did, name, len);

#ifdef DEBUG
    LOG(log_debug9, logtype_default, "cnid_lookup: Looked up did %u, name %s, as %u (needed update)", ntohl(did), name, ntohl(id));
#endif
    return id;
}