static dav_error * dav_rawx_close_stream(dav_stream *stream, int commit) { /* LAST STEP OF PUT REQUEST */ dav_error *e = NULL; DAV_DEBUG_REQ(stream->r->info->request, 0, "Closing (%s) the stream to [%s]", (commit ? "commit" : "rollback"), stream->pathname); if (!commit) { e = rawx_repo_rollback_upload(stream); } else { e = rawx_repo_write_last_data_crumble(stream); if (e) { DAV_DEBUG_REQ(stream->r->info->request, 0, "Cannot commit, an error occured while writing end of data"); dav_error *e_tmp = NULL; e_tmp = rawx_repo_rollback_upload(stream); if (e_tmp) { DAV_ERROR_REQ(stream->r->info->request, 0, "Error while rolling back upload: %s", e_tmp->desc); } } else { e = rawx_repo_commit_upload(stream); } } /* stats update */ if (stream->total_size > 0) { server_add_stat(resource_get_server_config(stream->r), RAWX_STATNAME_REP_BWRITTEN, stream->total_size, 0); } server_inc_request_stat(resource_get_server_config(stream->r), RAWX_STATNAME_REQ_CHUNKPUT, request_get_duration(stream->r->info->request)); if (stream->md5) { g_checksum_free(stream->md5); stream->md5 = NULL; } return e; }
void server_inc_stat(dav_rawx_server_conf *conf, const char *n, apr_time_t duration) { server_add_stat(conf, n, 1U, 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; }