* [RFC v2 obexd 02/11] build: Add --enable-fuse for obexfuse
2012-10-28 0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
@ 2012-10-28 0:29 ` Michał Poczwardowski
2012-10-28 0:29 ` [RFC v2 obexd 03/11] fuse: Add obexhlp_connect/disconnect functions with helpers Michał Poczwardowski
` (8 subsequent siblings)
9 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
---
Makefile.am | 9 +++++++++
configure.ac | 15 +++++++++++++++
2 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 724dd5d..01441dc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -132,6 +132,15 @@ client_obex_client_SOURCES = $(gdbus_sources) $(gobex_sources) \
client_obex_client_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ @BLUEZ_LIBS@
endif
+if FUSE
+bin_PROGRAMS = fuse/obexfuse
+
+fuse_obexfuse_SOURCES = $(gobex_sources) $(btio_sources) \
+ fuse/helpers.c fuse/obexfuse.c
+
+fuse_obexfuse_LDADD = @GLIB_LIBS@ @GTHREAD_LIBS@ @BLUEZ_LIBS@ @FUSE_LIBS@
+endif
+
service_DATA = $(service_in_files:.service.in=.service)
AM_CFLAGS = @BLUEZ_CFLAGS@ @EBOOK_CFLAGS@ @GTHREAD_CFLAGS@ @GLIB_CFLAGS@ \
diff --git a/configure.ac b/configure.ac
index c8e61ac..f380481 100644
--- a/configure.ac
+++ b/configure.ac
@@ -180,4 +180,19 @@ AM_CONDITIONAL(CLIENT, test "${enable_client}" != "no")
AM_CONDITIONAL(READLINE, test "${readline_found}" = "yes")
+AC_ARG_ENABLE(fuse, AC_HELP_STRING([--enable-fuse],
+ [Build obexfuse]), [
+ PKG_CHECK_MODULES(FUSE, fuse, dummy=yes,
+ AC_MSG_ERROR(FUSE is required))
+ AC_SUBST(FUSE_CFLAGS)
+ AC_SUBST(FUSE_LIBS)
+ enable_fuse=${enableval}
+
+ PKG_CHECK_MODULES(GTHREAD, gthread-2.0, dummy=yes,
+ AC_MSG_ERROR(libgthread is required))
+ AC_SUBST(GTHREAD_CFLAGS)
+ AC_SUBST(GTHREAD_LIBS)
+])
+AM_CONDITIONAL(FUSE, test "${enable_fuse}" != "no")
+
AC_OUTPUT(Makefile)
--
1.7.8.6
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [RFC v2 obexd 03/11] fuse: Add obexhlp_connect/disconnect functions with helpers
2012-10-28 0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
2012-10-28 0:29 ` [RFC v2 obexd 02/11] build: Add --enable-fuse for obexfuse Michał Poczwardowski
@ 2012-10-28 0:29 ` Michał Poczwardowski
2012-10-30 9:08 ` Luiz Augusto von Dentz
2012-10-28 0:29 ` [RFC v2 obexd 04/11] fuse: Add request helpers and setpath operation Michał Poczwardowski
` (7 subsequent siblings)
9 siblings, 1 reply; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
---
fuse/helpers.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
fuse/helpers.h | 4 +
fuse/obexfuse.c | 40 ++++++++++
3 files changed, 265 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index c36072d..856e1d5 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -43,6 +43,9 @@
#define OBEX_FTP_LS "x-obex/folder-listing"
+static GCond *gobexhlp_cond;
+static GMutex *gobexhlp_mutex;
+
struct gobexhlp_request {
gchar *name;
gboolean complete;
@@ -52,3 +55,221 @@ struct gobexhlp_location {
gchar *dir;
gchar *file;
};
+
+static uint16_t find_rfcomm_uuid(void *user_data)
+{
+ sdp_list_t *pds = (sdp_list_t*) user_data;
+ uint16_t channel = 0;
+
+ for (;pds;pds = pds->next) {
+ sdp_data_t *d = (sdp_data_t*)pds->data;
+ int proto = 0;
+ for (; d; d = d->next) {
+ switch(d->dtd) {
+ case SDP_UUID16:
+ case SDP_UUID32:
+ case SDP_UUID128:
+ proto = sdp_uuid_to_proto(&d->val.uuid);
+ break;
+ case SDP_UINT8:
+ if (proto == RFCOMM_UUID)
+ channel = d->val.int8;
+ break;
+ }
+ }
+ }
+ return channel;
+}
+
+static uint16_t get_ftp_channel(bdaddr_t *src, bdaddr_t *dst)
+{
+ sdp_session_t *sdp;
+ sdp_list_t *r, *search_list, *attrid_list;
+ sdp_list_t *response_list = NULL;
+ uuid_t uuid;
+
+ /* FTP_SDP_UUID "00001106-0000-1000-8000-00805f9b34fb" */
+ uint8_t uuid_int[] = {0, 0, 0x11, 0x06, 0, 0, 0x10, 0, 0x80,
+ 0, 0, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+ uint32_t range = 0x0000ffff;
+ uint16_t channel = 0;
+
+ sdp = sdp_connect(src, dst, SDP_RETRY_IF_BUSY );
+ if (sdp == NULL)
+ return channel;
+
+ sdp_uuid128_create(&uuid, uuid_int);
+ search_list = sdp_list_append(NULL, &uuid);
+ attrid_list = sdp_list_append(NULL, &range);
+ sdp_service_search_attr_req(sdp, search_list, SDP_ATTR_REQ_RANGE,
+ attrid_list, &response_list);
+ r = response_list;
+
+ for (; r;r = r->next) {
+ sdp_record_t *rec = (sdp_record_t*) r->data;
+ sdp_list_t *proto_list;
+
+ if (sdp_get_access_protos(rec, &proto_list ) == 0) {
+ sdp_list_t *p = proto_list;
+ for (; p; p = p->next) {
+ sdp_list_t *pds = (sdp_list_t*) p->data;
+ channel = find_rfcomm_uuid(pds);
+ sdp_list_free((sdp_list_t*) p->data, 0);
+ }
+ sdp_list_free(proto_list, 0);
+ }
+ sdp_record_free(rec);
+ }
+ sdp_close(sdp);
+
+ g_free(search_list);
+ g_free(attrid_list);
+ g_free(response_list);
+
+ return channel;
+}
+
+/* taken from client/bluetooth.c - bluetooth_getpacketopt */
+static int get_packet_opt(GIOChannel *io, int *tx_mtu, int *rx_mtu)
+{
+ int sk = g_io_channel_unix_get_fd(io);
+ int type;
+ int omtu = -1;
+ int imtu = -1;
+ socklen_t len = sizeof(int);
+
+ if (getsockopt(sk, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
+ return -errno;
+
+ if (type != SOCK_SEQPACKET)
+ return -EINVAL;
+
+ if (!bt_io_get(io, BT_IO_L2CAP, NULL, BT_IO_OPT_OMTU, &omtu,
+ BT_IO_OPT_IMTU, &imtu,
+ BT_IO_OPT_INVALID))
+ return -EINVAL;
+
+ if (tx_mtu)
+ *tx_mtu = omtu;
+
+ if (rx_mtu)
+ *rx_mtu = imtu;
+
+ return 0;
+}
+
+static void obex_callback(GObex *obex, GError *err, GObexPacket *rsp,
+ gpointer user_data)
+{
+ if (err != NULL) {
+ g_debug("Connect failed: %s\n", err->message);
+ g_error_free(err);
+ } else {
+ g_debug("Connect succeeded\n");
+ }
+}
+
+static void bt_io_callback(GIOChannel *io, GError *err, gpointer user_data)
+{
+ struct gobexhlp_session *session = user_data;
+ GObexTransportType type;
+ int tx_mtu = -1;
+ int rx_mtu = -1;
+
+ if (err != NULL) {
+ g_printerr("%s\n", err->message);
+ g_error_free(err);
+ return;
+ }
+
+ g_debug("Bluetooth socket connected\n");
+
+ g_io_channel_set_flags(session->io, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_channel_set_close_on_unref(session->io, TRUE);
+
+ if (get_packet_opt(session->io, &tx_mtu, &rx_mtu) == 0) {
+ type = G_OBEX_TRANSPORT_PACKET;
+ g_debug("PACKET transport tx:%d rx:%d\n", tx_mtu, rx_mtu);
+ } else {
+ type = G_OBEX_TRANSPORT_STREAM;
+ g_debug("STREAM transport\n");
+ }
+
+ session->obex = g_obex_new(io, type, tx_mtu, rx_mtu);
+ g_obex_connect(session->obex, obex_callback, session, NULL,
+ G_OBEX_HDR_TARGET, OBEX_FTP_UUID,
+ OBEX_FTP_UUID_LEN, G_OBEX_HDR_INVALID);
+}
+
+struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
+ const char *dststr)
+{
+ struct gobexhlp_session *session;
+ uint16_t channel;
+ bdaddr_t src, dst;
+
+ session = g_try_malloc0(sizeof(struct gobexhlp_session));
+ if (session == NULL)
+ return NULL;
+
+ if (srcstr == NULL)
+ bacpy(&src, BDADDR_ANY);
+ else
+ str2ba(srcstr, &src);
+
+ str2ba(dststr, &dst);
+ channel = get_ftp_channel(&src, &dst);
+
+ if (channel == 0)
+ return NULL;
+
+ if (channel > 31)
+ session->io = bt_io_connect(BT_IO_L2CAP, bt_io_callback,
+ session, NULL, &session->err,
+ BT_IO_OPT_SOURCE_BDADDR, &src,
+ BT_IO_OPT_DEST_BDADDR, &dst,
+ BT_IO_OPT_PSM, channel,
+ BT_IO_OPT_MODE, BT_IO_MODE_ERTM,
+ BT_IO_OPT_OMTU, BT_TX_MTU,
+ BT_IO_OPT_IMTU, BT_RX_MTU,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+ BT_IO_OPT_INVALID);
+ else
+ session->io = bt_io_connect(BT_IO_RFCOMM, bt_io_callback,
+ session, NULL, &session->err,
+ BT_IO_OPT_SOURCE_BDADDR, &src,
+ BT_IO_OPT_DEST_BDADDR, &dst,
+ BT_IO_OPT_CHANNEL, channel,
+ BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
+ BT_IO_OPT_INVALID);
+
+ if (session->err != NULL)
+ return NULL;
+
+ session->file_stat = g_hash_table_new_full( g_str_hash, g_str_equal,
+ g_free, g_free);
+ session->setpath = g_strdup("/");
+
+ gobexhlp_mutex = g_mutex_new();
+ gobexhlp_cond = g_cond_new();
+
+ return session;
+}
+
+void gobexhlp_disconnect(struct gobexhlp_session* session)
+{
+ if (session == NULL)
+ return;
+
+ g_obex_unref(session->obex);
+ g_free(session->io);
+
+ g_hash_table_remove_all(session->file_stat);
+ g_list_free_full(session->lsfiles, g_free);
+ g_free(session->setpath);
+
+ g_mutex_free(gobexhlp_mutex);
+ g_cond_free(gobexhlp_cond);
+
+ g_free(session);
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 142403f..29dc6cf 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -46,3 +46,7 @@ struct gobexhlp_session {
int status;
GError *err;
};
+
+struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
+ const char *dstsrc);
+void gobexhlp_disconnect(struct gobexhlp_session* session);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index fe4f4da..79eb990 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -33,6 +33,10 @@
#include "helpers.h"
+struct gobexhlp_session* session = NULL;
+static GMainLoop *main_loop;
+static GThread *main_gthread;
+
struct options {
char* dststr;
char* srcstr;
@@ -60,7 +64,34 @@ static struct fuse_opt obexfuse_opts[] =
FUSE_OPT_END
};
+gpointer main_loop_func(gpointer user_data)
+{
+ main_loop = g_main_loop_new(NULL, FALSE);
+ g_main_loop_run(main_loop);
+
+ return 0;
+}
+
+void* obexfuse_init(struct fuse_conn_info *conn)
+{
+ main_gthread = g_thread_create(main_loop_func, NULL, TRUE, NULL);
+
+ conn->async_read = 0;
+ conn->want &= ~FUSE_CAP_ASYNC_READ;
+
+ return 0;
+}
+
+void obexfuse_destroy()
+{
+ gobexhlp_disconnect(session);
+ g_main_loop_quit(main_loop);
+ g_thread_join(main_gthread);
+}
+
static struct fuse_operations obexfuse_oper = {
+ .init = obexfuse_init,
+ .destroy = obexfuse_destroy,
};
static int obexfuse_opt_proc(void *data, const char *arg, int key,
@@ -111,6 +142,15 @@ int main(int argc, char *argv[])
g_thread_init(NULL);
+ session = gobexhlp_connect(options.srcstr, options.dststr);
+ if (session == NULL || session->io == NULL) {
+ g_printerr("Connection to %s failed\n", options.dststr);
+ gobexhlp_disconnect(session);
+ return -EHOSTUNREACH;
+ } else {
+ g_print("Connected\nMounting %s\n", options.dststr);
+ }
+
fuse_opt_add_arg(&args, "-s"); /* force single threaded mode */
retfuse = fuse_main(args.argc, args.argv, &obexfuse_oper, NULL);
--
1.7.8.6
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [RFC v2 obexd 03/11] fuse: Add obexhlp_connect/disconnect functions with helpers
2012-10-28 0:29 ` [RFC v2 obexd 03/11] fuse: Add obexhlp_connect/disconnect functions with helpers Michał Poczwardowski
@ 2012-10-30 9:08 ` Luiz Augusto von Dentz
2012-11-01 22:33 ` Michał Poczwardowski
0 siblings, 1 reply; 16+ messages in thread
From: Luiz Augusto von Dentz @ 2012-10-30 9:08 UTC (permalink / raw)
To: Michał Poczwardowski; +Cc: linux-bluetooth
Hi Michal,
On Sun, Oct 28, 2012 at 2:29 AM, Michał Poczwardowski
<dmp0x7c5@gmail.com> wrote:
> ---
> fuse/helpers.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> fuse/helpers.h | 4 +
> fuse/obexfuse.c | 40 ++++++++++
> 3 files changed, 265 insertions(+), 0 deletions(-)
>
> diff --git a/fuse/helpers.c b/fuse/helpers.c
> index c36072d..856e1d5 100644
> --- a/fuse/helpers.c
> +++ b/fuse/helpers.c
> @@ -43,6 +43,9 @@
>
> #define OBEX_FTP_LS "x-obex/folder-listing"
>
> +static GCond *gobexhlp_cond;
> +static GMutex *gobexhlp_mutex;
> +
> struct gobexhlp_request {
> gchar *name;
> gboolean complete;
> @@ -52,3 +55,221 @@ struct gobexhlp_location {
> gchar *dir;
> gchar *file;
> };
> +
> +static uint16_t find_rfcomm_uuid(void *user_data)
> +{
> + sdp_list_t *pds = (sdp_list_t*) user_data;
> + uint16_t channel = 0;
> +
> + for (;pds;pds = pds->next) {
> + sdp_data_t *d = (sdp_data_t*)pds->data;
> + int proto = 0;
> + for (; d; d = d->next) {
> + switch(d->dtd) {
> + case SDP_UUID16:
> + case SDP_UUID32:
> + case SDP_UUID128:
> + proto = sdp_uuid_to_proto(&d->val.uuid);
> + break;
> + case SDP_UINT8:
> + if (proto == RFCOMM_UUID)
> + channel = d->val.int8;
> + break;
> + }
> + }
> + }
> + return channel;
> +}
> +
> +static uint16_t get_ftp_channel(bdaddr_t *src, bdaddr_t *dst)
> +{
> + sdp_session_t *sdp;
> + sdp_list_t *r, *search_list, *attrid_list;
> + sdp_list_t *response_list = NULL;
> + uuid_t uuid;
> +
> + /* FTP_SDP_UUID "00001106-0000-1000-8000-00805f9b34fb" */
> + uint8_t uuid_int[] = {0, 0, 0x11, 0x06, 0, 0, 0x10, 0, 0x80,
> + 0, 0, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
> + uint32_t range = 0x0000ffff;
> + uint16_t channel = 0;
> +
> + sdp = sdp_connect(src, dst, SDP_RETRY_IF_BUSY );
> + if (sdp == NULL)
> + return channel;
> +
> + sdp_uuid128_create(&uuid, uuid_int);
> + search_list = sdp_list_append(NULL, &uuid);
> + attrid_list = sdp_list_append(NULL, &range);
> + sdp_service_search_attr_req(sdp, search_list, SDP_ATTR_REQ_RANGE,
> + attrid_list, &response_list);
> + r = response_list;
> +
> + for (; r;r = r->next) {
> + sdp_record_t *rec = (sdp_record_t*) r->data;
> + sdp_list_t *proto_list;
> +
> + if (sdp_get_access_protos(rec, &proto_list ) == 0) {
> + sdp_list_t *p = proto_list;
> + for (; p; p = p->next) {
> + sdp_list_t *pds = (sdp_list_t*) p->data;
> + channel = find_rfcomm_uuid(pds);
> + sdp_list_free((sdp_list_t*) p->data, 0);
You dont really need to iterate in the list of protos there exist a
function that does that for you take a look at sdp_get_proto_port, btw
there exist a similar code in client/bluetooth.c
> + }
> + sdp_list_free(proto_list, 0);
> + }
> + sdp_record_free(rec);
> + }
> + sdp_close(sdp);
> +
> + g_free(search_list);
> + g_free(attrid_list);
> + g_free(response_list);
> +
> + return channel;
> +}
> +
> +/* taken from client/bluetooth.c - bluetooth_getpacketopt */
> +static int get_packet_opt(GIOChannel *io, int *tx_mtu, int *rx_mtu)
> +{
> + int sk = g_io_channel_unix_get_fd(io);
> + int type;
> + int omtu = -1;
> + int imtu = -1;
> + socklen_t len = sizeof(int);
> +
> + if (getsockopt(sk, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
> + return -errno;
> +
> + if (type != SOCK_SEQPACKET)
> + return -EINVAL;
> +
> + if (!bt_io_get(io, BT_IO_L2CAP, NULL, BT_IO_OPT_OMTU, &omtu,
> + BT_IO_OPT_IMTU, &imtu,
> + BT_IO_OPT_INVALID))
> + return -EINVAL;
> +
> + if (tx_mtu)
> + *tx_mtu = omtu;
> +
> + if (rx_mtu)
> + *rx_mtu = imtu;
> +
> + return 0;
> +}
> +
> +static void obex_callback(GObex *obex, GError *err, GObexPacket *rsp,
> + gpointer user_data)
> +{
> + if (err != NULL) {
> + g_debug("Connect failed: %s\n", err->message);
> + g_error_free(err);
> + } else {
> + g_debug("Connect succeeded\n");
> + }
> +}
> +
> +static void bt_io_callback(GIOChannel *io, GError *err, gpointer user_data)
> +{
> + struct gobexhlp_session *session = user_data;
> + GObexTransportType type;
> + int tx_mtu = -1;
> + int rx_mtu = -1;
> +
> + if (err != NULL) {
> + g_printerr("%s\n", err->message);
> + g_error_free(err);
> + return;
> + }
> +
> + g_debug("Bluetooth socket connected\n");
> +
> + g_io_channel_set_flags(session->io, G_IO_FLAG_NONBLOCK, NULL);
> + g_io_channel_set_close_on_unref(session->io, TRUE);
> +
> + if (get_packet_opt(session->io, &tx_mtu, &rx_mtu) == 0) {
> + type = G_OBEX_TRANSPORT_PACKET;
> + g_debug("PACKET transport tx:%d rx:%d\n", tx_mtu, rx_mtu);
> + } else {
> + type = G_OBEX_TRANSPORT_STREAM;
> + g_debug("STREAM transport\n");
> + }
> +
> + session->obex = g_obex_new(io, type, tx_mtu, rx_mtu);
> + g_obex_connect(session->obex, obex_callback, session, NULL,
> + G_OBEX_HDR_TARGET, OBEX_FTP_UUID,
> + OBEX_FTP_UUID_LEN, G_OBEX_HDR_INVALID);
> +}
> +
> +struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
> + const char *dststr)
> +{
> + struct gobexhlp_session *session;
> + uint16_t channel;
> + bdaddr_t src, dst;
> +
> + session = g_try_malloc0(sizeof(struct gobexhlp_session));
> + if (session == NULL)
> + return NULL;
> +
> + if (srcstr == NULL)
> + bacpy(&src, BDADDR_ANY);
> + else
> + str2ba(srcstr, &src);
> +
> + str2ba(dststr, &dst);
> + channel = get_ftp_channel(&src, &dst);
> +
> + if (channel == 0)
> + return NULL;
Currently you are not checking for L2CAP psm just RFCOMM channel so
the code bellow would never be used.
> + if (channel > 31)
> + session->io = bt_io_connect(BT_IO_L2CAP, bt_io_callback,
> + session, NULL, &session->err,
> + BT_IO_OPT_SOURCE_BDADDR, &src,
> + BT_IO_OPT_DEST_BDADDR, &dst,
> + BT_IO_OPT_PSM, channel,
> + BT_IO_OPT_MODE, BT_IO_MODE_ERTM,
> + BT_IO_OPT_OMTU, BT_TX_MTU,
> + BT_IO_OPT_IMTU, BT_RX_MTU,
> + BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
> + BT_IO_OPT_INVALID);
> + else
> + session->io = bt_io_connect(BT_IO_RFCOMM, bt_io_callback,
> + session, NULL, &session->err,
> + BT_IO_OPT_SOURCE_BDADDR, &src,
> + BT_IO_OPT_DEST_BDADDR, &dst,
> + BT_IO_OPT_CHANNEL, channel,
> + BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
> + BT_IO_OPT_INVALID);
> +
> + if (session->err != NULL)
> + return NULL;
> +
> + session->file_stat = g_hash_table_new_full( g_str_hash, g_str_equal,
> + g_free, g_free);
> + session->setpath = g_strdup("/");
> +
> + gobexhlp_mutex = g_mutex_new();
> + gobexhlp_cond = g_cond_new();
> +
> + return session;
> +}
> +
> +void gobexhlp_disconnect(struct gobexhlp_session* session)
> +{
> + if (session == NULL)
> + return;
> +
> + g_obex_unref(session->obex);
> + g_free(session->io);
> +
> + g_hash_table_remove_all(session->file_stat);
> + g_list_free_full(session->lsfiles, g_free);
> + g_free(session->setpath);
> +
> + g_mutex_free(gobexhlp_mutex);
> + g_cond_free(gobexhlp_cond);
> +
> + g_free(session);
> +}
> diff --git a/fuse/helpers.h b/fuse/helpers.h
> index 142403f..29dc6cf 100644
> --- a/fuse/helpers.h
> +++ b/fuse/helpers.h
> @@ -46,3 +46,7 @@ struct gobexhlp_session {
> int status;
> GError *err;
> };
> +
> +struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
> + const char *dstsrc);
> +void gobexhlp_disconnect(struct gobexhlp_session* session);
> diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
> index fe4f4da..79eb990 100644
> --- a/fuse/obexfuse.c
> +++ b/fuse/obexfuse.c
> @@ -33,6 +33,10 @@
>
> #include "helpers.h"
>
> +struct gobexhlp_session* session = NULL;
> +static GMainLoop *main_loop;
> +static GThread *main_gthread;
> +
> struct options {
> char* dststr;
> char* srcstr;
> @@ -60,7 +64,34 @@ static struct fuse_opt obexfuse_opts[] =
> FUSE_OPT_END
> };
>
> +gpointer main_loop_func(gpointer user_data)
> +{
> + main_loop = g_main_loop_new(NULL, FALSE);
> + g_main_loop_run(main_loop);
> +
> + return 0;
> +}
> +
> +void* obexfuse_init(struct fuse_conn_info *conn)
> +{
> + main_gthread = g_thread_create(main_loop_func, NULL, TRUE, NULL);
> +
> + conn->async_read = 0;
> + conn->want &= ~FUSE_CAP_ASYNC_READ;
> +
> + return 0;
> +}
> +
> +void obexfuse_destroy()
> +{
> + gobexhlp_disconnect(session);
> + g_main_loop_quit(main_loop);
> + g_thread_join(main_gthread);
> +}
> +
> static struct fuse_operations obexfuse_oper = {
> + .init = obexfuse_init,
> + .destroy = obexfuse_destroy,
> };
>
> static int obexfuse_opt_proc(void *data, const char *arg, int key,
> @@ -111,6 +142,15 @@ int main(int argc, char *argv[])
>
> g_thread_init(NULL);
>
I would suggest not mixing gobex prefix with your helper functions, in
fact it is probably fine to just use obexfuse e.g. obexfuse_connect.
> + session = gobexhlp_connect(options.srcstr, options.dststr);
> + if (session == NULL || session->io == NULL) {
> + g_printerr("Connection to %s failed\n", options.dststr);
> + gobexhlp_disconnect(session);
> + return -EHOSTUNREACH;
> + } else {
> + g_print("Connected\nMounting %s\n", options.dststr);
> + }
> +
> fuse_opt_add_arg(&args, "-s"); /* force single threaded mode */
> retfuse = fuse_main(args.argc, args.argv, &obexfuse_oper, NULL);
>
> --
> 1.7.8.6
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RFC v2 obexd 03/11] fuse: Add obexhlp_connect/disconnect functions with helpers
2012-10-30 9:08 ` Luiz Augusto von Dentz
@ 2012-11-01 22:33 ` Michał Poczwardowski
0 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-11-01 22:33 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
Hi Luiz,
On 30 October 2012 10:08, Luiz Augusto von Dentz <luiz.dentz@gmail.com> wrote:
> Hi Michal,
>
> On Sun, Oct 28, 2012 at 2:29 AM, Michał Poczwardowski
> <dmp0x7c5@gmail.com> wrote:
>> ---
>> fuse/helpers.c | 221 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> fuse/helpers.h | 4 +
>> fuse/obexfuse.c | 40 ++++++++++
>> 3 files changed, 265 insertions(+), 0 deletions(-)
>>
>> diff --git a/fuse/helpers.c b/fuse/helpers.c
>> index c36072d..856e1d5 100644
>> --- a/fuse/helpers.c
>> +++ b/fuse/helpers.c
>> @@ -43,6 +43,9 @@
>>
>> #define OBEX_FTP_LS "x-obex/folder-listing"
>>
>> +static GCond *gobexhlp_cond;
>> +static GMutex *gobexhlp_mutex;
>> +
>> struct gobexhlp_request {
>> gchar *name;
>> gboolean complete;
>> @@ -52,3 +55,221 @@ struct gobexhlp_location {
>> gchar *dir;
>> gchar *file;
>> };
>> +
>> +static uint16_t find_rfcomm_uuid(void *user_data)
>> +{
>> + sdp_list_t *pds = (sdp_list_t*) user_data;
>> + uint16_t channel = 0;
>> +
>> + for (;pds;pds = pds->next) {
>> + sdp_data_t *d = (sdp_data_t*)pds->data;
>> + int proto = 0;
>> + for (; d; d = d->next) {
>> + switch(d->dtd) {
>> + case SDP_UUID16:
>> + case SDP_UUID32:
>> + case SDP_UUID128:
>> + proto = sdp_uuid_to_proto(&d->val.uuid);
>> + break;
>> + case SDP_UINT8:
>> + if (proto == RFCOMM_UUID)
>> + channel = d->val.int8;
>> + break;
>> + }
>> + }
>> + }
>> + return channel;
>> +}
>> +
>> +static uint16_t get_ftp_channel(bdaddr_t *src, bdaddr_t *dst)
>> +{
>> + sdp_session_t *sdp;
>> + sdp_list_t *r, *search_list, *attrid_list;
>> + sdp_list_t *response_list = NULL;
>> + uuid_t uuid;
>> +
>> + /* FTP_SDP_UUID "00001106-0000-1000-8000-00805f9b34fb" */
>> + uint8_t uuid_int[] = {0, 0, 0x11, 0x06, 0, 0, 0x10, 0, 0x80,
>> + 0, 0, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
>> + uint32_t range = 0x0000ffff;
>> + uint16_t channel = 0;
>> +
>> + sdp = sdp_connect(src, dst, SDP_RETRY_IF_BUSY );
>> + if (sdp == NULL)
>> + return channel;
>> +
>> + sdp_uuid128_create(&uuid, uuid_int);
>> + search_list = sdp_list_append(NULL, &uuid);
>> + attrid_list = sdp_list_append(NULL, &range);
>> + sdp_service_search_attr_req(sdp, search_list, SDP_ATTR_REQ_RANGE,
>> + attrid_list, &response_list);
>> + r = response_list;
>> +
>> + for (; r;r = r->next) {
>> + sdp_record_t *rec = (sdp_record_t*) r->data;
>> + sdp_list_t *proto_list;
>> +
>> + if (sdp_get_access_protos(rec, &proto_list ) == 0) {
>> + sdp_list_t *p = proto_list;
>> + for (; p; p = p->next) {
>> + sdp_list_t *pds = (sdp_list_t*) p->data;
>> + channel = find_rfcomm_uuid(pds);
>> + sdp_list_free((sdp_list_t*) p->data, 0);
>
> You dont really need to iterate in the list of protos there exist a
> function that does that for you take a look at sdp_get_proto_port, btw
> there exist a similar code in client/bluetooth.c
>
I didn't notice sdp_get_proto_port when I was reading client/bluetooth.c code :)
>> + }
>> + sdp_list_free(proto_list, 0);
>> + }
>> + sdp_record_free(rec);
>> + }
>> + sdp_close(sdp);
>> +
>> + g_free(search_list);
>> + g_free(attrid_list);
>> + g_free(response_list);
>> +
>> + return channel;
>> +}
>> +
>> +/* taken from client/bluetooth.c - bluetooth_getpacketopt */
>> +static int get_packet_opt(GIOChannel *io, int *tx_mtu, int *rx_mtu)
>> +{
>> + int sk = g_io_channel_unix_get_fd(io);
>> + int type;
>> + int omtu = -1;
>> + int imtu = -1;
>> + socklen_t len = sizeof(int);
>> +
>> + if (getsockopt(sk, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
>> + return -errno;
>> +
>> + if (type != SOCK_SEQPACKET)
>> + return -EINVAL;
>> +
>> + if (!bt_io_get(io, BT_IO_L2CAP, NULL, BT_IO_OPT_OMTU, &omtu,
>> + BT_IO_OPT_IMTU, &imtu,
>> + BT_IO_OPT_INVALID))
>> + return -EINVAL;
>> +
>> + if (tx_mtu)
>> + *tx_mtu = omtu;
>> +
>> + if (rx_mtu)
>> + *rx_mtu = imtu;
>> +
>> + return 0;
>> +}
>> +
>> +static void obex_callback(GObex *obex, GError *err, GObexPacket *rsp,
>> + gpointer user_data)
>> +{
>> + if (err != NULL) {
>> + g_debug("Connect failed: %s\n", err->message);
>> + g_error_free(err);
>> + } else {
>> + g_debug("Connect succeeded\n");
>> + }
>> +}
>> +
>> +static void bt_io_callback(GIOChannel *io, GError *err, gpointer user_data)
>> +{
>> + struct gobexhlp_session *session = user_data;
>> + GObexTransportType type;
>> + int tx_mtu = -1;
>> + int rx_mtu = -1;
>> +
>> + if (err != NULL) {
>> + g_printerr("%s\n", err->message);
>> + g_error_free(err);
>> + return;
>> + }
>> +
>> + g_debug("Bluetooth socket connected\n");
>> +
>> + g_io_channel_set_flags(session->io, G_IO_FLAG_NONBLOCK, NULL);
>> + g_io_channel_set_close_on_unref(session->io, TRUE);
>> +
>> + if (get_packet_opt(session->io, &tx_mtu, &rx_mtu) == 0) {
>> + type = G_OBEX_TRANSPORT_PACKET;
>> + g_debug("PACKET transport tx:%d rx:%d\n", tx_mtu, rx_mtu);
>> + } else {
>> + type = G_OBEX_TRANSPORT_STREAM;
>> + g_debug("STREAM transport\n");
>> + }
>> +
>> + session->obex = g_obex_new(io, type, tx_mtu, rx_mtu);
>> + g_obex_connect(session->obex, obex_callback, session, NULL,
>> + G_OBEX_HDR_TARGET, OBEX_FTP_UUID,
>> + OBEX_FTP_UUID_LEN, G_OBEX_HDR_INVALID);
>> +}
>> +
>> +struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
>> + const char *dststr)
>> +{
>> + struct gobexhlp_session *session;
>> + uint16_t channel;
>> + bdaddr_t src, dst;
>> +
>> + session = g_try_malloc0(sizeof(struct gobexhlp_session));
>> + if (session == NULL)
>> + return NULL;
>> +
>> + if (srcstr == NULL)
>> + bacpy(&src, BDADDR_ANY);
>> + else
>> + str2ba(srcstr, &src);
>> +
>> + str2ba(dststr, &dst);
>> + channel = get_ftp_channel(&src, &dst);
>> +
>> + if (channel == 0)
>> + return NULL;
>
> Currently you are not checking for L2CAP psm just RFCOMM channel so
> the code bellow would never be used.
>
In client/bluetooth.c these lines (in search_callback):
data = sdp_data_get(rec, 0x0200);
/* PSM must be odd and lsb of upper byte must be 0 */
if (data != NULL && (data->val.uint16 & 0x0101) == 0x0001)
ch = data->val.uint16;
Are responsible for L2CAP psm, right?
>> + if (channel > 31)
>> + session->io = bt_io_connect(BT_IO_L2CAP, bt_io_callback,
>> + session, NULL, &session->err,
>> + BT_IO_OPT_SOURCE_BDADDR, &src,
>> + BT_IO_OPT_DEST_BDADDR, &dst,
>> + BT_IO_OPT_PSM, channel,
>> + BT_IO_OPT_MODE, BT_IO_MODE_ERTM,
>> + BT_IO_OPT_OMTU, BT_TX_MTU,
>> + BT_IO_OPT_IMTU, BT_RX_MTU,
>> + BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
>> + BT_IO_OPT_INVALID);
>> + else
>> + session->io = bt_io_connect(BT_IO_RFCOMM, bt_io_callback,
>> + session, NULL, &session->err,
>> + BT_IO_OPT_SOURCE_BDADDR, &src,
>> + BT_IO_OPT_DEST_BDADDR, &dst,
>> + BT_IO_OPT_CHANNEL, channel,
>> + BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_LOW,
>> + BT_IO_OPT_INVALID);
>> +
>> + if (session->err != NULL)
>> + return NULL;
>> +
>> + session->file_stat = g_hash_table_new_full( g_str_hash, g_str_equal,
>> + g_free, g_free);
>> + session->setpath = g_strdup("/");
>> +
>> + gobexhlp_mutex = g_mutex_new();
>> + gobexhlp_cond = g_cond_new();
>> +
>> + return session;
>> +}
>> +
>> +void gobexhlp_disconnect(struct gobexhlp_session* session)
>> +{
>> + if (session == NULL)
>> + return;
>> +
>> + g_obex_unref(session->obex);
>> + g_free(session->io);
>> +
>> + g_hash_table_remove_all(session->file_stat);
>> + g_list_free_full(session->lsfiles, g_free);
>> + g_free(session->setpath);
>> +
>> + g_mutex_free(gobexhlp_mutex);
>> + g_cond_free(gobexhlp_cond);
>> +
>> + g_free(session);
>> +}
>> diff --git a/fuse/helpers.h b/fuse/helpers.h
>> index 142403f..29dc6cf 100644
>> --- a/fuse/helpers.h
>> +++ b/fuse/helpers.h
>> @@ -46,3 +46,7 @@ struct gobexhlp_session {
>> int status;
>> GError *err;
>> };
>> +
>> +struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
>> + const char *dstsrc);
>> +void gobexhlp_disconnect(struct gobexhlp_session* session);
>> diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
>> index fe4f4da..79eb990 100644
>> --- a/fuse/obexfuse.c
>> +++ b/fuse/obexfuse.c
>> @@ -33,6 +33,10 @@
>>
>> #include "helpers.h"
>>
>> +struct gobexhlp_session* session = NULL;
>> +static GMainLoop *main_loop;
>> +static GThread *main_gthread;
>> +
>> struct options {
>> char* dststr;
>> char* srcstr;
>> @@ -60,7 +64,34 @@ static struct fuse_opt obexfuse_opts[] =
>> FUSE_OPT_END
>> };
>>
>> +gpointer main_loop_func(gpointer user_data)
>> +{
>> + main_loop = g_main_loop_new(NULL, FALSE);
>> + g_main_loop_run(main_loop);
>> +
>> + return 0;
>> +}
>> +
>> +void* obexfuse_init(struct fuse_conn_info *conn)
>> +{
>> + main_gthread = g_thread_create(main_loop_func, NULL, TRUE, NULL);
>> +
>> + conn->async_read = 0;
>> + conn->want &= ~FUSE_CAP_ASYNC_READ;
>> +
>> + return 0;
>> +}
>> +
>> +void obexfuse_destroy()
>> +{
>> + gobexhlp_disconnect(session);
>> + g_main_loop_quit(main_loop);
>> + g_thread_join(main_gthread);
>> +}
>> +
>> static struct fuse_operations obexfuse_oper = {
>> + .init = obexfuse_init,
>> + .destroy = obexfuse_destroy,
>> };
>>
>> static int obexfuse_opt_proc(void *data, const char *arg, int key,
>> @@ -111,6 +142,15 @@ int main(int argc, char *argv[])
>>
>> g_thread_init(NULL);
>>
>
> I would suggest not mixing gobex prefix with your helper functions, in
> fact it is probably fine to just use obexfuse e.g. obexfuse_connect.
>
Right, when I was removing 'g' from gobexfuse I forgot to change
gobexhlp to obexhlp.
I'll send RFC v3 after LinuxCon :)
>> + session = gobexhlp_connect(options.srcstr, options.dststr);
>> + if (session == NULL || session->io == NULL) {
>> + g_printerr("Connection to %s failed\n", options.dststr);
>> + gobexhlp_disconnect(session);
>> + return -EHOSTUNREACH;
>> + } else {
>> + g_print("Connected\nMounting %s\n", options.dststr);
>> + }
>> +
>> fuse_opt_add_arg(&args, "-s"); /* force single threaded mode */
>> retfuse = fuse_main(args.argc, args.argv, &obexfuse_oper, NULL);
>>
>> --
>> 1.7.8.6
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>
>
> --
> Luiz Augusto von Dentz
Thanks,
Michal
^ permalink raw reply [flat|nested] 16+ messages in thread
* [RFC v2 obexd 04/11] fuse: Add request helpers and setpath operation
2012-10-28 0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
2012-10-28 0:29 ` [RFC v2 obexd 02/11] build: Add --enable-fuse for obexfuse Michał Poczwardowski
2012-10-28 0:29 ` [RFC v2 obexd 03/11] fuse: Add obexhlp_connect/disconnect functions with helpers Michał Poczwardowski
@ 2012-10-28 0:29 ` Michał Poczwardowski
2012-10-30 9:35 ` Luiz Augusto von Dentz
2012-10-28 0:29 ` [RFC v2 obexd 05/11] fuse: Add readdir operation Michał Poczwardowski
` (6 subsequent siblings)
9 siblings, 1 reply; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
---
fuse/helpers.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 108 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index 856e1d5..1b8082f 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -273,3 +273,111 @@ void gobexhlp_disconnect(struct gobexhlp_session* session)
g_free(session);
}
+
+void request_new(struct gobexhlp_session *session,
+ gchar *name)
+{
+ g_print("REQUEST %s\n", name);
+
+ if (session->request != NULL)
+ g_error("Another request (%s) active!\n",
+ session->request->name);
+
+ session->status = 0;
+ session->request = g_malloc0(sizeof(struct gobexhlp_request));
+ session->request->name = name;
+
+ /*
+ * suspend/resume operations recreates g_io_add_watch(),
+ * it fixes obex->io freeze during transfer
+ */
+ g_obex_suspend(session->obex);
+ g_obex_resume(session->obex);
+}
+
+void request_wait_free(struct gobexhlp_session *session)
+{
+ g_print("WAIT for %s\n", session->request->name);
+
+ g_obex_suspend(session->obex);
+ g_obex_resume(session->obex);
+
+ if (session->err != NULL) {
+ g_print("ERROR: %s (%d)\n", session->err->message,
+ session->err->code);
+ g_error_free(session->err);
+ raise(SIGTERM);
+ return;
+ }
+
+ g_mutex_lock(gobexhlp_mutex);
+
+ while (session->request->complete != TRUE)
+ g_cond_wait(gobexhlp_cond, gobexhlp_mutex);
+
+ g_mutex_unlock(gobexhlp_mutex);
+
+ g_free(session->request->name);
+ g_free(session->request);
+ session->request = NULL;
+}
+
+static void complete_func(GObex *obex, GError *err,
+ gpointer user_data)
+{
+ struct gobexhlp_session *session = user_data;
+
+ if (err != NULL) {
+ g_print("ERROR: %s\n", err->message);
+ session->status = -ECANCELED;
+ g_error_free(err);
+ } else {
+ g_print("COMPLETE %s\n", session->request->name);
+ }
+
+ g_mutex_lock(gobexhlp_mutex);
+ session->request->complete = TRUE;
+ g_cond_signal(gobexhlp_cond);
+ g_mutex_unlock(gobexhlp_mutex);
+}
+
+static void response_func(GObex *obex, GError *err, GObexPacket *rsp,
+ gpointer user_data)
+{
+ complete_func(obex, err, user_data);
+}
+
+void gobexhlp_setpath(struct gobexhlp_session *session, const char *path)
+{
+ guint i = 0, split = 0;
+ gchar **path_v;
+ gsize len;
+
+ g_print("gobexhlp_setpath(%s)\n", path);
+
+ if (g_str_has_prefix(path, session->setpath)) {
+ split = strlen(session->setpath);
+ } else {
+ request_new(session, g_strdup_printf("setpath root"));
+ g_obex_setpath(session->obex, "", response_func,
+ session, &session->err);
+ request_wait_free(session);
+ }
+
+ path_v = g_strsplit(path+split, "/", -1);
+ len = g_strv_length(path_v);
+
+ for (i = 0; i < len; i++)
+ if (path_v[i][0] != '\0') {
+ request_new(session,
+ g_strdup_printf("setpath %s", path_v[i]));
+ g_obex_setpath(session->obex, path_v[i],
+ response_func, session, &session->err);
+ request_wait_free(session);
+ }
+
+ g_free(session->setpath);
+ session->setpath = g_strdup(path);
+
+ g_strfreev(path_v);
+}
--
1.7.8.6
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [RFC v2 obexd 04/11] fuse: Add request helpers and setpath operation
2012-10-28 0:29 ` [RFC v2 obexd 04/11] fuse: Add request helpers and setpath operation Michał Poczwardowski
@ 2012-10-30 9:35 ` Luiz Augusto von Dentz
2012-11-01 21:59 ` Michał Poczwardowski
0 siblings, 1 reply; 16+ messages in thread
From: Luiz Augusto von Dentz @ 2012-10-30 9:35 UTC (permalink / raw)
To: Michał Poczwardowski; +Cc: linux-bluetooth
Hi Michal,
On Sun, Oct 28, 2012 at 2:29 AM, Michał Poczwardowski
<dmp0x7c5@gmail.com> wrote:
> ---
> fuse/helpers.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 108 insertions(+), 0 deletions(-)
>
> diff --git a/fuse/helpers.c b/fuse/helpers.c
> index 856e1d5..1b8082f 100644
> --- a/fuse/helpers.c
> +++ b/fuse/helpers.c
> @@ -273,3 +273,111 @@ void gobexhlp_disconnect(struct gobexhlp_session* session)
>
> g_free(session);
> }
> +
> +void request_new(struct gobexhlp_session *session,
> + gchar *name)
> +{
> + g_print("REQUEST %s\n", name);
> +
> + if (session->request != NULL)
> + g_error("Another request (%s) active!\n",
> + session->request->name);
> +
> + session->status = 0;
> + session->request = g_malloc0(sizeof(struct gobexhlp_request));
> + session->request->name = name;
> +
> + /*
> + * suspend/resume operations recreates g_io_add_watch(),
> + * it fixes obex->io freeze during transfer
> + */
> + g_obex_suspend(session->obex);
> + g_obex_resume(session->obex);
It seems the issue here is that the mainloop is blocked then you have
to force the io checking by doing g_io_add_watch in a different
thread, we have dealt with this kind of problem before using
g_main_context_iteration. I would have been better if fuse supported
async io, but apparently all operations are blocking.
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RFC v2 obexd 04/11] fuse: Add request helpers and setpath operation
2012-10-30 9:35 ` Luiz Augusto von Dentz
@ 2012-11-01 21:59 ` Michał Poczwardowski
2012-11-20 17:52 ` Michał Poczwardowski
0 siblings, 1 reply; 16+ messages in thread
From: Michał Poczwardowski @ 2012-11-01 21:59 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
Hi Luiz,
On 30 October 2012 10:35, Luiz Augusto von Dentz <luiz.dentz@gmail.com> wrote:
> Hi Michal,
>
> On Sun, Oct 28, 2012 at 2:29 AM, Michał Poczwardowski
> <dmp0x7c5@gmail.com> wrote:
>> ---
>> fuse/helpers.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> 1 files changed, 108 insertions(+), 0 deletions(-)
>>
>> diff --git a/fuse/helpers.c b/fuse/helpers.c
>> index 856e1d5..1b8082f 100644
>> --- a/fuse/helpers.c
>> +++ b/fuse/helpers.c
>> @@ -273,3 +273,111 @@ void gobexhlp_disconnect(struct gobexhlp_session* session)
>>
>> g_free(session);
>> }
>> +
>> +void request_new(struct gobexhlp_session *session,
>> + gchar *name)
>> +{
>> + g_print("REQUEST %s\n", name);
>> +
>> + if (session->request != NULL)
>> + g_error("Another request (%s) active!\n",
>> + session->request->name);
>> +
>> + session->status = 0;
>> + session->request = g_malloc0(sizeof(struct gobexhlp_request));
>> + session->request->name = name;
>> +
>> + /*
>> + * suspend/resume operations recreates g_io_add_watch(),
>> + * it fixes obex->io freeze during transfer
>> + */
>> + g_obex_suspend(session->obex);
>> + g_obex_resume(session->obex);
>
> It seems the issue here is that the mainloop is blocked then you have
> to force the io checking by doing g_io_add_watch in a different
> thread, we have dealt with this kind of problem before using
> g_main_context_iteration. I would have been better if fuse supported
> async io, but apparently all operations are blocking.
>
> --
> Luiz Augusto von Dentz
I'll try g_main_context_iteration way to avoid the io freeze.
Unfortunately fuse with obex should use blocking operations.
Thanks,
Michal
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RFC v2 obexd 04/11] fuse: Add request helpers and setpath operation
2012-11-01 21:59 ` Michał Poczwardowski
@ 2012-11-20 17:52 ` Michał Poczwardowski
0 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-11-20 17:52 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
Hi Luiz,
Sorry for delay - I was a little overwhelmed by university stuff. I've
just replaced suspend/resume with g_main_context_iteration() but
unfortunately it doesn't work in this case.
Regarding requests queue - fuse handles it, also in single threaded mode :)
On 1 November 2012 22:59, Michał Poczwardowski <dmp0x7c5@gmail.com> wrote:
> Hi Luiz,
>
> On 30 October 2012 10:35, Luiz Augusto von Dentz <luiz.dentz@gmail.com> wrote:
>> Hi Michal,
>>
>> On Sun, Oct 28, 2012 at 2:29 AM, Michał Poczwardowski
>> <dmp0x7c5@gmail.com> wrote:
>>> ---
>>> fuse/helpers.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>> 1 files changed, 108 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/fuse/helpers.c b/fuse/helpers.c
>>> index 856e1d5..1b8082f 100644
>>> --- a/fuse/helpers.c
>>> +++ b/fuse/helpers.c
>>> @@ -273,3 +273,111 @@ void gobexhlp_disconnect(struct gobexhlp_session* session)
>>>
>>> g_free(session);
>>> }
>>> +
>>> +void request_new(struct gobexhlp_session *session,
>>> + gchar *name)
>>> +{
>>> + g_print("REQUEST %s\n", name);
>>> +
>>> + if (session->request != NULL)
>>> + g_error("Another request (%s) active!\n",
>>> + session->request->name);
>>> +
>>> + session->status = 0;
>>> + session->request = g_malloc0(sizeof(struct gobexhlp_request));
>>> + session->request->name = name;
>>> +
>>> + /*
>>> + * suspend/resume operations recreates g_io_add_watch(),
>>> + * it fixes obex->io freeze during transfer
>>> + */
>>> + g_obex_suspend(session->obex);
>>> + g_obex_resume(session->obex);
>>
>> It seems the issue here is that the mainloop is blocked then you have
>> to force the io checking by doing g_io_add_watch in a different
>> thread, we have dealt with this kind of problem before using
>> g_main_context_iteration. I would have been better if fuse supported
>> async io, but apparently all operations are blocking.
>>
>> --
>> Luiz Augusto von Dentz
>
> I'll try g_main_context_iteration way to avoid the io freeze.
> Unfortunately fuse with obex should use blocking operations.
>
> Thanks,
> Michal
^ permalink raw reply [flat|nested] 16+ messages in thread
* [RFC v2 obexd 05/11] fuse: Add readdir operation
2012-10-28 0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
` (2 preceding siblings ...)
2012-10-28 0:29 ` [RFC v2 obexd 04/11] fuse: Add request helpers and setpath operation Michał Poczwardowski
@ 2012-10-28 0:29 ` Michał Poczwardowski
2012-10-28 0:29 ` [RFC v2 obexd 06/11] fuse: Add getattr operation Michał Poczwardowski
` (5 subsequent siblings)
9 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
---
fuse/helpers.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
fuse/helpers.h | 2 +
fuse/obexfuse.c | 23 ++++++++++
3 files changed, 153 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index 1b8082f..cb0b51d 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -381,3 +381,131 @@ void gobexhlp_setpath(struct gobexhlp_session *session, const char *path)
g_strfreev(path_v);
}
+
+static void listfolder_xml_element(GMarkupParseContext *ctxt,
+ const gchar *element, const gchar **names,
+ const gchar **values, gpointer user_data,
+ GError **gerr)
+{
+ gchar *key, *pathname, *name = NULL;
+ struct gobexhlp_session *session = user_data;
+ struct stat *stbuf;
+ gint i = 0;
+
+ stbuf = g_malloc0(sizeof(struct stat));
+
+ if ((strcasecmp("file", element) == 0)) {
+ stbuf->st_mode = S_IFREG;
+ } else if ((strcasecmp("folder", element)) == 0) {
+ stbuf->st_mode = S_IFDIR;
+ stbuf->st_mtime = time(NULL);
+ } else {
+ g_free(stbuf);
+ return;
+ }
+
+ for (key = (gchar *) names[i]; key; key = (gchar *) names[++i]) {
+ if (g_str_equal("name", key) == TRUE) {
+ session->lsfiles = g_list_append(session->lsfiles,
+ g_strdup(values[i]));
+ name = g_strdup(values[i]);
+
+ } else if (g_str_equal("size", key) == TRUE) {
+ guint64 size;
+ size = g_ascii_strtoll(values[i], NULL, 10);
+ stbuf->st_size = size;
+
+ } else if (g_str_equal("created", key) == TRUE) {
+ GTimeVal time;
+ GDateTime *datetime;
+ g_time_val_from_iso8601(values[i], &time);
+ datetime = g_date_time_new_from_timeval_utc(&time);
+ stbuf->st_mtime = g_date_time_to_unix(datetime);
+ }
+ }
+
+ if (g_str_equal("/", session->setpath) == TRUE)
+ pathname = g_strdup_printf("/%s", name);
+ else
+ pathname = g_strdup_printf("%s/%s", session->setpath, name);
+
+ g_hash_table_replace(session->file_stat, pathname, stbuf);
+ g_free(name);
+}
+
+static const GMarkupParser parser = {
+ listfolder_xml_element,
+ NULL, NULL, NULL, NULL
+};
+
+static void complete_listfolder_func(GObex *obex, GError *err,
+ gpointer user_data)
+{
+ GMarkupParseContext *ctxt;
+ struct gobexhlp_session *session = user_data;
+ struct gobexhlp_buffer *buffer = session->buffer;
+
+ if (err == NULL) {
+ ctxt = g_markup_parse_context_new(&parser, 0, session, NULL);
+ g_markup_parse_context_parse(ctxt, buffer->data, buffer->size,
+ NULL);
+ g_markup_parse_context_free(ctxt);
+ }
+
+ complete_func(obex, err, user_data);
+}
+
+static gboolean async_get_consumer(const void *buf, gsize len,
+ gpointer user_data)
+{
+ struct gobexhlp_session *session = user_data;
+ struct gobexhlp_buffer *buffer = session->buffer;
+
+ if (buffer->size == 0)
+ buffer->data = g_malloc0(sizeof(char) * len);
+ else
+ buffer->data = g_realloc(buffer->data, buffer->size + len);
+
+ memcpy(buffer->data + buffer->size, buf, len);
+ buffer->size += len;
+
+ g_obex_suspend(session->obex);
+ g_obex_resume(session->obex);
+
+ return TRUE;
+}
+
+GList *gobexhlp_listfolder(struct gobexhlp_session* session,
+ const char *path)
+{
+ struct gobexhlp_buffer *buffer;
+ GObexPacket *req;
+ guint reqpkt;
+
+ gobexhlp_setpath(session, path);
+
+ g_print("gobexhlp_listfolder(%s)\n", path);
+
+ if (session->lsfiles != NULL) {
+ g_list_free_full(session->lsfiles, g_free);
+ session->lsfiles = NULL;
+ }
+
+ session->lsfiles = g_list_alloc();
+ buffer = g_malloc0(sizeof(struct gobexhlp_buffer));
+ session->buffer = buffer;
+
+ request_new(session, g_strdup_printf("listfolder %s", path));
+ req = g_obex_packet_new(G_OBEX_OP_GET, TRUE, G_OBEX_HDR_INVALID);
+ g_obex_packet_add_bytes(req, G_OBEX_HDR_TYPE, OBEX_FTP_LS,
+ strlen(OBEX_FTP_LS) + 1);
+ reqpkt = g_obex_get_req_pkt(session->obex, req,
+ async_get_consumer,
+ complete_listfolder_func,
+ session, &session->err);
+ request_wait_free(session);
+ g_free(buffer->data);
+ g_free(buffer);
+
+ return session->lsfiles;
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 29dc6cf..546d79c 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -50,3 +50,5 @@ struct gobexhlp_session {
struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
const char *dstsrc);
void gobexhlp_disconnect(struct gobexhlp_session* session);
+
+GList *gobexhlp_listfolder(struct gobexhlp_session* session, const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index 79eb990..5de82ec 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -89,7 +89,30 @@ void obexfuse_destroy()
g_thread_join(main_gthread);
}
+static int obexfuse_readdir(const char *path, void *buf,
+ fuse_fill_dir_t filler, off_t offset,
+ struct fuse_file_info *fi)
+{
+ int len, i;
+ gchar *string;
+ GList *files;
+
+ filler(buf, ".", NULL, 0);
+ filler(buf, "..", NULL, 0);
+
+ files = gobexhlp_listfolder(session, path);
+ len = g_list_length(files);
+
+ for (i = 1; i < len; i++) { /* element for i==0 is NULL */
+ string = g_list_nth_data(files, i);
+ filler(buf, string, NULL, 0);
+ }
+
+ return session->status;
+}
+
static struct fuse_operations obexfuse_oper = {
+ .readdir = obexfuse_readdir,
.init = obexfuse_init,
.destroy = obexfuse_destroy,
};
--
1.7.8.6
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [RFC v2 obexd 06/11] fuse: Add getattr operation
2012-10-28 0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
` (3 preceding siblings ...)
2012-10-28 0:29 ` [RFC v2 obexd 05/11] fuse: Add readdir operation Michał Poczwardowski
@ 2012-10-28 0:29 ` Michał Poczwardowski
2012-10-28 0:29 ` [RFC v2 obexd 07/11] fuse: Add open and read operations plus location helpers Michał Poczwardowski
` (4 subsequent siblings)
9 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
---
fuse/helpers.c | 6 ++++++
fuse/helpers.h | 2 ++
fuse/obexfuse.c | 34 ++++++++++++++++++++++++++++++++++
3 files changed, 42 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index cb0b51d..a10b706 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -509,3 +509,9 @@ GList *gobexhlp_listfolder(struct gobexhlp_session* session,
return session->lsfiles;
}
+
+struct stat *gobexhlp_getattr(struct gobexhlp_session* session,
+ const char *path)
+{
+ return g_hash_table_lookup(session->file_stat, path);
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 546d79c..047abae 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -52,3 +52,5 @@ struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
void gobexhlp_disconnect(struct gobexhlp_session* session);
GList *gobexhlp_listfolder(struct gobexhlp_session* session, const char *path);
+struct stat *gobexhlp_getattr(struct gobexhlp_session* session,
+ const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index 5de82ec..f4e85fa 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -111,8 +111,42 @@ static int obexfuse_readdir(const char *path, void *buf,
return session->status;
}
+static int obexfuse_getattr(const char *path, struct stat *stbuf)
+{
+ int res = 0;
+ struct stat *stfile;
+
+ memset(stbuf, 0, sizeof(struct stat));
+
+ if (strcmp(path, "/") == 0) {
+ stbuf->st_mode = S_IFDIR | 0755;
+ stbuf->st_nlink = 2;
+ } else {
+ stfile = gobexhlp_getattr(session, path);
+
+ if (stfile == NULL)
+ return -ENOENT;
+
+ if (stfile->st_mode == S_IFREG)
+ stbuf->st_mode = stfile->st_mode | 0666;
+ else /* S_IFDIR */
+ stbuf->st_mode = stfile->st_mode | 0755;
+
+ stbuf->st_nlink = 1;
+ stbuf->st_size = stfile->st_size;
+ stbuf->st_mtime = stbuf->st_atime = stbuf->st_ctime =
+ stfile->st_mtime;
+ stbuf->st_blksize = 512;
+ stbuf->st_blocks = (stbuf->st_size + stbuf->st_blksize)
+ / stbuf->st_blksize;
+ }
+
+ return res;
+}
+
static struct fuse_operations obexfuse_oper = {
.readdir = obexfuse_readdir,
+ .getattr = obexfuse_getattr,
.init = obexfuse_init,
.destroy = obexfuse_destroy,
};
--
1.7.8.6
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [RFC v2 obexd 07/11] fuse: Add open and read operations plus location helpers
2012-10-28 0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
` (4 preceding siblings ...)
2012-10-28 0:29 ` [RFC v2 obexd 06/11] fuse: Add getattr operation Michał Poczwardowski
@ 2012-10-28 0:29 ` Michał Poczwardowski
2012-10-28 0:29 ` [RFC v2 obexd 08/11] fuse: Add write operation Michał Poczwardowski
` (3 subsequent siblings)
9 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
---
fuse/helpers.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
fuse/helpers.h | 2 +
fuse/obexfuse.c | 32 ++++++++++++++++++++++++++++
3 files changed, 96 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index a10b706..9b453e0 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -515,3 +515,65 @@ struct stat *gobexhlp_getattr(struct gobexhlp_session* session,
{
return g_hash_table_lookup(session->file_stat, path);
}
+
+static struct gobexhlp_location *get_location(const char *path)
+{
+ struct gobexhlp_location *location;
+ gchar **directories;
+ guint i, len, fid = 0;
+
+ location = g_malloc0(sizeof(*location));
+ directories = g_strsplit(path, "/", -1);
+ len = g_strv_length(directories);
+
+ for (i = 0; i < len; i++)
+ if (directories[i][0] != '\0') /* protect multi slashes */
+ fid = i; /* last nonempty is a file */
+
+ location->file = g_strdup(directories[fid]);
+ directories[fid][0] = '\0'; /* remove file */
+ location->dir = g_strjoinv("/", directories);
+
+ g_strfreev(directories);
+
+ return location;
+}
+
+void free_location(struct gobexhlp_location *location)
+{
+ g_free(location->file);
+ g_free(location->dir);
+ g_free(location);
+}
+
+struct gobexhlp_buffer *gobexhlp_get(struct gobexhlp_session* session,
+ const char *path)
+{
+ struct gobexhlp_location *l;
+ struct gobexhlp_buffer *buffer;
+ struct stat *stfile;
+ l = get_location(path);
+
+ g_print("gobexhlp_get(%s%s)\n", l->dir, l->file);
+
+ stfile = gobexhlp_getattr(session, path);
+ if (stfile == NULL)
+ return NULL;
+
+ buffer = g_malloc0(sizeof(*buffer));
+
+ if (stfile->st_size == 0)
+ return buffer;
+
+ gobexhlp_setpath(session, l->dir);
+ request_new(session, g_strdup_printf("get %s", path));
+ session->buffer = buffer;
+ g_obex_get_req(session->obex, async_get_consumer,
+ complete_func, session, &session->err,
+ G_OBEX_HDR_NAME, l->file,
+ G_OBEX_HDR_INVALID);
+ free_location(l);
+ request_wait_free(session);
+
+ return buffer;
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 047abae..aa2a194 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -54,3 +54,5 @@ void gobexhlp_disconnect(struct gobexhlp_session* session);
GList *gobexhlp_listfolder(struct gobexhlp_session* session, const char *path);
struct stat *gobexhlp_getattr(struct gobexhlp_session* session,
const char *path);
+struct gobexhlp_buffer *gobexhlp_get(struct gobexhlp_session* session,
+ const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index f4e85fa..9fe2dea 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -144,9 +144,41 @@ static int obexfuse_getattr(const char *path, struct stat *stbuf)
return res;
}
+static int obexfuse_open(const char *path, struct fuse_file_info *fi)
+{
+ struct gobexhlp_buffer *file_buffer;
+
+ file_buffer = gobexhlp_get(session, path);
+
+ if (file_buffer == NULL)
+ return -ENOENT;
+
+ fi->fh = (uint64_t)file_buffer;
+
+ return session->status;
+}
+
+static int obexfuse_read(const char *path, char *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+{
+ gsize asize;
+ struct gobexhlp_buffer *file_buffer = (struct gobexhlp_buffer*)fi->fh;
+
+ asize = file_buffer->size - offset;
+
+ if (asize > size)
+ asize = size;
+
+ memcpy(buf, file_buffer->data + offset, asize);
+
+ return asize;
+}
+
static struct fuse_operations obexfuse_oper = {
.readdir = obexfuse_readdir,
.getattr = obexfuse_getattr,
+ .open = obexfuse_open,
+ .read = obexfuse_read,
.init = obexfuse_init,
.destroy = obexfuse_destroy,
};
--
1.7.8.6
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [RFC v2 obexd 08/11] fuse: Add write operation
2012-10-28 0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
` (5 preceding siblings ...)
2012-10-28 0:29 ` [RFC v2 obexd 07/11] fuse: Add open and read operations plus location helpers Michał Poczwardowski
@ 2012-10-28 0:29 ` Michał Poczwardowski
2012-10-28 0:29 ` [RFC v2 obexd 09/11] fuse: Add touch operation Michał Poczwardowski
` (2 subsequent siblings)
9 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
---
fuse/helpers.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
fuse/helpers.h | 3 +++
fuse/obexfuse.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 91 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index 9b453e0..796c4a3 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -577,3 +577,47 @@ struct gobexhlp_buffer *gobexhlp_get(struct gobexhlp_session* session,
return buffer;
}
+
+static gssize async_put_producer(void *buf, gsize len, gpointer user_data)
+{
+ gssize size;
+ struct gobexhlp_session *session = user_data;
+ struct gobexhlp_buffer *buffer = session->buffer;
+
+ size = buffer->size - buffer->tmpsize;
+
+ if (size > len)
+ size = len;
+
+ g_obex_suspend(session->obex);
+ g_obex_resume(session->obex);
+
+ if (size == 0)
+ return 0;
+
+ memcpy(buf, buffer->data + buffer->tmpsize, size);
+ buffer->tmpsize += size;
+
+ return size;
+}
+
+void gobexhlp_put(struct gobexhlp_session* session,
+ struct gobexhlp_buffer *buffer,
+ const char *path)
+{
+ struct gobexhlp_location *l;
+ l = get_location(path);
+
+ g_print("gobexhlp_put(%s%s)\n", l->dir, l->file);
+
+ gobexhlp_setpath(session, l->dir);
+ buffer->tmpsize = 0;
+ session->buffer = buffer;
+ request_new(session, g_strdup_printf("put %s", path));
+ g_obex_put_req(session->obex, async_put_producer,
+ complete_func, session, &session->err,
+ G_OBEX_HDR_NAME, l->file,
+ G_OBEX_HDR_INVALID);
+ free_location(l);
+ request_wait_free(session);
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index aa2a194..1eca29d 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -56,3 +56,6 @@ struct stat *gobexhlp_getattr(struct gobexhlp_session* session,
const char *path);
struct gobexhlp_buffer *gobexhlp_get(struct gobexhlp_session* session,
const char *path);
+void gobexhlp_put(struct gobexhlp_session* session,
+ struct gobexhlp_buffer *buffer,
+ const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index 9fe2dea..900e6d7 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -174,11 +174,55 @@ static int obexfuse_read(const char *path, char *buf, size_t size,
return asize;
}
+static int obexfuse_write(const char *path, const char *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+{
+ gsize nsize;
+ struct gobexhlp_buffer *file_buffer = (struct gobexhlp_buffer*)fi->fh;
+
+ if (file_buffer->size < offset + size) {
+ nsize = offset + size;
+ file_buffer->data = g_realloc(file_buffer->data, nsize);
+ file_buffer->size = nsize;
+ } else {
+ nsize = file_buffer->size;
+ }
+
+ file_buffer->edited = TRUE;
+ memcpy(file_buffer->data + offset, buf, size);
+
+ return size;
+}
+
+static int obexfuse_truncate(const char *path, off_t offset)
+{
+ /*
+ * Allow to change the size of a file.
+ */
+ return 0;
+}
+
+static int obexfuse_release(const char *path, struct fuse_file_info *fi)
+{
+ struct gobexhlp_buffer *file_buffer = (struct gobexhlp_buffer*)fi->fh;
+
+ if (file_buffer->edited == TRUE)
+ gobexhlp_put(session, file_buffer, path); /* send to device */
+
+ g_free(file_buffer->data);
+ g_free(file_buffer);
+
+ return session->status;
+}
+
static struct fuse_operations obexfuse_oper = {
.readdir = obexfuse_readdir,
.getattr = obexfuse_getattr,
.open = obexfuse_open,
.read = obexfuse_read,
+ .write = obexfuse_write,
+ .truncate = obexfuse_truncate,
+ .release = obexfuse_release,
.init = obexfuse_init,
.destroy = obexfuse_destroy,
};
--
1.7.8.6
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [RFC v2 obexd 09/11] fuse: Add touch operation
2012-10-28 0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
` (6 preceding siblings ...)
2012-10-28 0:29 ` [RFC v2 obexd 08/11] fuse: Add write operation Michał Poczwardowski
@ 2012-10-28 0:29 ` Michał Poczwardowski
2012-10-28 0:29 ` [RFC v2 obexd 10/11] fuse: Add unlink/rmdir operation Michał Poczwardowski
2012-10-28 0:29 ` [RFC v2 obexd 11/11] fuse: Add rename operation Michał Poczwardowski
9 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
---
fuse/helpers.c | 40 ++++++++++++++++++++++++++++++++++++++++
fuse/helpers.h | 1 +
fuse/obexfuse.c | 17 +++++++++++++++++
3 files changed, 58 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index 796c4a3..cabf8f7 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -56,6 +56,8 @@ struct gobexhlp_location {
gchar *file;
};
+void gobexhlp_touch_real(struct gobexhlp_session* session, gchar *path);
+
static uint16_t find_rfcomm_uuid(void *user_data)
{
sdp_list_t *pds = (sdp_list_t*) user_data;
@@ -279,6 +281,12 @@ void request_new(struct gobexhlp_session *session,
{
g_print("REQUEST %s\n", name);
+ if (session->vtouch == TRUE) {
+ session->vtouch = FALSE;
+ gobexhlp_touch_real(session, session->vtouch_path);
+ g_free(session->vtouch_path);
+ }
+
if (session->request != NULL)
g_error("Another request (%s) active!\n",
session->request->name);
@@ -621,3 +629,35 @@ void gobexhlp_put(struct gobexhlp_session* session,
free_location(l);
request_wait_free(session);
}
+
+/* virtual file creation */
+void gobexhlp_touch(struct gobexhlp_session* session, const char *path)
+{
+ struct stat *stbuf;
+
+ g_print("gobexhlp_touch(%s)\n", path);
+
+ stbuf = g_malloc0(sizeof(struct stat));
+ stbuf->st_mode = S_IFREG;
+ g_hash_table_replace(session->file_stat, g_strdup(path), stbuf);
+
+ session->vtouch = TRUE;
+ session->vtouch_path = g_strdup(path);
+}
+
+void gobexhlp_touch_real(struct gobexhlp_session* session, gchar *path)
+{
+ struct gobexhlp_buffer *buffer, *tmpbuf;
+
+ g_print("gobexhlp_touch_real(%s)\n", path);
+
+ tmpbuf = session->buffer; /* save buffer state */
+
+ buffer = g_malloc0(sizeof(struct gobexhlp_buffer));
+ session->rtouch = TRUE;
+ gobexhlp_put(session, buffer, path);
+ session->rtouch = FALSE;
+ g_free(buffer);
+
+ session->buffer = tmpbuf;
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 1eca29d..c2b28ca 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -59,3 +59,4 @@ struct gobexhlp_buffer *gobexhlp_get(struct gobexhlp_session* session,
void gobexhlp_put(struct gobexhlp_session* session,
struct gobexhlp_buffer *buffer,
const char *path);
+void gobexhlp_touch(struct gobexhlp_session* session, const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index 900e6d7..b4599d8 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -215,6 +215,21 @@ static int obexfuse_release(const char *path, struct fuse_file_info *fi)
return session->status;
}
+static int obexfuse_utimens(const char *path, const struct timespec tv[2])
+{
+ /*
+ * Important for mknod (touch) operation
+ */
+ return 0;
+}
+
+static int obexfuse_mknod(const char *path, mode_t mode, dev_t dev)
+{
+ gobexhlp_touch(session, path);
+
+ return 0;
+}
+
static struct fuse_operations obexfuse_oper = {
.readdir = obexfuse_readdir,
.getattr = obexfuse_getattr,
@@ -223,6 +238,8 @@ static struct fuse_operations obexfuse_oper = {
.write = obexfuse_write,
.truncate = obexfuse_truncate,
.release = obexfuse_release,
+ .utimens = obexfuse_utimens,
+ .mknod = obexfuse_mknod,
.init = obexfuse_init,
.destroy = obexfuse_destroy,
};
--
1.7.8.6
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [RFC v2 obexd 10/11] fuse: Add unlink/rmdir operation
2012-10-28 0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
` (7 preceding siblings ...)
2012-10-28 0:29 ` [RFC v2 obexd 09/11] fuse: Add touch operation Michał Poczwardowski
@ 2012-10-28 0:29 ` Michał Poczwardowski
2012-10-28 0:29 ` [RFC v2 obexd 11/11] fuse: Add rename operation Michał Poczwardowski
9 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
---
fuse/helpers.c | 28 ++++++++++++++++++++++++++++
fuse/helpers.h | 1 +
fuse/obexfuse.c | 9 +++++++++
3 files changed, 38 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index cabf8f7..d0580c2 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -618,6 +618,16 @@ void gobexhlp_put(struct gobexhlp_session* session,
g_print("gobexhlp_put(%s%s)\n", l->dir, l->file);
+ if (g_strcmp0(path, session->vtouch_path) == 0 &&
+ session->vtouch == TRUE) {
+ session->vtouch = FALSE;
+ g_free(session->vtouch_path);
+ } else {
+ /* delete existing file */
+ if (session->rtouch == FALSE)
+ gobexhlp_delete(session, path);
+ }
+
gobexhlp_setpath(session, l->dir);
buffer->tmpsize = 0;
session->buffer = buffer;
@@ -661,3 +671,21 @@ void gobexhlp_touch_real(struct gobexhlp_session* session, gchar *path)
session->buffer = tmpbuf;
}
+
+void gobexhlp_delete(struct gobexhlp_session* session, const char *path)
+{
+ struct gobexhlp_location *l;
+ l = get_location(path);
+
+ g_print("gobexhlp_delete(%s)\n", l->file);
+
+ gobexhlp_setpath(session, l->dir);
+ request_new(session, g_strdup_printf("delete %s", path));
+ g_obex_delete(session->obex, l->file, response_func, session,
+ &session->err);
+
+ g_hash_table_remove(session->file_stat, path);
+
+ free_location(l);
+ request_wait_free(session);
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index c2b28ca..803cb59 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -60,3 +60,4 @@ void gobexhlp_put(struct gobexhlp_session* session,
struct gobexhlp_buffer *buffer,
const char *path);
void gobexhlp_touch(struct gobexhlp_session* session, const char *path);
+void gobexhlp_delete(struct gobexhlp_session* session, const char *path);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index b4599d8..2a6ee11 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -230,6 +230,13 @@ static int obexfuse_mknod(const char *path, mode_t mode, dev_t dev)
return 0;
}
+static int obexfuse_unlink(const char *path)
+{
+ gobexhlp_delete(session, path);
+
+ return session->status;
+}
+
static struct fuse_operations obexfuse_oper = {
.readdir = obexfuse_readdir,
.getattr = obexfuse_getattr,
@@ -240,6 +247,8 @@ static struct fuse_operations obexfuse_oper = {
.release = obexfuse_release,
.utimens = obexfuse_utimens,
.mknod = obexfuse_mknod,
+ .unlink = obexfuse_unlink,
+ .rmdir = obexfuse_unlink,
.init = obexfuse_init,
.destroy = obexfuse_destroy,
};
--
1.7.8.6
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [RFC v2 obexd 11/11] fuse: Add rename operation
2012-10-28 0:29 [RFC v2 obexd 01/11] fuse: Add initial obexfuse files, fuse main and options parse Michał Poczwardowski
` (8 preceding siblings ...)
2012-10-28 0:29 ` [RFC v2 obexd 10/11] fuse: Add unlink/rmdir operation Michał Poczwardowski
@ 2012-10-28 0:29 ` Michał Poczwardowski
9 siblings, 0 replies; 16+ messages in thread
From: Michał Poczwardowski @ 2012-10-28 0:29 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Michał Poczwardowski
---
fuse/helpers.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
fuse/helpers.h | 3 +++
fuse/obexfuse.c | 16 ++++++++++++++++
3 files changed, 65 insertions(+), 0 deletions(-)
diff --git a/fuse/helpers.c b/fuse/helpers.c
index d0580c2..2487d09 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -689,3 +689,49 @@ void gobexhlp_delete(struct gobexhlp_session* session, const char *path)
free_location(l);
request_wait_free(session);
}
+
+void gobexhlp_mkdir(struct gobexhlp_session* session, const char *path)
+{
+ struct gobexhlp_location *l;
+ struct stat *stbuf;
+
+ g_print("gobexhlp_mkdir(%s)\n", path);
+
+ l = get_location(path);
+ gobexhlp_setpath(session, l->dir);
+
+ request_new(session, g_strdup_printf("mkdir %s", path));
+ /* g_obex_mkdir also sets path, to new folder */
+ g_obex_mkdir(session->obex, l->file, response_func, session,
+ &session->err);
+ g_free(session->setpath);
+ session->setpath = g_strdup(path);
+
+ stbuf = g_malloc0(sizeof(struct stat));
+ stbuf->st_mode = S_IFDIR;
+ stbuf->st_mtime = time(NULL);
+ g_hash_table_replace(session->file_stat, g_strdup(path), stbuf);
+
+ free_location(l);
+ request_wait_free(session);
+}
+
+void gobexhlp_move(struct gobexhlp_session* session, const char *oldpath,
+ const char* newpath)
+{
+ struct gobexhlp_location *l_from, *l_to;
+
+ l_to = get_location(newpath);
+ l_from = get_location(oldpath);
+ gobexhlp_setpath(session, l_from->dir);
+
+ g_print("gobexhlp_move(%s to %s)\n", l_from->file, l_to->file);
+
+ request_new(session, g_strdup_printf("move %s:%s",
+ oldpath, newpath));
+ g_obex_move(session->obex, l_from->file, l_to->file, response_func,
+ session, &session->err);
+ free_location(l_to);
+ free_location(l_from);
+ request_wait_free(session);
+}
diff --git a/fuse/helpers.h b/fuse/helpers.h
index 803cb59..80e3aa8 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -61,3 +61,6 @@ void gobexhlp_put(struct gobexhlp_session* session,
const char *path);
void gobexhlp_touch(struct gobexhlp_session* session, const char *path);
void gobexhlp_delete(struct gobexhlp_session* session, const char *path);
+void gobexhlp_mkdir(struct gobexhlp_session* session, const char *path);
+void gobexhlp_move(struct gobexhlp_session* session, const char *oldpath,
+ const char* newpath);
diff --git a/fuse/obexfuse.c b/fuse/obexfuse.c
index 2a6ee11..f9f9d0e 100644
--- a/fuse/obexfuse.c
+++ b/fuse/obexfuse.c
@@ -237,6 +237,20 @@ static int obexfuse_unlink(const char *path)
return session->status;
}
+static int obexfuse_mkdir(const char *path, mode_t mode)
+{
+ gobexhlp_mkdir(session, path);
+
+ return session->status;
+}
+
+static int obexfuse_rename(const char *from, const char *to)
+{
+ gobexhlp_move(session, from, to);
+
+ return session->status;
+}
+
static struct fuse_operations obexfuse_oper = {
.readdir = obexfuse_readdir,
.getattr = obexfuse_getattr,
@@ -249,6 +263,8 @@ static struct fuse_operations obexfuse_oper = {
.mknod = obexfuse_mknod,
.unlink = obexfuse_unlink,
.rmdir = obexfuse_unlink,
+ .mkdir = obexfuse_mkdir,
+ .rename = obexfuse_rename,
.init = obexfuse_init,
.destroy = obexfuse_destroy,
};
--
1.7.8.6
^ permalink raw reply related [flat|nested] 16+ messages in thread