static dav_error * dav_propdb_get_rollback(dav_db *db, const dav_prop_name *name, dav_deadprop_rollback **prollback) { dav_deadprop_rollback *rb = apr_pcalloc(db->pool, sizeof(*rb)); apr_datum_t key; apr_datum_t value; dav_error *err; key = dav_build_key(db, name); rb->key.dptr = apr_pstrdup(db->pool, key.dptr); rb->key.dsize = key.dsize; if ((err = dav_dbm_fetch(db, key, &value)) != NULL) return err; if (value.dptr != NULL) { rb->value.dptr = apr_pmemdup(db->pool, value.dptr, value.dsize); rb->value.dsize = value.dsize; } *prollback = rb; return NULL; }
static dav_error * dav_propdb_output_value(dav_db *db, const dav_prop_name *name, dav_xmlns_info *xi, apr_text_header *phdr, int *found) { apr_datum_t key = dav_build_key(db, name); apr_datum_t value; dav_error *err; if ((err = dav_dbm_fetch(db, key, &value)) != NULL) return err; if (value.dptr == NULL) { *found = 0; return NULL; } *found = 1; dav_append_prop(db->pool, key.dptr, value.dptr, phdr); dav_dbm_freedatum(db, value); return NULL; }
/* ** dav_load_lock_record: Reads lock information about key from lock db; ** creates linked lists of the direct and indirect locks. ** ** If add_method = DAV_APPEND_LIST, the result will be appended to the ** head of the direct and indirect lists supplied. ** ** Passive lock removal: If lock has timed out, it will not be returned. ** ### How much "logging" does RFC 2518 require? */ static dav_error * dav_fs_load_lock_record(dav_lockdb *lockdb, apr_datum_t key, int add_method, dav_lock_discovery **direct, dav_lock_indirect **indirect) { apr_pool_t *p = lockdb->info->pool; dav_error *err; apr_size_t offset = 0; int need_save = DAV_FALSE; apr_datum_t val = { 0 }; dav_lock_discovery *dp; dav_lock_indirect *ip; dav_buffer buf = { 0 }; if (add_method != DAV_APPEND_LIST) { *direct = NULL; *indirect = NULL; } if ((err = dav_fs_really_open_lockdb(lockdb)) != NULL) { /* ### add a higher-level error? */ return err; } /* ** If we opened readonly and the db wasn't there, then there are no ** locks for this resource. Just exit. */ if (lockdb->info->db == NULL) return NULL; if ((err = dav_dbm_fetch(lockdb->info->db, key, &val)) != NULL) return err; if (!val.dsize) return NULL; while (offset < val.dsize) { switch (*(val.dptr + offset++)) { case DAV_LOCK_DIRECT: /* Create and fill a dav_lock_discovery structure */ dp = apr_pcalloc(p, sizeof(*dp)); memcpy(dp, val.dptr + offset, sizeof(dp->f)); offset += sizeof(dp->f); dp->locktoken = apr_pmemdup(p, val.dptr + offset, sizeof(*dp->locktoken)); offset += sizeof(*dp->locktoken); if (*(val.dptr + offset) == '\0') { ++offset; } else { dp->owner = apr_pstrdup(p, val.dptr + offset); offset += strlen(dp->owner) + 1; } if (*(val.dptr + offset) == '\0') { ++offset; } else { dp->auth_user = apr_pstrdup(p, val.dptr + offset); offset += strlen(dp->auth_user) + 1; } if (!dav_fs_lock_expired(dp->f.timeout)) { dp->next = *direct; *direct = dp; } else { need_save = DAV_TRUE; /* Remove timed-out locknull fm .locknull list */ if (*key.dptr == DAV_TYPE_FNAME) { const char *fname = key.dptr + 1; apr_finfo_t finfo; apr_status_t rv; /* if we don't see the file, then it's a locknull */ rv = apr_stat(&finfo, fname, APR_FINFO_MIN | APR_FINFO_LINK, p); if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) { if ((err = dav_fs_remove_locknull_member(p, fname, &buf)) != NULL) { /* ### push a higher-level description? */ return err; } } } } break; case DAV_LOCK_INDIRECT: /* Create and fill a dav_lock_indirect structure */ ip = apr_pcalloc(p, sizeof(*ip)); ip->locktoken = apr_pmemdup(p, val.dptr + offset, sizeof(*ip->locktoken)); offset += sizeof(*ip->locktoken); memcpy(&ip->timeout, val.dptr + offset, sizeof(ip->timeout)); offset += sizeof(ip->timeout); memcpy(&ip->key.dsize, val.dptr + offset, sizeof(ip->key.dsize)); /* length of datum */ offset += sizeof(ip->key.dsize); ip->key.dptr = apr_pmemdup(p, val.dptr + offset, ip->key.dsize); offset += ip->key.dsize; if (!dav_fs_lock_expired(ip->timeout)) { ip->next = *indirect; *indirect = ip; } else { need_save = DAV_TRUE; /* A locknull resource will never be locked indirectly */ } break; default: dav_dbm_freedatum(lockdb->info->db, val); /* ### should use a computed_desc and insert corrupt token data */ --offset; return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, DAV_ERR_LOCK_CORRUPT_DB, 0, apr_psprintf(p, "The lock database was found to " "be corrupt. offset %" APR_SIZE_T_FMT ", c=%02x", offset, val.dptr[offset])); } } dav_dbm_freedatum(lockdb->info->db, val); /* Clean up this record if we found expired locks */ /* ** ### shouldn't do this if we've been opened READONLY. elide the ** ### timed-out locks from the response, but don't save that info back */ if (need_save == DAV_TRUE) { return dav_fs_save_lock_record(lockdb, key, *direct, *indirect); } return NULL; }
static dav_error * dav_propdb_open(apr_pool_t *pool, const dav_resource *resource, int ro, dav_db **pdb) { dav_db *db; dav_error *err; apr_datum_t key; apr_datum_t value = { 0 }; *pdb = NULL; /* ** Return if an error occurred, or there is no database. ** ** NOTE: db could be NULL if we attempted to open a readonly ** database that doesn't exist. If we require read/write ** access, then a database was created and opened. */ if ((err = dav_dbm_open(pool, resource, ro, &db)) != NULL || db == NULL) return err; db->uri_index = apr_hash_make(pool); key.dptr = DAV_GDBM_NS_KEY; key.dsize = DAV_GDBM_NS_KEY_LEN; if ((err = dav_dbm_fetch(db, key, &value)) != NULL) { /* ### push a higher-level description? */ return err; } if (value.dptr == NULL) { dav_propdb_metadata m = { DAV_DBVSN_MAJOR, DAV_DBVSN_MINOR, 0 }; /* ** If there is no METADATA key, then the database may be ** from versions 0.9.0 .. 0.9.4 (which would be incompatible). ** These can be identified by the presence of an NS_TABLE entry. */ key.dptr = "NS_TABLE"; key.dsize = 8; if (dav_dbm_exists(db, key)) { dav_dbm_close(db); /* call it a major version error */ return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, DAV_ERR_PROP_BAD_MAJOR, "Prop database has the wrong major " "version number and cannot be used."); } /* initialize a new metadata structure */ dav_set_bufsize(pool, &db->ns_table, sizeof(m)); memcpy(db->ns_table.buf, &m, sizeof(m)); } else { dav_propdb_metadata m; long ns; const char *uri; dav_set_bufsize(pool, &db->ns_table, value.dsize); memcpy(db->ns_table.buf, value.dptr, value.dsize); memcpy(&m, value.dptr, sizeof(m)); if (m.major != DAV_DBVSN_MAJOR) { dav_dbm_close(db); return dav_new_error(pool, HTTP_INTERNAL_SERVER_ERROR, DAV_ERR_PROP_BAD_MAJOR, "Prop database has the wrong major " "version number and cannot be used."); } db->version = m.minor; db->ns_count = ntohs(m.ns_count); dav_dbm_freedatum(db, value); /* create db->uri_index */ for (ns = 0, uri = db->ns_table.buf + sizeof(dav_propdb_metadata); ns++ < db->ns_count; uri += strlen(uri) + 1) { /* we must copy the key, in case ns_table.buf moves */ apr_hash_set(db->uri_index, apr_pstrdup(pool, uri), APR_HASH_KEY_STRING, (void *)ns); } } *pdb = db; return NULL; }