src/server/plugins/postgresql/vfs.c

branch
webdav
changeset 281
e9dc53661df4
parent 280
d0d5a970292f
child 282
cfb588e27198
--- a/src/server/plugins/postgresql/vfs.c	Mon Jan 31 21:33:46 2022 +0100
+++ b/src/server/plugins/postgresql/vfs.c	Tue Feb 01 17:47:50 2022 +0100
@@ -71,9 +71,12 @@
         select\n\
             resource_id,\n\
             parent_id,\n\
+            '' as fullpath,\n\
             iscollection,\n\
+            lastmodified,\n\
+            creationdate,\n\
+            contentlength,\n\
             regexp_split_to_array($1, '/') as pathelm,\n\
-            '' as fullpath,\n\
             1 as pathdepth\n\
         from Resource\n\
         where parent_id is null\n\
@@ -81,9 +84,12 @@
         select\n\
             r.resource_id,\n\
             r.parent_id,\n\
+            p.fullpath || '/' || r.nodename,\n\
             r.iscollection,\n\
+            r.lastmodified,\n\
+            r.creationdate,\n\
+            r.contentlength,\n\
             p.pathelm,\n\
-            p.fullpath || '/' || r.nodename,\n\
             p.pathdepth + 1\n\
         from Resource r\n\
         inner join resolvepath p on r.parent_id = p.resource_id\n\
@@ -94,12 +100,15 @@
 
 // Same as sql_resolve_path, but it returns the root collection
 // params: $1: path string (should be '/')
-static const char *sql_get_root = "select resource_id, parent_id, $1 as fullpath, true as iscollection from Resource where parent_id is null;";
+static const char *sql_get_root = "select resource_id, parent_id, $1 as fullpath, true as iscollection, lastmodified, creationdate, contentlength from Resource where parent_id is null;";
 
 // Get all children of a specific collection
 // params: $1: parent resource_id
-static const char *sql_get_children = "select resource_id, nodename, iscollection from Resource where parent_id = $1;";
+static const char *sql_get_children = "select resource_id, nodename, iscollection, lastmodified, creationdate, contentlength from Resource where parent_id = $1;";
 
+// Get resource
+// params: $1: resource_id
+static const char *sql_get_resource = "select resource_id, nodename, iscollection, lastmodified, creationdate, contentlength from Resource where resource_id = $1;";
 
 VFS* pg_vfs_create(Session *sn, Request *rq, pblock *pb) {
     // resourcepool is required
@@ -141,7 +150,15 @@
 }
 
 
-int pg_resolve_path(VFSContext *ctx, const char *path, int64_t *parent_id, int64_t *resource_id, const char **resource_name, WSBool *iscollection) {
+int pg_resolve_path(
+        VFSContext *ctx,
+        const char *path,
+        int64_t *parent_id,
+        int64_t *resource_id,
+        const char **resource_name,
+        WSBool *iscollection,
+        struct stat *s)
+{
     // basic path validation
     if(!path) return 1;
     size_t pathlen = strlen(path);
@@ -150,13 +167,21 @@
         return 1;
     }
     
+    char *pathf = NULL;
+    if(pathlen > 1 && path[pathlen-1] == '/') {
+        pathf = malloc(pathlen);
+        memcpy(pathf, path, pathlen);
+        pathf[pathlen-1] = 0; // remove trailing '/'
+        path = pathf;
+    }
+    
     // get last node of path
     *resource_name = util_resource_name(path);
     
     VFS *vfs = ctx->vfs;
     PgVFS *pg = vfs->instance;
     
-    const char *sql = pathlen == 1 ? sql_get_root : sql_resolve_path;
+    const char *sql = pathlen == 1 ? sql_get_root : sql_resolve_path;  
     PGresult *result = PQexecParams(
             pg->connection,
             sql,
@@ -167,15 +192,22 @@
             NULL,
             0);    // 0: result in text format
     
+    if(pathf) {
+        free(pathf);
+    }
+    
     if(!result) return 1;
     
     int ret = 1;
-    int nfields = PQnfields(result);
+    //int nfields = PQnfields(result);
     int nrows = PQntuples(result);
-    if(nrows == 1 && nfields == 4) {
+    if(nrows == 1) {
         char *resource_id_str = PQgetvalue(result, 0, 0);
         char *parent_id_str = PQgetvalue(result, 0, 1);
         char *iscol = PQgetvalue(result, 0, 3);
+        char *lastmodified = PQgetvalue(result, 0, 4);
+        char *creationdate = PQgetvalue(result, 0, 5);
+        char *contentlength = PQgetvalue(result, 0, 6);
         if(resource_id_str && parent_id_str) {
             if(util_strtoint(resource_id_str, resource_id)) {
                 ret = 0; // success
@@ -183,9 +215,31 @@
             // optionally get parent_id
             util_strtoint(parent_id_str, parent_id);
         }
-        if(iscol) {
+        
+        if(iscollection && iscol) {
             *iscollection = iscol[0] == 't' ? TRUE : FALSE;
         }
+        
+        if(s) {
+            memset(s, 0, sizeof(struct stat));
+            
+            s->st_ino = *resource_id;
+            if(iscol) {
+                s->st_mode |= 0x4000;
+            }
+            if(lastmodified) {
+                // TODO
+            }
+            if(creationdate) {
+                // TODO
+            }
+            if(contentlength) {
+                int64_t len;
+                if(util_strtoint(contentlength, &len)) {
+                    s->st_size = len;
+                }
+            }
+        }
     } else {
         ctx->vfs_errno = ENOENT;
     }
@@ -204,7 +258,8 @@
     resource_id = -1;
     parent_id = -1;
     WSBool iscollection;
-    if(pg_resolve_path(ctx, path, &parent_id, &resource_id, &resname, &iscollection)) {
+    struct stat s;
+    if(pg_resolve_path(ctx, path, &parent_id, &resource_id, &resname, &iscollection, &s)) {
         return NULL;
     }
     
@@ -221,9 +276,10 @@
     pgfile->iscollection = iscollection;
     pgfile->resource_id = resource_id;
     pgfile->parent_id = parent_id;
+    pgfile->s = s;
     
     file->ctx = ctx;
-    file->io = iscollection ? NULL : &pg_vfs_io_class;
+    file->io = iscollection ? &pg_vfs_io_class : &pg_vfs_io_class;
     file->fd = -1;
     file->data = pgfile;
     
@@ -231,11 +287,16 @@
 }
 
 int pg_vfs_stat(VFSContext *ctx, const char *path, struct stat *buf) {
-    
+    int64_t parent_id, resource_id;
+    const char *resname;
+    WSBool iscollection;
+    return pg_resolve_path(ctx, path, &parent_id, &resource_id, &resname, &iscollection, buf);
 }
 
 int pg_vfs_fstat(VFSContext *ctx, SYS_FILE fd, struct stat *buf) {
-    
+    PgFile *pgfile = fd->data;
+    memcpy(buf, &pgfile->s, sizeof(struct stat));
+    return 0;
 }
 
 VFS_DIR pg_vfs_opendir(VFSContext *ctx, const char *path) {
@@ -334,7 +395,7 @@
             sql_get_children,
             1,                                  // number of parameters
             NULL,
-            &param,  // param: parent resource_id 
+            &param,                             // param: parent resource_id 
             NULL,
             NULL,
             0);                                 // 0: result in text format

mercurial