static dav_error * dav_rainx_deliver_SPECIAL(const dav_resource *resource, ap_filter_t *output) { const char *result; int result_len; apr_status_t status; apr_pool_t *pool; apr_bucket_brigade *bb; apr_bucket *bkt; DAV_XDEBUG_RES(resource, 0, "%s()", __FUNCTION__); pool = resource->info->request->pool; /* Check resource type */ if (resource->type != DAV_RESOURCE_TYPE_PRIVATE) return server_create_and_stat_error(resource_get_server_config(resource), pool, HTTP_CONFLICT, 0, apr_pstrdup(pool, "Cannot GET this type of resource.")); if (resource->collection) return server_create_and_stat_error(resource_get_server_config(resource), pool, HTTP_CONFLICT, 0, apr_pstrdup(pool,"No GET on collections")); /* Generate the output */ result = resource->info->generator(resource, pool); result_len = strlen(result); /* We must reply a buffer */ bkt = apr_bucket_heap_create(result, result_len, NULL, output->c->bucket_alloc); bb = apr_brigade_create(pool, output->c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, bkt); /* Nothing more to reply */ bkt = apr_bucket_eos_create(output->c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, bkt); DAV_XDEBUG_RES(resource, 0, "%s : ready to deliver", __FUNCTION__); if ((status = ap_pass_brigade(output, bb)) != APR_SUCCESS) return server_create_and_stat_error(resource_get_server_config(resource), pool, HTTP_FORBIDDEN, 0, apr_pstrdup(pool,"Could not write contents to filter.")); server_inc_stat(resource_get_server_config(resource), RAWX_STATNAME_REP_2XX, 0); /* HERE ADD request counter */ switch(resource->info->type) { case STAT: server_inc_request_stat(resource_get_server_config(resource), RAWX_STATNAME_REQ_STAT, request_get_duration(resource->info->request)); break; case INFO: server_inc_request_stat(resource_get_server_config(resource), RAWX_STATNAME_REQ_INFO, request_get_duration(resource->info->request)); break; default: break; } return NULL; }
void server_inc_daverror_stat(dav_rawx_server_conf *conf, dav_error *derr) { if (!derr) { server_inc_stat(conf, RAWX_STATNAME_REP_2XX, 0); return; } switch (derr->status / 100) { case 2: server_inc_stat(conf, RAWX_STATNAME_REP_2XX, 0); return; case 4: server_inc_stat(conf, RAWX_STATNAME_REP_4XX, 0); if (derr->status == 403) server_inc_stat(conf, RAWX_STATNAME_REP_403, 0); else if (derr->status == 403) server_inc_stat(conf, RAWX_STATNAME_REP_404, 0); return; case 5: server_inc_stat(conf, RAWX_STATNAME_REP_5XX, 0); return; default: server_inc_stat(conf, RAWX_STATNAME_REP_OTHER, 0); return; } }
static dav_error * dav_rawx_move_resource(dav_resource *src_res, dav_resource *dst_res, dav_response **response) { char buff[128]; apr_pool_t *pool; pool = dst_res->pool; apr_status_t status; dav_error *e = NULL; dav_rawx_server_conf *srv_conf = resource_get_server_config(src_res); *response = NULL; if (DAV_RESOURCE_TYPE_REGULAR != src_res->type) { e = server_create_and_stat_error(srv_conf, pool, HTTP_CONFLICT, 0, "Cannot MOVE this type of resource."); goto end_move; } if (src_res->collection) { e = server_create_and_stat_error(srv_conf, pool, HTTP_CONFLICT, 0, "No MOVE on collections"); goto end_move; } if (apr_strnatcasecmp(src_res->info->hex_chunkid, dst_res->info->hex_chunkid)) { e = server_create_and_stat_error(srv_conf, pool, HTTP_FORBIDDEN, 0, "Source and destination chunk ids are not the same"); goto end_move; } DAV_DEBUG_RES(src_res, 0, "Moving %s to %s", resource_get_pathname(src_res), resource_get_pathname(dst_res)); status = apr_file_rename(resource_get_pathname(src_res), resource_get_pathname(dst_res), pool); if (status != APR_SUCCESS) { e = server_create_and_stat_error(srv_conf, pool, HTTP_INTERNAL_SERVER_ERROR, status, apr_pstrcat(pool, "Failed to MOVE this chunk: ", apr_strerror(status, buff, sizeof(buff)), NULL)); goto end_move; } server_inc_stat(srv_conf, RAWX_STATNAME_REP_2XX, 0); end_move: server_inc_request_stat(srv_conf, RAWX_STATNAME_REQ_OTHER, request_get_duration(src_res->info->request)); return e; }
static dav_error * dav_rawx_remove_resource(dav_resource *resource, dav_response **response) { char buff[128]; apr_pool_t *pool; apr_status_t status; dav_error *e = NULL; DAV_XDEBUG_RES(resource, 0, "%s(%s)", __FUNCTION__, resource_get_pathname(resource)); pool = resource->pool; *response = NULL; if (DAV_RESOURCE_TYPE_REGULAR != resource->type) { e = server_create_and_stat_error(resource_get_server_config(resource), pool, HTTP_CONFLICT, 0, "Cannot DELETE this type of resource."); goto end_remove; } if (resource->collection) { e = server_create_and_stat_error(resource_get_server_config(resource), pool, HTTP_CONFLICT, 0, "No DELETE on collections"); goto end_remove; } status = apr_file_remove(resource_get_pathname(resource), pool); if (APR_SUCCESS != status) { e = server_create_and_stat_error(resource_get_server_config(resource), pool, HTTP_FORBIDDEN, 0, apr_pstrcat(pool, "Failed to DELETE this chunk : ", apr_strerror(status, buff, sizeof(buff)), NULL)); goto end_remove; } send_chunk_event("storage.chunk.deleted", resource); resource->exists = 0; resource->collection = 0; server_inc_stat(resource_get_server_config(resource), RAWX_STATNAME_REP_2XX, 0); end_remove: /* Now we pass here even if an error occured, for process request duration */ server_inc_request_stat(resource_get_server_config(resource), RAWX_STATNAME_REQ_CHUNKDEL, request_get_duration(resource->info->request)); return e; }
void server_inc_request_stat(dav_rawx_server_conf *conf, const char *n, apr_time_t duration) { server_inc_stat(conf, n, duration); server_inc_stat(conf, RAWX_STATNAME_REQ_ALL, duration); }
static dav_error * dav_rawx_deliver(const dav_resource *resource, ap_filter_t *output) { dav_rawx_server_conf *conf; apr_pool_t *pool; apr_bucket_brigade *bb = NULL; apr_status_t status; apr_bucket *bkt = NULL; dav_resource_private *ctx; dav_error *e = NULL; apr_finfo_t info; DAV_XDEBUG_RES(resource, 0, "%s(%s)", __FUNCTION__, resource_get_pathname(resource)); pool = resource->pool; conf = resource_get_server_config(resource); /* Check resource type */ if (DAV_RESOURCE_TYPE_REGULAR != resource->type) { e = server_create_and_stat_error(conf, pool, HTTP_CONFLICT, 0, "Cannot GET this type of resource."); goto end_deliver; } if (resource->collection) { e = server_create_and_stat_error(conf, pool, HTTP_CONFLICT, 0, "No GET on collections"); goto end_deliver; } ctx = resource->info; if (ctx->update_only) { /* Check if it is not a busy file. We accept reads during * compression but not attr updates. */ char *pending_file = apr_pstrcat(pool, resource_get_pathname(resource), ".pending", NULL); status = apr_stat(&info, pending_file, APR_FINFO_ATIME, pool); if (status == APR_SUCCESS) { e = server_create_and_stat_error(conf, pool, HTTP_FORBIDDEN, 0, "File in pending mode."); goto end_deliver; } GError *error_local = NULL; /* UPDATE chunk attributes and go on */ const char *path = resource_get_pathname(resource); FILE *f = NULL; f = fopen(path, "r"); /* Try to open the file but forbids a creation */ if (!set_rawx_info_to_fd(fileno(f), &error_local, &(ctx->chunk))) { fclose(f); e = server_create_and_stat_error(conf, pool, HTTP_FORBIDDEN, 0, apr_pstrdup(pool, gerror_get_message(error_local))); g_clear_error(&error_local); goto end_deliver; } fclose(f); } else { bb = apr_brigade_create(pool, output->c->bucket_alloc); if (!ctx->compression){ apr_file_t *fd = NULL; /* Try to open the file but forbids a creation */ status = apr_file_open(&fd, resource_get_pathname(resource), APR_READ|APR_BINARY|APR_BUFFERED, 0, pool); if (APR_SUCCESS != status) { e = server_create_and_stat_error(conf, pool, HTTP_FORBIDDEN, 0, "File permissions deny server access."); goto end_deliver; } /* FIXME this does not handle large files. but this is test code anyway */ bkt = apr_bucket_file_create(fd, 0, (apr_size_t)resource->info->finfo.size, pool, output->c->bucket_alloc); } else { DAV_DEBUG_RES(resource, 0, "Building a compressed resource bucket"); gint i64; i64 = g_ascii_strtoll(ctx->cp_chunk.uncompressed_size, NULL, 10); /* creation of compression specific bucket */ bkt = apr_pcalloc(pool, sizeof(struct apr_bucket)); bkt->type = &chunk_bucket_type; bkt->length = i64; bkt->start = 0; bkt->data = ctx; bkt->free = chunk_bucket_free_noop; bkt->list = output->c->bucket_alloc; } APR_BRIGADE_INSERT_TAIL(bb, bkt); /* as soon as the chunk has been sent, end of stream!*/ bkt = apr_bucket_eos_create(output->c->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, bkt); if ((status = ap_pass_brigade(output, bb)) != APR_SUCCESS){ e = server_create_and_stat_error(conf, pool, HTTP_FORBIDDEN, 0, "Could not write contents to filter."); /* close file */ if (ctx->cp_chunk.fd) { fclose(ctx->cp_chunk.fd); } goto end_deliver; } if (ctx->cp_chunk.buf){ g_free(ctx->cp_chunk.buf); ctx->cp_chunk.buf = NULL; } if (ctx->cp_chunk.uncompressed_size){ g_free(ctx->cp_chunk.uncompressed_size); ctx->cp_chunk.uncompressed_size = NULL; } /* close file */ if (ctx->cp_chunk.fd) { fclose(ctx->cp_chunk.fd); } server_inc_stat(conf, RAWX_STATNAME_REP_2XX, 0); server_add_stat(conf, RAWX_STATNAME_REP_BWRITTEN, resource->info->finfo.size, 0); } end_deliver: if (bb) { apr_brigade_destroy(bb); bb = NULL; } /* Now we pass here even if an error occured, for process request duration */ server_inc_request_stat(resource_get_server_config(resource), RAWX_STATNAME_REQ_CHUNKGET, request_get_duration(resource->info->request)); return e; }