28 |
28 |
29 #include <stdio.h> |
29 #include <stdio.h> |
30 #include <stdlib.h> |
30 #include <stdlib.h> |
31 #include <string.h> |
31 #include <string.h> |
32 |
32 |
33 #include <ucx/buffer.h> |
33 #include <cx/buffer.h> |
34 #include <ucx/utils.h> |
34 #include <cx/utils.h> |
|
35 #include <cx/basic_mempool.h> |
|
36 #include <cx/hash_map.h> |
35 |
37 |
36 #include "utils.h" |
38 #include "utils.h" |
37 #include "session.h" |
39 #include "session.h" |
38 #include "resource.h" |
40 #include "resource.h" |
39 #include "methods.h" |
41 #include "methods.h" |
40 |
42 |
41 DavSession* dav_session_new(DavContext *context, char *base_url) { |
43 DavSession* dav_session_new(DavContext *context, char *base_url) { |
42 if(!base_url) { |
44 if(!base_url) { |
43 return NULL; |
45 return NULL; |
44 } |
46 } |
45 sstr_t url = sstr(base_url); |
47 cxstring url = cx_str(base_url); |
46 if(url.length == 0) { |
48 if(url.length == 0) { |
47 return NULL; |
49 return NULL; |
48 } |
50 } |
49 DavSession *sn = malloc(sizeof(DavSession)); |
51 DavSession *sn = malloc(sizeof(DavSession)); |
50 memset(sn, 0, sizeof(DavSession)); |
52 memset(sn, 0, sizeof(DavSession)); |
51 sn->mp = ucx_mempool_new(DAV_SESSION_MEMPOOL_SIZE); |
53 sn->mp = cxBasicMempoolCreate(DAV_SESSION_MEMPOOL_SIZE); |
52 sn->pathcache = ucx_map_new_a(sn->mp->allocator, DAV_PATH_CACHE_SIZE); |
54 sn->pathcache = cxHashMapCreate(sn->mp->allocator, CX_STORE_POINTERS, DAV_PATH_CACHE_SIZE); |
53 sn->key = NULL; |
55 sn->key = NULL; |
54 sn->errorstr = NULL; |
56 sn->errorstr = NULL; |
55 sn->error = DAV_OK; |
57 sn->error = DAV_OK; |
56 sn->flags = 0; |
58 sn->flags = 0; |
57 |
59 |
58 dav_session_set_baseurl(sn, base_url); |
60 dav_session_set_baseurl(sn, base_url); |
59 |
61 |
60 sn->handle = curl_easy_init(); |
62 sn->handle = curl_easy_init(); |
61 curl_easy_setopt(sn->handle, CURLOPT_FOLLOWLOCATION, 1L); |
63 curl_easy_setopt(sn->handle, CURLOPT_FOLLOWLOCATION, 1L); |
62 |
64 |
63 // create lock manager |
65 // lock manager is created on-demand |
64 DavLockManager *locks = ucx_mempool_malloc(sn->mp, sizeof(DavLockManager)); |
66 sn->locks = NULL; |
65 locks->resource_locks = ucx_map_new_a(sn->mp->allocator, 16); |
|
66 locks->collection_locks = NULL; |
|
67 sn->locks = locks; |
|
68 |
67 |
69 // set proxy |
68 // set proxy |
70 DavProxy *proxy = sstrprefix(url, S("https")) ? context->https_proxy |
69 DavProxy *proxy = cx_strprefix(url, CX_STR("https")) ? context->https_proxy |
71 : context->http_proxy; |
70 : context->http_proxy; |
72 |
71 |
73 if (proxy->url) { |
72 if (proxy->url) { |
74 curl_easy_setopt(sn->handle, CURLOPT_PROXY, proxy->url); |
73 curl_easy_setopt(sn->handle, CURLOPT_PROXY, proxy->url); |
75 if (proxy->username) { |
74 if (proxy->username) { |
272 sn->errorstr = errstr; |
272 sn->errorstr = errstr; |
273 } |
273 } |
274 |
274 |
275 void dav_session_destroy(DavSession *sn) { |
275 void dav_session_destroy(DavSession *sn) { |
276 // remove session from context |
276 // remove session from context |
277 UcxList *sessions = sn->context->sessions; |
277 CxList *sessions = sn->context->sessions; |
278 ssize_t i = ucx_list_find(sessions, sn, ucx_cmp_ptr, NULL); |
278 ssize_t i = cxListFind(sessions, sn); |
279 if(i >= 0) { |
279 if(i >= 0) { |
280 UcxList *elm = ucx_list_get(sessions, i); |
280 cxListRemove(sessions, i); |
281 if(elm) { |
281 } |
282 sn->context->sessions = ucx_list_remove(sessions, elm); |
282 |
283 } |
283 cxMempoolDestroy(sn->mp); |
284 } |
|
285 |
|
286 ucx_mempool_destroy(sn->mp); |
|
287 curl_easy_cleanup(sn->handle); |
284 curl_easy_cleanup(sn->handle); |
288 free(sn); |
285 free(sn); |
289 } |
286 } |
290 |
287 |
291 |
288 |
292 void* dav_session_malloc(DavSession *sn, size_t size) { |
289 void* dav_session_malloc(DavSession *sn, size_t size) { |
293 return ucx_mempool_malloc(sn->mp, size); |
290 return cxMalloc(sn->mp->allocator, size); |
294 } |
291 } |
295 |
292 |
296 void* dav_session_calloc(DavSession *sn, size_t nelm, size_t size) { |
293 void* dav_session_calloc(DavSession *sn, size_t nelm, size_t size) { |
297 return ucx_mempool_calloc(sn->mp, nelm, size); |
294 return cxCalloc(sn->mp->allocator, nelm, size); |
298 } |
295 } |
299 |
296 |
300 void* dav_session_realloc(DavSession *sn, void *ptr, size_t size) { |
297 void* dav_session_realloc(DavSession *sn, void *ptr, size_t size) { |
301 return ucx_mempool_realloc(sn->mp, ptr, size); |
298 return cxRealloc(sn->mp->allocator, ptr, size); |
302 } |
299 } |
303 |
300 |
304 void dav_session_free(DavSession *sn, void *ptr) { |
301 void dav_session_free(DavSession *sn, void *ptr) { |
305 ucx_mempool_free(sn->mp, ptr); |
302 cxFree(sn->mp->allocator, ptr); |
306 } |
303 } |
307 |
304 |
308 char* dav_session_strdup(DavSession *sn, const char *str) { |
305 char* dav_session_strdup(DavSession *sn, const char *str) { |
309 return sstrdup_a(sn->mp->allocator, sstr((char*)str)).ptr; |
306 return cx_strdup_a(sn->mp->allocator, cx_str((char*)str)).ptr; |
310 } |
307 } |
311 |
308 |
312 |
309 |
313 char* dav_session_create_plain_href(DavSession *sn, char *path) { |
310 char* dav_session_create_plain_href(DavSession *sn, const char *path) { |
314 if(!DAV_ENCRYPT_NAME(sn) && !DAV_DECRYPT_NAME(sn)) { |
311 if(!DAV_ENCRYPT_NAME(sn) && !DAV_DECRYPT_NAME(sn)) { |
315 // non encrypted file names |
312 // non encrypted file names |
316 char *url = util_path_to_url(sn, path); |
313 char *url = util_path_to_url(sn, path); |
317 char *href = dav_session_strdup(sn, util_url_path(url)); |
314 char *href = dav_session_strdup(sn, util_url_path(url)); |
318 free(url); |
315 free(url); |
320 } else { |
317 } else { |
321 return NULL; |
318 return NULL; |
322 } |
319 } |
323 } |
320 } |
324 |
321 |
325 char* dav_session_get_href(DavSession *sn, char *path) { |
322 char* dav_session_get_href(DavSession *sn, const char *path) { |
326 if(DAV_DECRYPT_NAME(sn) || DAV_ENCRYPT_NAME(sn)) { |
323 if(DAV_DECRYPT_NAME(sn) || DAV_ENCRYPT_NAME(sn)) { |
327 sstr_t p = sstr(path); |
324 cxstring p = cx_str(path); |
328 UcxBuffer *href = ucx_buffer_new(NULL, 256, UCX_BUFFER_AUTOEXTEND); |
325 CxBuffer href; |
329 UcxBuffer *pbuf = ucx_buffer_new(NULL, 256, UCX_BUFFER_AUTOEXTEND); |
326 CxBuffer pbuf; |
|
327 cxBufferInit(&href, NULL, 256, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND); |
|
328 cxBufferInit(&pbuf, NULL, 256, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND); |
|
329 |
330 int start = 0; |
330 int start = 0; |
331 int begin = 0; |
331 int begin = 0; |
332 |
332 |
333 // check path cache |
333 // check path cache |
334 char *cp = strdup(path); |
334 char *cp = strdup(path); |
335 //printf("cp: %s\n", cp); |
335 //printf("cp: %s\n", cp); |
336 while(strlen(cp) > 1) { |
336 while(strlen(cp) > 1) { |
337 char *cached = ucx_map_cstr_get(sn->pathcache, cp); |
337 char *cached = cxMapGet(sn->pathcache, cx_hash_key_str(cp)); |
338 if(cached) { |
338 if(cached) { |
339 start = strlen(cp); |
339 start = strlen(cp); |
340 begin = start; |
340 begin = start; |
341 ucx_buffer_puts(href, cached); |
341 cxBufferPutString(&href, cached); |
342 break; |
342 break; |
343 } else { |
343 } else { |
344 // check, if the parent path is cached |
344 // check, if the parent path is cached |
345 char *f = cp; |
345 char *f = cp; |
346 cp = util_parent_path(cp); |
346 cp = util_parent_path(cp); |
347 free(f); |
347 free(f); |
348 } |
348 } |
349 } |
349 } |
350 free(cp); |
350 free(cp); |
351 if(href->pos == 0) { |
351 if(href.pos == 0) { |
352 // if there are no cached elements we have to add the base url path |
352 // if there are no cached elements we have to add the base url path |
353 // to the href buffer |
353 // to the href buffer |
354 ucx_buffer_puts(href, util_url_path(sn->base_url)); |
354 cxBufferPutString(&href, util_url_path(sn->base_url)); |
355 } |
355 } |
356 |
356 |
357 // create resource for name lookup |
357 // create resource for name lookup |
358 sstr_t rp = sstrdup(sstrn(path, start)); |
358 cxmutstr rp = cx_strdup(cx_strn(path, start)); |
359 DavResource *root = dav_resource_new(sn, rp.ptr); |
359 DavResource *root = dav_resource_new(sn, rp.ptr); |
360 free(rp.ptr); |
360 free(rp.ptr); |
361 resource_set_href(root, sstrn(href->space, href->pos)); |
361 resource_set_href(root, cx_strn(href.space, href.pos)); |
362 |
362 |
363 // create request buffer for propfind requests |
363 // create request buffer for propfind requests |
364 UcxBuffer *rqbuf = create_basic_propfind_request(); |
364 CxBuffer *rqbuf = create_basic_propfind_request(); |
365 |
365 |
366 sstr_t remaining = sstrsubs(p, start); |
366 cxstring remaining = cx_strsubs(p, start); |
367 ssize_t nelm = 0; |
367 CxStrtokCtx elms = cx_strtok(remaining, CX_STR("/"), INT_MAX); |
368 sstr_t *elms = sstrsplit(remaining, S("/"), &nelm); |
|
369 DavResource *res = root; |
368 DavResource *res = root; |
370 ucx_buffer_puts(pbuf, res->path); |
369 cxBufferPutString(&pbuf, res->path); |
371 // iterate over all remaining path elements |
370 // iterate over all remaining path elements |
372 for(int i=0;i<nelm;i++) { |
371 cxstring elm; |
373 sstr_t elm = elms[i]; |
372 while(cx_strtok_next(&elms, &elm)) { |
374 if(elm.length > 0) { |
373 if(elm.length > 0) { |
375 //printf("elm: %.*s\n", elm.length, elm.ptr); |
374 //printf("elm: %.*s\n", elm.length, elm.ptr); |
376 DavResource *child = dav_find_child(sn, res, rqbuf, elm.ptr); |
375 DavResource *child = dav_find_child(sn, res, rqbuf, elm.ptr); |
377 |
376 |
378 // if necessary add a path separator |
377 // if necessary add a path separator |
379 if(pbuf->space[pbuf->pos-1] != '/') { |
378 if(pbuf.space[pbuf.pos-1] != '/') { |
380 if(href->space[href->pos-1] != '/') { |
379 if(href.space[href.pos-1] != '/') { |
381 ucx_buffer_putc(href, '/'); |
380 cxBufferPut(&href, '/'); |
382 } |
381 } |
383 ucx_buffer_putc(pbuf, '/'); |
382 cxBufferPut(&pbuf, '/'); |
384 } |
383 } |
385 // add last path/href to the cache |
384 // add last path/href to the cache |
386 sstr_t pp = sstrn(pbuf->space, pbuf->size); |
385 cxstring pp = cx_strn(pbuf.space, pbuf.size); |
387 sstr_t hh = sstrn(href->space, href->size); |
386 cxstring hh = cx_strn(href.space, href.size); |
388 dav_session_cache_path(sn, pp, hh); |
387 dav_session_cache_path(sn, pp, hh); |
389 |
388 |
390 ucx_buffer_write(elm.ptr, 1, elm.length, pbuf); |
389 cxBufferWrite(elm.ptr, 1, elm.length, &pbuf); |
391 if(child) { |
390 if(child) { |
392 // href is already URL encoded, so don't encode again |
391 // href is already URL encoded, so don't encode again |
393 ucx_buffer_puts(href, util_resource_name(child->href)); |
392 cxBufferPutString(&href, util_resource_name(child->href)); |
394 res = child; |
393 res = child; |
395 } else if(DAV_ENCRYPT_NAME(sn)) { |
394 } else if(DAV_ENCRYPT_NAME(sn)) { |
396 char *random_name = util_random_str(); |
395 char *random_name = util_random_str(); |
397 ucx_buffer_puts(href, random_name); |
396 cxBufferPutString(&href, random_name); |
398 free(random_name); |
397 free(random_name); |
399 } else { |
398 } else { |
400 // path is not URL encoded, so we have to do this here |
399 // path is not URL encoded, so we have to do this here |
401 scstr_t resname = scstr(util_resource_name(path)); |
400 cxstring resname = cx_str(util_resource_name((const char*)path)); |
402 // the name of collections ends with |
401 // the name of collections ends with |
403 // a trailing slash, which MUST NOT be encoded |
402 // a trailing slash, which MUST NOT be encoded |
404 if(resname.ptr[resname.length-1] == '/') { |
403 if(resname.ptr[resname.length-1] == '/') { |
405 char *esc = curl_easy_escape(sn->handle, |
404 char *esc = curl_easy_escape(sn->handle, |
406 resname.ptr, resname.length-1); |
405 resname.ptr, resname.length-1); |
407 ucx_buffer_write(esc, 1, strlen(esc), href); |
406 cxBufferWrite(esc, 1, strlen(esc), &href); |
408 ucx_buffer_putc(href, '/'); |
407 cxBufferPut(&href, '/'); |
409 curl_free(esc); |
408 curl_free(esc); |
410 } else { |
409 } else { |
411 char *esc = curl_easy_escape(sn->handle, |
410 char *esc = curl_easy_escape(sn->handle, |
412 resname.ptr, resname.length); |
411 resname.ptr, resname.length); |
413 ucx_buffer_write(esc, 1, strlen(esc), href); |
412 cxBufferWrite(esc, 1, strlen(esc), &href); |
414 curl_free(esc); |
413 curl_free(esc); |
415 } |
414 } |
416 } |
415 } |
417 } |
416 } |
418 |
417 } |
419 // cleanup |
|
420 free(elm.ptr); |
|
421 } |
|
422 free(elms); |
|
423 |
418 |
424 // if necessary add a path separator |
419 // if necessary add a path separator |
425 if(p.ptr[p.length-1] == '/') { |
420 if(p.ptr[p.length-1] == '/') { |
426 if(href->space[href->pos-1] != '/') { |
421 if(href.space[href.pos-1] != '/') { |
427 ucx_buffer_putc(href, '/'); |
422 cxBufferPut(&href, '/'); |
428 } |
423 } |
429 ucx_buffer_putc(pbuf, '/'); |
424 cxBufferPut(&pbuf, '/'); |
430 } |
425 } |
431 // add the final path to the cache |
426 // add the final path to the cache |
432 sstr_t pp = sstrn(pbuf->space, pbuf->size); |
427 cxstring pp = cx_strn(pbuf.space, pbuf.size); |
433 sstr_t hh = sstrn(href->space, href->size); |
428 cxstring hh = cx_strn(href.space, href.size); |
434 dav_session_cache_path(sn, pp, hh); |
429 dav_session_cache_path(sn, pp, hh); |
435 |
430 |
436 sstr_t href_str = sstrdup_a( |
431 cxmutstr href_str = cx_strdup_a( |
437 sn->mp->allocator, |
432 sn->mp->allocator, |
438 sstrn(href->space, |
433 cx_strn(href.space, href.size)); |
439 href->size)); |
|
440 |
434 |
441 // cleanup |
435 // cleanup |
442 dav_resource_free_all(root); |
436 dav_resource_free_all(root); |
443 ucx_buffer_free(rqbuf); |
437 cxBufferFree(rqbuf); |
444 ucx_buffer_free(pbuf); |
438 |
445 ucx_buffer_free(href); |
439 cxBufferDestroy(&pbuf); |
|
440 cxBufferDestroy(&href); |
446 |
441 |
447 return href_str.ptr; |
442 return href_str.ptr; |
448 } else { |
443 } else { |
449 return dav_session_create_plain_href(sn, path); |
444 return dav_session_create_plain_href(sn, path); |
450 } |
445 } |
451 } |
446 } |
452 |
447 |
453 DavResource* dav_find_child(DavSession *sn, DavResource *res, UcxBuffer *rqbuf, char *name) { |
448 DavResource* dav_find_child(DavSession *sn, DavResource *res, CxBuffer *rqbuf, const char *name) { |
454 if(res && !dav_propfind(sn, res, rqbuf)) { |
449 if(res && !dav_propfind(sn, res, rqbuf)) { |
455 DavResource *child = res->children; |
450 DavResource *child = res->children; |
456 while(child) { |
451 while(child) { |
457 if(!strcmp(child->name, name)) { |
452 if(!strcmp(child->name, name)) { |
458 return child; |
453 return child; |
488 dav_session_free(sn, lock->path); |
484 dav_session_free(sn, lock->path); |
489 } |
485 } |
490 dav_session_free(sn, lock); |
486 dav_session_free(sn, lock); |
491 } |
487 } |
492 |
488 |
493 int dav_add_resource_lock(DavSession *sn, char *path, DavLock *lock) { |
489 |
|
490 static int dav_lock_cmp(void const *left, void const *right) { |
|
491 const DavLock *l = left; |
|
492 const DavLock *r = right; |
|
493 return strcmp(l->path, r->path); |
|
494 } |
|
495 |
|
496 static int create_lock_manager(DavSession *sn) { |
|
497 // create lock manager |
|
498 DavLockManager *locks = cxMalloc(sn->mp->allocator, sizeof(DavLockManager)); |
|
499 locks->resource_locks = cxHashMapCreate(sn->mp->allocator, CX_STORE_POINTERS, 16); |
|
500 locks->collection_locks = cxLinkedListCreate(sn->mp->allocator, dav_lock_cmp, CX_STORE_POINTERS); |
|
501 sn->locks = locks; |
|
502 return 0; |
|
503 } |
|
504 |
|
505 static DavLockManager* get_lock_manager(DavSession *sn) { |
494 DavLockManager *locks = sn->locks; |
506 DavLockManager *locks = sn->locks; |
495 if(ucx_map_cstr_get(locks->resource_locks, path)) { |
507 if(!locks) { |
|
508 if(create_lock_manager(sn)) { |
|
509 return NULL; |
|
510 } |
|
511 locks = sn->locks; |
|
512 } |
|
513 return locks; |
|
514 } |
|
515 |
|
516 int dav_add_resource_lock(DavSession *sn, const char *path, DavLock *lock) { |
|
517 DavLockManager *locks = get_lock_manager(sn); |
|
518 if(!locks) { |
496 return -1; |
519 return -1; |
497 } |
520 } |
498 |
521 |
499 ucx_map_cstr_put(locks->resource_locks, path, lock); |
522 CxHashKey path_key = cx_hash_key_str(path); |
|
523 if(cxMapGet(locks->resource_locks, path_key)) { |
|
524 return -1; |
|
525 } |
|
526 |
|
527 cxMapPut(locks->resource_locks, path_key, lock); |
500 return 0; |
528 return 0; |
501 } |
529 } |
502 |
530 |
503 static void insert_lock(DavSession *sn, UcxList *elm, UcxList *newelm) { |
531 int dav_add_collection_lock(DavSession *sn, const char *path, DavLock *lock) { |
504 UcxList *next = elm->next; |
532 DavLockManager *locks = get_lock_manager(sn); |
505 if(next) { |
533 if(!locks) { |
506 next->prev = newelm; |
534 return -1; |
507 newelm->next = next; |
535 } |
508 } |
536 |
509 newelm->prev = elm; |
537 cxListAdd(locks->collection_locks, lock); |
510 elm->next = newelm; |
538 cxListSort(locks->collection_locks); |
511 } |
|
512 |
|
513 int dav_add_collection_lock(DavSession *sn, char *path, DavLock *lock) { |
|
514 DavLockManager *locks = sn->locks; |
|
515 if(!locks->collection_locks) { |
|
516 locks->collection_locks = ucx_list_append_a( |
|
517 sn->mp->allocator, |
|
518 NULL, |
|
519 lock); |
|
520 lock->path = dav_session_strdup(sn, path); |
|
521 return 0; |
|
522 } |
|
523 |
|
524 UcxList *elm = locks->collection_locks; |
|
525 for(;;) { |
|
526 DavLock *l = elm->data; |
|
527 int cmp = strcmp(path, l->path); |
|
528 if(cmp > 0) { |
|
529 UcxList *newelm = ucx_list_append_a(sn->mp->allocator, NULL, lock); |
|
530 lock->path = dav_session_strdup(sn, path); |
|
531 insert_lock(sn, elm, newelm); |
|
532 } else if(cmp == 0) { |
|
533 return -1; |
|
534 } |
|
535 |
|
536 if(elm->next) { |
|
537 elm = elm->next; |
|
538 } else { |
|
539 UcxList *newelm = ucx_list_append_a(sn->mp->allocator, NULL, lock); |
|
540 lock->path = dav_session_strdup(sn, path); |
|
541 ucx_list_concat(elm, newelm); |
|
542 break; |
|
543 } |
|
544 } |
|
545 |
539 |
546 return 0; |
540 return 0; |
547 } |
541 } |
548 |
542 |
549 DavLock* dav_get_lock(DavSession *sn, char *path) { |
543 DavLock* dav_get_lock(DavSession *sn, const char *path) { |
550 DavLockManager *locks = sn->locks; |
544 DavLockManager *locks = get_lock_manager(sn); |
551 |
545 if(!locks) { |
552 DavLock *lock = ucx_map_cstr_get(locks->resource_locks, path); |
546 return NULL; |
|
547 } |
|
548 |
|
549 cxstring p = cx_str(path); |
|
550 |
|
551 DavLock *lock = cxMapGet(locks->resource_locks, cx_hash_key(p.ptr, p.length)); |
553 if(lock) { |
552 if(lock) { |
554 return lock; |
553 return lock; |
555 } |
554 } |
556 |
555 |
557 sstr_t p = sstr(path); |
556 CxIterator i = cxListIterator(locks->collection_locks); |
558 UCX_FOREACH(elm, locks->collection_locks) { |
557 cx_foreach(DavLock*, cl, i) { |
559 DavLock *cl = elm->data; |
|
560 int cmd = strcmp(path, cl->path); |
558 int cmd = strcmp(path, cl->path); |
561 if(cmd == 0) { |
559 if(cmd == 0) { |
562 return cl; |
560 return cl; |
563 } else if(sstrprefix(p, sstr(cl->path))) { |
561 } else if(cx_strprefix(p, cx_str(cl->path))) { |
564 return cl; |
562 return cl; |
565 } else if(cmd > 0) { |
563 } else if(cmd > 0) { |
566 break; |
564 break; |
567 } |
565 } |
568 } |
566 } |
569 |
567 |
570 return NULL; |
568 return NULL; |
571 } |
569 } |
572 |
570 |
573 void dav_remove_lock(DavSession *sn, char *path, DavLock *lock) { |
571 void dav_remove_lock(DavSession *sn, const char *path, DavLock *lock) { |
574 DavLockManager *locks = sn->locks; |
572 DavLockManager *locks = get_lock_manager(sn); |
575 |
573 if(!locks) { |
576 if(ucx_map_cstr_remove(locks->resource_locks, path)) { |
|
577 return; |
574 return; |
578 } |
575 } |
579 |
576 |
580 UcxList *rm = NULL; |
577 if(cxMapRemoveAndGet(locks->resource_locks, cx_hash_key_str(path))) { |
581 UCX_FOREACH(elm, locks->collection_locks) { |
578 return; |
582 DavLock *cl = elm->data; |
579 } |
|
580 |
|
581 CxMutIterator i = cxListMutIterator(locks->collection_locks); |
|
582 int rm = 0; |
|
583 cx_foreach(DavLock* , cl, i) { |
|
584 if(rm) { |
|
585 break; |
|
586 } |
583 if(cl == lock) { |
587 if(cl == lock) { |
584 rm = elm; |
588 cxIteratorFlagRemoval(i); |
585 break; |
589 rm = 1; |
586 } |
590 } |
587 } |
591 } |
588 |
592 } |
589 if(rm) { |
|
590 locks->collection_locks = ucx_list_remove_a( |
|
591 sn->mp->allocator, |
|
592 locks->collection_locks, |
|
593 rm); |
|
594 } |
|
595 } |
|