1289177Speter/* 2289177Speter * stat.c : file and directory stat and read functions 3289177Speter * 4289177Speter * ==================================================================== 5289177Speter * Licensed to the Apache Software Foundation (ASF) under one 6289177Speter * or more contributor license agreements. See the NOTICE file 7289177Speter * distributed with this work for additional information 8289177Speter * regarding copyright ownership. The ASF licenses this file 9289177Speter * to you under the Apache License, Version 2.0 (the 10289177Speter * "License"); you may not use this file except in compliance 11289177Speter * with the License. You may obtain a copy of the License at 12289177Speter * 13289177Speter * http://www.apache.org/licenses/LICENSE-2.0 14289177Speter * 15289177Speter * Unless required by applicable law or agreed to in writing, 16289177Speter * software distributed under the License is distributed on an 17289177Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18289177Speter * KIND, either express or implied. See the License for the 19289177Speter * specific language governing permissions and limitations 20289177Speter * under the License. 21289177Speter * ==================================================================== 22289177Speter */ 23289177Speter 24289177Speter 25289177Speter 26289177Speter#define APR_WANT_STRFUNC 27289177Speter#include <apr_want.h> 28289177Speter 29289177Speter#include <serf.h> 30289177Speter 31289177Speter#include "svn_private_config.h" 32289177Speter#include "svn_pools.h" 33289177Speter#include "svn_xml.h" 34289177Speter#include "../libsvn_ra/ra_loader.h" 35289177Speter#include "svn_config.h" 36289177Speter#include "svn_dirent_uri.h" 37289177Speter#include "svn_hash.h" 38289177Speter#include "svn_path.h" 39289177Speter#include "svn_props.h" 40289177Speter#include "svn_time.h" 41289177Speter#include "svn_version.h" 42289177Speter 43289177Speter#include "private/svn_dav_protocol.h" 44289177Speter#include "private/svn_dep_compat.h" 45289177Speter#include "private/svn_fspath.h" 46289177Speter 47289177Speter#include "ra_serf.h" 48289177Speter 49289177Speter 50289177Speter 51289177Speter/* Implements svn_ra__vtable_t.check_path(). */ 52289177Spetersvn_error_t * 53289177Spetersvn_ra_serf__check_path(svn_ra_session_t *ra_session, 54289177Speter const char *relpath, 55289177Speter svn_revnum_t revision, 56289177Speter svn_node_kind_t *kind, 57289177Speter apr_pool_t *scratch_pool) 58289177Speter{ 59289177Speter svn_ra_serf__session_t *session = ra_session->priv; 60289177Speter apr_hash_t *props; 61289177Speter svn_error_t *err; 62289177Speter const char *url; 63289177Speter 64289177Speter url = session->session_url.path; 65289177Speter 66289177Speter /* If we have a relative path, append it. */ 67289177Speter if (relpath) 68289177Speter url = svn_path_url_add_component2(url, relpath, scratch_pool); 69289177Speter 70289177Speter /* If we were given a specific revision, get a URL that refers to that 71289177Speter specific revision (rather than floating with HEAD). */ 72289177Speter if (SVN_IS_VALID_REVNUM(revision)) 73289177Speter { 74289177Speter SVN_ERR(svn_ra_serf__get_stable_url(&url, NULL /* latest_revnum */, 75289177Speter session, 76289177Speter url, revision, 77289177Speter scratch_pool, scratch_pool)); 78289177Speter } 79289177Speter 80289177Speter /* URL is stable, so we use SVN_INVALID_REVNUM since it is now irrelevant. 81289177Speter Or we started with SVN_INVALID_REVNUM and URL may be floating. */ 82289177Speter err = svn_ra_serf__fetch_node_props(&props, session, 83289177Speter url, SVN_INVALID_REVNUM, 84289177Speter check_path_props, 85289177Speter scratch_pool, scratch_pool); 86289177Speter 87289177Speter if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND) 88289177Speter { 89289177Speter svn_error_clear(err); 90289177Speter *kind = svn_node_none; 91289177Speter } 92289177Speter else 93289177Speter { 94289177Speter apr_hash_t *dav_props; 95289177Speter const char *res_type; 96289177Speter 97289177Speter /* Any other error, raise to caller. */ 98289177Speter SVN_ERR(err); 99289177Speter 100289177Speter dav_props = apr_hash_get(props, "DAV:", 4); 101289177Speter res_type = svn_prop_get_value(dav_props, "resourcetype"); 102289177Speter if (!res_type) 103289177Speter { 104289177Speter /* How did this happen? */ 105289177Speter return svn_error_create(SVN_ERR_RA_DAV_PROPS_NOT_FOUND, NULL, 106289177Speter _("The PROPFIND response did not include the " 107289177Speter "requested resourcetype value")); 108289177Speter } 109289177Speter 110289177Speter if (strcmp(res_type, "collection") == 0) 111289177Speter *kind = svn_node_dir; 112289177Speter else 113289177Speter *kind = svn_node_file; 114289177Speter } 115289177Speter 116289177Speter return SVN_NO_ERROR; 117289177Speter} 118289177Speter 119289177Speter 120289177Speter/* Baton for fill_dirent_propfunc() */ 121289177Speterstruct fill_dirent_baton_t 122289177Speter{ 123289177Speter /* Update the fields in this entry. */ 124289177Speter svn_dirent_t *entry; 125289177Speter 126289177Speter svn_tristate_t *supports_deadprop_count; 127289177Speter 128289177Speter /* If allocations are necessary, then use this pool. */ 129289177Speter apr_pool_t *result_pool; 130289177Speter}; 131289177Speter 132289177Speter/* Implements svn_ra_serf__prop_func_t */ 133289177Speterstatic svn_error_t * 134289177Speterfill_dirent_propfunc(void *baton, 135289177Speter const char *path, 136289177Speter const char *ns, 137289177Speter const char *name, 138289177Speter const svn_string_t *val, 139289177Speter apr_pool_t *scratch_pool) 140289177Speter{ 141289177Speter struct fill_dirent_baton_t *fdb = baton; 142289177Speter 143289177Speter if (strcmp(ns, "DAV:") == 0) 144289177Speter { 145289177Speter if (strcmp(name, SVN_DAV__VERSION_NAME) == 0) 146289177Speter { 147289177Speter apr_int64_t rev; 148289177Speter SVN_ERR(svn_cstring_atoi64(&rev, val->data)); 149289177Speter 150289177Speter fdb->entry->created_rev = (svn_revnum_t)rev; 151289177Speter } 152289177Speter else if (strcmp(name, "creator-displayname") == 0) 153289177Speter { 154289177Speter fdb->entry->last_author = apr_pstrdup(fdb->result_pool, val->data); 155289177Speter } 156289177Speter else if (strcmp(name, SVN_DAV__CREATIONDATE) == 0) 157289177Speter { 158289177Speter SVN_ERR(svn_time_from_cstring(&fdb->entry->time, 159289177Speter val->data, 160289177Speter fdb->result_pool)); 161289177Speter } 162289177Speter else if (strcmp(name, "getcontentlength") == 0) 163289177Speter { 164289177Speter /* 'getcontentlength' property is empty for directories. */ 165289177Speter if (val->len) 166289177Speter { 167289177Speter SVN_ERR(svn_cstring_atoi64(&fdb->entry->size, val->data)); 168289177Speter } 169289177Speter } 170289177Speter else if (strcmp(name, "resourcetype") == 0) 171289177Speter { 172289177Speter if (strcmp(val->data, "collection") == 0) 173289177Speter { 174289177Speter fdb->entry->kind = svn_node_dir; 175289177Speter } 176289177Speter else 177289177Speter { 178289177Speter fdb->entry->kind = svn_node_file; 179289177Speter } 180289177Speter } 181289177Speter } 182289177Speter else if (strcmp(ns, SVN_DAV_PROP_NS_CUSTOM) == 0) 183289177Speter { 184289177Speter fdb->entry->has_props = TRUE; 185289177Speter } 186289177Speter else if (strcmp(ns, SVN_DAV_PROP_NS_SVN) == 0) 187289177Speter { 188289177Speter fdb->entry->has_props = TRUE; 189289177Speter } 190289177Speter else if (strcmp(ns, SVN_DAV_PROP_NS_DAV) == 0) 191289177Speter { 192289177Speter if(strcmp(name, "deadprop-count") == 0) 193289177Speter { 194289177Speter if (*val->data) 195289177Speter { 196289177Speter apr_int64_t deadprop_count; 197289177Speter SVN_ERR(svn_cstring_atoi64(&deadprop_count, val->data)); 198289177Speter fdb->entry->has_props = deadprop_count > 0; 199289177Speter if (fdb->supports_deadprop_count) 200289177Speter *fdb->supports_deadprop_count = svn_tristate_true; 201289177Speter } 202289177Speter else if (fdb->supports_deadprop_count) 203289177Speter *fdb->supports_deadprop_count = svn_tristate_false; 204289177Speter } 205289177Speter } 206289177Speter 207289177Speter return SVN_NO_ERROR; 208289177Speter} 209289177Speter 210289177Speterstatic const svn_ra_serf__dav_props_t * 211289177Speterget_dirent_props(apr_uint32_t dirent_fields, 212289177Speter svn_ra_serf__session_t *session, 213289177Speter apr_pool_t *pool) 214289177Speter{ 215289177Speter svn_ra_serf__dav_props_t *prop; 216289177Speter apr_array_header_t *props = apr_array_make 217289177Speter (pool, 7, sizeof(svn_ra_serf__dav_props_t)); 218289177Speter 219289177Speter if (session->supports_deadprop_count != svn_tristate_false 220289177Speter || ! (dirent_fields & SVN_DIRENT_HAS_PROPS)) 221289177Speter { 222289177Speter if (dirent_fields & SVN_DIRENT_KIND) 223289177Speter { 224289177Speter prop = apr_array_push(props); 225289177Speter prop->xmlns = "DAV:"; 226289177Speter prop->name = "resourcetype"; 227289177Speter } 228289177Speter 229289177Speter if (dirent_fields & SVN_DIRENT_SIZE) 230289177Speter { 231289177Speter prop = apr_array_push(props); 232289177Speter prop->xmlns = "DAV:"; 233289177Speter prop->name = "getcontentlength"; 234289177Speter } 235289177Speter 236289177Speter if (dirent_fields & SVN_DIRENT_HAS_PROPS) 237289177Speter { 238289177Speter prop = apr_array_push(props); 239289177Speter prop->xmlns = SVN_DAV_PROP_NS_DAV; 240289177Speter prop->name = "deadprop-count"; 241289177Speter } 242289177Speter 243289177Speter if (dirent_fields & SVN_DIRENT_CREATED_REV) 244289177Speter { 245289177Speter svn_ra_serf__dav_props_t *p = apr_array_push(props); 246289177Speter p->xmlns = "DAV:"; 247289177Speter p->name = SVN_DAV__VERSION_NAME; 248289177Speter } 249289177Speter 250289177Speter if (dirent_fields & SVN_DIRENT_TIME) 251289177Speter { 252289177Speter prop = apr_array_push(props); 253289177Speter prop->xmlns = "DAV:"; 254289177Speter prop->name = SVN_DAV__CREATIONDATE; 255289177Speter } 256289177Speter 257289177Speter if (dirent_fields & SVN_DIRENT_LAST_AUTHOR) 258289177Speter { 259289177Speter prop = apr_array_push(props); 260289177Speter prop->xmlns = "DAV:"; 261289177Speter prop->name = "creator-displayname"; 262289177Speter } 263289177Speter } 264289177Speter else 265289177Speter { 266289177Speter /* We found an old subversion server that can't handle 267289177Speter the deadprop-count property in the way we expect. 268289177Speter 269289177Speter The neon behavior is to retrieve all properties in this case */ 270289177Speter prop = apr_array_push(props); 271289177Speter prop->xmlns = "DAV:"; 272289177Speter prop->name = "allprop"; 273289177Speter } 274289177Speter 275289177Speter prop = apr_array_push(props); 276289177Speter prop->xmlns = NULL; 277289177Speter prop->name = NULL; 278289177Speter 279289177Speter return (svn_ra_serf__dav_props_t *) props->elts; 280289177Speter} 281289177Speter 282289177Speter/* Implements svn_ra__vtable_t.stat(). */ 283289177Spetersvn_error_t * 284289177Spetersvn_ra_serf__stat(svn_ra_session_t *ra_session, 285289177Speter const char *relpath, 286289177Speter svn_revnum_t revision, 287289177Speter svn_dirent_t **dirent, 288289177Speter apr_pool_t *pool) 289289177Speter{ 290289177Speter svn_ra_serf__session_t *session = ra_session->priv; 291289177Speter svn_error_t *err; 292289177Speter struct fill_dirent_baton_t fdb; 293289177Speter svn_tristate_t deadprop_count = svn_tristate_unknown; 294289177Speter svn_ra_serf__handler_t *handler; 295289177Speter const char *url; 296289177Speter 297289177Speter url = session->session_url.path; 298289177Speter 299289177Speter /* If we have a relative path, append it. */ 300289177Speter if (relpath) 301289177Speter url = svn_path_url_add_component2(url, relpath, pool); 302289177Speter 303289177Speter /* If we were given a specific revision, get a URL that refers to that 304289177Speter specific revision (rather than floating with HEAD). */ 305289177Speter if (SVN_IS_VALID_REVNUM(revision)) 306289177Speter { 307289177Speter SVN_ERR(svn_ra_serf__get_stable_url(&url, NULL /* latest_revnum */, 308289177Speter session, 309289177Speter url, revision, 310289177Speter pool, pool)); 311289177Speter } 312289177Speter 313289177Speter fdb.entry = svn_dirent_create(pool); 314289177Speter fdb.supports_deadprop_count = &deadprop_count; 315289177Speter fdb.result_pool = pool; 316289177Speter 317289177Speter SVN_ERR(svn_ra_serf__create_propfind_handler(&handler, session, url, 318289177Speter SVN_INVALID_REVNUM, "0", 319289177Speter get_dirent_props(SVN_DIRENT_ALL, 320289177Speter session, 321289177Speter pool), 322289177Speter fill_dirent_propfunc, &fdb, pool)); 323289177Speter 324289177Speter err = svn_ra_serf__context_run_one(handler, pool); 325289177Speter 326289177Speter if (err) 327289177Speter { 328289177Speter if (err->apr_err == SVN_ERR_FS_NOT_FOUND) 329289177Speter { 330289177Speter svn_error_clear(err); 331289177Speter *dirent = NULL; 332289177Speter return SVN_NO_ERROR; 333289177Speter } 334289177Speter else 335289177Speter return svn_error_trace(err); 336289177Speter } 337289177Speter 338289177Speter if (deadprop_count == svn_tristate_false 339289177Speter && session->supports_deadprop_count == svn_tristate_unknown 340289177Speter && !fdb.entry->has_props) 341289177Speter { 342289177Speter /* We have to requery as the server didn't give us the right 343289177Speter information */ 344289177Speter session->supports_deadprop_count = svn_tristate_false; 345289177Speter 346289177Speter /* Run the same handler again */ 347289177Speter SVN_ERR(svn_ra_serf__context_run_one(handler, pool)); 348289177Speter } 349289177Speter 350289177Speter if (deadprop_count != svn_tristate_unknown) 351289177Speter session->supports_deadprop_count = deadprop_count; 352289177Speter 353289177Speter *dirent = fdb.entry; 354289177Speter 355289177Speter return SVN_NO_ERROR; 356289177Speter} 357289177Speter 358289177Speter/* Baton for get_dir_dirents_cb and get_dir_props_cb */ 359289177Speterstruct get_dir_baton_t 360289177Speter{ 361289177Speter apr_pool_t *result_pool; 362289177Speter apr_hash_t *dirents; 363289177Speter apr_hash_t *ret_props; 364289177Speter svn_boolean_t is_directory; 365289177Speter svn_tristate_t supports_deadprop_count; 366289177Speter const char *path; 367289177Speter}; 368289177Speter 369289177Speter/* Implements svn_ra_serf__prop_func_t */ 370289177Speterstatic svn_error_t * 371289177Speterget_dir_dirents_cb(void *baton, 372289177Speter const char *path, 373289177Speter const char *ns, 374289177Speter const char *name, 375289177Speter const svn_string_t *value, 376289177Speter apr_pool_t *scratch_pool) 377289177Speter{ 378289177Speter struct get_dir_baton_t *db = baton; 379289177Speter const char *relpath; 380289177Speter 381289177Speter relpath = svn_fspath__skip_ancestor(db->path, path); 382289177Speter 383289177Speter if (relpath && relpath[0] != '\0') 384289177Speter { 385289177Speter struct fill_dirent_baton_t fdb; 386289177Speter 387289177Speter relpath = svn_path_uri_decode(relpath, scratch_pool); 388289177Speter fdb.entry = svn_hash_gets(db->dirents, relpath); 389289177Speter 390289177Speter if (!fdb.entry) 391289177Speter { 392289177Speter fdb.entry = svn_dirent_create(db->result_pool); 393289177Speter svn_hash_sets(db->dirents, 394289177Speter apr_pstrdup(db->result_pool, relpath), 395289177Speter fdb.entry); 396289177Speter } 397289177Speter 398289177Speter fdb.result_pool = db->result_pool; 399289177Speter fdb.supports_deadprop_count = &db->supports_deadprop_count; 400289177Speter SVN_ERR(fill_dirent_propfunc(&fdb, path, ns, name, value, scratch_pool)); 401289177Speter } 402289177Speter else if (relpath && !db->is_directory) 403289177Speter { 404289177Speter if (strcmp(ns, "DAV:") == 0 && strcmp(name, "resourcetype") == 0) 405289177Speter { 406289177Speter if (strcmp(value->data, "collection") != 0) 407289177Speter { 408289177Speter /* Tell a lie to exit early */ 409289177Speter return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL, 410289177Speter _("Can't get properties of non-directory")); 411289177Speter } 412289177Speter else 413289177Speter db->is_directory = TRUE; 414289177Speter } 415289177Speter } 416289177Speter 417289177Speter return SVN_NO_ERROR; 418289177Speter} 419289177Speter 420289177Speter/* Implements svn_ra_serf__prop_func */ 421289177Speterstatic svn_error_t * 422289177Speterget_dir_props_cb(void *baton, 423289177Speter const char *path, 424289177Speter const char *ns, 425289177Speter const char *name, 426289177Speter const svn_string_t *value, 427289177Speter apr_pool_t *scratch_pool) 428289177Speter{ 429289177Speter struct get_dir_baton_t *db = baton; 430289177Speter const char *propname; 431289177Speter 432289177Speter propname = svn_ra_serf__svnname_from_wirename(ns, name, db->result_pool); 433289177Speter if (propname) 434289177Speter { 435289177Speter svn_hash_sets(db->ret_props, propname, 436289177Speter svn_string_dup(value, db->result_pool)); 437289177Speter return SVN_NO_ERROR; 438289177Speter } 439289177Speter 440289177Speter if (!db->is_directory) 441289177Speter { 442289177Speter if (strcmp(ns, "DAV:") == 0 && strcmp(name, "resourcetype") == 0) 443289177Speter { 444289177Speter if (strcmp(value->data, "collection") != 0) 445289177Speter { 446289177Speter /* Tell a lie to exit early */ 447289177Speter return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL, 448289177Speter _("Can't get properties of non-directory")); 449289177Speter } 450289177Speter else 451289177Speter db->is_directory = TRUE; 452289177Speter } 453289177Speter } 454289177Speter 455289177Speter return SVN_NO_ERROR; 456289177Speter} 457289177Speter 458289177Speter/* Implements svn_ra__vtable_t.get_dir(). */ 459289177Spetersvn_error_t * 460289177Spetersvn_ra_serf__get_dir(svn_ra_session_t *ra_session, 461289177Speter apr_hash_t **dirents, 462289177Speter svn_revnum_t *fetched_rev, 463289177Speter apr_hash_t **ret_props, 464289177Speter const char *rel_path, 465289177Speter svn_revnum_t revision, 466289177Speter apr_uint32_t dirent_fields, 467289177Speter apr_pool_t *result_pool) 468289177Speter{ 469289177Speter svn_ra_serf__session_t *session = ra_session->priv; 470289177Speter apr_pool_t *scratch_pool = svn_pool_create(result_pool); 471289177Speter svn_ra_serf__handler_t *dirent_handler = NULL; 472289177Speter svn_ra_serf__handler_t *props_handler = NULL; 473289177Speter const char *path; 474289177Speter struct get_dir_baton_t gdb; 475289177Speter svn_error_t *err = SVN_NO_ERROR; 476289177Speter 477289177Speter gdb.result_pool = result_pool; 478289177Speter gdb.is_directory = FALSE; 479289177Speter gdb.supports_deadprop_count = svn_tristate_unknown; 480289177Speter 481289177Speter path = session->session_url.path; 482289177Speter 483289177Speter /* If we have a relative path, URI encode and append it. */ 484289177Speter if (rel_path) 485289177Speter { 486289177Speter path = svn_path_url_add_component2(path, rel_path, scratch_pool); 487289177Speter } 488289177Speter 489289177Speter /* If the user specified a peg revision other than HEAD, we have to fetch 490289177Speter the baseline collection url for that revision. If not, we can use the 491289177Speter public url. */ 492289177Speter if (SVN_IS_VALID_REVNUM(revision) || fetched_rev) 493289177Speter { 494289177Speter SVN_ERR(svn_ra_serf__get_stable_url(&path, fetched_rev, 495289177Speter session, 496289177Speter path, revision, 497289177Speter scratch_pool, scratch_pool)); 498289177Speter revision = SVN_INVALID_REVNUM; 499289177Speter } 500289177Speter /* REVISION is always SVN_INVALID_REVNUM */ 501289177Speter SVN_ERR_ASSERT(!SVN_IS_VALID_REVNUM(revision)); 502289177Speter 503289177Speter gdb.path = path; 504289177Speter 505289177Speter /* If we're asked for children, fetch them now. */ 506289177Speter if (dirents) 507289177Speter { 508289177Speter /* Always request node kind to check that path is really a 509289177Speter * directory. */ 510289177Speter if (!ret_props) 511289177Speter dirent_fields |= SVN_DIRENT_KIND; 512289177Speter 513289177Speter gdb.dirents = apr_hash_make(result_pool); 514289177Speter 515289177Speter SVN_ERR(svn_ra_serf__create_propfind_handler( 516289177Speter &dirent_handler, session, 517289177Speter path, SVN_INVALID_REVNUM, "1", 518289177Speter get_dirent_props(dirent_fields, 519289177Speter session, 520289177Speter scratch_pool), 521289177Speter get_dir_dirents_cb, &gdb, 522289177Speter scratch_pool)); 523289177Speter 524289177Speter svn_ra_serf__request_create(dirent_handler); 525289177Speter } 526289177Speter else 527289177Speter gdb.dirents = NULL; 528289177Speter 529289177Speter if (ret_props) 530289177Speter { 531289177Speter gdb.ret_props = apr_hash_make(result_pool); 532289177Speter SVN_ERR(svn_ra_serf__create_propfind_handler( 533289177Speter &props_handler, session, 534289177Speter path, SVN_INVALID_REVNUM, "0", 535289177Speter all_props, 536289177Speter get_dir_props_cb, &gdb, 537289177Speter scratch_pool)); 538289177Speter 539289177Speter svn_ra_serf__request_create(props_handler); 540289177Speter } 541289177Speter else 542289177Speter gdb.ret_props = NULL; 543289177Speter 544289177Speter if (dirent_handler) 545289177Speter { 546289177Speter err = svn_error_trace( 547289177Speter svn_ra_serf__context_run_wait(&dirent_handler->done, 548289177Speter session, 549289177Speter scratch_pool)); 550289177Speter 551289177Speter if (err) 552289177Speter { 553289177Speter svn_pool_clear(scratch_pool); /* Unregisters outstanding requests */ 554289177Speter return err; 555289177Speter } 556289177Speter 557289177Speter if (gdb.supports_deadprop_count == svn_tristate_false 558289177Speter && session->supports_deadprop_count == svn_tristate_unknown 559289177Speter && dirent_fields & SVN_DIRENT_HAS_PROPS) 560289177Speter { 561289177Speter /* We have to requery as the server didn't give us the right 562289177Speter information */ 563289177Speter session->supports_deadprop_count = svn_tristate_false; 564289177Speter 565289177Speter apr_hash_clear(gdb.dirents); 566289177Speter 567289177Speter SVN_ERR(svn_ra_serf__create_propfind_handler( 568289177Speter &dirent_handler, session, 569289177Speter path, SVN_INVALID_REVNUM, "1", 570289177Speter get_dirent_props(dirent_fields, 571289177Speter session, 572289177Speter scratch_pool), 573289177Speter get_dir_dirents_cb, &gdb, 574289177Speter scratch_pool)); 575289177Speter 576289177Speter svn_ra_serf__request_create(dirent_handler); 577289177Speter } 578289177Speter } 579289177Speter 580289177Speter if (props_handler) 581289177Speter { 582289177Speter err = svn_error_trace( 583289177Speter svn_ra_serf__context_run_wait(&props_handler->done, 584289177Speter session, 585289177Speter scratch_pool)); 586289177Speter } 587289177Speter 588289177Speter /* And dirent again for the case when we had to send the request again */ 589289177Speter if (! err && dirent_handler) 590289177Speter { 591289177Speter err = svn_error_trace( 592289177Speter svn_ra_serf__context_run_wait(&dirent_handler->done, 593289177Speter session, 594289177Speter scratch_pool)); 595289177Speter } 596289177Speter 597289177Speter if (!err && gdb.supports_deadprop_count != svn_tristate_unknown) 598289177Speter session->supports_deadprop_count = gdb.supports_deadprop_count; 599289177Speter 600289177Speter svn_pool_destroy(scratch_pool); /* Unregisters outstanding requests */ 601289177Speter 602289177Speter SVN_ERR(err); 603289177Speter 604289177Speter if (!gdb.is_directory) 605289177Speter return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL, 606289177Speter _("Can't get entries of non-directory")); 607289177Speter 608289177Speter if (ret_props) 609289177Speter *ret_props = gdb.ret_props; 610289177Speter 611289177Speter if (dirents) 612289177Speter *dirents = gdb.dirents; 613289177Speter 614289177Speter return SVN_NO_ERROR; 615289177Speter} 616