v2: Fixed wrong arguments order in last patch
On Wed, Jul 20, 2011 at 2:23 PM, Luiz Augusto von Dentz
<[email protected]> wrote:
> Hi,
>
> On Wed, Jul 20, 2011 at 2:14 PM, Slawomir Bochenski <[email protected]> wrote:
>> On Wed, Jul 20, 2011 at 12:47 PM, Luiz Augusto von Dentz
>> <[email protected]> wrote:
>>> Hi,
>>>
>>> On Wed, Jul 20, 2011 at 1:08 PM, Slawomir Bochenski <[email protected]> wrote:
>>>> Hi,
>>>>
>>>> On Wed, Jul 20, 2011 at 11:50 AM, Luiz Augusto von Dentz
>>>> <[email protected]> wrote:
>>>>> Hi,
>>>>>
>>>>> On Tue, Jul 19, 2011 at 3:06 PM, Slawomir Bochenski <[email protected]> wrote:
>>>>>> ---
>>>>>> ?plugins/mas.c | ? 78 ++++++++++++++++++++++++++++++++++++++++++++++----------
>>>>>> ?1 files changed, 64 insertions(+), 14 deletions(-)
>>>>>>
>>>>>> diff --git a/plugins/mas.c b/plugins/mas.c
>>>>>> index 0ef8c81..e88a0f0 100644
>>>>>> --- a/plugins/mas.c
>>>>>> +++ b/plugins/mas.c
>>>>>> @@ -27,6 +27,9 @@
>>>>>>
>>>>>> ?#include <errno.h>
>>>>>> ?#include <glib.h>
>>>>>> +#include <sys/types.h>
>>>>>> +#include <sys/stat.h>
>>>>>> +#include <fcntl.h>
>>>>>> ?#include <openobex/obex.h>
>>>>>>
>>>>>> ?#include "plugin.h"
>>>>>> @@ -86,9 +89,19 @@
>>>>>> ? </attribute> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
>>>>>> ?</record>"
>>>>>>
>>>>>> +#define EVENT_TYPE ? ? ? ? ? ? "x-bt/MAP-event-report"
>>>>>> +#define MESSAGE_TYPE ? ? ? ? ? "x-bt/message"
>>>>>> +#define FOLDER_LISTING_TYPE ? ?"x-obex/folder-listing"
>>>>>> +#define MESSAGES_LISTING_TYPE ?"x-bt/MAP-msg-listing"
>>>>>> +#define NOTIFICATION_TYPE ? ? ?"x-bt/MAP-NotificationRegistration"
>>>>>> +#define STATUS_TYPE ? ? ? ? ? ?"x-bt/messageStatus"
>>>>>> +#define UPDATE_TYPE ? ? ? ? ? ?"x-bt/MAP-messageUpdate"
>>>>>> +
>>>>>> ?struct mas_session {
>>>>>> ? ? ? ?struct mas_request *request;
>>>>>> ? ? ? ?void *backend_data;
>>>>>> + ? ? ? const char *name;
>>>>>> + ? ? ? const char *type;
>>>>>> ?};
>>>>>>
>>>>>> ?static const uint8_t MAS_TARGET[TARGET_SIZE] = {
>>>>>> @@ -137,17 +150,14 @@ static void mas_disconnect(struct obex_session *os, void *user_data)
>>>>>> ?static int mas_get(struct obex_session *os, obex_object_t *obj, void *user_data)
>>>>>> ?{
>>>>>> ? ? ? ?struct mas_session *mas = user_data;
>>>>>> - ? ? ? const char *type = obex_get_type(os);
>>>>>> - ? ? ? const char *name = obex_get_name(os);
>>>>>> ? ? ? ?int ret;
>>>>>>
>>>>>> - ? ? ? DBG("GET: name %s type %s mas %p",
>>>>>> - ? ? ? ? ? ? ? ? ? ? ? name, type, mas);
>>>>>> + ? ? ? mas->name = obex_get_name(os);
>>>>>> + ? ? ? mas->type = obex_get_type(os);
>>>>>>
>>>>>> - ? ? ? if (type == NULL)
>>>>>> - ? ? ? ? ? ? ? return -EBADR;
>>>>>> + ? ? ? DBG("GET: name %s type %s mas %p", mas->name, mas->type, mas);
>>>>>>
>>>>>> - ? ? ? ret = obex_get_stream_start(os, name);
>>>>>> + ? ? ? ret = obex_get_stream_start(os, mas->name);
>>>>>> ? ? ? ?if (ret < 0)
>>>>>> ? ? ? ? ? ? ? ?goto failed;
>>>>>>
>>>>>> @@ -160,16 +170,14 @@ failed:
>>>>>> ?static int mas_put(struct obex_session *os, obex_object_t *obj, void *user_data)
>>>>>> ?{
>>>>>> ? ? ? ?struct mas_session *mas = user_data;
>>>>>> - ? ? ? const char *type = obex_get_type(os);
>>>>>> - ? ? ? const char *name = obex_get_name(os);
>>>>>> ? ? ? ?int ret;
>>>>>>
>>>>>> - ? ? ? DBG("PUT: name %s type %s mas %p", name, type, mas);
>>>>>> + ? ? ? mas->name = obex_get_name(os);
>>>>>> + ? ? ? mas->type = obex_get_type(os);
>>>>>>
>>>>>> - ? ? ? if (type == NULL)
>>>>>> - ? ? ? ? ? ? ? return -EBADR;
>>>>>> + ? ? ? DBG("PUT: name %s type %s mas %p", mas->name, mas->type, mas);
>>>>>>
>>>>>> - ? ? ? ret = obex_put_stream_start(os, name);
>>>>>> + ? ? ? ret = obex_put_stream_start(os, mas->name);
>>>>>> ? ? ? ?if (ret < 0)
>>>>>> ? ? ? ? ? ? ? ?goto failed;
>>>>>>
>>>>>> @@ -179,6 +187,38 @@ failed:
>>>>>> ? ? ? ?return ret;
>>>>>> ?}
>>>>>
>>>>> I would suggest adding a mimetype driver for each type so you don't
>>>>> have to do the check inside the service driver and it is also
>>>>> consistent with what other plugins do when they support multiple
>>>>> types.
>>>>>
>>>> I would not. That's the whole point. Functions for the mime driver
>>>> would do exactly the same.
>>>
>>> There we go again, so your point is that you don't want to be
>>> consistent with other plugins and you like to see duplicated code
>>> checking for matching types the very same way the core does for
>>> mimetype drivers? Or do you mean the spec got this wrong and there is
>>> no use of types because all of them do exactly the same?
>>
>> This was discussed before. More than half of "types" are not really
>> mime types at all (there's no even body involved in request). Type is
>> used in MAP merely as a function selector (this _is_ called a function
>> in MAP). All specific handling of request is done in callback from MAP
>> API. The only thing that each and every mime driver would do is to
>> read buffer prepared by a callback. I've specifically chosen to use
>> the already present feature of universal target-specific mime driver
>> in order to avoid registering 6 mime drivers with the same handlers,
>> or worse - 6 times identical functions. The approach is minimalistic
>> and pretty. Implementation is easy to understand in terms of MAP
>> specification instead of putting it into some obexd specific
>> abstraction.
>
> What does a function selection mean? Doesn't it means they do
> something different? Why you are saying you will have 6 driver with
> the same handlers if they map to different functions? I would
> understand if you said you have done this way and it works just fine,
Yes, I've done it. Works just fine.
> but arguing that your approach is minimalistic and pretty? What about
> consistency, reliability and maintainability? The abstraction is there
> no matter how hard you try to make it go away, it is the interface to
> which the core daemon talks to backends, it doesn't really matter what
> you put in between. Your minimalistic approach just confuses the core
> daemon making it believe there is no driver for a specific mimetype
> selecting its default fallback for the target.
Nothing confusing here. Just the normal driver selection.
>
>>>Sorry but I
>>> don't think this has any valid technical point, in fact the mimetype
>>> and service separation does help plugins to not mix object and session
>>> handling.
>>
>> There can be only one active request per session. No mixing problems there.
>
> Partially correct, basically you can only handle one request per
> session, period. Note, it doesn't break OBEX or MAP, but if we already
> have infrastructure in place to handle this properly why not do it?
> Why not doing it right since the beginning? Shall our answer be
> minimalism and prettiness?
"Right" is quite a subjective term here.
>
>>>>>> +static int start_get(struct mas_session *mas)
>>>>>> +{
>>>>>> + ? ? ? /* NOTE: type is case-insensitive! */
>>>>>> + ? ? ? if (g_ascii_strcasecmp(mas->type, FOLDER_LISTING_TYPE) == 0)
>>>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGES_LISTING_TYPE) == 0)
>>>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGE_TYPE) == 0)
>>>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>>>> + ? ? ? else {
>>>>>> + ? ? ? ? ? ? ? DBG("Incorrect type for get: %s", mas->type);
>>>>>> + ? ? ? ? ? ? ? return -EBADR;
>>>>>> + ? ? ? }
>>>>>> +}
>>>>>> +
>>>>>> +static int start_put(struct mas_session *mas)
>>>>>> +{
>>>>>> + ? ? ? /* NOTE: type is case-insensitive! */
>>>>>> + ? ? ? if (g_ascii_strcasecmp(mas->type, NOTIFICATION_TYPE) == 0)
>>>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, STATUS_TYPE) == 0)
>>>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGE_TYPE) == 0)
>>>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, UPDATE_TYPE) == 0)
>>>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>>>> + ? ? ? else {
>>>>>> + ? ? ? ? ? ? ? DBG("Incorrect type for put: %s", mas->type);
>>>>>> + ? ? ? ? ? ? ? return -EBADR;
>>>>>> + ? ? ? }
>>>>>> +}
>>>>>> +
>>>>>> ?static int mas_setpath(struct obex_session *os, obex_object_t *obj,
>>>>>> ? ? ? ? ? ? ? ?void *user_data)
>>>>>> ?{
>>>>>> @@ -210,7 +250,17 @@ static void *any_open(const char *name, int oflag, mode_t mode,
>>>>>>
>>>>>> ? ? ? ?DBG("");
>>>>>>
>>>>>> - ? ? ? *err = 0;
>>>>>> + ? ? ? if ((oflag & O_RDONLY) == O_RDONLY) {
>>>>>> + ? ? ? ? ? ? ? *err = start_get(mas);
>>>>>> + ? ? ? } else if ((oflag & O_WRONLY) == O_WRONLY) {
>>>>>> + ? ? ? ? ? ? ? *err = start_put(mas);
>>>>>> + ? ? ? } else {
>>>>>> + ? ? ? ? ? ? ? DBG("Invalid open flag!");
>>>>>> + ? ? ? ? ? ? ? *err = -EIO;
>>>>>> + ? ? ? }
>>>>>> +
>>>>>> + ? ? ? if (*err)
>>>>>> + ? ? ? ? ? ? ? return NULL;
>>>>>>
>>>>>> ? ? ? ?return mas;
>>>>>> ?}
>>>>>> --
>>>>>> 1.7.4.1
>>>>>
>>>>> --
>>>>> Luiz Augusto von Dentz
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> Slawomir Bochenski
>>>>
>>>
>>>
>>>
>>> --
>>> Luiz Augusto von Dentz
>>>
>>
>>
>>
>> --
>> Slawomir Bochenski
>>
>
>
>
> --
> Luiz Augusto von Dentz
>
--
Slawomir Bochenski
Hi,
On Wed, Jul 20, 2011 at 2:14 PM, Slawomir Bochenski <[email protected]> wrote:
> On Wed, Jul 20, 2011 at 12:47 PM, Luiz Augusto von Dentz
> <[email protected]> wrote:
>> Hi,
>>
>> On Wed, Jul 20, 2011 at 1:08 PM, Slawomir Bochenski <[email protected]> wrote:
>>> Hi,
>>>
>>> On Wed, Jul 20, 2011 at 11:50 AM, Luiz Augusto von Dentz
>>> <[email protected]> wrote:
>>>> Hi,
>>>>
>>>> On Tue, Jul 19, 2011 at 3:06 PM, Slawomir Bochenski <[email protected]> wrote:
>>>>> ---
>>>>> ?plugins/mas.c | ? 78 ++++++++++++++++++++++++++++++++++++++++++++++----------
>>>>> ?1 files changed, 64 insertions(+), 14 deletions(-)
>>>>>
>>>>> diff --git a/plugins/mas.c b/plugins/mas.c
>>>>> index 0ef8c81..e88a0f0 100644
>>>>> --- a/plugins/mas.c
>>>>> +++ b/plugins/mas.c
>>>>> @@ -27,6 +27,9 @@
>>>>>
>>>>> ?#include <errno.h>
>>>>> ?#include <glib.h>
>>>>> +#include <sys/types.h>
>>>>> +#include <sys/stat.h>
>>>>> +#include <fcntl.h>
>>>>> ?#include <openobex/obex.h>
>>>>>
>>>>> ?#include "plugin.h"
>>>>> @@ -86,9 +89,19 @@
>>>>> ? </attribute> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
>>>>> ?</record>"
>>>>>
>>>>> +#define EVENT_TYPE ? ? ? ? ? ? "x-bt/MAP-event-report"
>>>>> +#define MESSAGE_TYPE ? ? ? ? ? "x-bt/message"
>>>>> +#define FOLDER_LISTING_TYPE ? ?"x-obex/folder-listing"
>>>>> +#define MESSAGES_LISTING_TYPE ?"x-bt/MAP-msg-listing"
>>>>> +#define NOTIFICATION_TYPE ? ? ?"x-bt/MAP-NotificationRegistration"
>>>>> +#define STATUS_TYPE ? ? ? ? ? ?"x-bt/messageStatus"
>>>>> +#define UPDATE_TYPE ? ? ? ? ? ?"x-bt/MAP-messageUpdate"
>>>>> +
>>>>> ?struct mas_session {
>>>>> ? ? ? ?struct mas_request *request;
>>>>> ? ? ? ?void *backend_data;
>>>>> + ? ? ? const char *name;
>>>>> + ? ? ? const char *type;
>>>>> ?};
>>>>>
>>>>> ?static const uint8_t MAS_TARGET[TARGET_SIZE] = {
>>>>> @@ -137,17 +150,14 @@ static void mas_disconnect(struct obex_session *os, void *user_data)
>>>>> ?static int mas_get(struct obex_session *os, obex_object_t *obj, void *user_data)
>>>>> ?{
>>>>> ? ? ? ?struct mas_session *mas = user_data;
>>>>> - ? ? ? const char *type = obex_get_type(os);
>>>>> - ? ? ? const char *name = obex_get_name(os);
>>>>> ? ? ? ?int ret;
>>>>>
>>>>> - ? ? ? DBG("GET: name %s type %s mas %p",
>>>>> - ? ? ? ? ? ? ? ? ? ? ? name, type, mas);
>>>>> + ? ? ? mas->name = obex_get_name(os);
>>>>> + ? ? ? mas->type = obex_get_type(os);
>>>>>
>>>>> - ? ? ? if (type == NULL)
>>>>> - ? ? ? ? ? ? ? return -EBADR;
>>>>> + ? ? ? DBG("GET: name %s type %s mas %p", mas->name, mas->type, mas);
>>>>>
>>>>> - ? ? ? ret = obex_get_stream_start(os, name);
>>>>> + ? ? ? ret = obex_get_stream_start(os, mas->name);
>>>>> ? ? ? ?if (ret < 0)
>>>>> ? ? ? ? ? ? ? ?goto failed;
>>>>>
>>>>> @@ -160,16 +170,14 @@ failed:
>>>>> ?static int mas_put(struct obex_session *os, obex_object_t *obj, void *user_data)
>>>>> ?{
>>>>> ? ? ? ?struct mas_session *mas = user_data;
>>>>> - ? ? ? const char *type = obex_get_type(os);
>>>>> - ? ? ? const char *name = obex_get_name(os);
>>>>> ? ? ? ?int ret;
>>>>>
>>>>> - ? ? ? DBG("PUT: name %s type %s mas %p", name, type, mas);
>>>>> + ? ? ? mas->name = obex_get_name(os);
>>>>> + ? ? ? mas->type = obex_get_type(os);
>>>>>
>>>>> - ? ? ? if (type == NULL)
>>>>> - ? ? ? ? ? ? ? return -EBADR;
>>>>> + ? ? ? DBG("PUT: name %s type %s mas %p", mas->name, mas->type, mas);
>>>>>
>>>>> - ? ? ? ret = obex_put_stream_start(os, name);
>>>>> + ? ? ? ret = obex_put_stream_start(os, mas->name);
>>>>> ? ? ? ?if (ret < 0)
>>>>> ? ? ? ? ? ? ? ?goto failed;
>>>>>
>>>>> @@ -179,6 +187,38 @@ failed:
>>>>> ? ? ? ?return ret;
>>>>> ?}
>>>>
>>>> I would suggest adding a mimetype driver for each type so you don't
>>>> have to do the check inside the service driver and it is also
>>>> consistent with what other plugins do when they support multiple
>>>> types.
>>>>
>>> I would not. That's the whole point. Functions for the mime driver
>>> would do exactly the same.
>>
>> There we go again, so your point is that you don't want to be
>> consistent with other plugins and you like to see duplicated code
>> checking for matching types the very same way the core does for
>> mimetype drivers? Or do you mean the spec got this wrong and there is
>> no use of types because all of them do exactly the same?
>
> This was discussed before. More than half of "types" are not really
> mime types at all (there's no even body involved in request). Type is
> used in MAP merely as a function selector (this _is_ called a function
> in MAP). All specific handling of request is done in callback from MAP
> API. The only thing that each and every mime driver would do is to
> read buffer prepared by a callback. I've specifically chosen to use
> the already present feature of universal target-specific mime driver
> in order to avoid registering 6 mime drivers with the same handlers,
> or worse - 6 times identical functions. The approach is minimalistic
> and pretty. Implementation is easy to understand in terms of MAP
> specification instead of putting it into some obexd specific
> abstraction.
What does a function selection mean? Doesn't it means they do
something different? Why you are saying you will have 6 driver with
the same handlers if they map to different functions? I would
understand if you said you have done this way and it works just fine,
but arguing that your approach is minimalistic and pretty? What about
consistency, reliability and maintainability? The abstraction is there
no matter how hard you try to make it go away, it is the interface to
which the core daemon talks to backends, it doesn't really matter what
you put in between. Your minimalistic approach just confuses the core
daemon making it believe there is no driver for a specific mimetype
selecting its default fallback for the target.
>>Sorry but I
>> don't think this has any valid technical point, in fact the mimetype
>> and service separation does help plugins to not mix object and session
>> handling.
>
> There can be only one active request per session. No mixing problems there.
Partially correct, basically you can only handle one request per
session, period. Note, it doesn't break OBEX or MAP, but if we already
have infrastructure in place to handle this properly why not do it?
Why not doing it right since the beginning? Shall our answer be
minimalism and prettiness?
>>>>> +static int start_get(struct mas_session *mas)
>>>>> +{
>>>>> + ? ? ? /* NOTE: type is case-insensitive! */
>>>>> + ? ? ? if (g_ascii_strcasecmp(mas->type, FOLDER_LISTING_TYPE) == 0)
>>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGES_LISTING_TYPE) == 0)
>>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGE_TYPE) == 0)
>>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>>> + ? ? ? else {
>>>>> + ? ? ? ? ? ? ? DBG("Incorrect type for get: %s", mas->type);
>>>>> + ? ? ? ? ? ? ? return -EBADR;
>>>>> + ? ? ? }
>>>>> +}
>>>>> +
>>>>> +static int start_put(struct mas_session *mas)
>>>>> +{
>>>>> + ? ? ? /* NOTE: type is case-insensitive! */
>>>>> + ? ? ? if (g_ascii_strcasecmp(mas->type, NOTIFICATION_TYPE) == 0)
>>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, STATUS_TYPE) == 0)
>>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGE_TYPE) == 0)
>>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, UPDATE_TYPE) == 0)
>>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>>> + ? ? ? else {
>>>>> + ? ? ? ? ? ? ? DBG("Incorrect type for put: %s", mas->type);
>>>>> + ? ? ? ? ? ? ? return -EBADR;
>>>>> + ? ? ? }
>>>>> +}
>>>>> +
>>>>> ?static int mas_setpath(struct obex_session *os, obex_object_t *obj,
>>>>> ? ? ? ? ? ? ? ?void *user_data)
>>>>> ?{
>>>>> @@ -210,7 +250,17 @@ static void *any_open(const char *name, int oflag, mode_t mode,
>>>>>
>>>>> ? ? ? ?DBG("");
>>>>>
>>>>> - ? ? ? *err = 0;
>>>>> + ? ? ? if ((oflag & O_RDONLY) == O_RDONLY) {
>>>>> + ? ? ? ? ? ? ? *err = start_get(mas);
>>>>> + ? ? ? } else if ((oflag & O_WRONLY) == O_WRONLY) {
>>>>> + ? ? ? ? ? ? ? *err = start_put(mas);
>>>>> + ? ? ? } else {
>>>>> + ? ? ? ? ? ? ? DBG("Invalid open flag!");
>>>>> + ? ? ? ? ? ? ? *err = -EIO;
>>>>> + ? ? ? }
>>>>> +
>>>>> + ? ? ? if (*err)
>>>>> + ? ? ? ? ? ? ? return NULL;
>>>>>
>>>>> ? ? ? ?return mas;
>>>>> ?}
>>>>> --
>>>>> 1.7.4.1
>>>>
>>>> --
>>>> Luiz Augusto von Dentz
>>>>
>>>
>>>
>>>
>>> --
>>> Slawomir Bochenski
>>>
>>
>>
>>
>> --
>> Luiz Augusto von Dentz
>>
>
>
>
> --
> Slawomir Bochenski
>
--
Luiz Augusto von Dentz
On Wed, Jul 20, 2011 at 12:47 PM, Luiz Augusto von Dentz
<[email protected]> wrote:
> Hi,
>
> On Wed, Jul 20, 2011 at 1:08 PM, Slawomir Bochenski <[email protected]> wrote:
>> Hi,
>>
>> On Wed, Jul 20, 2011 at 11:50 AM, Luiz Augusto von Dentz
>> <[email protected]> wrote:
>>> Hi,
>>>
>>> On Tue, Jul 19, 2011 at 3:06 PM, Slawomir Bochenski <[email protected]> wrote:
>>>> ---
>>>> ?plugins/mas.c | ? 78 ++++++++++++++++++++++++++++++++++++++++++++++----------
>>>> ?1 files changed, 64 insertions(+), 14 deletions(-)
>>>>
>>>> diff --git a/plugins/mas.c b/plugins/mas.c
>>>> index 0ef8c81..e88a0f0 100644
>>>> --- a/plugins/mas.c
>>>> +++ b/plugins/mas.c
>>>> @@ -27,6 +27,9 @@
>>>>
>>>> ?#include <errno.h>
>>>> ?#include <glib.h>
>>>> +#include <sys/types.h>
>>>> +#include <sys/stat.h>
>>>> +#include <fcntl.h>
>>>> ?#include <openobex/obex.h>
>>>>
>>>> ?#include "plugin.h"
>>>> @@ -86,9 +89,19 @@
>>>> ? </attribute> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
>>>> ?</record>"
>>>>
>>>> +#define EVENT_TYPE ? ? ? ? ? ? "x-bt/MAP-event-report"
>>>> +#define MESSAGE_TYPE ? ? ? ? ? "x-bt/message"
>>>> +#define FOLDER_LISTING_TYPE ? ?"x-obex/folder-listing"
>>>> +#define MESSAGES_LISTING_TYPE ?"x-bt/MAP-msg-listing"
>>>> +#define NOTIFICATION_TYPE ? ? ?"x-bt/MAP-NotificationRegistration"
>>>> +#define STATUS_TYPE ? ? ? ? ? ?"x-bt/messageStatus"
>>>> +#define UPDATE_TYPE ? ? ? ? ? ?"x-bt/MAP-messageUpdate"
>>>> +
>>>> ?struct mas_session {
>>>> ? ? ? ?struct mas_request *request;
>>>> ? ? ? ?void *backend_data;
>>>> + ? ? ? const char *name;
>>>> + ? ? ? const char *type;
>>>> ?};
>>>>
>>>> ?static const uint8_t MAS_TARGET[TARGET_SIZE] = {
>>>> @@ -137,17 +150,14 @@ static void mas_disconnect(struct obex_session *os, void *user_data)
>>>> ?static int mas_get(struct obex_session *os, obex_object_t *obj, void *user_data)
>>>> ?{
>>>> ? ? ? ?struct mas_session *mas = user_data;
>>>> - ? ? ? const char *type = obex_get_type(os);
>>>> - ? ? ? const char *name = obex_get_name(os);
>>>> ? ? ? ?int ret;
>>>>
>>>> - ? ? ? DBG("GET: name %s type %s mas %p",
>>>> - ? ? ? ? ? ? ? ? ? ? ? name, type, mas);
>>>> + ? ? ? mas->name = obex_get_name(os);
>>>> + ? ? ? mas->type = obex_get_type(os);
>>>>
>>>> - ? ? ? if (type == NULL)
>>>> - ? ? ? ? ? ? ? return -EBADR;
>>>> + ? ? ? DBG("GET: name %s type %s mas %p", mas->name, mas->type, mas);
>>>>
>>>> - ? ? ? ret = obex_get_stream_start(os, name);
>>>> + ? ? ? ret = obex_get_stream_start(os, mas->name);
>>>> ? ? ? ?if (ret < 0)
>>>> ? ? ? ? ? ? ? ?goto failed;
>>>>
>>>> @@ -160,16 +170,14 @@ failed:
>>>> ?static int mas_put(struct obex_session *os, obex_object_t *obj, void *user_data)
>>>> ?{
>>>> ? ? ? ?struct mas_session *mas = user_data;
>>>> - ? ? ? const char *type = obex_get_type(os);
>>>> - ? ? ? const char *name = obex_get_name(os);
>>>> ? ? ? ?int ret;
>>>>
>>>> - ? ? ? DBG("PUT: name %s type %s mas %p", name, type, mas);
>>>> + ? ? ? mas->name = obex_get_name(os);
>>>> + ? ? ? mas->type = obex_get_type(os);
>>>>
>>>> - ? ? ? if (type == NULL)
>>>> - ? ? ? ? ? ? ? return -EBADR;
>>>> + ? ? ? DBG("PUT: name %s type %s mas %p", mas->name, mas->type, mas);
>>>>
>>>> - ? ? ? ret = obex_put_stream_start(os, name);
>>>> + ? ? ? ret = obex_put_stream_start(os, mas->name);
>>>> ? ? ? ?if (ret < 0)
>>>> ? ? ? ? ? ? ? ?goto failed;
>>>>
>>>> @@ -179,6 +187,38 @@ failed:
>>>> ? ? ? ?return ret;
>>>> ?}
>>>
>>> I would suggest adding a mimetype driver for each type so you don't
>>> have to do the check inside the service driver and it is also
>>> consistent with what other plugins do when they support multiple
>>> types.
>>>
>> I would not. That's the whole point. Functions for the mime driver
>> would do exactly the same.
>
> There we go again, so your point is that you don't want to be
> consistent with other plugins and you like to see duplicated code
> checking for matching types the very same way the core does for
> mimetype drivers? Or do you mean the spec got this wrong and there is
> no use of types because all of them do exactly the same?
This was discussed before. More than half of "types" are not really
mime types at all (there's no even body involved in request). Type is
used in MAP merely as a function selector (this _is_ called a function
in MAP). All specific handling of request is done in callback from MAP
API. The only thing that each and every mime driver would do is to
read buffer prepared by a callback. I've specifically chosen to use
the already present feature of universal target-specific mime driver
in order to avoid registering 6 mime drivers with the same handlers,
or worse - 6 times identical functions. The approach is minimalistic
and pretty. Implementation is easy to understand in terms of MAP
specification instead of putting it into some obexd specific
abstraction.
>Sorry but I
> don't think this has any valid technical point, in fact the mimetype
> and service separation does help plugins to not mix object and session
> handling.
There can be only one active request per session. No mixing problems there.
>>>> +static int start_get(struct mas_session *mas)
>>>> +{
>>>> + ? ? ? /* NOTE: type is case-insensitive! */
>>>> + ? ? ? if (g_ascii_strcasecmp(mas->type, FOLDER_LISTING_TYPE) == 0)
>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGES_LISTING_TYPE) == 0)
>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGE_TYPE) == 0)
>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>> + ? ? ? else {
>>>> + ? ? ? ? ? ? ? DBG("Incorrect type for get: %s", mas->type);
>>>> + ? ? ? ? ? ? ? return -EBADR;
>>>> + ? ? ? }
>>>> +}
>>>> +
>>>> +static int start_put(struct mas_session *mas)
>>>> +{
>>>> + ? ? ? /* NOTE: type is case-insensitive! */
>>>> + ? ? ? if (g_ascii_strcasecmp(mas->type, NOTIFICATION_TYPE) == 0)
>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, STATUS_TYPE) == 0)
>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGE_TYPE) == 0)
>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, UPDATE_TYPE) == 0)
>>>> + ? ? ? ? ? ? ? return -EINVAL;
>>>> + ? ? ? else {
>>>> + ? ? ? ? ? ? ? DBG("Incorrect type for put: %s", mas->type);
>>>> + ? ? ? ? ? ? ? return -EBADR;
>>>> + ? ? ? }
>>>> +}
>>>> +
>>>> ?static int mas_setpath(struct obex_session *os, obex_object_t *obj,
>>>> ? ? ? ? ? ? ? ?void *user_data)
>>>> ?{
>>>> @@ -210,7 +250,17 @@ static void *any_open(const char *name, int oflag, mode_t mode,
>>>>
>>>> ? ? ? ?DBG("");
>>>>
>>>> - ? ? ? *err = 0;
>>>> + ? ? ? if ((oflag & O_RDONLY) == O_RDONLY) {
>>>> + ? ? ? ? ? ? ? *err = start_get(mas);
>>>> + ? ? ? } else if ((oflag & O_WRONLY) == O_WRONLY) {
>>>> + ? ? ? ? ? ? ? *err = start_put(mas);
>>>> + ? ? ? } else {
>>>> + ? ? ? ? ? ? ? DBG("Invalid open flag!");
>>>> + ? ? ? ? ? ? ? *err = -EIO;
>>>> + ? ? ? }
>>>> +
>>>> + ? ? ? if (*err)
>>>> + ? ? ? ? ? ? ? return NULL;
>>>>
>>>> ? ? ? ?return mas;
>>>> ?}
>>>> --
>>>> 1.7.4.1
>>>
>>> --
>>> Luiz Augusto von Dentz
>>>
>>
>>
>>
>> --
>> Slawomir Bochenski
>>
>
>
>
> --
> Luiz Augusto von Dentz
>
--
Slawomir Bochenski
Hi,
On Wed, Jul 20, 2011 at 1:08 PM, Slawomir Bochenski <[email protected]> wrote:
> Hi,
>
> On Wed, Jul 20, 2011 at 11:50 AM, Luiz Augusto von Dentz
> <[email protected]> wrote:
>> Hi,
>>
>> On Tue, Jul 19, 2011 at 3:06 PM, Slawomir Bochenski <[email protected]> wrote:
>>> ---
>>> ?plugins/mas.c | ? 78 ++++++++++++++++++++++++++++++++++++++++++++++----------
>>> ?1 files changed, 64 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/plugins/mas.c b/plugins/mas.c
>>> index 0ef8c81..e88a0f0 100644
>>> --- a/plugins/mas.c
>>> +++ b/plugins/mas.c
>>> @@ -27,6 +27,9 @@
>>>
>>> ?#include <errno.h>
>>> ?#include <glib.h>
>>> +#include <sys/types.h>
>>> +#include <sys/stat.h>
>>> +#include <fcntl.h>
>>> ?#include <openobex/obex.h>
>>>
>>> ?#include "plugin.h"
>>> @@ -86,9 +89,19 @@
>>> ? </attribute> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
>>> ?</record>"
>>>
>>> +#define EVENT_TYPE ? ? ? ? ? ? "x-bt/MAP-event-report"
>>> +#define MESSAGE_TYPE ? ? ? ? ? "x-bt/message"
>>> +#define FOLDER_LISTING_TYPE ? ?"x-obex/folder-listing"
>>> +#define MESSAGES_LISTING_TYPE ?"x-bt/MAP-msg-listing"
>>> +#define NOTIFICATION_TYPE ? ? ?"x-bt/MAP-NotificationRegistration"
>>> +#define STATUS_TYPE ? ? ? ? ? ?"x-bt/messageStatus"
>>> +#define UPDATE_TYPE ? ? ? ? ? ?"x-bt/MAP-messageUpdate"
>>> +
>>> ?struct mas_session {
>>> ? ? ? ?struct mas_request *request;
>>> ? ? ? ?void *backend_data;
>>> + ? ? ? const char *name;
>>> + ? ? ? const char *type;
>>> ?};
>>>
>>> ?static const uint8_t MAS_TARGET[TARGET_SIZE] = {
>>> @@ -137,17 +150,14 @@ static void mas_disconnect(struct obex_session *os, void *user_data)
>>> ?static int mas_get(struct obex_session *os, obex_object_t *obj, void *user_data)
>>> ?{
>>> ? ? ? ?struct mas_session *mas = user_data;
>>> - ? ? ? const char *type = obex_get_type(os);
>>> - ? ? ? const char *name = obex_get_name(os);
>>> ? ? ? ?int ret;
>>>
>>> - ? ? ? DBG("GET: name %s type %s mas %p",
>>> - ? ? ? ? ? ? ? ? ? ? ? name, type, mas);
>>> + ? ? ? mas->name = obex_get_name(os);
>>> + ? ? ? mas->type = obex_get_type(os);
>>>
>>> - ? ? ? if (type == NULL)
>>> - ? ? ? ? ? ? ? return -EBADR;
>>> + ? ? ? DBG("GET: name %s type %s mas %p", mas->name, mas->type, mas);
>>>
>>> - ? ? ? ret = obex_get_stream_start(os, name);
>>> + ? ? ? ret = obex_get_stream_start(os, mas->name);
>>> ? ? ? ?if (ret < 0)
>>> ? ? ? ? ? ? ? ?goto failed;
>>>
>>> @@ -160,16 +170,14 @@ failed:
>>> ?static int mas_put(struct obex_session *os, obex_object_t *obj, void *user_data)
>>> ?{
>>> ? ? ? ?struct mas_session *mas = user_data;
>>> - ? ? ? const char *type = obex_get_type(os);
>>> - ? ? ? const char *name = obex_get_name(os);
>>> ? ? ? ?int ret;
>>>
>>> - ? ? ? DBG("PUT: name %s type %s mas %p", name, type, mas);
>>> + ? ? ? mas->name = obex_get_name(os);
>>> + ? ? ? mas->type = obex_get_type(os);
>>>
>>> - ? ? ? if (type == NULL)
>>> - ? ? ? ? ? ? ? return -EBADR;
>>> + ? ? ? DBG("PUT: name %s type %s mas %p", mas->name, mas->type, mas);
>>>
>>> - ? ? ? ret = obex_put_stream_start(os, name);
>>> + ? ? ? ret = obex_put_stream_start(os, mas->name);
>>> ? ? ? ?if (ret < 0)
>>> ? ? ? ? ? ? ? ?goto failed;
>>>
>>> @@ -179,6 +187,38 @@ failed:
>>> ? ? ? ?return ret;
>>> ?}
>>
>> I would suggest adding a mimetype driver for each type so you don't
>> have to do the check inside the service driver and it is also
>> consistent with what other plugins do when they support multiple
>> types.
>>
> I would not. That's the whole point. Functions for the mime driver
> would do exactly the same.
There we go again, so your point is that you don't want to be
consistent with other plugins and you like to see duplicated code
checking for matching types the very same way the core does for
mimetype drivers? Or do you mean the spec got this wrong and there is
no use of types because all of them do exactly the same? Sorry but I
don't think this has any valid technical point, in fact the mimetype
and service separation does help plugins to not mix object and session
handling.
>>> +static int start_get(struct mas_session *mas)
>>> +{
>>> + ? ? ? /* NOTE: type is case-insensitive! */
>>> + ? ? ? if (g_ascii_strcasecmp(mas->type, FOLDER_LISTING_TYPE) == 0)
>>> + ? ? ? ? ? ? ? return -EINVAL;
>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGES_LISTING_TYPE) == 0)
>>> + ? ? ? ? ? ? ? return -EINVAL;
>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGE_TYPE) == 0)
>>> + ? ? ? ? ? ? ? return -EINVAL;
>>> + ? ? ? else {
>>> + ? ? ? ? ? ? ? DBG("Incorrect type for get: %s", mas->type);
>>> + ? ? ? ? ? ? ? return -EBADR;
>>> + ? ? ? }
>>> +}
>>> +
>>> +static int start_put(struct mas_session *mas)
>>> +{
>>> + ? ? ? /* NOTE: type is case-insensitive! */
>>> + ? ? ? if (g_ascii_strcasecmp(mas->type, NOTIFICATION_TYPE) == 0)
>>> + ? ? ? ? ? ? ? return -EINVAL;
>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, STATUS_TYPE) == 0)
>>> + ? ? ? ? ? ? ? return -EINVAL;
>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGE_TYPE) == 0)
>>> + ? ? ? ? ? ? ? return -EINVAL;
>>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, UPDATE_TYPE) == 0)
>>> + ? ? ? ? ? ? ? return -EINVAL;
>>> + ? ? ? else {
>>> + ? ? ? ? ? ? ? DBG("Incorrect type for put: %s", mas->type);
>>> + ? ? ? ? ? ? ? return -EBADR;
>>> + ? ? ? }
>>> +}
>>> +
>>> ?static int mas_setpath(struct obex_session *os, obex_object_t *obj,
>>> ? ? ? ? ? ? ? ?void *user_data)
>>> ?{
>>> @@ -210,7 +250,17 @@ static void *any_open(const char *name, int oflag, mode_t mode,
>>>
>>> ? ? ? ?DBG("");
>>>
>>> - ? ? ? *err = 0;
>>> + ? ? ? if ((oflag & O_RDONLY) == O_RDONLY) {
>>> + ? ? ? ? ? ? ? *err = start_get(mas);
>>> + ? ? ? } else if ((oflag & O_WRONLY) == O_WRONLY) {
>>> + ? ? ? ? ? ? ? *err = start_put(mas);
>>> + ? ? ? } else {
>>> + ? ? ? ? ? ? ? DBG("Invalid open flag!");
>>> + ? ? ? ? ? ? ? *err = -EIO;
>>> + ? ? ? }
>>> +
>>> + ? ? ? if (*err)
>>> + ? ? ? ? ? ? ? return NULL;
>>>
>>> ? ? ? ?return mas;
>>> ?}
>>> --
>>> 1.7.4.1
>>
>> --
>> Luiz Augusto von Dentz
>>
>
>
>
> --
> Slawomir Bochenski
>
--
Luiz Augusto von Dentz
Hi,
On Wed, Jul 20, 2011 at 11:50 AM, Luiz Augusto von Dentz
<[email protected]> wrote:
> Hi,
>
> On Tue, Jul 19, 2011 at 3:06 PM, Slawomir Bochenski <[email protected]> wrote:
>> ---
>> ?plugins/mas.c | ? 78 ++++++++++++++++++++++++++++++++++++++++++++++----------
>> ?1 files changed, 64 insertions(+), 14 deletions(-)
>>
>> diff --git a/plugins/mas.c b/plugins/mas.c
>> index 0ef8c81..e88a0f0 100644
>> --- a/plugins/mas.c
>> +++ b/plugins/mas.c
>> @@ -27,6 +27,9 @@
>>
>> ?#include <errno.h>
>> ?#include <glib.h>
>> +#include <sys/types.h>
>> +#include <sys/stat.h>
>> +#include <fcntl.h>
>> ?#include <openobex/obex.h>
>>
>> ?#include "plugin.h"
>> @@ -86,9 +89,19 @@
>> ? </attribute> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
>> ?</record>"
>>
>> +#define EVENT_TYPE ? ? ? ? ? ? "x-bt/MAP-event-report"
>> +#define MESSAGE_TYPE ? ? ? ? ? "x-bt/message"
>> +#define FOLDER_LISTING_TYPE ? ?"x-obex/folder-listing"
>> +#define MESSAGES_LISTING_TYPE ?"x-bt/MAP-msg-listing"
>> +#define NOTIFICATION_TYPE ? ? ?"x-bt/MAP-NotificationRegistration"
>> +#define STATUS_TYPE ? ? ? ? ? ?"x-bt/messageStatus"
>> +#define UPDATE_TYPE ? ? ? ? ? ?"x-bt/MAP-messageUpdate"
>> +
>> ?struct mas_session {
>> ? ? ? ?struct mas_request *request;
>> ? ? ? ?void *backend_data;
>> + ? ? ? const char *name;
>> + ? ? ? const char *type;
>> ?};
>>
>> ?static const uint8_t MAS_TARGET[TARGET_SIZE] = {
>> @@ -137,17 +150,14 @@ static void mas_disconnect(struct obex_session *os, void *user_data)
>> ?static int mas_get(struct obex_session *os, obex_object_t *obj, void *user_data)
>> ?{
>> ? ? ? ?struct mas_session *mas = user_data;
>> - ? ? ? const char *type = obex_get_type(os);
>> - ? ? ? const char *name = obex_get_name(os);
>> ? ? ? ?int ret;
>>
>> - ? ? ? DBG("GET: name %s type %s mas %p",
>> - ? ? ? ? ? ? ? ? ? ? ? name, type, mas);
>> + ? ? ? mas->name = obex_get_name(os);
>> + ? ? ? mas->type = obex_get_type(os);
>>
>> - ? ? ? if (type == NULL)
>> - ? ? ? ? ? ? ? return -EBADR;
>> + ? ? ? DBG("GET: name %s type %s mas %p", mas->name, mas->type, mas);
>>
>> - ? ? ? ret = obex_get_stream_start(os, name);
>> + ? ? ? ret = obex_get_stream_start(os, mas->name);
>> ? ? ? ?if (ret < 0)
>> ? ? ? ? ? ? ? ?goto failed;
>>
>> @@ -160,16 +170,14 @@ failed:
>> ?static int mas_put(struct obex_session *os, obex_object_t *obj, void *user_data)
>> ?{
>> ? ? ? ?struct mas_session *mas = user_data;
>> - ? ? ? const char *type = obex_get_type(os);
>> - ? ? ? const char *name = obex_get_name(os);
>> ? ? ? ?int ret;
>>
>> - ? ? ? DBG("PUT: name %s type %s mas %p", name, type, mas);
>> + ? ? ? mas->name = obex_get_name(os);
>> + ? ? ? mas->type = obex_get_type(os);
>>
>> - ? ? ? if (type == NULL)
>> - ? ? ? ? ? ? ? return -EBADR;
>> + ? ? ? DBG("PUT: name %s type %s mas %p", mas->name, mas->type, mas);
>>
>> - ? ? ? ret = obex_put_stream_start(os, name);
>> + ? ? ? ret = obex_put_stream_start(os, mas->name);
>> ? ? ? ?if (ret < 0)
>> ? ? ? ? ? ? ? ?goto failed;
>>
>> @@ -179,6 +187,38 @@ failed:
>> ? ? ? ?return ret;
>> ?}
>
> I would suggest adding a mimetype driver for each type so you don't
> have to do the check inside the service driver and it is also
> consistent with what other plugins do when they support multiple
> types.
>
I would not. That's the whole point. Functions for the mime driver
would do exactly the same.
>> +static int start_get(struct mas_session *mas)
>> +{
>> + ? ? ? /* NOTE: type is case-insensitive! */
>> + ? ? ? if (g_ascii_strcasecmp(mas->type, FOLDER_LISTING_TYPE) == 0)
>> + ? ? ? ? ? ? ? return -EINVAL;
>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGES_LISTING_TYPE) == 0)
>> + ? ? ? ? ? ? ? return -EINVAL;
>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGE_TYPE) == 0)
>> + ? ? ? ? ? ? ? return -EINVAL;
>> + ? ? ? else {
>> + ? ? ? ? ? ? ? DBG("Incorrect type for get: %s", mas->type);
>> + ? ? ? ? ? ? ? return -EBADR;
>> + ? ? ? }
>> +}
>> +
>> +static int start_put(struct mas_session *mas)
>> +{
>> + ? ? ? /* NOTE: type is case-insensitive! */
>> + ? ? ? if (g_ascii_strcasecmp(mas->type, NOTIFICATION_TYPE) == 0)
>> + ? ? ? ? ? ? ? return -EINVAL;
>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, STATUS_TYPE) == 0)
>> + ? ? ? ? ? ? ? return -EINVAL;
>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGE_TYPE) == 0)
>> + ? ? ? ? ? ? ? return -EINVAL;
>> + ? ? ? else if (g_ascii_strcasecmp(mas->type, UPDATE_TYPE) == 0)
>> + ? ? ? ? ? ? ? return -EINVAL;
>> + ? ? ? else {
>> + ? ? ? ? ? ? ? DBG("Incorrect type for put: %s", mas->type);
>> + ? ? ? ? ? ? ? return -EBADR;
>> + ? ? ? }
>> +}
>> +
>> ?static int mas_setpath(struct obex_session *os, obex_object_t *obj,
>> ? ? ? ? ? ? ? ?void *user_data)
>> ?{
>> @@ -210,7 +250,17 @@ static void *any_open(const char *name, int oflag, mode_t mode,
>>
>> ? ? ? ?DBG("");
>>
>> - ? ? ? *err = 0;
>> + ? ? ? if ((oflag & O_RDONLY) == O_RDONLY) {
>> + ? ? ? ? ? ? ? *err = start_get(mas);
>> + ? ? ? } else if ((oflag & O_WRONLY) == O_WRONLY) {
>> + ? ? ? ? ? ? ? *err = start_put(mas);
>> + ? ? ? } else {
>> + ? ? ? ? ? ? ? DBG("Invalid open flag!");
>> + ? ? ? ? ? ? ? *err = -EIO;
>> + ? ? ? }
>> +
>> + ? ? ? if (*err)
>> + ? ? ? ? ? ? ? return NULL;
>>
>> ? ? ? ?return mas;
>> ?}
>> --
>> 1.7.4.1
>
> --
> Luiz Augusto von Dentz
>
--
Slawomir Bochenski
Hi,
On Tue, Jul 19, 2011 at 3:06 PM, Slawomir Bochenski <[email protected]> wrote:
> ---
> ?plugins/mas.c | ? 78 ++++++++++++++++++++++++++++++++++++++++++++++----------
> ?1 files changed, 64 insertions(+), 14 deletions(-)
>
> diff --git a/plugins/mas.c b/plugins/mas.c
> index 0ef8c81..e88a0f0 100644
> --- a/plugins/mas.c
> +++ b/plugins/mas.c
> @@ -27,6 +27,9 @@
>
> ?#include <errno.h>
> ?#include <glib.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> ?#include <openobex/obex.h>
>
> ?#include "plugin.h"
> @@ -86,9 +89,19 @@
> ? </attribute> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? \
> ?</record>"
>
> +#define EVENT_TYPE ? ? ? ? ? ? "x-bt/MAP-event-report"
> +#define MESSAGE_TYPE ? ? ? ? ? "x-bt/message"
> +#define FOLDER_LISTING_TYPE ? ?"x-obex/folder-listing"
> +#define MESSAGES_LISTING_TYPE ?"x-bt/MAP-msg-listing"
> +#define NOTIFICATION_TYPE ? ? ?"x-bt/MAP-NotificationRegistration"
> +#define STATUS_TYPE ? ? ? ? ? ?"x-bt/messageStatus"
> +#define UPDATE_TYPE ? ? ? ? ? ?"x-bt/MAP-messageUpdate"
> +
> ?struct mas_session {
> ? ? ? ?struct mas_request *request;
> ? ? ? ?void *backend_data;
> + ? ? ? const char *name;
> + ? ? ? const char *type;
> ?};
>
> ?static const uint8_t MAS_TARGET[TARGET_SIZE] = {
> @@ -137,17 +150,14 @@ static void mas_disconnect(struct obex_session *os, void *user_data)
> ?static int mas_get(struct obex_session *os, obex_object_t *obj, void *user_data)
> ?{
> ? ? ? ?struct mas_session *mas = user_data;
> - ? ? ? const char *type = obex_get_type(os);
> - ? ? ? const char *name = obex_get_name(os);
> ? ? ? ?int ret;
>
> - ? ? ? DBG("GET: name %s type %s mas %p",
> - ? ? ? ? ? ? ? ? ? ? ? name, type, mas);
> + ? ? ? mas->name = obex_get_name(os);
> + ? ? ? mas->type = obex_get_type(os);
>
> - ? ? ? if (type == NULL)
> - ? ? ? ? ? ? ? return -EBADR;
> + ? ? ? DBG("GET: name %s type %s mas %p", mas->name, mas->type, mas);
>
> - ? ? ? ret = obex_get_stream_start(os, name);
> + ? ? ? ret = obex_get_stream_start(os, mas->name);
> ? ? ? ?if (ret < 0)
> ? ? ? ? ? ? ? ?goto failed;
>
> @@ -160,16 +170,14 @@ failed:
> ?static int mas_put(struct obex_session *os, obex_object_t *obj, void *user_data)
> ?{
> ? ? ? ?struct mas_session *mas = user_data;
> - ? ? ? const char *type = obex_get_type(os);
> - ? ? ? const char *name = obex_get_name(os);
> ? ? ? ?int ret;
>
> - ? ? ? DBG("PUT: name %s type %s mas %p", name, type, mas);
> + ? ? ? mas->name = obex_get_name(os);
> + ? ? ? mas->type = obex_get_type(os);
>
> - ? ? ? if (type == NULL)
> - ? ? ? ? ? ? ? return -EBADR;
> + ? ? ? DBG("PUT: name %s type %s mas %p", mas->name, mas->type, mas);
>
> - ? ? ? ret = obex_put_stream_start(os, name);
> + ? ? ? ret = obex_put_stream_start(os, mas->name);
> ? ? ? ?if (ret < 0)
> ? ? ? ? ? ? ? ?goto failed;
>
> @@ -179,6 +187,38 @@ failed:
> ? ? ? ?return ret;
> ?}
I would suggest adding a mimetype driver for each type so you don't
have to do the check inside the service driver and it is also
consistent with what other plugins do when they support multiple
types.
> +static int start_get(struct mas_session *mas)
> +{
> + ? ? ? /* NOTE: type is case-insensitive! */
> + ? ? ? if (g_ascii_strcasecmp(mas->type, FOLDER_LISTING_TYPE) == 0)
> + ? ? ? ? ? ? ? return -EINVAL;
> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGES_LISTING_TYPE) == 0)
> + ? ? ? ? ? ? ? return -EINVAL;
> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGE_TYPE) == 0)
> + ? ? ? ? ? ? ? return -EINVAL;
> + ? ? ? else {
> + ? ? ? ? ? ? ? DBG("Incorrect type for get: %s", mas->type);
> + ? ? ? ? ? ? ? return -EBADR;
> + ? ? ? }
> +}
> +
> +static int start_put(struct mas_session *mas)
> +{
> + ? ? ? /* NOTE: type is case-insensitive! */
> + ? ? ? if (g_ascii_strcasecmp(mas->type, NOTIFICATION_TYPE) == 0)
> + ? ? ? ? ? ? ? return -EINVAL;
> + ? ? ? else if (g_ascii_strcasecmp(mas->type, STATUS_TYPE) == 0)
> + ? ? ? ? ? ? ? return -EINVAL;
> + ? ? ? else if (g_ascii_strcasecmp(mas->type, MESSAGE_TYPE) == 0)
> + ? ? ? ? ? ? ? return -EINVAL;
> + ? ? ? else if (g_ascii_strcasecmp(mas->type, UPDATE_TYPE) == 0)
> + ? ? ? ? ? ? ? return -EINVAL;
> + ? ? ? else {
> + ? ? ? ? ? ? ? DBG("Incorrect type for put: %s", mas->type);
> + ? ? ? ? ? ? ? return -EBADR;
> + ? ? ? }
> +}
> +
> ?static int mas_setpath(struct obex_session *os, obex_object_t *obj,
> ? ? ? ? ? ? ? ?void *user_data)
> ?{
> @@ -210,7 +250,17 @@ static void *any_open(const char *name, int oflag, mode_t mode,
>
> ? ? ? ?DBG("");
>
> - ? ? ? *err = 0;
> + ? ? ? if ((oflag & O_RDONLY) == O_RDONLY) {
> + ? ? ? ? ? ? ? *err = start_get(mas);
> + ? ? ? } else if ((oflag & O_WRONLY) == O_WRONLY) {
> + ? ? ? ? ? ? ? *err = start_put(mas);
> + ? ? ? } else {
> + ? ? ? ? ? ? ? DBG("Invalid open flag!");
> + ? ? ? ? ? ? ? *err = -EIO;
> + ? ? ? }
> +
> + ? ? ? if (*err)
> + ? ? ? ? ? ? ? return NULL;
>
> ? ? ? ?return mas;
> ?}
> --
> 1.7.4.1
--
Luiz Augusto von Dentz
---
plugins/messages-dummy.c | 181 ++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 176 insertions(+), 5 deletions(-)
diff --git a/plugins/messages-dummy.c b/plugins/messages-dummy.c
index 295eb61..dd748bb 100644
--- a/plugins/messages-dummy.c
+++ b/plugins/messages-dummy.c
@@ -25,10 +25,12 @@
#include <config.h>
#endif
+#include <dirent.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include "log.h"
#include "messages.h"
static char *root_folder = NULL;
@@ -36,6 +38,16 @@ static char *root_folder = NULL;
struct session {
char *cwd;
char *cwd_absolute;
+ void *request;
+};
+
+struct folder_listing_data {
+ struct session *session;
+ const char *name;
+ messages_folder_listing_cb callback;
+ void *user_data;
+ uint16_t max;
+ uint16_t offset;
};
int messages_init(void)
@@ -142,14 +154,167 @@ int messages_set_folder(void *s, const char *name, gboolean cdup)
return 0;
}
-int messages_get_folder_listing(void *session,
+/* NOTE: Neither IrOBEX nor MAP specs says that folder listing needs to
+ * be sorted (in IrOBEX examples it is not). However existing implementations
+ * seem to follow the fig. 3-2 from MAP specification v1.0, and I've seen a
+ * test suite requiring folder listing to be in that order.
+ */
+static gint folder_names_cmp(gconstpointer a, gconstpointer b,
+ gpointer user_data)
+{
+ static const char *order[] = {
+ "inbox", "outbox", "sent", "deleted", "draft", NULL
+ };
+ struct session *session = user_data;
+ int ia, ib;
+
+ if (g_strcmp0(session->cwd, "telecom/msg") == 0) {
+ for (ia = 0; order[ia]; ++ia) {
+ if (g_strcmp0(a, order[ia]) == 0)
+ break;
+ }
+ for (ib = 0; order[ib]; ++ib) {
+ if (g_strcmp0(b, order[ib]) == 0)
+ break;
+ }
+ if (ia != ib)
+ return ia - ib;
+ }
+
+ return g_strcmp0(a, b);
+}
+
+static int get_subdirs(struct folder_listing_data *fld, GSList **list,
+ uint16_t *n)
+{
+ DIR *dp;
+ struct dirent *ep;
+ char *path;
+ char *abs;
+ char *name;
+
+ *n = 0;
+
+ path = g_build_filename(fld->session->cwd_absolute, fld->name, NULL);
+ dp = opendir(path);
+
+ if (dp == NULL) {
+ int err = errno;
+
+ DBG("opendir(): %d, %s", err, strerror(err));
+ g_free(path);
+
+ return -err;
+ }
+
+ while ((ep = readdir(dp)) != NULL) {
+ if (ep->d_name[0] == '.' &&
+ (ep->d_name[1] == 0 || ep->d_name[1] == '.'))
+ continue;
+
+ abs = g_build_filename(path, ep->d_name,
+ NULL);
+
+ if (!g_file_test(abs, G_FILE_TEST_IS_DIR)) {
+ g_free(abs);
+ continue;
+ }
+
+ g_free(abs);
+ name = g_filename_to_utf8(ep->d_name, -1, NULL, NULL, NULL);
+
+ if (name == NULL) {
+ error("g_filename_to_utf8(): invalid filename");
+ continue;
+ }
+
+ ++*n;
+
+ if (fld->max != 0)
+ *list = g_slist_prepend(*list, name);
+ }
+
+ closedir(dp);
+ g_free(path);
+
+ *list = g_slist_sort_with_data(*list, folder_names_cmp, fld->session);
+
+ return 0;
+}
+
+static gboolean get_folder_listing(void *d)
+{
+ struct folder_listing_data *fld = d;
+ struct session *session = fld->session;
+ uint16_t n;
+ uint16_t o;
+ GSList *list = NULL;
+ GSList *cur;
+ int err;
+
+ err = get_subdirs(fld, &list, &n);
+
+ if (err < 0) {
+ fld->callback(session, err, 0, NULL, fld->user_data);
+ return FALSE;
+ }
+
+ if (fld->max == 0) {
+ fld->callback(session, 0, n, NULL, fld->user_data);
+ return FALSE;
+ }
+
+ n = 0;
+ o = 0;
+
+ /* XXX: This isn't really documented for MAP. Need to take a look at
+ * other implementations.
+ */
+ if (session->cwd[0] != 0 && fld->offset == 0) {
+ ++n;
+ fld->callback(session, -EAGAIN, 0, "..", fld->user_data);
+ } else {
+ ++o;
+ }
+
+ for (cur = list; o < fld->offset; ++o) {
+ cur = cur->next;
+ if (cur == NULL)
+ break;
+ }
+
+ for (; cur != NULL && n < fld->max; cur = cur->next, ++n)
+ fld->callback(session, -EAGAIN, 0, cur->data, fld->user_data);
+
+ fld->callback(session, 0, 0, NULL, fld->user_data);
+
+ g_slist_free_full(list, g_free);
+
+ return FALSE;
+}
+
+int messages_get_folder_listing(void *s,
const char *name,
uint16_t max, uint16_t offset,
- void (*callback)(void *session, int err, uint16_t size,
- const char *name, void *user_data),
+ messages_folder_listing_cb callback,
void *user_data)
{
- return -EINVAL;
+ struct session *session = s;
+ struct folder_listing_data *fld;
+
+ fld = g_new0(struct folder_listing_data, 1);
+ fld->name = name;
+ fld->max = max;
+ fld->offset = offset;
+ fld->callback = callback;
+ fld->session = session;
+ fld->user_data = user_data;
+ session->request = fld;
+
+ g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, get_folder_listing,
+ fld, g_free);
+
+ return 0;
}
int messages_get_messages_listing(void *session,
@@ -173,6 +338,12 @@ int messages_get_message(void *session,
return -EINVAL;
}
-void messages_abort(void *session)
+void messages_abort(void *s)
{
+ struct session *session = s;
+
+ if (session->request) {
+ g_idle_remove_by_data(session->request);
+ session->request = NULL;
+ }
}
--
1.7.4.1
This adds a basic (without parsing or sending back application
parameters) handling of folder listing requests for Message Access
Profile.
---
plugins/mas.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++-
plugins/messages.h | 6 ++-
2 files changed, 105 insertions(+), 4 deletions(-)
diff --git a/plugins/mas.c b/plugins/mas.c
index e88a0f0..4e1e07f 100644
--- a/plugins/mas.c
+++ b/plugins/mas.c
@@ -37,6 +37,7 @@
#include "obex.h"
#include "service.h"
#include "mimetype.h"
+#include "filesystem.h"
#include "dbus.h"
#include "messages.h"
@@ -97,19 +98,44 @@
#define STATUS_TYPE "x-bt/messageStatus"
#define UPDATE_TYPE "x-bt/MAP-messageUpdate"
+#define XML_DECL "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+
+/* Building blocks for x-obex/folder-listing */
+#define FL_DTD "<!DOCTYPE folder-listing SYSTEM \"obex-folder-listing.dtd\">"
+#define FL_BODY_BEGIN "<folder-listing version=\"1.0\">"
+#define FL_BODY_EMPTY "<folder-listing version=\"1.0\"/>"
+#define FL_PARENT_FOLDER_ELEMENT "<parent-folder/>"
+#define FL_FOLDER_ELEMENT "<folder name=\"%s\"/>"
+#define FL_BODY_END "</folder-listing>"
+
struct mas_session {
struct mas_request *request;
void *backend_data;
const char *name;
const char *type;
+ gboolean nth_call;
+ gboolean finished;
+ GString *buffer;
};
static const uint8_t MAS_TARGET[TARGET_SIZE] = {
0xbb, 0x58, 0x2b, 0x40, 0x42, 0x0c, 0x11, 0xdb,
0xb0, 0xde, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 };
+static void reset_request(struct mas_session *mas)
+{
+ if (mas->buffer) {
+ g_string_free(mas->buffer, TRUE);
+ mas->buffer = NULL;
+ }
+
+ mas->nth_call = FALSE;
+ mas->finished = FALSE;
+}
+
static void mas_clean(struct mas_session *mas)
{
+ reset_request(mas);
g_free(mas);
}
@@ -187,11 +213,65 @@ failed:
return ret;
}
+/* FIXME: Preserve whitespaces */
+static void g_string_append_escaped_printf(GString *string, const gchar *format,
+ ...)
+{
+ va_list ap;
+ char *escaped;
+
+ va_start(ap, format);
+ escaped = g_markup_vprintf_escaped(format, ap);
+ g_string_append(string, escaped);
+ g_free(escaped);
+ va_end(ap);
+}
+
+static void get_folder_listing_cb(void *session, int err, uint16_t size,
+ const char *name, void *user_data)
+{
+ struct mas_session *mas = user_data;
+
+ if (err < 0 && err != -EAGAIN) {
+ obex_object_set_io_flags(mas, G_IO_ERR, err);
+ return;
+ }
+
+ if (!mas->nth_call) {
+ g_string_append(mas->buffer, XML_DECL);
+ g_string_append(mas->buffer, FL_DTD);
+ if (!name) {
+ g_string_append(mas->buffer, FL_BODY_EMPTY);
+ mas->finished = TRUE;
+ goto proceed;
+ }
+ g_string_append(mas->buffer, FL_BODY_BEGIN);
+ mas->nth_call = TRUE;
+ }
+
+ if (!name) {
+ g_string_append(mas->buffer, FL_BODY_END);
+ mas->finished = TRUE;
+ goto proceed;
+ }
+
+ if (g_strcmp0(name, "..") == 0)
+ g_string_append(mas->buffer, FL_PARENT_FOLDER_ELEMENT);
+ else
+ g_string_append_escaped_printf(mas->buffer, FL_FOLDER_ELEMENT,
+ name);
+
+proceed:
+ if (err != -EAGAIN)
+ obex_object_set_io_flags(mas, G_IO_IN, err);
+}
+
static int start_get(struct mas_session *mas)
{
/* NOTE: type is case-insensitive! */
if (g_ascii_strcasecmp(mas->type, FOLDER_LISTING_TYPE) == 0)
- return -EINVAL;
+ return messages_get_folder_listing(mas->backend_data, mas->name,
+ 0xffff, 0, get_folder_listing_cb, mas);
else if (g_ascii_strcasecmp(mas->type, MESSAGES_LISTING_TYPE) == 0)
return -EINVAL;
else if (g_ascii_strcasecmp(mas->type, MESSAGE_TYPE) == 0)
@@ -262,6 +342,10 @@ static void *any_open(const char *name, int oflag, mode_t mode,
if (*err)
return NULL;
+ mas->finished = FALSE;
+ mas->nth_call = FALSE;
+ mas->buffer = g_string_new("");
+
return mas;
}
@@ -274,15 +358,30 @@ static ssize_t any_write(void *object, const void *buf, size_t count)
static ssize_t any_read(void *obj, void *buf, size_t count)
{
+ struct mas_session *mas = obj;
+ ssize_t len;
+
DBG("");
- return 0;
+ len = string_read(mas->buffer, buf, count);
+
+ if (len == 0 && !mas->finished)
+ return -EAGAIN;
+
+ return len;
}
static int any_close(void *obj)
{
+ struct mas_session *mas = obj;
+
DBG("");
+ if (!mas->finished)
+ messages_abort(mas->backend_data);
+
+ reset_request(mas);
+
return 0;
}
diff --git a/plugins/messages.h b/plugins/messages.h
index c862b07..d9348c7 100644
--- a/plugins/messages.h
+++ b/plugins/messages.h
@@ -202,11 +202,13 @@ int messages_set_folder(void *session, const char *name, gboolean cdup);
* Callback shall be called for every entry of the listing. 'name' is the
* subdirectory name.
*/
+typedef void (*messages_folder_listing_cb)(void *session, int err,
+ uint16_t size, const char *name, void *user_data);
+
int messages_get_folder_listing(void *session,
const char *name,
uint16_t max, uint16_t offset,
- void (*callback)(void *session, int err, uint16_t size,
- const char *name, void *user_data),
+ messages_folder_listing_cb callback,
void *user_data);
/* Retrieves messages listing from a current directory.
--
1.7.4.1
---
plugins/mas.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 64 insertions(+), 14 deletions(-)
diff --git a/plugins/mas.c b/plugins/mas.c
index 0ef8c81..e88a0f0 100644
--- a/plugins/mas.c
+++ b/plugins/mas.c
@@ -27,6 +27,9 @@
#include <errno.h>
#include <glib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include <openobex/obex.h>
#include "plugin.h"
@@ -86,9 +89,19 @@
</attribute> \
</record>"
+#define EVENT_TYPE "x-bt/MAP-event-report"
+#define MESSAGE_TYPE "x-bt/message"
+#define FOLDER_LISTING_TYPE "x-obex/folder-listing"
+#define MESSAGES_LISTING_TYPE "x-bt/MAP-msg-listing"
+#define NOTIFICATION_TYPE "x-bt/MAP-NotificationRegistration"
+#define STATUS_TYPE "x-bt/messageStatus"
+#define UPDATE_TYPE "x-bt/MAP-messageUpdate"
+
struct mas_session {
struct mas_request *request;
void *backend_data;
+ const char *name;
+ const char *type;
};
static const uint8_t MAS_TARGET[TARGET_SIZE] = {
@@ -137,17 +150,14 @@ static void mas_disconnect(struct obex_session *os, void *user_data)
static int mas_get(struct obex_session *os, obex_object_t *obj, void *user_data)
{
struct mas_session *mas = user_data;
- const char *type = obex_get_type(os);
- const char *name = obex_get_name(os);
int ret;
- DBG("GET: name %s type %s mas %p",
- name, type, mas);
+ mas->name = obex_get_name(os);
+ mas->type = obex_get_type(os);
- if (type == NULL)
- return -EBADR;
+ DBG("GET: name %s type %s mas %p", mas->name, mas->type, mas);
- ret = obex_get_stream_start(os, name);
+ ret = obex_get_stream_start(os, mas->name);
if (ret < 0)
goto failed;
@@ -160,16 +170,14 @@ failed:
static int mas_put(struct obex_session *os, obex_object_t *obj, void *user_data)
{
struct mas_session *mas = user_data;
- const char *type = obex_get_type(os);
- const char *name = obex_get_name(os);
int ret;
- DBG("PUT: name %s type %s mas %p", name, type, mas);
+ mas->name = obex_get_name(os);
+ mas->type = obex_get_type(os);
- if (type == NULL)
- return -EBADR;
+ DBG("PUT: name %s type %s mas %p", mas->name, mas->type, mas);
- ret = obex_put_stream_start(os, name);
+ ret = obex_put_stream_start(os, mas->name);
if (ret < 0)
goto failed;
@@ -179,6 +187,38 @@ failed:
return ret;
}
+static int start_get(struct mas_session *mas)
+{
+ /* NOTE: type is case-insensitive! */
+ if (g_ascii_strcasecmp(mas->type, FOLDER_LISTING_TYPE) == 0)
+ return -EINVAL;
+ else if (g_ascii_strcasecmp(mas->type, MESSAGES_LISTING_TYPE) == 0)
+ return -EINVAL;
+ else if (g_ascii_strcasecmp(mas->type, MESSAGE_TYPE) == 0)
+ return -EINVAL;
+ else {
+ DBG("Incorrect type for get: %s", mas->type);
+ return -EBADR;
+ }
+}
+
+static int start_put(struct mas_session *mas)
+{
+ /* NOTE: type is case-insensitive! */
+ if (g_ascii_strcasecmp(mas->type, NOTIFICATION_TYPE) == 0)
+ return -EINVAL;
+ else if (g_ascii_strcasecmp(mas->type, STATUS_TYPE) == 0)
+ return -EINVAL;
+ else if (g_ascii_strcasecmp(mas->type, MESSAGE_TYPE) == 0)
+ return -EINVAL;
+ else if (g_ascii_strcasecmp(mas->type, UPDATE_TYPE) == 0)
+ return -EINVAL;
+ else {
+ DBG("Incorrect type for put: %s", mas->type);
+ return -EBADR;
+ }
+}
+
static int mas_setpath(struct obex_session *os, obex_object_t *obj,
void *user_data)
{
@@ -210,7 +250,17 @@ static void *any_open(const char *name, int oflag, mode_t mode,
DBG("");
- *err = 0;
+ if ((oflag & O_RDONLY) == O_RDONLY) {
+ *err = start_get(mas);
+ } else if ((oflag & O_WRONLY) == O_WRONLY) {
+ *err = start_put(mas);
+ } else {
+ DBG("Invalid open flag!");
+ *err = -EIO;
+ }
+
+ if (*err)
+ return NULL;
return mas;
}
--
1.7.4.1