dav/sync.c

changeset 52
91517b874a86
parent 51
e94bf8530d56
child 53
ddc4efc9b0f8
equal deleted inserted replaced
51:e94bf8530d56 52:91517b874a86
33 #include <unistd.h> 33 #include <unistd.h>
34 #include <time.h> 34 #include <time.h>
35 #include <libxml/xmlerror.h> 35 #include <libxml/xmlerror.h>
36 #include <sys/types.h> 36 #include <sys/types.h>
37 #include <ucx/string.h> 37 #include <ucx/string.h>
38 #include <ucx/utils.h>
38 #include <dirent.h> 39 #include <dirent.h>
39 40
40 #include <libidav/webdav.h> 41 #include <libidav/webdav.h>
41 #include <libidav/utils.h> 42 #include <libidav/utils.h>
42 43
190 char *etag = dav_get_property(res, "D:getetag"); 191 char *etag = dav_get_property(res, "D:getetag");
191 struct stat s; 192 struct stat s;
192 if(local) { 193 if(local) {
193 if(stat(local_path, &s)) { 194 if(stat(local_path, &s)) {
194 if(errno == ENOENT) { 195 if(errno == ENOENT) {
195 printf("removed %s\n", res->path); 196 printf("removed: %s\n", res->path);
196 // the file is in the database, but doesn't exists 197 // the file is in the database, but doesn't exists
197 // mark the file as removed to delete it on next push 198 // mark the file as removed to delete it on next push
198 ucx_map_cstr_remove(db->resources, local->path); 199 ucx_map_cstr_remove(db->resources, local->path);
199 ucx_map_cstr_put(db->remove, local->path, local); 200 ucx_map_cstr_put(db->remove, local->path, local);
200 return 0; 201 return 0;
201 } else { 202 } else {
202 fprintf(stderr, "stat failed: %s\n", local_path); 203 fprintf(stderr, "Cannot stat file: %s\n", local_path);
203 free(local_path); 204 free(local_path);
204 return -1; 205 return -1;
205 } 206 }
206 } 207 }
207 208
208 if(local->etag) { 209 if(local->etag) {
209 sstr_t e = sstr(etag); 210 sstr_t e = sstr(etag);
210 if(sstrprefix(e, S("W/"))) { 211 if(sstrprefix(e, S("W/"))) {
211 e = sstrsubs(e, 2); 212 e = sstrsubs(e, 2);
212 } 213 }
213 if(!strcmp(e.ptr, local->etag)) { 214 if(!strcmp(e.ptr, local->etag)) {
214 // resource is already up-to-date on the client 215 // resource is already up-to-date on the client
215 return 0; 216 return 0;
216 } 217 }
217 } 218 }
218 } 219
219 220 if(s.st_mtim.tv_sec != local->last_modified) {
221 // file modified on the server and on the client
222 rename_local_file(dir, db, local->path);
223 }
224 } else {
225 if(stat(local_path, &s)) {
226 if(errno != ENOENT) {
227 fprintf(stderr, "Cannot stat file: %s\n", local_path);
228 }
229 } else if(!S_ISDIR(s.st_mode)) {
230 rename_local_file(dir, db, res->path);
231 }
232 }
233
220 int ret = 0; 234 int ret = 0;
221 if(res->iscollection) { 235 if(res->iscollection) {
222 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 236 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
223 //printf("mkdir %s\n", local_path); 237 //printf("mkdir %s\n", local_path);
224 if(util_mkdir(local_path, mode) && errno != EEXIST) { 238 if(util_mkdir(local_path, mode) && errno != EEXIST) {
225 ret = -1; 239 ret = -1;
226 } 240 }
227 } else { 241 } else {
228 FILE *out = fopen(local_path, "w"); 242 FILE *out = fopen(local_path, "w");
229 if(!out) { 243 if(!out) {
230 fprintf(stderr, "cannot open output file: %s\n", local_path); 244 fprintf(stderr, "Cannot open output file: %s\n", local_path);
231 free(local_path); 245 free(local_path);
232 return -1; 246 return -1;
233 } 247 }
234 printf("get %s\n", res->path); 248 printf("get: %s\n", res->path);
235 if(dav_get_content(res, out, (dav_write_func)fwrite)) { 249 if(dav_get_content(res, out, (dav_write_func)fwrite)) {
236 ret = -1; 250 ret = -1;
237 } 251 }
238 fclose(out); 252 fclose(out);
253
254 if(stat(local_path, &s)) {
255 fprintf(stderr, "Cannot stat file: %s\n", local_path);
256 }
239 257
240 if(ret == 0) { 258 if(ret == 0) {
241 if(!local) { 259 if(!local) {
242 // new local resource 260 // new local resource
243 local = calloc(1, sizeof(LocalResource)); 261 local = calloc(1, sizeof(LocalResource));
275 printf("delete: %s\n", res->path); 293 printf("delete: %s\n", res->path);
276 if(unlink(local_path)) { 294 if(unlink(local_path)) {
277 fprintf(stderr, "Cannot remove file %s\n", local_path); 295 fprintf(stderr, "Cannot remove file %s\n", local_path);
278 } 296 }
279 free(local_path); 297 free(local_path);
298 }
299
300 void rename_local_file(SyncDirectory *dir, SyncDatabase *db, char *path) {
301 char *local_path = util_concat_path(dir->path, path);
302 char *parent = util_parent_path(local_path);
303
304 int rev = 0;
305 struct stat s;
306 int loop = 1;
307 do {
308 sstr_t new_path = ucx_asprintf(
309 ucx_default_allocator(),
310 "%sorig.%d.%s",
311 parent,
312 rev,
313 util_resource_name(path));
314
315
316 if(stat(new_path.ptr, &s)) {
317 if(errno == ENOENT) {
318 loop = 0;
319 printf("conflict: %s\n", local_path);
320 if(rename(local_path, new_path.ptr)) {
321 printf("errno: %d\n", errno);
322 fprintf(
323 stderr,
324 "Cannot rename file %s to %s\n",
325 local_path,
326 new_path.ptr);
327 }
328 }
329 }
330 rev++;
331 free(new_path.ptr);
332 } while(loop);
333 free(parent);
280 } 334 }
281 335
282 int cmd_push(CmdArgs *a) { 336 int cmd_push(CmdArgs *a) {
283 if(a->argc != 1) { 337 if(a->argc != 1) {
284 fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many"); 338 fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many");

mercurial