src/server/plugins/postgresql/vfs.c

branch
webdav
changeset 278
38bf7b42b58c
parent 276
0cb4eda146c4
child 279
79029fe26aae
equal deleted inserted replaced
277:7608af69739f 278:38bf7b42b58c
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include "vfs.h" 29 #include "vfs.h"
30 30
31 #include "../../util/util.h"
32
31 static VFS pg_vfs_class = { 33 static VFS pg_vfs_class = {
32 pg_vfs_open, 34 pg_vfs_open,
33 pg_vfs_stat, 35 pg_vfs_stat,
34 pg_vfs_fstat, 36 pg_vfs_fstat,
35 pg_vfs_opendir, 37 pg_vfs_opendir,
54 pg_vfs_dirio_readdir, 56 pg_vfs_dirio_readdir,
55 pg_vfs_dirio_close 57 pg_vfs_dirio_close
56 }; 58 };
57 59
58 60
61 /*
62 * SQL Queries
63 */
64
65 // Resolvs a path into resource_id and parent_id
66 // params: $1: path string
67 static const char *sql_resolve_path =
68 "with recursive resolvepath as (\n\
69 select\n\
70 resource_id,\n\
71 parent_id,\n\
72 iscollection,\n\
73 regexp_split_to_array($1, '/') as pathelm,\n\
74 '' as fullpath,\n\
75 1 as pathdepth\n\
76 from Resource\n\
77 where parent_id is null\n\
78 union\n\
79 select\n\
80 r.resource_id,\n\
81 r.parent_id,\n\
82 iscollection,\n\
83 p.pathelm,\n\
84 p.fullpath || '/' || r.nodename,\n\
85 p.pathdepth + 1\n\
86 from Resource r\n\
87 inner join resolvepath p on r.parent_id = p.resource_id\n\
88 where p.pathelm[p.pathdepth+1] = r.nodename\n\
89 )\
90 select resource_id, parent_id, fullpath, iscollection from resolvepath\n\
91 where fullpath = '$1;";
92
93
59 94
60 VFS* pg_vfs_create(Session *sn, Request *rq, pblock *pb) { 95 VFS* pg_vfs_create(Session *sn, Request *rq, pblock *pb) {
61 // resourcepool is required 96 // resourcepool is required
62 char *resource_pool = pblock_find("resourcepool", pb); 97 char *resource_pool = pblock_findval("resourcepool", pb);
63 if(!resource_pool) { 98 if(!resource_pool) {
64 log_ereport(LOG_MISCONFIG, "pg_vfs_create: missing resourcepool parameter"); 99 log_ereport(LOG_MISCONFIG, "pg_vfs_create: missing resourcepool parameter");
65 return NULL; 100 return NULL;
66 } 101 }
67 102
93 128
94 return vfs; 129 return vfs;
95 } 130 }
96 131
97 132
133 int pg_resolve_path(VFSContext *ctx, const char *path, int64_t *parent_id, int64_t *resource_id, const char **resource_name, WSBool *iscollection) {
134 // basic path validation
135 if(!path) return 1;
136 size_t pathlen = strlen(path);
137 if(pathlen == 0) return 1;
138 if(path[0] != '/') {
139 return 1;
140 }
141
142 // get last node of path
143 *resource_name = util_resource_name(path);
144
145 VFS *vfs = ctx->vfs;
146 PgVFS *pg = vfs->instance;
147
148
149 PGresult *result = PQexecParams(
150 pg->connection,
151 sql_resolve_path,
152 1, // number of parameters
153 NULL,
154 &path, // parameter value
155 NULL,
156 NULL,
157 0); // 1: result in text format
158
159 if(!result) return 1;
160
161 int ret = 1;
162 int nfields = PQnfields(result);
163 int nrows = PQntuples(result);
164 if(nrows == 1 && nfields == 4) {
165 char *resource_id_str = PQgetvalue(result, 0, 0);
166 char *parent_id_str = PQgetvalue(result, 0, 1);
167 char *iscol = PQgetvalue(result, 0, 2);
168 if(resource_id_str && parent_id_str) {
169 if(util_strtoint(resource_id_str, resource_id) && util_strtoint(parent_id_str, parent_id)) {
170 ret = 0; // success
171 }
172 }
173 if(iscol) {
174 *iscollection = iscol[0] == 't' ? TRUE : FALSE;
175 }
176 } else {
177 ctx->vfs_errno = ENOENT;
178 }
179
180 PQclear(result);
181
182 return ret;
183 }
184
185
98 /* -------------------------- VFS functions -------------------------- */ 186 /* -------------------------- VFS functions -------------------------- */
99 187
100 SYS_FILE pg_vfs_open(VFSContext *ctx, const char *path, int oflags) { 188 SYS_FILE pg_vfs_open(VFSContext *ctx, const char *path, int oflags) {
101 189 const char *resname;
190 int64_t resource_id, parent_id;
191 WSBool iscollection;
192 if(pg_resolve_path(ctx, path, &resource_id, &parent_id, &resname, &iscollection)) {
193 return NULL;
194 }
195
196 VFSFile *file = pool_malloc(ctx->pool, sizeof(VFSFile));
197 if(!file) {
198 return NULL;
199 }
200 PgFile *pgfile = pool_malloc(ctx->pool, sizeof(PgFile));
201 if(!pgfile) {
202 pool_free(ctx->pool, file);
203 return NULL;
204 }
205
206 pgfile->iscollection = iscollection;
207 pgfile->resource_id = resource_id;
208 pgfile->parent_id = parent_id;
209
210 file->ctx = ctx;
211 file->io = iscollection ? NULL : &pg_vfs_io_class;
212 file->fd = -1;
213 file->data = pgfile;
214
215 return file;
102 } 216 }
103 217
104 int pg_vfs_stat(VFSContext *ctx, const char *path, struct stat *buf) { 218 int pg_vfs_stat(VFSContext *ctx, const char *path, struct stat *buf) {
105 219
106 } 220 }

mercurial