/* ** dav_fs_load_locknull_list: Returns a dav_buffer dump of the locknull file ** for the given directory. */ static dav_error * dav_fs_load_locknull_list(apr_pool_t *p, const char *dirpath, dav_buffer *pbuf) { apr_finfo_t finfo; apr_file_t *file = NULL; dav_error *err = NULL; apr_size_t amt; apr_status_t rv; dav_buffer_init(p, pbuf, dirpath); if (pbuf->buf[pbuf->cur_len - 1] == '/') pbuf->buf[--pbuf->cur_len] = '\0'; dav_buffer_place(p, pbuf, "/" DAV_FS_STATE_DIR "/" DAV_FS_LOCK_NULL_FILE); /* reset this in case we leave w/o reading into the buffer */ pbuf->cur_len = 0; if (apr_file_open(&file, pbuf->buf, APR_READ | APR_BINARY, APR_OS_DEFAULT, p) != APR_SUCCESS) { return NULL; } rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, file); if (rv != APR_SUCCESS) { err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, rv, apr_psprintf(p, "Opened but could not stat file %s", pbuf->buf)); goto loaderror; } if (finfo.size != (apr_size_t)finfo.size) { err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, 0, apr_psprintf(p, "Opened but rejected huge file %s", pbuf->buf)); goto loaderror; } amt = (apr_size_t)finfo.size; dav_set_bufsize(p, pbuf, amt); if ((rv = apr_file_read(file, pbuf->buf, &amt)) != APR_SUCCESS || amt != finfo.size) { err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, rv, apr_psprintf(p, "Failure reading locknull file " "for %s", dirpath)); /* just in case the caller disregards the returned error */ pbuf->cur_len = 0; goto loaderror; } loaderror: apr_file_close(file); return err; }
/* ** dav_fs_load_locknull_list: Returns a dav_buffer dump of the locknull file ** for the given directory. */ static dav_error * dav_fs_load_locknull_list(pool *p, const char *dirpath, dav_buffer *pbuf) { struct stat finfo; int fd; dav_error *err = NULL; dav_buffer_init(p, pbuf, dirpath); if (pbuf->buf[pbuf->cur_len - 1] == '/') pbuf->buf[--pbuf->cur_len] = '\0'; dav_buffer_place(p, pbuf, "/" DAV_FS_STATE_DIR "/" DAV_FS_LOCK_NULL_FILE); /* reset this in case we leave w/o reading into the buffer */ pbuf->cur_len = 0; if ((fd = open(pbuf->buf, O_RDONLY | O_BINARY)) == -1) { return NULL; } if (fstat(fd, &finfo) == -1) { err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, ap_psprintf(p, "Opened but could not stat file %s", pbuf->buf)); goto loaderror; } dav_set_bufsize(p, pbuf, finfo.st_size); if (read(fd, pbuf->buf, finfo.st_size) != finfo.st_size) { err = dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0, ap_psprintf(p, "Failure reading locknull file " "for %s", dirpath)); /* just in case the caller disregards the returned error */ pbuf->cur_len = 0; goto loaderror; } loaderror: close(fd); return err; }
/* ** Internal function to build a key ** ** WARNING: returns a pointer to a "static" buffer holding the key. The ** value must be copied or no longer used if this function is ** called again. */ static apr_datum_t dav_build_key(dav_db *db, const dav_prop_name *name) { char nsbuf[20]; apr_size_t l_ns, l_name = strlen(name->name); apr_datum_t key = { 0 }; /* * Convert namespace ID to a string. "no namespace" is an empty string, * so the keys will have the form ":name". Otherwise, the keys will * have the form "#:name". */ if (*name->ns == '\0') { nsbuf[0] = '\0'; l_ns = 0; } else { long ns_id = (long)apr_hash_get(db->uri_index, name->ns, APR_HASH_KEY_STRING); if (ns_id == 0) { /* the namespace was not found(!) */ return key; /* zeroed */ } l_ns = sprintf(nsbuf, "%ld", ns_id - 1); } /* assemble: #:name */ dav_set_bufsize(db->pool, &db->wb_key, l_ns + 1 + l_name + 1); memcpy(db->wb_key.buf, nsbuf, l_ns); db->wb_key.buf[l_ns] = ':'; memcpy(&db->wb_key.buf[l_ns + 1], name->name, l_name + 1); /* build the database key */ key.dsize = l_ns + 1 + l_name + 1; key.dptr = db->wb_key.buf; return key; }
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; }