135 WebdavResource *resource, |
135 WebdavResource *resource, |
136 struct stat *s) |
136 struct stat *s) |
137 { |
137 { |
138 Session *sn = request->sn; |
138 Session *sn = request->sn; |
139 Request *rq = request->rq; |
139 Request *rq = request->rq; |
|
140 CxAllocator *a = pool_allocator(sn->pool); |
140 |
141 |
141 WebdavXAttrBackend *xdav = request->dav->instance; |
142 WebdavXAttrBackend *xdav = request->dav->instance; |
142 WebdavXAttrRepository *repo = xdav->repo; |
143 WebdavXAttrRepository *repo = xdav->repo; |
143 XAttrPropfind *xprop = request->userdata; |
144 XAttrPropfind *xprop = request->userdata; |
144 |
145 |
|
146 // get resource path |
145 const char *path; |
147 const char *path; |
146 char *path_dp = NULL; |
148 char *path_dp = NULL; |
147 if(!parent) { |
149 if(!parent) { |
148 // use base path |
150 // use base path |
149 path = xprop->base_path; |
151 path = xprop->base_path; |
173 (libxattr_free_func)pool_free, |
175 (libxattr_free_func)pool_free, |
174 path, |
176 path, |
175 repo->xattr_name, |
177 repo->xattr_name, |
176 &xattr_data_len); |
178 &xattr_data_len); |
177 |
179 |
178 if(xattr_data) { |
180 if(!xattr_data) { |
179 |
181 // no properties for this resource |
180 } |
182 return 0; |
181 |
183 } |
182 |
184 |
183 return 0; |
185 CxMap *pmap = webdav_xattr_parse_data(a, xattr_data, xattr_data_len, path); |
|
186 pool_free(sn->pool, xattr_data); |
|
187 if(!pmap) { |
|
188 return 1; |
|
189 } |
|
190 |
|
191 int err; |
|
192 if(request->allprop || request->propname) { |
|
193 err = webdav_xattr_propfind_allprop(request, resource, a, pmap); |
|
194 } else { |
|
195 err = webdav_xattr_propfind_get_requested_properties(request, resource, a, pmap); |
|
196 } |
|
197 |
|
198 return err; |
184 } |
199 } |
185 |
200 |
186 int webdav_xattr_propfind_finish(WebdavPropfindRequest *rq) { |
201 int webdav_xattr_propfind_finish(WebdavPropfindRequest *rq) { |
187 return 0; |
202 return 0; |
188 } |
203 } |
|
204 |
|
205 // helper functions for propfind_do |
|
206 |
|
207 int webdav_xattr_propfind_get_requested_properties( |
|
208 WebdavPropfindRequest *request, |
|
209 WebdavResource *resource, |
|
210 CxAllocator *a, |
|
211 CxMap *pmap) |
|
212 { |
|
213 WebdavPListIterator i = webdav_plist_iterator(&request->properties); |
|
214 WebdavPList *cur; |
|
215 while(webdav_plist_iterator_next(&i, &cur)) { |
|
216 WebdavProperty *reqprop = cur->property; |
|
217 |
|
218 CxHashKey key = webdav_property_key_a( |
|
219 a, |
|
220 (const char*)reqprop->namespace->href, |
|
221 (const char*)reqprop->name); |
|
222 if(!key.data.str) { |
|
223 return 1; |
|
224 } |
|
225 |
|
226 WebdavProperty *prop = cxMapGet(pmap, key); |
|
227 if(prop) { |
|
228 if(resource->addproperty(resource, prop, 200)) { |
|
229 return 1; |
|
230 } |
|
231 } |
|
232 } |
|
233 |
|
234 return 0; |
|
235 } |
|
236 |
|
237 int webdav_xattr_propfind_allprop( |
|
238 WebdavPropfindRequest *request, |
|
239 WebdavResource *resource, |
|
240 CxAllocator *a, |
|
241 CxMap *pmap) |
|
242 { |
|
243 CxIterator i = cxMapIteratorValues(pmap); |
|
244 cx_foreach(WebdavProperty*, prop, i) { |
|
245 if(request->propname) { |
|
246 prop->vtype = WS_VALUE_NO_TYPE; |
|
247 } |
|
248 if(resource->addproperty(resource, prop, 200)) { |
|
249 return 1; |
|
250 } |
|
251 } |
|
252 return 0; |
|
253 } |
|
254 |
|
255 |
189 |
256 |
190 int webdav_xattr_proppatch_do( |
257 int webdav_xattr_proppatch_do( |
191 WebdavProppatchRequest *request, |
258 WebdavProppatchRequest *request, |
192 WebdavResource *response, |
259 WebdavResource *response, |
193 VFSFile *file, |
260 VFSFile *file, |
198 Request *rq = request->rq; |
265 Request *rq = request->rq; |
199 CxAllocator *a = pool_allocator(sn->pool); |
266 CxAllocator *a = pool_allocator(sn->pool); |
200 |
267 |
201 WebdavXAttrBackend *xdav = request->dav->instance; |
268 WebdavXAttrBackend *xdav = request->dav->instance; |
202 WebdavXAttrRepository *repo = xdav->repo; |
269 WebdavXAttrRepository *repo = xdav->repo; |
|
270 |
|
271 char *path = pblock_findkeyval(pb_key_path, rq->vars); |
|
272 |
|
273 // How xattr proppatch works: |
|
274 // 1. get existing property data from the file's xattr |
|
275 // 2. do set/remove operations to the existing data |
|
276 // 3. write new property data to the xattr (webdav_xattr_proppatch_finish) |
|
277 |
|
278 // TODO: proppatch file lock (in-process userspace lock) |
203 |
279 |
204 XAttrProppatch *xprop = pool_malloc(sn->pool, sizeof(XAttrProppatch)); |
280 XAttrProppatch *xprop = pool_malloc(sn->pool, sizeof(XAttrProppatch)); |
205 if(!xprop) { |
281 if(!xprop) { |
206 return 1; |
282 return 1; |
207 } |
283 } |
208 request->userdata = xprop; |
284 request->userdata = xprop; |
209 |
|
210 char *path = pblock_findkeyval(pb_key_path, rq->vars); |
|
211 |
285 |
212 // get existing property data |
286 // get existing property data |
213 ssize_t xattr_data_len = 0; |
287 ssize_t xattr_data_len = 0; |
214 char *xattr_data = xattr_get_alloc( |
288 char *xattr_data = xattr_get_alloc( |
215 sn->pool, |
289 sn->pool, |
220 &xattr_data_len); |
294 &xattr_data_len); |
221 |
295 |
222 CxMap *pmap; |
296 CxMap *pmap; |
223 if(xattr_data) { |
297 if(xattr_data) { |
224 pmap = webdav_xattr_parse_data(a, xattr_data, xattr_data_len, path); |
298 pmap = webdav_xattr_parse_data(a, xattr_data, xattr_data_len, path); |
|
299 pool_free(sn->pool, xattr_data); |
225 } else { |
300 } else { |
226 // empty map |
301 // empty map |
227 pmap = cxHashMapCreate(a, request->setcount + 8); |
302 pmap = cxHashMapCreate(a, request->setcount + 8); |
228 } |
303 } |
229 if(!pmap) { |
304 if(!pmap) { |
230 return 1; |
305 return 1; |
231 } |
306 } |
|
307 xprop->properties = pmap; |
232 |
308 |
233 // remove properties |
309 // remove properties |
234 WebdavPListIterator i = webdav_plist_iterator(removeInOut); |
310 WebdavPListIterator i = webdav_plist_iterator(removeInOut); |
235 WebdavPList *cur; |
311 WebdavPList *cur; |
236 while(webdav_plist_iterator_next(&i, &cur)) { |
312 while(webdav_plist_iterator_next(&i, &cur)) { |
274 } |
350 } |
275 |
351 |
276 webdav_plist_iterator_remove_current(&i); |
352 webdav_plist_iterator_remove_current(&i); |
277 } |
353 } |
278 |
354 |
279 //printf("\n\n%.*s\n\n", (int)buf.size, buf.space); |
355 return 0; |
280 //fflush(stdout); |
|
281 |
|
282 int ret = 0; |
|
283 cxmutstr new_data = webdav_xattr_serialze_map(a, pmap); |
|
284 if(new_data.ptr) { |
|
285 xattr_set(path, repo->xattr_name, new_data.ptr, new_data.length); |
|
286 } else { |
|
287 cxMapDestroy(pmap); |
|
288 ret = 1; |
|
289 } |
|
290 |
|
291 return ret; |
|
292 } |
356 } |
293 |
357 |
294 int webdav_xattr_proppatch_finish( |
358 int webdav_xattr_proppatch_finish( |
295 WebdavProppatchRequest *request, |
359 WebdavProppatchRequest *request, |
296 WebdavResource *response, |
360 WebdavResource *response, |
297 VFSFile *file, |
361 VFSFile *file, |
298 WSBool commit) |
362 WSBool commit) |
299 { |
363 { |
|
364 Session *sn = request->sn; |
|
365 Request *rq = request->rq; |
|
366 CxAllocator *a = pool_allocator(sn->pool); |
|
367 |
|
368 WebdavXAttrBackend *xdav = request->dav->instance; |
|
369 WebdavXAttrRepository *repo = xdav->repo; |
|
370 |
|
371 XAttrProppatch *xprop = request->userdata; |
|
372 |
|
373 char *path = pblock_findkeyval(pb_key_path, rq->vars); |
|
374 |
|
375 int ret = 0; |
|
376 if(commit) { |
|
377 cxmutstr new_data = webdav_xattr_serialze_map(a, xprop->properties); |
|
378 if(new_data.ptr) { |
|
379 if(xattr_set(path, repo->xattr_name, new_data.ptr, new_data.length)) { |
|
380 ret = 1; |
|
381 } |
|
382 } else { |
|
383 ret = 1; |
|
384 } |
|
385 } |
|
386 |
300 return 0; |
387 return 0; |
301 } |
388 } |
302 |
389 |
303 |
390 |
304 /* ----------------------- properties xattr data ----------------------- */ |
391 /* ----------------------- properties xattr data ----------------------- */ |