diff options
author | Yorhel <git@yorhel.nl> | 2013-06-16 12:40:59 +0200 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2013-06-16 12:40:59 +0200 |
commit | 997de91a2db054aa53b648d98bc821e0069f91c8 (patch) | |
tree | 2837c253cda94a374d288f38cdcb1ef057e166f8 | |
parent | b64c9faf52a22139ed9023466dff4807c02d0729 (diff) |
share,api: Add + implement basic browse interface
-rw-r--r-- | doc/api.pod | 13 | ||||
-rw-r--r-- | src/share/conf.c | 54 | ||||
-rw-r--r-- | src/share/fl.c | 31 | ||||
-rw-r--r-- | src/share/fl.h | 5 |
4 files changed, 100 insertions, 3 deletions
diff --git a/doc/api.pod b/doc/api.pod index 47389ce..2b3f233 100644 --- a/doc/api.pod +++ b/doc/api.pod @@ -689,9 +689,18 @@ I<TODO:> Cookie(File|Hash)? C</net/blicky/Globster/Share/$id> and re-usable for remote file lists. - method List(s path) -> (a(syay)) + method List(s path) -> (a{s(tay)} list) -syay = name, size, hash. Directories have a '/' appended to their name. +Returns a dictionary of files and directories, with the name as key and a +struct containing the size and hash as value. Directories have an empty +(zero-length) hash and have a '/' appended to their name. + +The I<path> argument must be absolute. An error (I<TODO:> which?) is thrown if +the given path does not exist in the file list or if it is not a directory. + +I<TODO:> Specify what the size of a directory means. Giving it a meaningful +value would be useful, since most file list browsers allow ordering by dir +sizes. =head2 org.freedesktop.DBus.ObjectManager (objman) diff --git a/src/share/conf.c b/src/share/conf.c index 6e195fe..3ceb2a0 100644 --- a/src/share/conf.c +++ b/src/share/conf.c @@ -260,14 +260,66 @@ static void GetManagedObjects(share_t *s, DBusMessage *msg) { } +static void share_List(share_t *s, DBusMessage *msg, const char *_vpath) { + /* To prevent a stack overflow */ + if(*_vpath != '/' || strlen(_vpath) > 10000) { + dbo_sendfree(dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, "Invalid path")); + return; + } + + char vpath[strlen(_vpath)]; + strcpy(vpath, _vpath); + path_normalize(vpath); + + share_fl_t *dir = share_fl_resolve(s->ss->root, vpath); + if(!dir) { + dbo_sendfree(dbus_message_new_error(msg, DBUS_ERROR_FILE_NOT_FOUND, "No directory found at the given path")); + return; + } + + DBusMessage *r = dbus_message_new_method_return(msg); + DBusMessageIter iter[5]; + kstring_t buf = {}; + + /* TODO: Unhashed files shouldn't be sent. Empty directories should + * probably be excluded too, because they aren't included in the public + * share. */ + dbus_message_iter_init_append(r, iter); + dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{s(tay)}", iter+1); + size_t i; + for(i=0; i<dir->sub.n; i++) { + share_fl_t *fl = dir->sub.a[i]; + buf.l = 0; + casestr_orig(share_fl_name(fl), &buf); + if(fl->size == UINT64_MAX) + kputc('/', &buf); + const char *arr = fl->size == UINT64_MAX ? "" : fl->tth; + + dbus_message_iter_open_container(iter+1, DBUS_TYPE_DICT_ENTRY, NULL, iter+2); + dbus_message_iter_append_basic(iter+2, DBUS_TYPE_STRING, &buf.s); + dbus_message_iter_open_container(iter+2, DBUS_TYPE_STRUCT, NULL, iter+3); + dbus_message_iter_append_basic(iter+3, DBUS_TYPE_UINT64, &fl->size); + dbus_message_iter_open_container(iter+3, DBUS_TYPE_ARRAY, "y", iter+4); + dbus_message_iter_append_fixed_array(iter+4, DBUS_TYPE_BYTE, &arr, fl->size == UINT64_MAX ? 0 : sizeof(fl->tth)); + dbus_message_iter_close_container(iter+3, iter+4); + dbus_message_iter_close_container(iter+2, iter+3); + dbus_message_iter_close_container(iter+1, iter+2); + } + free(buf.s); + dbus_message_iter_close_container(iter, iter+1); + dbo_sendfree(r); +} + + static share_t *share_create(uint16_t id) { static const dbo_share_vtable_t(share_t) svt = dbo_share_funcs(); + static const dbo_browse_vtable_t(share_t) bvt = dbo_browse_funcs(share_); static const dbo_objman_vtable_t(share_t) ovt = dbo_objman_funcs(); static const dbo_reg_t reg[] = { { &dbo_share_interface, (void**)&svt, offsetof(share_t, props) }, + { &dbo_browse_interface, (void**)&bvt, 0 }, { &dbo_objman_interface, (void**)&ovt, 0 } }; - /* TODO: Add browse interface */ share_t *s = calloc(1, sizeof(share_t)); s->id = id; diff --git a/src/share/fl.c b/src/share/fl.c index 903d0b4..439832d 100644 --- a/src/share/fl.c +++ b/src/share/fl.c @@ -89,6 +89,37 @@ share_fl_t *share_fl_getdir(share_fl_t *root, char *path, char *pathf, kstring_t } +share_fl_t *share_fl_resolve(share_fl_t *root, char *path) { + if(*path == '/') + path++; + if(!*path) + return root; + assert(root->size == UINT64_MAX); + char *end = strchr(path, '/'); + if(end) + *end = 0; + + kstring_t buf = {}; + casestr_create(path, &buf); + + size_t r = (size_t)-1; + vec_search(root->sub, strcmp(share_fl_name(root->sub.a[i]), buf.s), r=i); + + share_fl_t *fl = r == (size_t)-1 ? NULL : root->sub.a[r]; + share_fl_t *ret = NULL; + if(fl && casestr_cmp(share_fl_name(fl), buf.s) == 0) { + if(!end) + ret = fl; + else if(fl->size == UINT64_MAX) + ret = share_fl_resolve(fl, end+1); + } + free(buf.s); + if(end) + *end = '/'; + return ret; +} + + void share_fl_path(share_fl_t *fl, kstring_t *dest) { vec_t(char *) lst = {}; size_t i; diff --git a/src/share/fl.h b/src/share/fl.h index 15697e5..ae4ec57 100644 --- a/src/share/fl.h +++ b/src/share/fl.h @@ -97,6 +97,11 @@ share_fl_t *share_fl_getdir(share_fl_t *root, char *path, char *pathf, kstring_t * dest. */ void share_fl_path(share_fl_t *fl, kstring_t *dest); + +/* Resolve a virtual path to a share_fl_t item. Returns NULL if it doesn't + * exist. The given path buffer is temporarily modified in-place. */ +share_fl_t *share_fl_resolve(share_fl_t *root, char *path); + #endif /* vim: set noet sw=4 ts=4: */ |