diff -r b8f798d240ab -r c36eddf167a8 dav/sync.c --- a/dav/sync.c Sun Apr 14 19:39:08 2019 +0200 +++ b/dav/sync.c Sun Apr 14 20:08:18 2019 +0200 @@ -2401,33 +2401,54 @@ LocalResource* local_resource_new(SyncDirectory *dir, SyncDatabase *db, char *path) { char *file_path = create_local_path(dir, path); SYS_STAT s; - if(sys_stat(file_path, &s)) { + if(sys_lstat(file_path, &s)) { fprintf(stderr, "Cannot stat file %s\n", file_path); free(file_path); return NULL; } - free(file_path); + LocalResource *res = calloc(1, sizeof(LocalResource)); + res->mode = s.st_mode & 07777; + res->uid = s.st_uid; + res->gid = s.st_gid; + res->last_modified = s.st_mtime; if(!S_ISDIR(s.st_mode)) { - LocalResource *res = calloc(1, sizeof(LocalResource)); res->path = strdup(path); - res->etag = NULL; - res->last_modified = s.st_mtime; res->size = s.st_size; - res->mode = s.st_mode & 07777; - res->uid = s.st_uid; - res->gid = s.st_gid; - return res; } else { - LocalResource *res = calloc(1, sizeof(LocalResource)); res->path = util_concat_path(path, "/"); - res->last_modified = s.st_mtime; - res->mode = s.st_mode & 07777; - res->uid = s.st_uid; - res->gid = s.st_gid; res->isdirectory = 1; - return res; - } + } + + if(S_ISLNK(s.st_mode)) { + size_t lnksize = s.st_size > 256 ? s.st_size : 256; + char *lnkbuf = malloc(lnksize); + + ssize_t len = 0; + for(int i=0;i<4;i++) { + // we try to read the link at most 4 times + // only repeat if the buffer is too small + len = sys_readlink(file_path, lnkbuf, lnksize); + if(len != lnksize) { + break; + } + lnksize *= 2; + lnkbuf = realloc(lnkbuf, lnksize); + } + + if(len > 0) { + res->link_target = lnkbuf; + res->link_target[len] = 0; + } else { + free(lnkbuf); + } + + free(lnkbuf); + } + + free(file_path); + + return res; } int local_resource_is_changed(