184 return -1; |
189 return -1; |
185 } |
190 } |
186 printf("get %s\n", res->path); |
191 printf("get %s\n", res->path); |
187 if(dav_get_content(res, out, (dav_write_func)fwrite)) { |
192 if(dav_get_content(res, out, (dav_write_func)fwrite)) { |
188 ret = -1; |
193 ret = -1; |
189 } else { |
|
190 if(local) { |
|
191 if(local->etag) { |
|
192 free(local->etag); |
|
193 } |
|
194 local->etag = etag; |
|
195 } |
|
196 } |
194 } |
197 fclose(out); |
195 fclose(out); |
|
196 |
|
197 if(ret == 0) { |
|
198 // get file informations for db update |
|
199 struct stat s; |
|
200 if(stat(local_path, &s)) { |
|
201 fprintf(stderr, "stat failed: %s\n", local_path); |
|
202 ret = -1; |
|
203 } |
|
204 |
|
205 if(!local) { |
|
206 local = calloc(1, sizeof(LocalResource)); |
|
207 local->path = strdup(res->path); |
|
208 ucx_map_cstr_put(db, local->path, local); |
|
209 } |
|
210 |
|
211 if(local->etag) { |
|
212 free(local->etag); |
|
213 } |
|
214 local->etag = etag; |
|
215 local->last_modified = s.st_mtim.tv_sec; |
|
216 local->size = s.st_size; |
|
217 } |
198 } |
218 } |
199 |
219 |
200 free(local_path); |
220 free(local_path); |
201 return ret; |
221 return ret; |
202 } |
222 } |
203 |
223 |
204 int cmd_push(CmdArgs *a) { |
224 int cmd_push(CmdArgs *a) { |
|
225 if(a->argc != 1) { |
|
226 fprintf(stderr, "Too %s arguments\n", a->argc < 1 ? "few" : "many"); |
|
227 return -1; |
|
228 } |
|
229 |
|
230 SyncDirectory *dir = scfg_get_dir(a->argv[0]); |
|
231 if(!dir) { |
|
232 fprintf(stderr, "Unknown sync dir: %s\n", a->argv[0]); |
|
233 return -1; |
|
234 } |
|
235 |
|
236 Repository *repo = get_repository(sstr(dir->repository)); |
|
237 if(!repo) { |
|
238 fprintf(stderr, "Unkown repository %s\n", dir->name); |
|
239 return -1; |
|
240 } |
|
241 |
|
242 UcxMap *db = load_db(dir->database); |
|
243 if(!db) { |
|
244 fprintf(stderr, "Cannot load database file: %s\n", dir->database); |
|
245 return -1; |
|
246 } |
|
247 |
|
248 DavSession *sn = dav_session_new_auth( |
|
249 ctx, |
|
250 repo->url, |
|
251 repo->user, |
|
252 repo->password); |
|
253 dav_session_set_flags(sn, get_repository_flags(repo)); |
|
254 sn->key = dav_context_get_key(ctx, repo->default_key); |
|
255 |
|
256 UcxList *resources = local_scan(dir, db); |
|
257 UCX_FOREACH(elm, resources) { |
|
258 char *path = elm->data; |
|
259 printf("put: %s\n", path); |
|
260 DavResource *res = dav_resource_new(sn, path); |
|
261 sync_put_resource(dir, res, db); |
|
262 dav_resource_free(res); |
|
263 free(path); |
|
264 } |
|
265 ucx_list_free(resources); |
|
266 |
|
267 // store db |
|
268 if(store_db(db, dir->database)) { |
|
269 fprintf(stderr, "Cannot store sync db\n"); |
|
270 return -1; |
|
271 } |
|
272 |
205 return 0; |
273 return 0; |
206 } |
274 } |
|
275 |
|
276 UcxList* local_scan(SyncDirectory *dir, UcxMap *db) { |
|
277 UcxList *resources = NULL; |
|
278 |
|
279 char *path = strdup("/"); |
|
280 UcxList *stack = ucx_list_prepend(NULL, path); |
|
281 while(stack) { |
|
282 // get a directory path from the stack and read all entries |
|
283 // if an entry is a directory, put it on the stack |
|
284 // otherwise compare the metadata with the db content |
|
285 |
|
286 char *p = stack->data; |
|
287 stack = ucx_list_remove(stack, stack); |
|
288 char *local_path = util_concat_path(dir->path, p); |
|
289 DIR *local_dir = opendir(local_path); |
|
290 |
|
291 if(!local_dir) { |
|
292 fprintf(stderr, "Cannot open directory %s\n", local_path); |
|
293 } else { |
|
294 long namemax = namemax = pathconf(path, _PC_NAME_MAX); |
|
295 if(namemax == 0) { |
|
296 namemax = 255; |
|
297 } |
|
298 struct dirent *ent = malloc(sizeof(struct dirent) + namemax + 1); |
|
299 struct dirent *res = NULL; |
|
300 while(!readdir_r(local_dir, ent, &res) && res) { |
|
301 if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) { |
|
302 continue; |
|
303 } |
|
304 |
|
305 char *new_path = util_concat_path(p, ent->d_name); |
|
306 char *file_path = util_concat_path(dir->path, new_path); |
|
307 struct stat s; |
|
308 if(stat(file_path, &s)) { |
|
309 fprintf(stderr, "Cannot stat file %s\n", file_path); |
|
310 free(new_path); |
|
311 free(file_path); |
|
312 continue; |
|
313 } |
|
314 free(file_path); |
|
315 |
|
316 if(S_ISDIR(s.st_mode)) { |
|
317 stack = ucx_list_prepend(stack, new_path); |
|
318 } else { |
|
319 LocalResource *res = ucx_map_cstr_get(db, new_path); |
|
320 if(res) { |
|
321 // the file is already in the database |
|
322 // compare length and lastmodified date |
|
323 |
|
324 if(res->last_modified == s.st_mtim.tv_sec |
|
325 && res->size == s.st_size) |
|
326 { |
|
327 // skip this file |
|
328 free(new_path); |
|
329 } else { |
|
330 // add file to list |
|
331 resources = ucx_list_append( |
|
332 resources, |
|
333 new_path); |
|
334 |
|
335 // update db entries |
|
336 res->size = s.st_size; |
|
337 res->last_modified = s.st_mtim.tv_sec; |
|
338 } |
|
339 } else { |
|
340 // add file to list |
|
341 LocalResource *res = calloc(1, sizeof(LocalResource)); |
|
342 res->path = strdup(new_path); |
|
343 res->etag = NULL; |
|
344 res->last_modified = s.st_mtim.tv_sec; |
|
345 res->size = s.st_size; |
|
346 ucx_map_cstr_put(db, res->path, res); |
|
347 resources = ucx_list_append(resources, new_path); |
|
348 } |
|
349 } |
|
350 } |
|
351 closedir(local_dir); |
|
352 free(ent); |
|
353 } |
|
354 free(local_path); |
|
355 free(p); |
|
356 } |
|
357 |
|
358 return resources; |
|
359 } |
|
360 |
|
361 int sync_put_resource(SyncDirectory *dir, DavResource *res, UcxMap *db) { |
|
362 char *local_path = util_concat_path(dir->path, res->path); |
|
363 FILE *in = fopen(local_path, "r"); |
|
364 if(!in) { |
|
365 fprintf(stderr, "Cannot open file %s\n", local_path); |
|
366 free(local_path); |
|
367 return -1; |
|
368 } |
|
369 free(local_path); |
|
370 |
|
371 dav_set_content(res, in, (dav_read_func)fread); |
|
372 |
|
373 int ret = -1; |
|
374 for(;;) { |
|
375 if(dav_create(res)) { |
|
376 break; |
|
377 } |
|
378 if(dav_store(res)) { |
|
379 break; |
|
380 } |
|
381 if(dav_load(res)) { |
|
382 break; |
|
383 } |
|
384 ret = 0; |
|
385 break; |
|
386 } |
|
387 |
|
388 if(ret == 0) { |
|
389 LocalResource *local_res = ucx_map_cstr_get(db, res->path); |
|
390 if(local_res->etag) { |
|
391 free(local_res->etag); |
|
392 } |
|
393 char *etag = dav_get_property(res, "D:getetag"); |
|
394 if(etag) { |
|
395 local_res->etag = strdup(dav_get_property(res, "D:getetag")); |
|
396 } else { |
|
397 local_res->etag = NULL; |
|
398 } |
|
399 } |
|
400 |
|
401 fclose(in); |
|
402 |
|
403 return 0; |
|
404 } |
|
405 |
|
406 |
207 |
407 |
208 int cmd_sync(CmdArgs *a) { |
408 int cmd_sync(CmdArgs *a) { |
209 return 0; |
409 return 0; |
210 } |
410 } |
211 |
411 |