As Johan insisted, here is another approach.
Functions used for accessing message storage are going to be a bit more
independent from MAP architecture and so more reusable in other places.
There may be some initialization needed before storage is usable. This is
introduced in first patch. I was thinking about other ways to do it:
1) Add OBEX_PLUGIN_DEFINE to messages-*.c and so make it a plugin (this
is related to what Luiz suggested before).
This would however prevent MAP plugin from being able to refuse to load
if message storage is not functional. Also it breaks the idea of message
storage API being independent from obexd architecture.
2) Add reference counter of plugin users, so only last messages_exit
would free common resources (like it is the case with root_folder in
messages_dummy.c).
This would get harder is someone would wish to use threads at some point.
3) Get rid of static data and return pointer from messages_init() that
would be passed to all message storage functions calls.
This option still may need some reference counting and data shared
between API clients at some point (I'm thinking about implementation of
undelete behaviour, required by MAP, when actual storage does not have
that possibility).
What do you think?
This adds support for MAP SetFolder function (served by OBEX SetPath
request).
Current directory is kept in plugin code. Storage backend offers
messages_dir_exists() function which is used by MAP plugin to check
whether new path is correct.
---
plugins/mas.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
plugins/messages-dummy.c | 17 +++++++++++++++++
plugins/messages.h | 2 ++
3 files changed, 63 insertions(+), 1 deletions(-)
diff --git a/plugins/mas.c b/plugins/mas.c
index 243d2f6..1d33ca1 100644
--- a/plugins/mas.c
+++ b/plugins/mas.c
@@ -27,6 +27,7 @@
#include <errno.h>
#include <glib.h>
+#include <string.h>
#include <openobex/obex.h>
#include "plugin.h"
@@ -87,6 +88,7 @@
</record>"
struct mas_session {
+ char *cwd;
struct mas_request *request;
};
@@ -96,6 +98,7 @@ static const uint8_t MAS_TARGET[TARGET_SIZE] = {
static void mas_clean(struct mas_session *mas)
{
+ g_free(mas->cwd);
g_free(mas);
}
@@ -108,6 +111,7 @@ static void *mas_connect(struct obex_session *os, int *err)
*err = 0;
mas = g_new0(struct mas_session, 1);
+ mas->cwd = g_strdup("");
manager_register_session(os);
@@ -173,9 +177,48 @@ failed:
return ret;
}
+static int set_folder(struct mas_session *mas, const char *name, int cdup)
+{
+ char *newcwd = NULL;
+ char *tmp;
+
+ if (name && (strchr(name, '/') || strcmp(name, "..") == 0))
+ return -EBADR;
+
+ if (cdup) {
+ if (mas->cwd[0] == 0)
+ return -ENOENT;
+
+ newcwd = g_path_get_dirname(mas->cwd);
+
+ /* We use empty string for indication of the root directory */
+ if (newcwd[0] == '.' && newcwd[1] == 0)
+ newcwd[0] = 0;
+ }
+
+ tmp = newcwd;
+ if (!cdup && (!name || name[0] == 0))
+ newcwd = g_strdup("");
+ else
+ newcwd = g_build_filename(newcwd ? newcwd : mas->cwd, name,
+ NULL);
+ g_free(tmp);
+
+ if (!messages_dir_exists(newcwd)) {
+ g_free(newcwd);
+ return -ENOENT;
+ }
+
+ g_free(mas->cwd);
+ mas->cwd = newcwd;
+
+ return 0;
+}
+
static int mas_setpath(struct obex_session *os, obex_object_t *obj,
void *user_data)
{
+ struct mas_session *mas = user_data;
const char *name;
uint8_t *nonhdr;
@@ -193,7 +236,7 @@ static int mas_setpath(struct obex_session *os, obex_object_t *obj,
return -EBADR;
}
- return 0;
+ return set_folder(mas, name, nonhdr[0] & 0x01);
}
static void *any_open(const char *name, int oflag, mode_t mode,
diff --git a/plugins/messages-dummy.c b/plugins/messages-dummy.c
index 9bb1ba1..805ce80 100644
--- a/plugins/messages-dummy.c
+++ b/plugins/messages-dummy.c
@@ -57,3 +57,20 @@ void messages_exit(void)
g_free(root_folder);
root_folder = NULL;
}
+
+gboolean messages_dir_exists(const char *path)
+{
+ char *abs;
+ gboolean ret;
+
+ abs = g_build_filename(root_folder, path, NULL);
+
+ if (g_file_test(abs, G_FILE_TEST_IS_DIR))
+ ret = TRUE;
+ else
+ ret = FALSE;
+
+ g_free(abs);
+
+ return ret;
+}
diff --git a/plugins/messages.h b/plugins/messages.h
index 65e2274..dccdb74 100644
--- a/plugins/messages.h
+++ b/plugins/messages.h
@@ -24,3 +24,5 @@
int messages_init(void);
void messages_exit(void);
+
+gboolean messages_dir_exists(const char *path);
--
1.7.1
This adds functions for initializing and freeing resources used by
message storage access backend and example implementation in the dummy
(or rather - filesystem) backend.
Dummy backend uses $HOME/map-messages for its message storage. This
directory should at least contain basic folders required by the MAP
specification. It represents the root as seen from the perspective of
MAP client. You can prepare it as follows:
$ MAPROOT=$HOME/map-messages
$ mkdir -p "$MAPROOT/telecom/msg/inbox"
$ mkdir "$MAPROOT/telecom/msg/sent"
$ mkdir "$MAPROOT/telecom/msg/deleted"
$ mkdir "$MAPROOT/telecom/msg/outbox"
---
plugins/mas.c | 8 ++++++++
plugins/messages-dummy.c | 31 +++++++++++++++++++++++++++++++
plugins/messages.h | 4 ++++
3 files changed, 43 insertions(+), 0 deletions(-)
diff --git a/plugins/mas.c b/plugins/mas.c
index a84b8fd..243d2f6 100644
--- a/plugins/mas.c
+++ b/plugins/mas.c
@@ -261,6 +261,10 @@ static int mas_init(void)
{
int err;
+ err = messages_init();
+ if (err < 0)
+ goto failed_messages_init;
+
err = obex_mime_type_driver_register(&mime_map);
if (err < 0)
goto failed_mime;
@@ -275,6 +279,9 @@ failed_mas_reg:
obex_mime_type_driver_unregister(&mime_map);
failed_mime:
+ messages_exit();
+
+failed_messages_init:
return err;
}
@@ -282,6 +289,7 @@ static void mas_exit(void)
{
obex_service_driver_unregister(&mas);
obex_mime_type_driver_unregister(&mime_map);
+ messages_exit();
}
OBEX_PLUGIN_DEFINE(mas, mas_init, mas_exit)
diff --git a/plugins/messages-dummy.c b/plugins/messages-dummy.c
index fd9679d..9bb1ba1 100644
--- a/plugins/messages-dummy.c
+++ b/plugins/messages-dummy.c
@@ -25,4 +25,35 @@
#include <config.h>
#endif
+#include <glib.h>
+#include <stdlib.h>
+
#include "messages.h"
+
+static char *root_folder = NULL;
+
+int messages_init(void)
+{
+ char *home;
+
+ if (root_folder)
+ return 0;
+
+ home = getenv("HOME");
+ if (!home)
+ return -1;
+
+ /* XXX: It would be great to have per plugin parameters support, for
+ * example $ obexd --mas=param1=value1:param2:param3, so user would be
+ * able to select different root directory.
+ */
+ root_folder = g_build_filename(home, "map-messages", NULL);
+
+ return 0;
+}
+
+void messages_exit(void)
+{
+ g_free(root_folder);
+ root_folder = NULL;
+}
diff --git a/plugins/messages.h b/plugins/messages.h
index c510244..65e2274 100644
--- a/plugins/messages.h
+++ b/plugins/messages.h
@@ -20,3 +20,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
+
+int messages_init(void);
+
+void messages_exit(void);
--
1.7.1
Hi Slawek,
On Mon, May 23, 2011, Slawomir Bochenski wrote:
> + err = messages_init();
> + if (err < 0)
> + goto failed_messages_init;
> +
> err = obex_mime_type_driver_register(&mime_map);
> if (err < 0)
> goto failed_mime;
> @@ -275,6 +279,9 @@ failed_mas_reg:
> obex_mime_type_driver_unregister(&mime_map);
>
> failed_mime:
> + messages_exit();
> +
> +failed_messages_init:
> return err;
> }
In this case it'd be simpler to do the following instead of adding the
new label:
if (err < 0)
return err;
If there was more complex cleanup involved then the new label would make
sense, but not really with a simple return statement.
Johan