79 { DAV_NS, "status" }, |
79 { DAV_NS, "status" }, |
80 { DAV_NS, "finfo" }, |
80 { DAV_NS, "finfo" }, |
81 { DAV_NS, "tags" }, |
81 { DAV_NS, "tags" }, |
82 { DAV_NS, "xattributes" }, |
82 { DAV_NS, "xattributes" }, |
83 { DAV_NS, "content-hash" }, |
83 { DAV_NS, "content-hash" }, |
84 { DAV_NS, "split" } |
84 { DAV_NS, "split" }, |
|
85 { DAV_NS, "link" } |
85 }; |
86 }; |
86 static size_t numdefprops = 6; |
87 static size_t numdefprops = 8 ; |
87 |
88 |
88 /* |
89 /* |
89 * strcmp version that works with NULL pointers |
90 * strcmp version that works with NULL pointers |
90 */ |
91 */ |
91 static int nullstrcmp(const char *s1, const char *s2) { |
92 static int nullstrcmp(const char *s1, const char *s2) { |
1761 UcxList *elm = ls_new; |
1762 UcxList *elm = ls_new; |
1762 while(elm) { |
1763 while(elm) { |
1763 LocalResource *local = elm->data; |
1764 LocalResource *local = elm->data; |
1764 UcxList *prev = elm->prev; |
1765 UcxList *prev = elm->prev; |
1765 UcxList *next = elm->next; |
1766 UcxList *next = elm->next; |
1766 if(local->isdirectory) { |
1767 if(local->isdirectory || local->link_target) { |
1767 elm = elm->next; |
1768 elm = elm->next; |
1768 continue; |
1769 continue; |
1769 } |
1770 } |
1770 |
1771 |
1771 char *local_path = util_concat_path(dir->path, local->path); |
1772 char *local_path = util_concat_path(dir->path, local->path); |
2554 } else if(xattr) { |
2555 } else if(xattr) { |
2555 xattributes_free(xattr); |
2556 xattributes_free(xattr); |
2556 } |
2557 } |
2557 } |
2558 } |
2558 |
2559 |
2559 if(db_res->last_modified == res->last_modified && db_res->size == res->size) { |
2560 if(nullstrcmp(db_res->link_target, res->link_target)) { |
|
2561 res->link_updated = 1; |
|
2562 } else if(db_res->last_modified == res->last_modified && db_res->size == res->size) { |
2560 return 0; |
2563 return 0; |
2561 } |
2564 } |
2562 |
2565 |
2563 if(db_res->parts) { |
2566 if(db_res->parts) { |
2564 // if the resource is splitted, move the part infos to the new |
2567 // if the resource is splitted, move the part infos to the new |
2565 // LocalResource obj, because we need it later |
2568 // LocalResource obj, because we need it later |
2566 res->parts = db_res->parts; |
2569 res->parts = db_res->parts; |
2588 DavPropName properties[] = { |
2591 DavPropName properties[] = { |
2589 {"DAV:", "getetag"}, |
2592 {"DAV:", "getetag"}, |
2590 {DAV_NS, "tags"}, |
2593 {DAV_NS, "tags"}, |
2591 {DAV_NS, "version-collection"}, |
2594 {DAV_NS, "version-collection"}, |
2592 {DAV_NS, "content-hash"}, |
2595 {DAV_NS, "content-hash"}, |
2593 {DAV_NS, "split" } |
2596 {DAV_NS, "split" }, |
|
2597 {DAV_NS, "link" } |
2594 }; |
2598 }; |
2595 int err = dav_load_prop(remote, properties, 4); |
2599 int err = dav_load_prop(remote, properties, 6); |
2596 |
2600 |
2597 if(res->restore) { |
2601 if(res->restore) { |
2598 return 0; |
2602 return 0; |
2599 } |
2603 } |
2600 |
2604 |
3477 perror(""); |
3481 perror(""); |
3478 free(local_path); |
3482 free(local_path); |
3479 return -1; |
3483 return -1; |
3480 } |
3484 } |
3481 |
3485 |
|
3486 DavBool islink = local->link_target ? 1 : 0; |
|
3487 if(!local->link_target && local->link_updated) { |
|
3488 dav_remove_property_ns(res, DAV_NS, "link"); |
|
3489 } |
|
3490 |
3482 size_t split_blocksize = resource_get_blocksize(dir, local, res, s.st_size); |
3491 size_t split_blocksize = resource_get_blocksize(dir, local, res, s.st_size); |
3483 |
3492 |
3484 FILE *in = sys_fopen(local_path, "rb"); |
3493 FILE *in = sys_fopen(local_path, "rb"); |
3485 if(!in) { |
3494 if(!in) { |
3486 fprintf(stderr, "Cannot open file %s\n", local_path); |
3495 fprintf(stderr, "Cannot open file %s\n", local_path); |
3490 |
3499 |
3491 DavBool issplit = split_blocksize == 0 ? FALSE : TRUE; |
3500 DavBool issplit = split_blocksize == 0 ? FALSE : TRUE; |
3492 int split_err = 0; |
3501 int split_err = 0; |
3493 UcxList *parts = NULL; |
3502 UcxList *parts = NULL; |
3494 uint64_t blockcount = 0; |
3503 uint64_t blockcount = 0; |
3495 if(!issplit) { |
3504 |
3496 // regular file upload |
3505 if(islink) { |
3497 dav_set_content(res, in, (dav_read_func)myread, (dav_seek_func)file_seek); |
3506 dav_set_string_property_ns(res, DAV_NS, "link", local->link_target); |
3498 dav_set_content_length(res, s.st_size); |
3507 } else if(issplit) { |
3499 } else { |
|
3500 // set split property |
3508 // set split property |
3501 char blocksize_str[32]; |
3509 char blocksize_str[32]; |
3502 snprintf(blocksize_str, 32, "%zu", split_blocksize); |
3510 snprintf(blocksize_str, 32, "%zu", split_blocksize); |
3503 dav_set_string_property_ns(res, DAV_NS, "split", blocksize_str); |
3511 dav_set_string_property_ns(res, DAV_NS, "split", blocksize_str); |
3504 |
3512 |
3561 // check contentlength and get new etag |
3573 // check contentlength and get new etag |
3562 DavResource *up_res = dav_get(res->session, res->path, "D:getetag,idav:status"); |
3574 DavResource *up_res = dav_get(res->session, res->path, "D:getetag,idav:status"); |
3563 |
3575 |
3564 if(up_res) { |
3576 if(up_res) { |
3565 // the new content length must be equal or greater than the file size |
3577 // the new content length must be equal or greater than the file size |
3566 if(up_res->contentlength < s.st_size && !issplit) { |
3578 if(up_res->contentlength < s.st_size && !issplit && !islink) { |
3567 fprintf(stderr, "Incomplete Upload: %s\n", local_path); |
3579 fprintf(stderr, "Incomplete Upload: %s\n", local_path); |
3568 ret = -1; |
3580 ret = -1; |
3569 // try to set the resource status to 'broken' |
3581 // try to set the resource status to 'broken' |
3570 sync_set_status(res, "broken"); |
3582 sync_set_status(res, "broken"); |
3571 } else { |
3583 } else { |