diff -r 3cfe65695a8c -r 36a7f2ea7d12 dav/sync.c --- a/dav/sync.c Thu Jul 20 21:16:19 2023 +0200 +++ b/dav/sync.c Thu Jul 20 21:55:45 2023 +0200 @@ -119,6 +119,13 @@ va_end(ap); } +void log_resource_error(DavSession *sn, const char *path) { + print_resource_error(sn, path); + if(synclog) { + print_resource_error_to_file(synclog, sn, path); + } +} + int logfile_open(SyncDirectory *dir) { int ret = 0; @@ -704,9 +711,9 @@ root->iscollection = TRUE; if((dir->lockpush || cmd_getoption(a, "lock")) && !cmd_getoption(a, "nolock")) { if(dav_lock_t(root, dir->lock_timeout)) { - print_resource_error(sn, "/"); + log_resource_error(sn, "/"); dav_session_destroy(sn); - fprintf(stderr, "Abort\n"); + log_error("Abort\n"); return -1; } DavLock *lock = dav_get_lock(sn, "/"); @@ -720,16 +727,16 @@ int ret = 0; DavResource *ls = dav_query(sn, "select D:getetag,idav:split,idav:status,`idav:content-hash`,idavprops:tags,idavprops:finfo,idavprops:xattributes,idavprops:link from / with depth = infinity"); if(!ls) { - print_resource_error(sn, "/"); + log_resource_error(sn, "/"); if(locked) { if(dav_unlock(root)) { - print_resource_error(sn, "/"); + log_resource_error(sn, "/"); } else { locked = FALSE; } } - fprintf(stderr, "Abort\n"); + log_error("Abort\n"); dav_session_destroy(sn); // TODO: free @@ -739,7 +746,7 @@ fprintf(stderr, "%s is not a collection.\nAbort.\n", ls->path); if(locked) { if(dav_unlock(root)) { - print_resource_error(sn, "/"); + log_resource_error(sn, "/"); } else { locked = FALSE; } @@ -1061,7 +1068,7 @@ // unlock repository if(locked) { if(dav_unlock(root)) { - print_resource_error(sn, "/"); + log_resource_error(sn, "/"); ret = -1; } else { locked = FALSE; @@ -2041,9 +2048,9 @@ DavResource *root = dav_query(sn, "select D:getetag,idav:status from / with depth = %d", depth); if(!root) { - print_resource_error(sn, "/"); + log_resource_error(sn, "/"); dav_session_destroy(sn); - fprintf(stderr, "Abort\n"); + log_error("Abort\n"); return -1; } @@ -2060,9 +2067,9 @@ char *locktokenfile = NULL; if((dir->lockpush || cmd_getoption(a, "lock")) && !cmd_getoption(a, "nolock") && !outgoing) { if(dav_lock_t(root, dir->lock_timeout)) { - print_resource_error(sn, "/"); + log_resource_error(sn, "/"); dav_session_destroy(sn); - fprintf(stderr, "Abort\n"); + log_error("Abort\n"); return -1; } DavLock *lock = dav_get_lock(sn, "/"); @@ -2164,8 +2171,7 @@ if(local_res->isnew) { if(local_resource_load_metadata(dir, local_res)) { - fprintf( - stderr, + log_error( "Failed to load metadata: %s\n", local_resource_path(local_res)); } @@ -2280,7 +2286,7 @@ DavResource *res = dav_resource_new(sn, local_res->path); if(!res) { - print_resource_error(sn, local_res->path); + log_resource_error(sn, local_res->path); ret = -1; sync_error++; } @@ -2293,7 +2299,7 @@ // TODO: show 405 log_printf("mkcol: %s\n", local_res->path); if(sync_mkdir(dir, res, local_res) && sn->error != DAV_METHOD_NOT_ALLOWED) { - print_resource_error(sn, res->path); + log_resource_error(sn, res->path); ret = -1; sync_error++; error = 1; @@ -2301,7 +2307,7 @@ } } else if(sn->error != DAV_OK) { // dav_exists() failed - print_resource_error(sn, local_res->path); + log_resource_error(sn, local_res->path); ret = -1; sync_error++; error = 1; @@ -2374,7 +2380,7 @@ if(err) { sync_error++; - print_resource_error(sn, res->path); + log_resource_error(sn, res->path); ret = -1; error = 1; } else { @@ -2399,7 +2405,7 @@ DavResource *res = dav_resource_new(sn, local_res->path); if(!res) { - print_resource_error(sn, local_res->path); + log_resource_error(sn, local_res->path); ret = -1; sync_error++; } else { @@ -2445,7 +2451,7 @@ } if(sync_put_resource(dir, res, local_res, &sync_success)) { sync_error++; - print_resource_error(sn, res->path); + log_resource_error(sn, res->path); ret = -1; error = 1; @@ -2506,7 +2512,7 @@ } if(sync_delete_remote_resource(dir, sn, local, &sync_delete, col_list)) { if(sn->error != DAV_NOT_FOUND) { - print_resource_error(sn, local->path); + log_resource_error(sn, local->path); sync_error++; break; } @@ -2525,7 +2531,7 @@ // unlock repository if(locked) { if(dav_unlock(root)) { - print_resource_error(sn, "/"); + log_resource_error(sn, "/"); ret = -1; } else { locked = FALSE; @@ -2534,7 +2540,7 @@ // store db if(store_db(db, dir->database, dir->db_settings)) { - fprintf(stderr, "Cannot store sync db\n"); + log_error("Cannot store sync db\n"); ret = -2; } @@ -2637,7 +2643,7 @@ SyncDatabase *db = load_db(dir->database); if(!db) { - fprintf(stderr, "Cannot load database file: %s\n", dir->database); + log_error("Cannot load database file: %s\n", dir->database); return -1; } remove_deleted_conflicts(dir, db); @@ -2665,8 +2671,8 @@ cxListAdd(deleted, resource); } } else { - fprintf(stderr, "Cannot stat file: %s\n", file_path); - perror(""); + log_error("Cannot stat file: %s\n", file_path); + log_error("%s\n", strerror(errno)); } } else { if(files) { @@ -2692,7 +2698,7 @@ // create DavSession Repository *repo = get_repository(cx_str(dir->repository)); if(!repo) { - fprintf(stderr, "Unkown repository %s\n", dir->name); + log_error("Unkown repository %s\n", dir->name); return -1; } DavSession *sn = create_session(a, ctx, repo, dir->collection); @@ -2709,9 +2715,9 @@ root->iscollection = TRUE; if((dir->lockpush || cmd_getoption(a, "lock")) && !cmd_getoption(a, "nolock")) { if(dav_lock_t(root, dir->lock_timeout)) { - print_resource_error(sn, "/"); + log_resource_error(sn, "/"); dav_session_destroy(sn); - fprintf(stderr, "Abort\n"); + log_error("Abort\n"); return -1; } DavLock *lock = dav_get_lock(sn, "/"); @@ -2740,7 +2746,7 @@ } char *status = dav_get_string_property(res, "idav:status"); if(status && !strcmp(status, "broken")) { - fprintf(stderr, "Resource %s broken\n", res->path); + log_error("Resource %s broken\n", res->path); continue; } @@ -2753,7 +2759,7 @@ vres = versioning_deltav_find(res, version); } if(!vres) { - fprintf(stderr, "Cannot find specified version for resource %s\n", res->path); + log_error("Cannot find specified version for resource %s\n", res->path); ret = 1; break; } @@ -2772,14 +2778,14 @@ if(resource->isdirectory) { char *local_path = create_local_path(dir, res->path); if(sys_mkdir(local_path) && errno != EEXIST) { - fprintf(stderr, + log_error( "Cannot create directory %s: %s", local_path, strerror(errno)); } free(local_path); } else { if(sync_get_resource(a, dir, res->path, vres, db, update_local_entry, &sync_success)) { - fprintf(stderr, "sync_get_resource failed for resource: %s\n", res->path); + log_error("sync_get_resource failed for resource: %s\n", res->path); sync_error++; } else if(!update_local_entry) { LocalResource *lr = cxMapGet(db->resources, cx_hash_key_str(res->path)); @@ -2798,7 +2804,7 @@ // unlock repository if(locked) { if(dav_unlock(root)) { - print_resource_error(sn, "/"); + log_resource_error(sn, "/"); ret = -1; } else { locked = FALSE; @@ -2807,7 +2813,7 @@ // store db if(store_db(db, dir->database, dir->db_settings)) { - fprintf(stderr, "Cannot store sync db\n"); + log_error("Cannot store sync db\n"); ret = -2; } @@ -2869,7 +2875,7 @@ log_printf("%s\n", "File Last Modified Size"); log_printf("%s\n", "=============================================================================="); - if(ls_mkcol) { + if(ls_mkcol->size > 0) { log_printf("Directories:\n"); CxIterator i = cxListIterator(ls_mkcol); cx_foreach(LocalResource *, res, i) { @@ -2877,7 +2883,7 @@ total_size += res->size; } } - if(ls_new) { + if(ls_new->size > 0) { log_printf("New:\n"); CxIterator i = cxListIterator(ls_new); cx_foreach(LocalResource *, res, i) { @@ -2885,7 +2891,7 @@ total_size += res->size; } } - if(ls_modified) { + if(ls_modified->size > 0) { log_printf("Modified:\n"); CxIterator i = cxListIterator(ls_modified); cx_foreach(LocalResource *, res, i) { @@ -2893,7 +2899,7 @@ total_size += res->size; } } - if(ls_update) { + if(ls_update->size > 0) { log_printf("Update:\n"); CxIterator i = cxListIterator(ls_update); cx_foreach(LocalResource *, res, i) { @@ -2902,28 +2908,28 @@ free(lastmodified); } } - if(ls_delete) { + if(ls_delete->size > 0) { log_printf("Delete:\n"); CxIterator i = cxListIterator(ls_delete); cx_foreach(LocalResource *, res, i) { log_printf(" %s\n", res->path+1); } } - if(ls_copy) { + if(ls_copy->size > 0) { log_printf("Copy:\n"); CxIterator i = cxListIterator(ls_copy); cx_foreach(LocalResource *, res, i) { log_printf("%s -> %s\n", res->origin->path+1, res->path); } } - if(ls_move) { + if(ls_move->size > 0) { log_printf("Move:\n"); CxIterator i = cxListIterator(ls_move); cx_foreach(LocalResource *, res, i) { log_printf("%s -> %s\n", res->origin->path+1, res->path); } } - if(ls_conflict) { + if(ls_conflict->size > 0) { log_printf("Conflict\n"); CxIterator i = cxListIterator(ls_conflict); cx_foreach(LocalResource *, res, i) { @@ -2962,7 +2968,7 @@ SYS_DIR local_dir = sys_opendir(local_path); if(!local_dir) { - fprintf(stderr, "Cannot open directory %s\n", local_path); + log_error("Cannot open directory %s: %s\n", local_path, strerror(errno)); } else { SysDirEnt *ent; while((ent = sys_readdir(local_dir)) != NULL) { @@ -3001,7 +3007,7 @@ char *file_path = create_local_path(dir, path); SYS_STAT s; if(sys_lstat(file_path, &s)) { - fprintf(stderr, "Cannot stat file %s\n", file_path); + log_error("Cannot stat file %s: %s\n", file_path, strerror(errno)); free(file_path); return NULL; } @@ -3472,7 +3478,7 @@ if(dav_load_prop(vcol, defprops, numdefprops)) { - print_resource_error(res->session, vcol->path); + log_resource_error(res->session, vcol->path); dav_resource_free(vcol); return NULL; } @@ -3542,7 +3548,7 @@ t.actime = f.last_modified; t.modtime = f.last_modified; if(utime(path, &t)) { - fprintf(stderr, "utime failed for file: %s : %s\n", path, strerror(errno)); + log_error("utime failed for file: %s : %s\n", path, strerror(errno)); ret = 1; } else { local->last_modified = f.last_modified; @@ -3551,7 +3557,7 @@ if((dir->metadata & FINFO_MODE) == FINFO_MODE && f.mode_set) { // set mode if(chmod(path, f.mode)) { - fprintf(stderr, "chmod failed for file: %s : %s\n", path, strerror(errno)); + log_error("chmod failed for file: %s : %s\n", path, strerror(errno)); ret = 1; } else { local->mode = f.mode; @@ -3601,7 +3607,7 @@ for(int i=0;ivalues[i]; if(xattr_set(path, xattr->names[i], value.ptr, value.length)) { - fprintf(stderr, + log_error( "Cannot store xattr '%s' for file: %s\n", xattr->names[i], path); @@ -4064,7 +4070,7 @@ if(res->exists) { if(!res->iscollection) { if(dav_delete(res)) { - print_resource_error(res->session, res->path); + log_resource_error(res->session, res->path); *err = 1; return NULL; } @@ -4074,7 +4080,7 @@ } else { res->iscollection = 1; if(dav_create(res)) { - print_resource_error(res->session, res->path); + log_resource_error(res->session, res->path); *err = 1; return NULL; } @@ -4083,7 +4089,7 @@ if(!res->href) { // this should never happen, but just make sure it doesn't crash - fprintf(stderr, "href is NULL\n"); + log_error("href is NULL\n"); *err = 1; return NULL; } @@ -4100,7 +4106,7 @@ int nblocks = filesize / blocksize; int digits = LOG10((double)nblocks) + 1; if(digits > 127) { - fprintf(stderr, "Too many parts\n"); + log_error("Too many parts\n"); *err = 1; free(buffer); return NULL; @@ -4152,7 +4158,7 @@ dav_set_content_data(part, buffer, r); if(dav_store(part)) { *err = 1; - print_resource_error(res->session, part->path); + log_resource_error(res->session, part->path); } else { // successfully uploaded part @@ -4193,7 +4199,7 @@ CxList *updated_parts = cxLinkedListCreateSimple(CX_STORE_POINTERS); DavResource *parts = dav_query(res->session, "select D:getetag from %s order by name", res->path); if(!parts) { - print_resource_error(res->session, parts->path); + log_resource_error(res->session, parts->path); *err = 1; cxMapDestroy(updated_parts_map); return NULL; @@ -4230,7 +4236,7 @@ if(delete_part) { if(dav_delete(part)) { - print_resource_error(part->session, part->path); + log_resource_error(part->session, part->path); } } } @@ -4304,8 +4310,7 @@ SYS_STAT s; if(sys_stat(local_path, &s)) { - fprintf(stderr, "Cannot stat file: %s\n", local_path); - perror(""); + log_error("Cannot stat file: %s: %s\n", local_path, strerror(errno)); free(local_path); return -1; } @@ -4319,7 +4324,7 @@ FILE *in = sys_fopen(local_path, "rb"); if(!in) { - fprintf(stderr, "Cannot open file %s\n", local_path); + log_error("Cannot open file %s: %s\n", local_path, strerror(errno)); free(local_path); return -1; } @@ -4368,13 +4373,13 @@ // versioncontrol (DeltaV only, does nothing with simple versioning) if(exists && versioning_init(dir, local, res)) { // init failed - fprintf(stderr, "Cannot activate versioncontrol for resource: %s\n", res->href); + log_error("Cannot activate versioncontrol for resource: %s\n", res->href); free(local_path); return -1; } else { int err = versioning_begin(dir, res, &exists, &vend_required); if(err) { - fprintf(stderr, "Cannot store version for resource: %s\n", res->href); + log_error("Cannot store version for resource: %s\n", res->href); free(local_path); return -1; } @@ -4397,7 +4402,7 @@ if(vend_required) { if(versioning_end(dir, res)) { - fprintf(stderr, "Cannot checkin resource\n"); + log_error("Cannot checkin resource\n"); ret = 1; } } @@ -4416,7 +4421,7 @@ if(up_res) { // the new content length must be equal or greater than the file size if(up_res->contentlength < s.st_size && !issplit && !islink) { - fprintf(stderr, "Incomplete Upload: %s\n", local_path); + log_error("Incomplete Upload: %s\n", local_path); ret = -1; // try to set the resource status to 'broken' sync_set_status(res, "broken"); @@ -4476,8 +4481,7 @@ SYS_STAT s; if(sys_stat(local_path, &s)) { - fprintf(stderr, "Cannot stat file: %s\n", local_path); - perror(""); + log_error("Cannot stat file: %s: %s\n", local_path, strerror(errno)); free(local_path); return -1; } @@ -4509,7 +4513,7 @@ MetadataHashes hashes; hashes = sync_set_metadata_properties(dir, up_res->session, up_res, local, TRUE); if(dav_store(up_res)) { - fprintf(stderr, "Error: cannot store resource metadata\n"); + log_error("Error: cannot store resource metadata\n"); } // get new etag @@ -4554,7 +4558,7 @@ log_printf("delete: %s\n", res->path); if(dav_delete(res)) { ret = 1; - fprintf(stderr, "Cannot delete collection %s\n", res->path); + log_error("Cannot delete collection %s\n", res->path); } else { (*counter)++; } @@ -4575,16 +4579,14 @@ int vend_required = 0; if(dir->versioning && dir->versioning->always) { if(versioning_delete_begin(dir, res, &exists, &vend_required)) { - fprintf( - stderr, - "Cannot save resource version before deletion\n"); + log_error("Cannot save resource version before deletion\n"); ret = 1; } } if(!ret && dav_delete(res) && exists) { if(sn->error != DAV_NOT_FOUND) { - fprintf(stderr, "Cannot delete resource %s\n", res->path); + log_error("Cannot delete resource %s\n", res->path); ret = 1; } } else { @@ -4633,7 +4635,7 @@ p.ns = DAV_PROPS_NS; p.name = "tags"; if(dav_load_prop(res, &p, 1) && sn->error != DAV_NOT_FOUND) { - print_resource_error(sn, res->path); + log_resource_error(sn, res->path); } CxList *remote_tags = NULL; DavXmlNode *tagsprop = dav_get_property_ns(res, DAV_PROPS_NS, "tags"); @@ -4736,7 +4738,7 @@ int err = 0; if(dav_store(res)) { - print_resource_error(sn, local->path); + log_resource_error(sn, local->path); err = 1; } else { update_metadata_hashes(local, hashes); @@ -4759,8 +4761,7 @@ dc[numdc] = res->path; numdc++; } else { - fprintf(stderr, "Cannot stat file: %s\n", path); - perror(""); + log_error("Cannot stat file: %s: %s\n", path, strerror(errno)); } } free(path); @@ -4779,11 +4780,11 @@ cx_foreach(LocalResource *, res, i) { if(res->skipped) { skipped++; - fprintf(stderr, "skipped from push: %s\n", res->path); + log_error("skipped from push: %s\n", res->path); } } if(skipped > 0) { - fprintf(stderr, + log_error( " To resolve conflict resources skipped by push run dav-sync pull first\n" " before resolve-conflicts or delete-conflicts.\n\n"); } @@ -4791,13 +4792,13 @@ int cmd_resolve_conflicts(CmdArgs *a) { if(a->argc != 1) { - fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many"); + log_error("Too %s arguments\n", a->argc < 1 ? "few" : "many"); return -1; } SyncDirectory *dir = scfg_get_dir(a->argv[0]); if(!dir) { - fprintf(stderr, "Unknown sync dir: %s\n", a->argv[0]); + log_error("Unknown sync dir: %s\n", a->argv[0]); return -1; } if(scfg_check_dir(dir)) { @@ -4809,7 +4810,7 @@ SyncDatabase *db = load_db(dir->database); if(!db) { - fprintf(stderr, "Cannot load database file: %s\n", dir->database); + log_error("Cannot load database file: %s\n", dir->database); return -1; } @@ -4824,8 +4825,8 @@ // store db if(store_db(db, dir->database, dir->db_settings)) { - fprintf(stderr, "Cannot store sync db\n"); - fprintf(stderr, "Abort\n"); + log_error("Cannot store sync db\n"); + log_error("Abort\n"); ret = -2; } @@ -4861,7 +4862,7 @@ SyncDatabase *db = load_db(dir->database); if(!db) { - fprintf(stderr, "Cannot load database file: %s\n", dir->database); + log_error("Cannot load database file: %s\n", dir->database); return -1; } @@ -4879,7 +4880,7 @@ char *path = create_local_path(dir, res->path); if(sys_unlink(path)) { if(errno != ENOENT) { - perror("unlink"); + log_error("unlink: %s", strerror(errno)); num_err++; } } else { @@ -4892,8 +4893,8 @@ // store db if(store_db(db, dir->database, dir->db_settings)) { - fprintf(stderr, "Cannot store sync db\n"); - fprintf(stderr, "Abort\n"); + log_error("Cannot store sync db\n"); + log_error("Abort\n"); ret = -1; } @@ -5235,14 +5236,14 @@ } if(!syncdir->trash) { - fprintf(stderr, "trash not configured for %s\n", syncdir->name); + log_error("trash not configured for %s\n", syncdir->name); return -1; } SYS_DIR dir = sys_opendir(syncdir->trash); if(!dir) { - fprintf(stderr, "cannot open trash directory: %s\n", syncdir->trash); - perror("opendir"); + log_error("cannot open trash directory: %s\n", syncdir->trash); + log_error("opendir: %s\n", strerror(errno)); return -1; } @@ -5257,17 +5258,17 @@ SYS_STAT s; if(sys_stat(path, &s)) { - perror("stat"); + log_error("stat: %s\n", strerror(errno)); free(path); continue; } if(S_ISDIR(s.st_mode)) { if(rmdir(path)) { - perror("rmdir"); + log_error("rmdir: %s\n", strerror(errno)); } } else { if(sys_unlink(path)) { - perror("unlink"); + log_error("unlink: %s\n", strerror(errno)); } } @@ -5534,12 +5535,12 @@ void sync_print_get_file_err(const char *path, int err) { switch(err) { - case 1: fprintf(stderr, "File %s: not found\n", path); break; - case 2: fprintf(stderr, "File %s: permission denied\n", path); break; - case 3: fprintf(stderr, "File %s: stat failed: %s\n", path, strerror(errno)); break; - case 4: fprintf(stderr, "File %s is not in any syncdir\n", path); break; - case 5: fprintf(stderr, "File %s is in multiple syncdirs\n", path); break; - case 6: fprintf(stderr, "Syncdir not found\n"); break; + case 1: log_error("File %s: not found\n", path); break; + case 2: log_error("File %s: permission denied\n", path); break; + case 3: log_error("File %s: stat failed: %s\n", path, strerror(errno)); break; + case 4: log_error("File %s is not in any syncdir\n", path); break; + case 5: log_error("File %s is in multiple syncdirs\n", path); break; + case 6: log_error("Syncdir not found\n"); break; } } @@ -5701,11 +5702,11 @@ FILE *file = sys_fopen(path, "w"); if(file) { - fprintf(file, "%s\n", locktoken); + log_error("%s\n", locktoken); fclose(file); return path; } else { - perror("Cannot create locktoken file"); + log_error("Cannot create locktoken file: %s", strerror(errno)); free(path); return NULL; }