read link on LocalResource creation

Sun, 14 Apr 2019 20:08:18 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 14 Apr 2019 20:08:18 +0200
changeset 574
c36eddf167a8
parent 573
b8f798d240ab
child 575
f746f601c35c

read link on LocalResource creation

dav/sync.c file | annotate | diff | comparison | revisions
dav/system.c file | annotate | diff | comparison | revisions
dav/system.h file | annotate | diff | comparison | revisions
--- 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(
--- a/dav/system.c	Sun Apr 14 19:39:08 2019 +0200
+++ b/dav/system.c	Sun Apr 14 20:08:18 2019 +0200
@@ -91,6 +91,10 @@
     return stat(path, s);
 }
 
+int sys_lstat(const char *path, SYS_STAT *s) {
+    return lstat(path, s);
+}
+
 int sys_rename(const char *oldpath, const char *newpath) {
     return rename(oldpath, newpath);
 }
@@ -103,6 +107,10 @@
     return mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
 }
 
+ssize_t sys_readlink(const char *path, char *buffer, size_t size) {
+    return readlink(path, buffer, size);
+}
+
 #else
 /* ---------- Windows implementation ---------- */
 
@@ -226,6 +234,18 @@
     return ret;
 }
 
+int sys_lstat(const char *path, SYS_STAT *s) {
+    // TODO: fix
+    wchar_t *fpath = path2winpath(path, FALSE, NULL);
+    if(!fpath) {
+        fprintf(stderr, "Cannot convert path \"%s\" to UTF16\n", path);
+        return -1;
+    }
+    int ret = _wstat64(fpath, s);
+    free(fpath);
+    return ret;
+}
+
 int sys_rename(const char *oldpath, const char *newpath) {
     wchar_t *o = path2winpath(oldpath, FALSE, NULL);
     wchar_t *n = path2winpath(newpath, FALSE, NULL);
@@ -268,4 +288,10 @@
     return ret;
 }
 
+ssize_t sys_readlink(const char *path, char *buffer, size_t size) {
+    // TODO
+    fprintf(stderr, "sys_readlink: implement me\n");
+    return 1;
+}
+
 #endif
--- a/dav/system.h	Sun Apr 14 19:39:08 2019 +0200
+++ b/dav/system.h	Sun Apr 14 20:08:18 2019 +0200
@@ -76,11 +76,14 @@
 FILE* sys_fopen(const char *path, const char *mode);
 
 int sys_stat(const char *path, SYS_STAT *s);
+int sys_lstat(const char *path, SYS_STAT *s);
 
 int sys_rename(const char *oldpath, const char *newpath);
 int sys_unlink(const char *path);
 int sys_mkdir(const char *path);
 
+ssize_t sys_readlink(const char *path, char *buffer, size_t size);
+
 #ifdef __cplusplus
 }
 #endif

mercurial