192 } |
192 } |
193 |
193 |
194 DavResource *ls = dav_query(sn, "select D:getetag,idav:status from / with depth = infinity"); |
194 DavResource *ls = dav_query(sn, "select D:getetag,idav:status from / with depth = infinity"); |
195 if(!ls) { |
195 if(!ls) { |
196 print_resource_error(sn, "/"); |
196 print_resource_error(sn, "/"); |
|
197 fprintf(stderr, "Abort\n"); |
|
198 |
|
199 dav_session_destroy(sn); |
197 // TODO: free |
200 // TODO: free |
198 return -1; |
201 return -1; |
199 } |
202 } |
|
203 |
|
204 int sync_success = 0; |
|
205 int sync_delete = 0; |
|
206 int sync_error = 0; |
200 |
207 |
201 if(!ls->children) { |
208 if(!ls->children) { |
202 // TODO: free |
209 // TODO: free |
203 fprintf(stderr, "Repository is empty\n"); |
210 fprintf(stderr, "Repository is empty\n"); |
204 return 0; // empty repository |
211 return 0; // empty repository |
222 res = res->next; |
229 res = res->next; |
223 continue; |
230 continue; |
224 } |
231 } |
225 |
232 |
226 // download the resource |
233 // download the resource |
227 if(sync_get_resource(a, dir, res, db)) { |
234 if(sync_get_resource(a, dir, res, db, &sync_success)) { |
228 fprintf(stderr, "sync_get_resource failed for resource: %s\n", res->path); |
235 fprintf(stderr, "sync_get_resource failed for resource: %s\n", res->path); |
|
236 sync_error++; |
229 } |
237 } |
230 |
238 |
231 // add every resource from the server to svrres |
239 // add every resource from the server to svrres |
232 // then db-resources only contains resources which are not on the |
240 // then db-resources only contains resources which are not on the |
233 // server |
241 // server |
249 UCX_MAP_FOREACH(key, local, i) { |
257 UCX_MAP_FOREACH(key, local, i) { |
250 if (res_matches_filter(dir, local->path)) { |
258 if (res_matches_filter(dir, local->path)) { |
251 continue; |
259 continue; |
252 } |
260 } |
253 // sync_remove_resource does all necessary tests |
261 // sync_remove_resource does all necessary tests |
254 if(sync_remove_local_resource(dir, local)) { |
262 int ret = sync_remove_local_resource(dir, local); |
|
263 if(ret == -1) { |
255 rmdirs = ucx_list_append(rmdirs, local); |
264 rmdirs = ucx_list_append(rmdirs, local); |
|
265 } else if(ret == 0) { |
|
266 sync_delete++; |
256 } |
267 } |
257 } |
268 } |
258 UCX_FOREACH(elm, rmdirs) { |
269 UCX_FOREACH(elm, rmdirs) { |
259 LocalResource *local_dir = elm->data; |
270 LocalResource *local_dir = elm->data; |
260 sync_remove_local_directory(dir, local_dir); |
271 sync_remove_local_directory(dir, local_dir); |
261 } |
272 } |
262 ucx_map_free(db->resources); |
273 ucx_map_free(db->resources); |
263 db->resources = svrres; |
274 db->resources = svrres; |
264 |
275 |
265 // TODO: cleanup - BUT DONT CLEANUP SYNC CONFIG (do this in main!) |
|
266 |
|
267 // store db |
276 // store db |
268 if(store_db(db, dir->database)) { |
277 if(store_db(db, dir->database)) { |
269 fprintf(stderr, "Cannot store sync db\n"); |
278 fprintf(stderr, "Cannot store sync db\n"); |
270 return -1; |
279 fprintf(stderr, "Abort\n"); |
271 } |
280 return -1; // TODO: don't return here |
|
281 } |
|
282 |
|
283 // TODO: cleanup - BUT DONT CLEANUP SYNC CONFIG (do this in main!) |
|
284 dav_session_destroy(sn); |
|
285 |
|
286 // Report |
|
287 char *str_success = sync_success == 1 ? "file" : "files"; |
|
288 char *str_delete = sync_delete == 1 ? "file" : "files"; |
|
289 char *str_error = sync_error == 1 ? "error" : "errors"; |
|
290 printf("Result: %d %s pulled, %d %s deleted, %d %s\n", |
|
291 sync_success, str_success, |
|
292 sync_delete,str_delete, |
|
293 sync_error, str_error); |
272 |
294 |
273 return 0; |
295 return 0; |
274 } |
296 } |
275 |
297 |
276 int sync_get_resource(CmdArgs *a, SyncDirectory *dir, DavResource *res, SyncDatabase *db) { |
298 int sync_get_resource( |
|
299 CmdArgs *a, |
|
300 SyncDirectory *dir, |
|
301 DavResource *res, |
|
302 SyncDatabase *db, |
|
303 int *counter) |
|
304 { |
277 int cdt = cmd_getoption(a, "conflict") ? 0 : 1; // conflict detection |
305 int cdt = cmd_getoption(a, "conflict") ? 0 : 1; // conflict detection |
278 |
306 |
279 LocalResource *local = ucx_map_cstr_get(db->resources, res->path); |
307 LocalResource *local = ucx_map_cstr_get(db->resources, res->path); |
280 char *local_path = util_concat_path(dir->path, res->path); |
308 char *local_path = util_concat_path(dir->path, res->path); |
281 |
309 |
410 int sync_remove_local_resource(SyncDirectory *dir, LocalResource *res) { |
440 int sync_remove_local_resource(SyncDirectory *dir, LocalResource *res) { |
411 char *local_path = util_concat_path(dir->path, res->path); |
441 char *local_path = util_concat_path(dir->path, res->path); |
412 struct stat s; |
442 struct stat s; |
413 if(stat(local_path, &s)) { |
443 if(stat(local_path, &s)) { |
414 free(local_path); |
444 free(local_path); |
415 return 0; |
445 return -2; |
416 } |
446 } |
417 |
447 |
418 if(S_ISDIR(s.st_mode)) { |
448 if(S_ISDIR(s.st_mode)) { |
419 free(local_path); |
449 free(local_path); |
420 return 1; |
450 return -1; |
421 } |
451 } |
422 |
452 |
423 if(s.st_mtime != res->last_modified) { |
453 if(s.st_mtime != res->last_modified) { |
424 free(local_path); |
454 free(local_path); |
425 return 0; |
455 return -2; |
426 } |
456 } |
427 |
457 |
428 printf("delete: %s\n", res->path); |
458 printf("delete: %s\n", res->path); |
429 |
459 int ret = 0; |
430 if(dir->trash) { |
460 if(dir->trash) { |
431 move_to_trash(dir, local_path); |
461 move_to_trash(dir, local_path); |
432 } else if(unlink(local_path)) { |
462 } else if(unlink(local_path)) { |
433 fprintf(stderr, "Cannot remove file %s\n", local_path); |
463 fprintf(stderr, "Cannot remove file %s\n", local_path); |
|
464 ret = -2; |
434 } |
465 } |
435 free(local_path); |
466 free(local_path); |
436 |
467 |
437 return 0; |
468 return ret; |
438 } |
469 } |
439 |
470 |
440 void sync_remove_local_directory(SyncDirectory *dir, LocalResource *res) { |
471 void sync_remove_local_directory(SyncDirectory *dir, LocalResource *res) { |
441 char *local_path = util_concat_path(dir->path, res->path); |
472 char *local_path = util_concat_path(dir->path, res->path); |
442 |
473 |
581 if (cmd_getoption(a, "verbose")) { |
612 if (cmd_getoption(a, "verbose")) { |
582 curl_easy_setopt(sn->handle, CURLOPT_VERBOSE, 1L); |
613 curl_easy_setopt(sn->handle, CURLOPT_VERBOSE, 1L); |
583 curl_easy_setopt(sn->handle, CURLOPT_STDERR, stderr); |
614 curl_easy_setopt(sn->handle, CURLOPT_STDERR, stderr); |
584 } |
615 } |
585 |
616 |
|
617 DavResource *testsvr = dav_query(sn, "select - from / with depth = 0"); |
|
618 if(!testsvr) { |
|
619 print_resource_error(sn, "/"); |
|
620 dav_session_destroy(sn); |
|
621 fprintf(stderr, "Abort\n"); |
|
622 return -1; |
|
623 } |
|
624 |
|
625 int sync_success = 0; |
|
626 int sync_delete = 0; |
|
627 int sync_error = 0; |
|
628 |
586 // upload all changed files |
629 // upload all changed files |
587 UcxList *resources = cmd_getoption(a, "read") ? |
630 UcxList *resources = cmd_getoption(a, "read") ? |
588 read_changes(dir, db) : local_scan(dir, db); |
631 read_changes(dir, db) : local_scan(dir, db); |
589 |
632 |
590 UcxMap *lclres = ucx_map_new(db->resources->count); |
633 UcxMap *lclres = ucx_map_new(db->resources->count); |
|
634 int ret = 0; |
591 UCX_FOREACH(elm, resources) { |
635 UCX_FOREACH(elm, resources) { |
592 LocalResource *local_res = elm->data; |
636 LocalResource *local_res = elm->data; |
593 if (!res_matches_filter(dir, local_res->path+1)) { |
637 if (!res_matches_filter(dir, local_res->path+1)) { |
594 // upload every changed file |
638 // upload every changed file |
595 if (local_resource_is_changed(dir, db, local_res)) { |
639 if (local_resource_is_changed(dir, db, local_res)) { |
596 DavResource *res = dav_resource_new(sn, local_res->path); |
640 DavResource *res = dav_resource_new(sn, local_res->path); |
597 if(!res) { |
641 if(!res) { |
598 print_resource_error(sn, local_res->path); |
642 print_resource_error(sn, local_res->path); |
599 break; |
643 ret = -1; |
|
644 sync_error++; |
600 } |
645 } |
601 |
646 |
602 if(local_res->isdirectory) { |
647 if(local_res->isdirectory) { |
603 printf("mkcol: %s\n", local_res->path); |
648 printf("mkcol: %s\n", local_res->path); |
604 if(sync_mkdir(dir, res, local_res)) { |
649 if(sync_mkdir(dir, res, local_res) && sn->error != DAV_METHOD_NOT_ALLOWED) { |
605 print_resource_error(sn, res->path); |
650 print_resource_error(sn, res->path); |
606 dav_resource_free(res); |
651 ret = -1; |
607 break; |
652 sync_error++; |
608 } |
653 } |
609 } else { |
654 } else { |
610 printf("put: %s\n", local_res->path); |
655 printf("put: %s\n", local_res->path); |
611 if(sync_put_resource(dir, res, local_res)) { |
656 if(sync_put_resource(dir, res, local_res, &sync_success)) { |
|
657 sync_error++; |
612 print_resource_error(sn, res->path); |
658 print_resource_error(sn, res->path); |
613 dav_resource_free(res); |
659 ret = -1; |
614 break; |
660 sync_error++; |
615 } |
661 } |
616 } |
662 } |
617 dav_resource_free(res); |
663 dav_resource_free(res); |
618 } |
664 } |
619 |
665 |
624 } |
670 } |
625 } |
671 } |
626 ucx_list_free(resources); |
672 ucx_list_free(resources); |
627 |
673 |
628 // delete all removed files |
674 // delete all removed files |
629 UcxMapIterator i = ucx_map_iterator(db->resources); |
675 if(ret == 0) { |
630 LocalResource *local; |
676 UcxMapIterator i = ucx_map_iterator(db->resources); |
631 UCX_MAP_FOREACH(key, local, i) { |
677 LocalResource *local; |
632 if (!res_matches_filter(dir, local->path+1)) { |
678 UCX_MAP_FOREACH(key, local, i) { |
633 if(sync_delete_remote_resource(sn, local)) { |
679 if (!res_matches_filter(dir, local->path+1)) { |
634 ucx_map_cstr_put(lclres, local->path, local); |
680 if(sync_delete_remote_resource(sn, local, &sync_delete)) { |
635 if(sn->error != DAV_NOT_FOUND) { |
681 ucx_map_cstr_put(lclres, local->path, local); |
636 print_resource_error(sn, local->path); |
682 if(sn->error != DAV_NOT_FOUND) { |
637 break; |
683 print_resource_error(sn, local->path); |
|
684 sync_error++; |
|
685 break; |
|
686 } |
638 } |
687 } |
639 } |
688 } |
640 } |
689 } |
641 } |
690 } |
642 ucx_map_free(db->resources); |
691 ucx_map_free(db->resources); |
643 db->resources = lclres; |
692 db->resources = lclres; |
644 |
|
645 // TODO: free res |
|
646 |
693 |
647 // store db |
694 // store db |
648 if(store_db(db, dir->database)) { |
695 if(store_db(db, dir->database)) { |
649 fprintf(stderr, "Cannot store sync db\n"); |
696 fprintf(stderr, "Cannot store sync db\n"); |
650 return -1; |
697 return -1; |
651 } |
698 } |
|
699 |
|
700 // TODO: free res |
|
701 |
|
702 // Report |
|
703 char *str_success = sync_success == 1 ? "file" : "files"; |
|
704 char *str_delete = sync_delete == 1 ? "file" : "files"; |
|
705 char *str_error = sync_error == 1 ? "error" : "errors"; |
|
706 printf("Result: %d %s pushed, %d %s deleted, %d %s\n", |
|
707 sync_success, str_success, |
|
708 sync_delete,str_delete, |
|
709 sync_error, str_error); |
652 |
710 |
653 return 0; |
711 return 0; |
654 } |
712 } |
655 |
713 |
656 UcxList* local_scan(SyncDirectory *dir, SyncDatabase *db) { |
714 UcxList* local_scan(SyncDirectory *dir, SyncDatabase *db) { |
809 int ret = dav_store(resource); |
867 int ret = dav_store(resource); |
810 dav_resource_free(resource); |
868 dav_resource_free(resource); |
811 return ret; |
869 return ret; |
812 } |
870 } |
813 |
871 |
814 int sync_put_resource(SyncDirectory *dir, DavResource *res, LocalResource *local) { |
872 int sync_put_resource( |
|
873 SyncDirectory *dir, |
|
874 DavResource *res, |
|
875 LocalResource *local, |
|
876 int *counter) |
|
877 { |
815 char *local_path = util_concat_path(dir->path, res->path); |
878 char *local_path = util_concat_path(dir->path, res->path); |
816 |
879 |
817 struct stat s; |
880 struct stat s; |
818 if(stat(local_path, &s)) { |
881 if(stat(local_path, &s)) { |
819 fprintf(stderr, "cannot stat file: %s\n", local_path); |
882 fprintf(stderr, "cannot stat file: %s\n", local_path); |