📄 serve.c
字号:
/* Check authorizations */ SVN_ERR(must_have_access(conn, pool, b, svn_authz_read, full_path, FALSE)); if (!SVN_IS_VALID_REVNUM(rev)) SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->fs, pool)); SVN_CMD_ERR(svn_fs_revision_root(&root, b->fs, rev, pool)); SVN_CMD_ERR(svn_repos_stat(&dirent, root, full_path, pool)); /* Need to return the equivalent of "(?l)", since that's what the client is reading. */ if (dirent == NULL) { SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "()")); return SVN_NO_ERROR; } cdate = (dirent->time == (time_t) -1) ? NULL : svn_time_to_cstring(dirent->time, pool); SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "((wnbr(?c)(?c)))", kind_word(dirent->kind), (apr_uint64_t) dirent->size, dirent->has_props, dirent->created_rev, cdate, dirent->last_author)); return SVN_NO_ERROR;}static svn_error_t *get_locations(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_array_header_t *params, void *baton){ svn_error_t *err, *write_err; server_baton_t *b = baton; svn_revnum_t revision; apr_array_header_t *location_revisions, *loc_revs_proto; svn_ra_svn_item_t *elt; int i; const char *relative_path; svn_revnum_t peg_revision; apr_hash_t *fs_locations; apr_hash_index_t *iter; const char *abs_path; const void *iter_key; void *iter_value; /* Parse the arguments. */ SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "crl", &relative_path, &peg_revision, &loc_revs_proto)); relative_path = svn_path_canonicalize(relative_path, pool); abs_path = svn_path_join(b->fs_path->data, relative_path, pool); location_revisions = apr_array_make(pool, loc_revs_proto->nelts, sizeof(svn_revnum_t)); for (i = 0; i < loc_revs_proto->nelts; i++) { elt = &APR_ARRAY_IDX(loc_revs_proto, i, svn_ra_svn_item_t); if (elt->kind != SVN_RA_SVN_NUMBER) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, "Get-locations location revisions entry " "not a revision number"); revision = (svn_revnum_t)(elt->u.number); APR_ARRAY_PUSH(location_revisions, svn_revnum_t) = revision; } SVN_ERR(trivial_auth_request(conn, pool, b)); /* All the parameters are fine - let's perform the query against the * repository. */ /* We store both err and write_err here, so the client will get * the "done" even if there was an error in fetching the results. */ err = svn_repos_trace_node_locations(b->fs, &fs_locations, abs_path, peg_revision, location_revisions, authz_check_access_cb_func(b), b, pool); /* Now, write the results to the connection. */ if (!err) { if (fs_locations) { for (iter = apr_hash_first(pool, fs_locations); iter; iter = apr_hash_next(iter)) { apr_hash_this(iter, &iter_key, NULL, &iter_value); SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "rc", *(const svn_revnum_t *)iter_key, (const char *)iter_value)); } } } write_err = svn_ra_svn_write_word(conn, pool, "done"); if (write_err) { svn_error_clear(err); return write_err; } SVN_CMD_ERR(err); SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "")); return SVN_NO_ERROR;}/* This implements svn_write_fn_t. Write LEN bytes starting at DATA to the client as a string. */static svn_error_t *svndiff_handler(void *baton, const char *data, apr_size_t *len){ file_revs_baton_t *b = baton; svn_string_t str; str.data = data; str.len = *len; return svn_ra_svn_write_string(b->conn, b->pool, &str);}/* This implements svn_close_fn_t. Mark the end of the data by writing an empty string to the client. */static svn_error_t *svndiff_close_handler(void *baton){ file_revs_baton_t *b = baton; SVN_ERR(svn_ra_svn_write_cstring(b->conn, b->pool, "")); return SVN_NO_ERROR;}/* This implements the svn_repos_file_rev_handler_t interface. */static svn_error_t *file_rev_handler(void *baton, const char *path, svn_revnum_t rev, apr_hash_t *rev_props, svn_txdelta_window_handler_t *d_handler, void **d_baton, apr_array_header_t *prop_diffs, apr_pool_t *pool){ file_revs_baton_t *frb = baton; svn_stream_t *stream; SVN_ERR(svn_ra_svn_write_tuple(frb->conn, pool, "cr(!", path, rev)); SVN_ERR(write_proplist(frb->conn, pool, rev_props)); SVN_ERR(svn_ra_svn_write_tuple(frb->conn, pool, "!)(!")); SVN_ERR(write_prop_diffs(frb->conn, pool, prop_diffs)); SVN_ERR(svn_ra_svn_write_tuple(frb->conn, pool, "!)")); /* Store the pool for the delta stream. */ frb->pool = pool; /* Prepare for the delta or just write an empty string. */ if (d_handler) { stream = svn_stream_create(baton, pool); svn_stream_set_write(stream, svndiff_handler); svn_stream_set_close(stream, svndiff_close_handler); svn_txdelta_to_svndiff(stream, pool, d_handler, d_baton); } else SVN_ERR(svn_ra_svn_write_cstring(frb->conn, pool, "")); return SVN_NO_ERROR;}static svn_error_t *get_file_revs(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_array_header_t *params, void *baton){ server_baton_t *b = baton; svn_error_t *err, *write_err; file_revs_baton_t frb; svn_revnum_t start_rev, end_rev; const char *path; const char *full_path; /* Parse arguments. */ SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?r)(?r)", &path, &start_rev, &end_rev)); path = svn_path_canonicalize(path, pool); SVN_ERR(trivial_auth_request(conn, pool, b)); full_path = svn_path_join(b->fs_path->data, path, pool); frb.conn = conn; frb.pool = NULL; err = svn_repos_get_file_revs(b->repos, full_path, start_rev, end_rev, authz_check_access_cb_func(b), b, file_rev_handler, &frb, pool); write_err = svn_ra_svn_write_word(conn, pool, "done"); if (write_err) { svn_error_clear(err); return write_err; } SVN_CMD_ERR(err); SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "")); return SVN_NO_ERROR;}static svn_error_t *lock(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_array_header_t *params, void *baton){ server_baton_t *b = baton; const char *path; const char *comment; const char *full_path; svn_boolean_t steal_lock; svn_revnum_t current_rev; svn_lock_t *l; SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?c)b(?r)", &path, &comment, &steal_lock, ¤t_rev)); full_path = svn_path_join(b->fs_path->data, svn_path_canonicalize(path, pool), pool); SVN_ERR(must_have_access(conn, pool, b, svn_authz_write, full_path, TRUE)); SVN_CMD_ERR(svn_repos_fs_lock(&l, b->repos, full_path, NULL, comment, 0, 0, /* No expiration time. */ current_rev, steal_lock, pool)); SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "w(!", "success")); SVN_ERR(write_lock(conn, pool, l)); SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)")); return SVN_NO_ERROR;}static svn_error_t *lock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_array_header_t *params, void *baton){ server_baton_t *b = baton; apr_array_header_t *path_revs; const char *comment; svn_boolean_t steal_lock; int i; apr_pool_t *subpool; const char *path; const char *full_path; svn_revnum_t current_rev; svn_lock_t *l; svn_error_t *err = SVN_NO_ERROR, *write_err; SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "(?c)bl", &comment, &steal_lock, &path_revs)); subpool = svn_pool_create(pool); /* Because we can only send a single auth reply per request, we send a reply before parsing the lock commands. This means an authz access denial will abort the processing of the locks and return an error. */ SVN_ERR(must_have_access(conn, pool, b, svn_authz_write, NULL, TRUE)); /* Loop through the lock requests. */ for (i = 0; i < path_revs->nelts; ++i) { svn_ra_svn_item_t *item = &APR_ARRAY_IDX(path_revs, i, svn_ra_svn_item_t); svn_pool_clear(subpool); if (item->kind != SVN_RA_SVN_LIST) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, "Lock requests should be list of lists"); SVN_ERR(svn_ra_svn_parse_tuple(item->u.list, pool, "c(?r)", &path, ¤t_rev)); full_path = svn_path_join(b->fs_path->data, svn_path_canonicalize(path, subpool), subpool); if (! lookup_access(pool, b, svn_authz_write, full_path, TRUE)) { err = svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL, NULL); break; } err = svn_repos_fs_lock(&l, b->repos, full_path, NULL, comment, FALSE, 0, /* No expiration time. */ current_rev, steal_lock, subpool); if (err) { if (SVN_ERR_IS_LOCK_ERROR(err)) { write_err = svn_ra_svn_write_cmd_failure(conn, pool, err); svn_error_clear(err); err = NULL; SVN_ERR(write_err); } else break; } else { SVN_ERR(svn_ra_svn_write_tuple(conn, subpool, "w!", "success")); SVN_ERR(write_lock(conn, subpool, l)); SVN_ERR(svn_ra_svn_write_tuple(conn, subpool, "!")); } } svn_pool_destroy(subpool); /* NOTE: err might contain a fatal locking error from the loop above. */ write_err = svn_ra_svn_write_word(conn, pool, "done"); if (!write_err) SVN_CMD_ERR(err); svn_error_clear(err); SVN_ERR(write_err); SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "")); return SVN_NO_ERROR;}static svn_error_t *unlock(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_array_header_t *params, void *baton){ server_baton_t *b = baton; const char *path, *token, *full_path; svn_boolean_t break_lock; SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?c)b", &path, &token, &break_lock)); full_path = svn_path_join(b->fs_path->data, svn_path_canonicalize(path, pool), pool); /* Username required unless break_lock was specified. */ SVN_ERR(must_have_access(conn, pool, b, svn_authz_write, full_path, ! break_lock)); SVN_CMD_ERR(svn_repos_fs_unlock(b->repos, full_path, token, break_lock, pool)); SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "")); return SVN_NO_ERROR;}static svn_error_t *unlock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_array_header_t *params, void *baton){ server_baton_t *b = baton; svn_boolean_t break_lock; apr_array_header_t *unlock_tokens; int i; apr_pool_t *subpool; const char *path; const char *full_path; const char *token; svn_error_t *err = SVN_NO_ERROR, *write_err; SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "bl", &break_lock,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -