1593 char *hash = util_file_hash(local_path); |
1593 char *hash = util_file_hash(local_path); |
1594 local->hash = hash; |
1594 local->hash = hash; |
1595 // check if a file with this hash already exists |
1595 // check if a file with this hash already exists |
1596 LocalResource *origin = ucx_map_cstr_get(db_hashes, hash); |
1596 LocalResource *origin = ucx_map_cstr_get(db_hashes, hash); |
1597 if(origin) { |
1597 if(origin) { |
1598 local->origin = strdup(origin->path); |
1598 local->origin = local_resource_copy(origin, origin->path); |
1599 // the file is a copied/moved file |
1599 // the file is a copied/moved file |
1600 // check if the file is in the resources_map, because then |
1600 // check if the file is in the resources_map, because then |
1601 // it still exists |
1601 // it still exists |
1602 if(ucx_map_cstr_get(resources_map, origin->path)) { |
1602 if(ucx_map_cstr_get(resources_map, origin->path)) { |
1603 ls_copy = ucx_list_append(ls_copy, local); |
1603 ls_copy = ucx_list_append(ls_copy, local); |
1730 } |
1730 } |
1731 |
1731 |
1732 DavBool copy = TRUE; |
1732 DavBool copy = TRUE; |
1733 for(UcxList *elm=ls_copy;elm && !sync_shutdown;elm=elm->next) { |
1733 for(UcxList *elm=ls_copy;elm && !sync_shutdown;elm=elm->next) { |
1734 LocalResource *local = elm->data; |
1734 LocalResource *local = elm->data; |
1735 DavResource *res = dav_resource_new(sn, local->origin); |
1735 |
1736 int err = 0; |
1736 int err = 0; |
1737 if(copy) { |
1737 DavResource *res = dav_resource_new(sn, local->path); |
1738 printf("copy: %s -> %s\n", local->origin, local->path); |
1738 if(dav_exists(res)) { |
1739 err = dav_copy_o(res, local->path, FALSE); |
1739 printf("conflict: %s\n", local->path); |
1740 |
1740 sync_skipped++; |
1741 if(!elm->next) { |
|
1742 // finished copy, begin move |
|
1743 elm->next = ls_move; |
|
1744 copy = FALSE; |
|
1745 } |
|
1746 } else { |
1741 } else { |
1747 printf("move: %s -> %s\n", local->origin, local->path); |
1742 DavResource *origin_res = dav_resource_new(sn, local->origin->path); |
1748 err = dav_move_o(res, local->path, FALSE); |
1743 int origin_changed = remote_resource_is_changed( |
|
1744 sn, |
|
1745 dir, |
|
1746 db, |
|
1747 origin_res, |
|
1748 local->origin); |
|
1749 if(origin_changed) { |
|
1750 // upload with put |
|
1751 printf("put: %s\n", local->path); |
|
1752 err = sync_put_resource(dir, res, local, &sync_success); |
|
1753 } else { |
|
1754 printf("%s: %s -> %s\n", copy ? "copy":"move", local->origin->path, local->path); |
|
1755 err = sync_move_remote_resource( |
|
1756 dir, |
|
1757 origin_res, |
|
1758 local, |
|
1759 copy, |
|
1760 &sync_success); |
|
1761 } |
1749 } |
1762 } |
1750 |
1763 |
1751 if(err) { |
1764 if(err) { |
1752 if(sn->error == DAV_PRECONDITION_FAILED) { |
1765 sync_error++; |
1753 printf("conflict: %s\n", local->path); |
1766 print_resource_error(sn, res->path); |
1754 local->last_modified = 0; |
1767 ret = -1; |
1755 local->skipped = TRUE; |
1768 error = 1; |
1756 sync_skipped++; |
1769 } |
1757 } else { |
1770 |
1758 sync_error++; |
|
1759 print_resource_error(sn, res->path); |
|
1760 ret = -1; |
|
1761 error = 1; |
|
1762 } |
|
1763 } |
|
1764 |
|
1765 dav_resource_free(res); |
|
1766 LocalResource *dbres = ucx_map_cstr_remove(db->resources, local->path); |
1771 LocalResource *dbres = ucx_map_cstr_remove(db->resources, local->path); |
1767 ucx_map_cstr_put(db->resources, local->path, local); |
1772 ucx_map_cstr_put(db->resources, local->path, local); |
|
1773 |
|
1774 if(copy && !elm->next) { |
|
1775 // finished copy, begin move |
|
1776 elm->next = ls_move; |
|
1777 copy = FALSE; |
|
1778 } |
1768 } |
1779 } |
1769 |
1780 |
1770 // metadata updates |
1781 // metadata updates |
1771 for(UcxList *elm=ls_update;elm && !sync_shutdown;elm=elm->next) { |
1782 for(UcxList *elm=ls_update;elm && !sync_shutdown;elm=elm->next) { |
1772 LocalResource *local_res = elm->data; |
1783 LocalResource *local_res = elm->data; |
2224 res->uid = s.st_uid; |
2235 res->uid = s.st_uid; |
2225 res->gid = s.st_gid; |
2236 res->gid = s.st_gid; |
2226 res->isdirectory = 1; |
2237 res->isdirectory = 1; |
2227 return res; |
2238 return res; |
2228 } |
2239 } |
2229 } |
|
2230 |
|
2231 LocalResource* local_resource_copy(LocalResource *res) { |
|
2232 LocalResource *newres = calloc(1, sizeof(LocalResource)); |
|
2233 if(res->name) { |
|
2234 newres->name = strdup(res->name); |
|
2235 } |
|
2236 if(res->path) { |
|
2237 newres->path = strdup(res->path); |
|
2238 } |
|
2239 if(res->etag) { |
|
2240 newres->etag = strdup(res->etag); |
|
2241 } |
|
2242 newres->skipped = res->skipped; |
|
2243 newres->size = res->size; |
|
2244 newres->last_modified = res->last_modified; |
|
2245 newres->isdirectory = res->isdirectory; |
|
2246 if(res->tags_hash) { |
|
2247 newres->tags_hash = strdup(res->tags_hash); |
|
2248 } |
|
2249 newres->tags_updated = res->tags_updated; |
|
2250 return newres; |
|
2251 } |
2240 } |
2252 |
2241 |
2253 int local_resource_is_changed( |
2242 int local_resource_is_changed( |
2254 SyncDirectory *dir, |
2243 SyncDirectory *dir, |
2255 SyncDatabase *db, |
2244 SyncDatabase *db, |
3404 break; |
3393 break; |
3405 } |
3394 } |
3406 return ret; |
3395 return ret; |
3407 } |
3396 } |
3408 |
3397 |
|
3398 int sync_move_remote_resource( |
|
3399 SyncDirectory *dir, |
|
3400 DavResource *origin, |
|
3401 LocalResource *local, |
|
3402 DavBool copy, |
|
3403 int *counter) |
|
3404 { |
|
3405 char *local_path = create_local_path(dir, local->path); |
|
3406 |
|
3407 SYS_STAT s; |
|
3408 if(sys_stat(local_path, &s)) { |
|
3409 fprintf(stderr, "Cannot stat file: %s\n", local_path); |
|
3410 perror(""); |
|
3411 free(local_path); |
|
3412 return -1; |
|
3413 } |
|
3414 free(local_path); |
|
3415 |
|
3416 int result = 0; |
|
3417 if(copy) { |
|
3418 result = dav_copy_o(origin, local->path, FALSE); |
|
3419 } else { |
|
3420 result = dav_move_o(origin, local->path, FALSE); |
|
3421 } |
|
3422 |
|
3423 if(result != 0) { |
|
3424 return result; |
|
3425 } |
|
3426 |
|
3427 // replace LocalResource with origin content |
|
3428 LocalResource *local_origin = local->origin; |
|
3429 local->origin = NULL; |
|
3430 char *path = strdup(local->path); |
|
3431 // TODO: free stuff before replacing it |
|
3432 memcpy(local, local_origin, sizeof(LocalResource)); |
|
3433 local->path = path; |
|
3434 |
|
3435 free(local_origin); // only free origin pointer |
|
3436 |
|
3437 // get new etag |
|
3438 DavResource *up_res = dav_get(origin->session, origin->path, "D:getetag"); |
|
3439 if(up_res) { |
|
3440 (*counter)++; |
|
3441 |
|
3442 // everything seems fine, we can update the local resource |
|
3443 char *etag = dav_get_string_property(up_res, "D:getetag"); |
|
3444 if(etag) { |
|
3445 if(strlen(etag) > 2 && etag[0] == 'W' && etag[1] == '/') { |
|
3446 etag = etag + 2; |
|
3447 } |
|
3448 } |
|
3449 |
|
3450 if(local->etag) { |
|
3451 free(local->etag); |
|
3452 } |
|
3453 |
|
3454 if(etag) { |
|
3455 local->etag = strdup(etag); |
|
3456 } else { |
|
3457 local->etag = NULL; |
|
3458 } |
|
3459 |
|
3460 local->last_modified = s.st_mtime; |
|
3461 |
|
3462 dav_resource_free(up_res); |
|
3463 } else { |
|
3464 result = 1; |
|
3465 } |
|
3466 |
|
3467 return result; |
|
3468 } |
|
3469 |
3409 int sync_delete_remote_resource( |
3470 int sync_delete_remote_resource( |
3410 SyncDirectory *dir, |
3471 SyncDirectory *dir, |
3411 DavSession *sn, |
3472 DavSession *sn, |
3412 LocalResource *local_res, |
3473 LocalResource *local_res, |
3413 int *counter, |
3474 int *counter, |
3438 if(strlen(etag) > 2 && etag[0] == 'W' && etag[1] == '/') { |
3499 if(strlen(etag) > 2 && etag[0] == 'W' && etag[1] == '/') { |
3439 etag = etag + 2; |
3500 etag = etag + 2; |
3440 } |
3501 } |
3441 } |
3502 } |
3442 |
3503 |
3443 if(etag && !strcmp(etag, local_res->etag)) { |
3504 if(nullstrcmp(etag, local_res->etag)) { |
3444 // local resource metadata == remote resource metadata |
3505 // local resource metadata == remote resource metadata |
3445 // resource can be deleted |
3506 // resource can be deleted |
3446 printf("delete: %s\n", res->path); |
3507 printf("delete: %s\n", res->path); |
3447 |
3508 |
3448 if(dir->versioning && dir->versioning->always) { |
3509 if(dir->versioning && dir->versioning->always) { |