88 // copy proxy config |
88 // copy proxy config |
89 memcpy(ctx->http_proxy, get_http_proxy(), sizeof(Proxy)); |
89 memcpy(ctx->http_proxy, get_http_proxy(), sizeof(Proxy)); |
90 memcpy(ctx->https_proxy, get_https_proxy(), sizeof(Proxy)); |
90 memcpy(ctx->https_proxy, get_https_proxy(), sizeof(Proxy)); |
91 |
91 |
92 if(load_sync_config()) { |
92 if(load_sync_config()) { |
|
93 cmd_args_free(args); |
|
94 dav_context_destroy(ctx); |
93 return EXIT_FAILURE; |
95 return EXIT_FAILURE; |
94 } |
96 } |
95 } |
97 } |
96 |
98 |
97 if(!strcmp(cmd, "pull")) { |
99 if(!strcmp(cmd, "pull")) { |
111 } else if(!strcmp(cmd, "list-directories")) { |
113 } else if(!strcmp(cmd, "list-directories")) { |
112 ret = list_syncdirs(); |
114 ret = list_syncdirs(); |
113 } |
115 } |
114 |
116 |
115 // TODO: cleanup sync config (don't forget to call regfree for regex) |
117 // TODO: cleanup sync config (don't forget to call regfree for regex) |
|
118 cmd_args_free(args); |
|
119 dav_context_destroy(ctx); |
|
120 |
|
121 free_config(); |
116 |
122 |
117 return ret; |
123 return ret; |
118 } |
124 } |
119 |
125 |
120 void print_usage(char *cmd) { |
126 void print_usage(char *cmd) { |
206 } |
212 } |
207 |
213 |
208 SyncDatabase *db = load_db(dir->database); |
214 SyncDatabase *db = load_db(dir->database); |
209 if(!db) { |
215 if(!db) { |
210 fprintf(stderr, "Cannot load database file: %s\n", dir->database); |
216 fprintf(stderr, "Cannot load database file: %s\n", dir->database); |
|
217 destroy_db(db); |
211 return -1; |
218 return -1; |
212 } |
219 } |
213 remove_deleted_conflicts(dir, db); |
220 remove_deleted_conflicts(dir, db); |
214 |
221 |
215 char *new_url = NULL; |
222 char *new_url = NULL; |
216 if(dir->collection) { |
223 if(dir->collection) { |
217 new_url = util_concat_path(repo->url, dir->collection); |
224 new_url = util_concat_path(repo->url, dir->collection); |
218 } |
225 } |
219 DavSession *sn = create_session(ctx, repo, new_url ? new_url : repo->url); |
226 DavSession *sn = create_session(ctx, repo, new_url ? new_url : repo->url); |
|
227 ucx_mempool_reg_destr(sn->mp, db, (ucx_destructor)destroy_db); |
220 if(new_url) { |
228 if(new_url) { |
221 free(new_url); |
229 free(new_url); |
222 } |
230 } |
223 if (cmd_getoption(a, "verbose")) { |
231 if (cmd_getoption(a, "verbose")) { |
224 curl_easy_setopt(sn->handle, CURLOPT_VERBOSE, 1L); |
232 curl_easy_setopt(sn->handle, CURLOPT_VERBOSE, 1L); |
398 if(sstrprefix(e, S("W/"))) { |
406 if(sstrprefix(e, S("W/"))) { |
399 e = sstrsubs(e, 2); |
407 e = sstrsubs(e, 2); |
400 } |
408 } |
401 if(!strcmp(e.ptr, local->etag)) { |
409 if(!strcmp(e.ptr, local->etag)) { |
402 // resource is already up-to-date on the client |
410 // resource is already up-to-date on the client |
|
411 free(local_path); |
403 return 0; |
412 return 0; |
404 } |
413 } |
405 } |
414 } |
406 |
415 |
407 if(cdt && exists && s.st_mtime != local->last_modified) { |
416 if(cdt && exists && s.st_mtime != local->last_modified) { |
489 |
498 |
490 if(local->etag) { |
499 if(local->etag) { |
491 free(local->etag); |
500 free(local->etag); |
492 } |
501 } |
493 // set metadata from stat |
502 // set metadata from stat |
494 local->etag = etag; |
503 local->etag = strdup(etag); |
495 local->last_modified = s.st_mtime; |
504 local->last_modified = s.st_mtime; |
496 local->size = s.st_size; |
505 local->size = s.st_size; |
497 } else { |
506 } else { |
498 if(unlink(tmp_path)) { |
507 if(unlink(tmp_path)) { |
499 fprintf(stderr, "Cannot remove tmp file: %s\n", tmp_path); |
508 fprintf(stderr, "Cannot remove tmp file: %s\n", tmp_path); |
693 char *new_url = NULL; |
702 char *new_url = NULL; |
694 if(dir->collection) { |
703 if(dir->collection) { |
695 new_url = util_concat_path(repo->url, dir->collection); |
704 new_url = util_concat_path(repo->url, dir->collection); |
696 } |
705 } |
697 DavSession *sn = create_session(ctx, repo, new_url ? new_url : repo->url); |
706 DavSession *sn = create_session(ctx, repo, new_url ? new_url : repo->url); |
|
707 ucx_mempool_reg_destr(sn->mp, db, (ucx_destructor)destroy_db); |
698 if(new_url) { |
708 if(new_url) { |
699 free(new_url); |
709 free(new_url); |
700 } |
710 } |
701 if (cmd_getoption(a, "verbose")) { |
711 if (cmd_getoption(a, "verbose")) { |
702 curl_easy_setopt(sn->handle, CURLOPT_VERBOSE, 1L); |
712 curl_easy_setopt(sn->handle, CURLOPT_VERBOSE, 1L); |
741 LocalResource *local_res = elm->data; |
751 LocalResource *local_res = elm->data; |
742 if (!res_matches_filter(dir, local_res->path+1)) { |
752 if (!res_matches_filter(dir, local_res->path+1)) { |
743 if(res_isconflict(db, local_res)) { |
753 if(res_isconflict(db, local_res)) { |
744 printf("skip: %s\n", local_res->path); |
754 printf("skip: %s\n", local_res->path); |
745 sync_skipped++; |
755 sync_skipped++; |
|
756 local_resource_free(local_res); |
746 continue; |
757 continue; |
747 } |
758 } |
748 |
759 |
749 // upload every changed file |
760 // upload every changed file |
750 if (local_resource_is_changed(dir, db, local_res)) { |
761 if (local_resource_is_changed(dir, db, local_res)) { |
764 } |
775 } |
765 } else { |
776 } else { |
766 if(cdt && remote_resource_is_changed(sn, dir, db, local_res)) { |
777 if(cdt && remote_resource_is_changed(sn, dir, db, local_res)) { |
767 printf("conflict: %s\n", local_res->path); |
778 printf("conflict: %s\n", local_res->path); |
768 sync_skipped++; |
779 sync_skipped++; |
|
780 local_resource_free(local_res); |
769 continue; |
781 continue; |
770 } |
782 } |
771 |
783 |
772 printf("put: %s\n", local_res->path); |
784 printf("put: %s\n", local_res->path); |
773 if(sync_put_resource(dir, res, local_res, &sync_success)) { |
785 if(sync_put_resource(dir, res, local_res, &sync_success)) { |
781 } |
793 } |
782 |
794 |
783 // remove every locally available resource from db->resource |
795 // remove every locally available resource from db->resource |
784 // the remaining elements are all deleted files |
796 // the remaining elements are all deleted files |
785 ucx_map_cstr_put(lclres, local_res->path, local_res); |
797 ucx_map_cstr_put(lclres, local_res->path, local_res); |
786 ucx_map_cstr_remove(db->resources, local_res->path); // TODO: element leaked |
798 LocalResource *lr = ucx_map_cstr_remove(db->resources, local_res->path); |
|
799 if(lr) { |
|
800 local_resource_free(lr); |
|
801 } |
787 } |
802 } |
788 } |
803 } |
789 ucx_list_free(resources); |
804 ucx_list_free(resources); |
790 |
805 |
791 // delete all removed files |
806 // delete all removed files |
1192 } |
1208 } |
1193 |
1209 |
1194 for(int i=0;i<numdc;i++) { |
1210 for(int i=0;i<numdc;i++) { |
1195 ucx_map_cstr_remove(db->conflict, dc[i]); |
1211 ucx_map_cstr_remove(db->conflict, dc[i]); |
1196 } |
1212 } |
|
1213 |
|
1214 free(dc); |
1197 } |
1215 } |
1198 |
1216 |
1199 int cmd_resolve_conflicts(CmdArgs *a) { |
1217 int cmd_resolve_conflicts(CmdArgs *a) { |
1200 if(a->argc != 1) { |
1218 if(a->argc != 1) { |
1201 fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many"); |
1219 fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many"); |
1211 SyncDatabase *db = load_db(dir->database); |
1229 SyncDatabase *db = load_db(dir->database); |
1212 if(!db) { |
1230 if(!db) { |
1213 fprintf(stderr, "Cannot load database file: %s\n", dir->database); |
1231 fprintf(stderr, "Cannot load database file: %s\n", dir->database); |
1214 return -1; |
1232 return -1; |
1215 } |
1233 } |
|
1234 |
|
1235 int ret = 0; |
1216 |
1236 |
1217 // remove conflicts |
1237 // remove conflicts |
1218 int num_conflict = db->conflict->count; |
1238 int num_conflict = db->conflict->count; |
1219 //TODO: ucx_map_free_content(db->conflict, destr); |
1239 //TODO: ucx_map_free_content(db->conflict, destr); |
1220 ucx_map_clear(db->conflict); |
1240 ucx_map_clear(db->conflict); |
1221 |
1241 |
1222 // store db |
1242 // store db |
1223 if(store_db(db, dir->database)) { |
1243 if(store_db(db, dir->database)) { |
1224 fprintf(stderr, "Cannot store sync db\n"); |
1244 fprintf(stderr, "Cannot store sync db\n"); |
1225 fprintf(stderr, "Abort\n"); |
1245 fprintf(stderr, "Abort\n"); |
1226 return -1; // TODO: don't return here |
1246 ret = -1; |
1227 } |
1247 } |
|
1248 destroy_db(db); |
1228 |
1249 |
1229 // Report |
1250 // Report |
1230 char *str_conflict = num_conflict == 1 ? "conflict" : "conflicts"; |
1251 if(ret == 0) { |
1231 printf("Result: %d %s resolved\n", num_conflict, str_conflict); |
1252 char *str_conflict = num_conflict == 1 ? "conflict" : "conflicts"; |
1232 |
1253 printf("Result: %d %s resolved\n", num_conflict, str_conflict); |
1233 return 0; |
1254 } |
|
1255 |
|
1256 return ret; |
1234 } |
1257 } |
1235 |
1258 |
1236 int cmd_delete_conflicts(CmdArgs *a) { |
1259 int cmd_delete_conflicts(CmdArgs *a) { |
1237 if(a->argc != 1) { |
1260 if(a->argc != 1) { |
1238 fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many"); |
1261 fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many"); |
1275 |
1300 |
1276 // store db |
1301 // store db |
1277 if(store_db(db, dir->database)) { |
1302 if(store_db(db, dir->database)) { |
1278 fprintf(stderr, "Cannot store sync db\n"); |
1303 fprintf(stderr, "Cannot store sync db\n"); |
1279 fprintf(stderr, "Abort\n"); |
1304 fprintf(stderr, "Abort\n"); |
1280 return -1; // TODO: don't return here |
1305 ret = -1; |
1281 } |
1306 } |
|
1307 destroy_db(db); |
1282 |
1308 |
1283 // Report |
1309 // Report |
1284 char *str_delete = num_del == 1 ? "file" : "files"; |
1310 if(ret == 0) { |
1285 char *str_error = num_err == 1 ? "error" : "errors"; |
1311 char *str_delete = num_del == 1 ? "file" : "files"; |
1286 printf("Result: %d conflict %s deleted, %d %s\n", |
1312 char *str_error = num_err == 1 ? "error" : "errors"; |
1287 num_del, str_delete, |
1313 printf("Result: %d conflict %s deleted, %d %s\n", |
1288 num_err, str_error); |
1314 num_del, str_delete, |
1289 |
1315 num_err, str_error); |
1290 return 0; |
1316 } |
|
1317 |
|
1318 return ret; |
1291 } |
1319 } |
1292 |
1320 |
1293 |
1321 |
1294 // TODO: remove code dup (main.c ls_size_str) |
1322 // TODO: remove code dup (main.c ls_size_str) |
1295 static char* size_str(uint64_t size) { |
1323 static char* size_str(uint64_t size) { |