diff -r c2c02c9b3be4 -r 82475dc12dd4 dav/sync.c --- a/dav/sync.c Sat Oct 03 13:33:15 2015 +0200 +++ b/dav/sync.c Sat Oct 03 14:36:12 2015 +0200 @@ -268,7 +268,7 @@ int exists = 1; if(stat(local_path, &s)) { // Ignore the fact, that the file is locally removed. If the - // server has an updated version, we readd the file or the + // server has an updated version, we read the file or the // next push will delete it on the server. if(errno != ENOENT) { fprintf(stderr, "Cannot stat file: %s\n", local_path); @@ -308,16 +308,23 @@ } int ret = 0; + char *tmp_path = create_tmp_download_path(local_path); if(res->iscollection) { mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; if(util_mkdir(local_path, mode) && errno != EEXIST) { ret = -1; } } else { - FILE *out = fopen(local_path, "wb"); + if(!tmp_path) { + fprintf(stderr, "Cannot create tmp path for %s\n", local_path); + free(local_path); + return -1; + } + FILE *out = fopen(tmp_path, "wb"); if(!out) { fprintf(stderr, "Cannot open output file: %s\n", local_path); free(local_path); + free(tmp_path); return -1; } printf("get: %s\n", res->path); @@ -326,11 +333,27 @@ } fclose(out); - if(stat(local_path, &s)) { - fprintf(stderr, "Cannot stat file: %s\n", local_path); - } - if(ret == 0) { + if(dir->trash && dir->backuppull) { + move_to_trash(dir, local_path); + } + if(rename(tmp_path, local_path)) { + fprintf( + stderr, + "Cannot rename file %s to %s\n", + tmp_path, + local_path); + perror(""); + free(tmp_path); + free(local_path); + return -1; + } + + if(stat(local_path, &s)) { + fprintf(stderr, "Cannot stat file: %s\n", local_path); + perror(""); + } + if(!local) { // new local resource local = calloc(1, sizeof(LocalResource)); @@ -345,9 +368,14 @@ local->etag = etag; local->last_modified = s.st_mtime; local->size = s.st_size; + } else { + if(unlink(tmp_path)) { + fprintf(stderr, "Cannot remove tmp file: %s\n", tmp_path); + } } } + free(tmp_path); free(local_path); return ret; } @@ -411,6 +439,31 @@ free(parent); } +char* create_tmp_download_path(char *path) { + char *new_path = NULL; + char *parent = util_parent_path(path); + for (int i=0;;i++) { + sstr_t np = ucx_asprintf( + ucx_default_allocator(), + "%sdownload%d-%s", + parent, + i, + util_resource_name(path)); + + struct stat s; + if(stat(np.ptr, &s)) { + if(errno == ENOENT) { + new_path = np.ptr; + } + break; + } + free(np.ptr); + }; + + free(parent); + return new_path; +} + void move_to_trash(SyncDirectory *dir, char *path) { char *new_path = NULL; for (int i=0;;i++) {