linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC obexd 01/11] fuse: Add initial gobexfuse files, fuse main and options parse
@ 2012-10-09 18:15 Michał Poczwardowski
  2012-10-09 18:15 ` [RFC obexd 02/11] build: Add --enable-fuse for gobexfuse Michał Poczwardowski
                   ` (9 more replies)
  0 siblings, 10 replies; 14+ messages in thread
From: Michał Poczwardowski @ 2012-10-09 18:15 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/gobexfuse.c |  119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fuse/helpers.c   |   55 +++++++++++++++++++++++++
 fuse/helpers.h   |   49 ++++++++++++++++++++++
 3 files changed, 223 insertions(+), 0 deletions(-)
 create mode 100644 fuse/gobexfuse.c
 create mode 100644 fuse/helpers.c
 create mode 100644 fuse/helpers.h

diff --git a/fuse/gobexfuse.c b/fuse/gobexfuse.c
new file mode 100644
index 0000000..d9709fd
--- /dev/null
+++ b/fuse/gobexfuse.c
@@ -0,0 +1,119 @@
+/*
+ *  OBEX Filesystem in Userspace
+ *
+ *  Copyright (C) 2012  Michał Poczwardowski <dmp0x7c5@gmail.com>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#define FUSE_USE_VERSION 26
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <fuse.h>
+#include <fuse/fuse_opt.h>
+
+#include "helpers.h"
+
+struct options {
+	char* dststr;
+	char* srcstr;
+} options;
+
+#define GOBEXFUSE_OPT_KEY(t, p, v) { t, offsetof(struct options, p), v }
+
+enum
+{
+   KEY_VERSION,
+   KEY_HELP,
+};
+
+static struct fuse_opt gobexfuse_opts[] =
+{
+	GOBEXFUSE_OPT_KEY("--target=%s",dststr, 0),
+	GOBEXFUSE_OPT_KEY("-t %s",	dststr, 0),
+	GOBEXFUSE_OPT_KEY("--source=%s",srcstr, 0),
+	GOBEXFUSE_OPT_KEY("-s %s",	srcstr, 0),
+
+	FUSE_OPT_KEY("-V",             KEY_VERSION),
+	FUSE_OPT_KEY("--version",      KEY_VERSION),
+	FUSE_OPT_KEY("-h",             KEY_HELP),
+	FUSE_OPT_KEY("--help",         KEY_HELP),
+	FUSE_OPT_END
+};
+
+static struct fuse_operations gobexfuse_oper = {
+};
+
+static int gobexfuse_opt_proc(void *data, const char *arg, int key,
+					struct fuse_args *outargs)
+{
+	switch (key) {
+	case KEY_HELP:
+		g_printerr("Usage: %s mountpoint [options]\n"
+				"\n"
+				"general options:\n"
+				"    -o opt,[opt...]  mount options\n"
+				"    -h   --help      print help\n"
+				"    -V   --version   print version\n"
+				"\n"
+				"gobexfuse options:\n"
+				"    -t   --target    target btaddr "
+				"(mandatory)\n"
+				"    -s   --source    source btaddr\n"
+				"\n"
+				, outargs->argv[0]);
+		fuse_opt_add_arg(outargs, "-ho");
+		fuse_main(outargs->argc, outargs->argv, &gobexfuse_oper, NULL);
+		exit(1);
+	case KEY_VERSION:
+		g_print("gobexfuse upon:\n");
+		fuse_opt_add_arg(outargs, "--version");
+		fuse_main(outargs->argc, outargs->argv, &gobexfuse_oper, NULL);
+		exit(0);
+	}
+	return 1;
+}
+
+int main(int argc, char *argv[])
+{
+	int retfuse;
+	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+
+	memset(&options, 0, sizeof(struct options));
+
+	if (fuse_opt_parse(&args, &options, gobexfuse_opts,
+				gobexfuse_opt_proc) == -1)
+		return -EINVAL;
+
+	if (options.dststr == NULL) {
+		g_printerr("Target not specified\n");
+		return -EINVAL;
+	}
+
+	g_thread_init(NULL);
+
+	fuse_opt_add_arg(&args, "-s"); /* force single threaded mode */
+	retfuse = fuse_main(args.argc, args.argv, &gobexfuse_oper, NULL);
+
+	fuse_opt_free_args(&args);
+	return retfuse;
+}
diff --git a/fuse/helpers.c b/fuse/helpers.c
new file mode 100644
index 0000000..53bba57
--- /dev/null
+++ b/fuse/helpers.c
@@ -0,0 +1,55 @@
+/*
+ *  OBEX Filesystem in Userspace
+ *
+ *  Copyright (C) 2012  Michał Poczwardowski <dmp0x7c5@gmail.com>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <gobex/gobex.h>
+#include <btio/btio.h>
+
+#include <glib.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/rfcomm.h>
+#include <bluetooth/sdp.h>
+#include <bluetooth/sdp_lib.h>
+
+#define BT_RX_MTU 32767
+#define BT_TX_MTU 32767
+
+#include "helpers.h"
+
+#define OBEX_FTP_UUID \
+	"\xF9\xEC\x7B\xC4\x95\x3C\x11\xD2\x98\x4E\x52\x54\x00\xDC\x9E\x09"
+#define OBEX_FTP_UUID_LEN 16
+
+#define OBEX_FTP_LS "x-obex/folder-listing"
+
+struct gobexhlp_request {
+	gchar *name;
+	gboolean complete;
+};
+
+struct gobexhlp_location {
+	gchar *dir;
+	gchar *file;
+};
+
diff --git a/fuse/helpers.h b/fuse/helpers.h
new file mode 100644
index 0000000..21972b2
--- /dev/null
+++ b/fuse/helpers.h
@@ -0,0 +1,49 @@
+/*
+ *  OBEX Filesystem in Userspace
+ *
+ *  Copyright (C) 2012  Michał Poczwardowski <dmp0x7c5@gmail.com>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <gobex/gobex.h>
+#include <glib.h>
+
+struct gobexhlp_request;
+
+struct gobexhlp_buffer {
+	void *data;
+	gsize tmpsize;
+	gsize size;
+	gboolean edited;
+};
+
+struct gobexhlp_session {
+	GObex *obex;
+	GList *lsfiles;
+	GIOChannel *io;
+	GHashTable *file_stat;
+	gchar *setpath;
+	struct gobexhlp_request *request;
+	struct gobexhlp_buffer *buffer;
+	gboolean vtouch;
+	gchar *vtouch_path;
+	gboolean rtouch;
+	int status;
+	GError *err;
+};
+
-- 
1.7.8.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [RFC obexd 02/11] build: Add --enable-fuse for gobexfuse
  2012-10-09 18:15 [RFC obexd 01/11] fuse: Add initial gobexfuse files, fuse main and options parse Michał Poczwardowski
@ 2012-10-09 18:15 ` Michał Poczwardowski
  2012-10-09 18:34   ` Marcel Holtmann
  2012-10-09 18:15 ` [RFC obexd 03/11] fuse: Add gobexhlp_connect/disconnect functions with helpers Michał Poczwardowski
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 14+ messages in thread
From: Michał Poczwardowski @ 2012-10-09 18:15 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..95b99a6 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/gobexfuse
+
+fuse_gobexfuse_SOURCES = $(gobex_sources) $(btio_sources) \
+		fuse/helpers.c fuse/gobexfuse.c
+
+fuse_gobexfuse_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..7190f3f 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 gobexfuse]), [
+	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] 14+ messages in thread

* [RFC obexd 03/11] fuse: Add gobexhlp_connect/disconnect functions with helpers
  2012-10-09 18:15 [RFC obexd 01/11] fuse: Add initial gobexfuse files, fuse main and options parse Michał Poczwardowski
  2012-10-09 18:15 ` [RFC obexd 02/11] build: Add --enable-fuse for gobexfuse Michał Poczwardowski
@ 2012-10-09 18:15 ` Michał Poczwardowski
  2012-10-09 18:15 ` [RFC obexd 04/11] fuse: Add request helpers and setpath operation Michał Poczwardowski
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Michał Poczwardowski @ 2012-10-09 18:15 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/gobexfuse.c |   40 ++++++++++
 fuse/helpers.c   |  220 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fuse/helpers.h   |    5 +
 3 files changed, 265 insertions(+), 0 deletions(-)

diff --git a/fuse/gobexfuse.c b/fuse/gobexfuse.c
index d9709fd..cc5fedb 100644
--- a/fuse/gobexfuse.c
+++ b/fuse/gobexfuse.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 gobexfuse_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* gobexfuse_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 gobexfuse_destroy()
+{
+	gobexhlp_disconnect(session);
+	g_main_loop_quit(main_loop);
+	g_thread_join(main_gthread);
+}
+
 static struct fuse_operations gobexfuse_oper = {
+	.init = gobexfuse_init,
+	.destroy = gobexfuse_destroy,
 };
 
 static int gobexfuse_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, &gobexfuse_oper, NULL);
 
diff --git a/fuse/helpers.c b/fuse/helpers.c
index 53bba57..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;
@@ -53,3 +56,220 @@ struct gobexhlp_location {
 	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 21972b2..f1d787b 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -47,3 +47,8 @@ struct gobexhlp_session {
 	GError *err;
 };
 
+struct gobexhlp_session* gobexhlp_connect(const char *srcstr,
+						const char *dstsrc);
+void gobexhlp_disconnect(struct gobexhlp_session* session);
+
+
-- 
1.7.8.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [RFC obexd 04/11] fuse: Add request helpers and setpath operation
  2012-10-09 18:15 [RFC obexd 01/11] fuse: Add initial gobexfuse files, fuse main and options parse Michał Poczwardowski
  2012-10-09 18:15 ` [RFC obexd 02/11] build: Add --enable-fuse for gobexfuse Michał Poczwardowski
  2012-10-09 18:15 ` [RFC obexd 03/11] fuse: Add gobexhlp_connect/disconnect functions with helpers Michał Poczwardowski
@ 2012-10-09 18:15 ` Michał Poczwardowski
  2012-10-09 18:15 ` [RFC obexd 05/11] fuse: Add readdir operation Michał Poczwardowski
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Michał Poczwardowski @ 2012-10-09 18:15 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] 14+ messages in thread

* [RFC obexd 05/11] fuse: Add readdir operation
  2012-10-09 18:15 [RFC obexd 01/11] fuse: Add initial gobexfuse files, fuse main and options parse Michał Poczwardowski
                   ` (2 preceding siblings ...)
  2012-10-09 18:15 ` [RFC obexd 04/11] fuse: Add request helpers and setpath operation Michał Poczwardowski
@ 2012-10-09 18:15 ` Michał Poczwardowski
  2012-10-09 18:15 ` [RFC obexd 06/11] fuse: Add getattr operation Michał Poczwardowski
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Michał Poczwardowski @ 2012-10-09 18:15 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/gobexfuse.c |   23 ++++++++++
 fuse/helpers.c   |  129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fuse/helpers.h   |    2 +
 3 files changed, 154 insertions(+), 0 deletions(-)

diff --git a/fuse/gobexfuse.c b/fuse/gobexfuse.c
index cc5fedb..2bdfc09 100644
--- a/fuse/gobexfuse.c
+++ b/fuse/gobexfuse.c
@@ -89,7 +89,30 @@ void gobexfuse_destroy()
 	g_thread_join(main_gthread);
 }
 
+static int gobexfuse_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 gobexfuse_oper = {
+	.readdir = gobexfuse_readdir,
 	.init = gobexfuse_init,
 	.destroy = gobexfuse_destroy,
 };
diff --git a/fuse/helpers.c b/fuse/helpers.c
index 1b8082f..1d3faa5 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -381,3 +381,132 @@ 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 f1d787b..84238c9 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -51,4 +51,6 @@ 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);
+
 
-- 
1.7.8.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [RFC obexd 06/11] fuse: Add getattr operation
  2012-10-09 18:15 [RFC obexd 01/11] fuse: Add initial gobexfuse files, fuse main and options parse Michał Poczwardowski
                   ` (3 preceding siblings ...)
  2012-10-09 18:15 ` [RFC obexd 05/11] fuse: Add readdir operation Michał Poczwardowski
@ 2012-10-09 18:15 ` Michał Poczwardowski
  2012-10-09 18:15 ` [RFC obexd 07/11] fuse: Add open and read operations plus location helpers Michał Poczwardowski
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Michał Poczwardowski @ 2012-10-09 18:15 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/gobexfuse.c |   34 ++++++++++++++++++++++++++++++++++
 fuse/helpers.c   |    6 ++++++
 fuse/helpers.h   |    2 ++
 3 files changed, 42 insertions(+), 0 deletions(-)

diff --git a/fuse/gobexfuse.c b/fuse/gobexfuse.c
index 2bdfc09..c886176 100644
--- a/fuse/gobexfuse.c
+++ b/fuse/gobexfuse.c
@@ -111,8 +111,42 @@ static int gobexfuse_readdir(const char *path, void *buf,
 	return session->status;
 }
 
+static int gobexfuse_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 gobexfuse_oper = {
 	.readdir = gobexfuse_readdir,
+	.getattr = gobexfuse_getattr,
 	.init = gobexfuse_init,
 	.destroy = gobexfuse_destroy,
 };
diff --git a/fuse/helpers.c b/fuse/helpers.c
index 1d3faa5..249d0c9 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -510,3 +510,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 84238c9..0a0f366 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -52,5 +52,7 @@ 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);
 
 
-- 
1.7.8.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [RFC obexd 07/11] fuse: Add open and read operations plus location helpers
  2012-10-09 18:15 [RFC obexd 01/11] fuse: Add initial gobexfuse files, fuse main and options parse Michał Poczwardowski
                   ` (4 preceding siblings ...)
  2012-10-09 18:15 ` [RFC obexd 06/11] fuse: Add getattr operation Michał Poczwardowski
@ 2012-10-09 18:15 ` Michał Poczwardowski
  2012-10-09 18:15 ` [RFC obexd 08/11] fuse: Add write operation Michał Poczwardowski
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Michał Poczwardowski @ 2012-10-09 18:15 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/gobexfuse.c |   32 ++++++++++++++++++++++++++++
 fuse/helpers.c   |   61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fuse/helpers.h   |    3 +-
 3 files changed, 95 insertions(+), 1 deletions(-)

diff --git a/fuse/gobexfuse.c b/fuse/gobexfuse.c
index c886176..446a757 100644
--- a/fuse/gobexfuse.c
+++ b/fuse/gobexfuse.c
@@ -144,9 +144,41 @@ static int gobexfuse_getattr(const char *path, struct stat *stbuf)
 	return res;
 }
 
+static int gobexfuse_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 gobexfuse_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 gobexfuse_oper = {
 	.readdir = gobexfuse_readdir,
 	.getattr = gobexfuse_getattr,
+	.open = gobexfuse_open,
+	.read = gobexfuse_read,
 	.init = gobexfuse_init,
 	.destroy = gobexfuse_destroy,
 };
diff --git a/fuse/helpers.c b/fuse/helpers.c
index 249d0c9..9b453e0 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -516,3 +516,64 @@ 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 0a0f366..50c750d 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -54,5 +54,6 @@ 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);
 
-- 
1.7.8.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [RFC obexd 08/11] fuse: Add write operation
  2012-10-09 18:15 [RFC obexd 01/11] fuse: Add initial gobexfuse files, fuse main and options parse Michał Poczwardowski
                   ` (5 preceding siblings ...)
  2012-10-09 18:15 ` [RFC obexd 07/11] fuse: Add open and read operations plus location helpers Michał Poczwardowski
@ 2012-10-09 18:15 ` Michał Poczwardowski
  2012-10-09 18:15 ` [RFC obexd 09/11] fuse: Add touch operation Michał Poczwardowski
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Michał Poczwardowski @ 2012-10-09 18:15 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/gobexfuse.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 fuse/helpers.c   |   45 +++++++++++++++++++++++++++++++++++++++++++++
 fuse/helpers.h   |    3 +++
 3 files changed, 92 insertions(+), 0 deletions(-)

diff --git a/fuse/gobexfuse.c b/fuse/gobexfuse.c
index 446a757..a49a8f9 100644
--- a/fuse/gobexfuse.c
+++ b/fuse/gobexfuse.c
@@ -174,11 +174,55 @@ static int gobexfuse_read(const char *path, char *buf, size_t size,
 	return asize;
 }
 
+static int gobexfuse_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 gobexfuse_truncate(const char *path, off_t offset)
+{
+	/*
+	 *  Allow to change the size of a file.
+	 */
+	return 0;
+}
+
+static int gobexfuse_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 gobexfuse_oper = {
 	.readdir = gobexfuse_readdir,
 	.getattr = gobexfuse_getattr,
 	.open = gobexfuse_open,
 	.read = gobexfuse_read,
+	.write = gobexfuse_write,
+	.truncate = gobexfuse_truncate,
+	.release = gobexfuse_release,
 	.init = gobexfuse_init,
 	.destroy = gobexfuse_destroy,
 };
diff --git a/fuse/helpers.c b/fuse/helpers.c
index 9b453e0..b807f15 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -577,3 +577,48 @@ 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 50c750d..95987c4 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -56,4 +56,7 @@ 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);
 
-- 
1.7.8.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [RFC obexd 09/11] fuse: Add touch operation
  2012-10-09 18:15 [RFC obexd 01/11] fuse: Add initial gobexfuse files, fuse main and options parse Michał Poczwardowski
                   ` (6 preceding siblings ...)
  2012-10-09 18:15 ` [RFC obexd 08/11] fuse: Add write operation Michał Poczwardowski
@ 2012-10-09 18:15 ` Michał Poczwardowski
  2012-10-09 18:15 ` [RFC obexd 10/11] fuse: Add unlink/rmdir operation Michał Poczwardowski
  2012-10-09 18:15 ` [RFC obexd 11/11] fuse: Add rename operation Michał Poczwardowski
  9 siblings, 0 replies; 14+ messages in thread
From: Michał Poczwardowski @ 2012-10-09 18:15 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/gobexfuse.c |   17 +++++++++++++++++
 fuse/helpers.c   |   40 ++++++++++++++++++++++++++++++++++++++++
 fuse/helpers.h   |    1 +
 3 files changed, 58 insertions(+), 0 deletions(-)

diff --git a/fuse/gobexfuse.c b/fuse/gobexfuse.c
index a49a8f9..b47d203 100644
--- a/fuse/gobexfuse.c
+++ b/fuse/gobexfuse.c
@@ -215,6 +215,21 @@ static int gobexfuse_release(const char *path, struct fuse_file_info *fi)
 	return session->status;
 }
 
+static int gobexfuse_utimens(const char *path, const struct timespec tv[2])
+{
+	/*
+	 * Important for mknod (touch) operation
+	 */
+	return 0;
+}
+
+static int gobexfuse_mknod(const char *path, mode_t mode, dev_t dev)
+{
+	gobexhlp_touch(session, path);
+
+	return 0;
+}
+
 static struct fuse_operations gobexfuse_oper = {
 	.readdir = gobexfuse_readdir,
 	.getattr = gobexfuse_getattr,
@@ -223,6 +238,8 @@ static struct fuse_operations gobexfuse_oper = {
 	.write = gobexfuse_write,
 	.truncate = gobexfuse_truncate,
 	.release = gobexfuse_release,
+	.utimens = gobexfuse_utimens,
+	.mknod = gobexfuse_mknod,
 	.init = gobexfuse_init,
 	.destroy = gobexfuse_destroy,
 };
diff --git a/fuse/helpers.c b/fuse/helpers.c
index b807f15..05948be 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);
@@ -622,3 +630,35 @@ void gobexhlp_put(struct gobexhlp_session* session,
 	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 95987c4..da5f96c 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -59,4 +59,5 @@ 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);
 
-- 
1.7.8.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [RFC obexd 10/11] fuse: Add unlink/rmdir operation
  2012-10-09 18:15 [RFC obexd 01/11] fuse: Add initial gobexfuse files, fuse main and options parse Michał Poczwardowski
                   ` (7 preceding siblings ...)
  2012-10-09 18:15 ` [RFC obexd 09/11] fuse: Add touch operation Michał Poczwardowski
@ 2012-10-09 18:15 ` Michał Poczwardowski
  2012-10-09 18:15 ` [RFC obexd 11/11] fuse: Add rename operation Michał Poczwardowski
  9 siblings, 0 replies; 14+ messages in thread
From: Michał Poczwardowski @ 2012-10-09 18:15 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/gobexfuse.c |    9 +++++++++
 fuse/helpers.c   |   28 ++++++++++++++++++++++++++++
 fuse/helpers.h   |    1 +
 3 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/fuse/gobexfuse.c b/fuse/gobexfuse.c
index b47d203..c45d056 100644
--- a/fuse/gobexfuse.c
+++ b/fuse/gobexfuse.c
@@ -230,6 +230,13 @@ static int gobexfuse_mknod(const char *path, mode_t mode, dev_t dev)
 	return 0;
 }
 
+static int gobexfuse_unlink(const char *path)
+{
+	gobexhlp_delete(session, path);
+
+	return session->status;
+}
+
 static struct fuse_operations gobexfuse_oper = {
 	.readdir = gobexfuse_readdir,
 	.getattr = gobexfuse_getattr,
@@ -240,6 +247,8 @@ static struct fuse_operations gobexfuse_oper = {
 	.release = gobexfuse_release,
 	.utimens = gobexfuse_utimens,
 	.mknod = gobexfuse_mknod,
+	.unlink = gobexfuse_unlink,
+	.rmdir = gobexfuse_unlink,
 	.init = gobexfuse_init,
 	.destroy = gobexfuse_destroy,
 };
diff --git a/fuse/helpers.c b/fuse/helpers.c
index 05948be..0ad8cbb 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;
@@ -662,3 +672,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 da5f96c..baa6bf1 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -60,4 +60,5 @@ 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);
 
-- 
1.7.8.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [RFC obexd 11/11] fuse: Add rename operation
  2012-10-09 18:15 [RFC obexd 01/11] fuse: Add initial gobexfuse files, fuse main and options parse Michał Poczwardowski
                   ` (8 preceding siblings ...)
  2012-10-09 18:15 ` [RFC obexd 10/11] fuse: Add unlink/rmdir operation Michał Poczwardowski
@ 2012-10-09 18:15 ` Michał Poczwardowski
  9 siblings, 0 replies; 14+ messages in thread
From: Michał Poczwardowski @ 2012-10-09 18:15 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Michał Poczwardowski

---
 fuse/gobexfuse.c |   16 ++++++++++++++++
 fuse/helpers.c   |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 fuse/helpers.h   |    3 +++
 3 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/fuse/gobexfuse.c b/fuse/gobexfuse.c
index c45d056..2f6a7c0 100644
--- a/fuse/gobexfuse.c
+++ b/fuse/gobexfuse.c
@@ -237,6 +237,20 @@ static int gobexfuse_unlink(const char *path)
 	return session->status;
 }
 
+static int gobexfuse_mkdir(const char *path, mode_t mode)
+{
+	gobexhlp_mkdir(session, path);
+
+	return session->status;
+}
+
+static int gobexfuse_rename(const char *from, const char *to)
+{
+	gobexhlp_move(session, from, to);
+
+	return session->status;
+}
+
 static struct fuse_operations gobexfuse_oper = {
 	.readdir = gobexfuse_readdir,
 	.getattr = gobexfuse_getattr,
@@ -249,6 +263,8 @@ static struct fuse_operations gobexfuse_oper = {
 	.mknod = gobexfuse_mknod,
 	.unlink = gobexfuse_unlink,
 	.rmdir = gobexfuse_unlink,
+	.mkdir = gobexfuse_mkdir,
+	.rename = gobexfuse_rename,
 	.init = gobexfuse_init,
 	.destroy = gobexfuse_destroy,
 };
diff --git a/fuse/helpers.c b/fuse/helpers.c
index 0ad8cbb..698781a 100644
--- a/fuse/helpers.c
+++ b/fuse/helpers.c
@@ -690,3 +690,49 @@ void gobexhlp_delete(struct gobexhlp_session* session, const char *path)
 	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 baa6bf1..cc2d9a8 100644
--- a/fuse/helpers.h
+++ b/fuse/helpers.h
@@ -61,4 +61,7 @@ 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);
 
-- 
1.7.8.6


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [RFC obexd 02/11] build: Add --enable-fuse for gobexfuse
  2012-10-09 18:15 ` [RFC obexd 02/11] build: Add --enable-fuse for gobexfuse Michał Poczwardowski
@ 2012-10-09 18:34   ` Marcel Holtmann
  2012-10-15 14:43     ` Luiz Augusto von Dentz
  0 siblings, 1 reply; 14+ messages in thread
From: Marcel Holtmann @ 2012-10-09 18:34 UTC (permalink / raw)
  To: Michał Poczwardowski; +Cc: linux-bluetooth

Hi Michal,

>  Makefile.am  |    9 +++++++++
>  configure.ac |   15 +++++++++++++++
>  2 files changed, 24 insertions(+), 0 deletions(-)
> 
> diff --git a/Makefile.am b/Makefile.am
> index 724dd5d..95b99a6 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/gobexfuse

I rather call this obexfuse or similar. I don't want to have any "g"
prefixes in the future anymore.

Regards

Marcel



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC obexd 02/11] build: Add --enable-fuse for gobexfuse
  2012-10-09 18:34   ` Marcel Holtmann
@ 2012-10-15 14:43     ` Luiz Augusto von Dentz
  2012-10-15 15:37       ` Michał Poczwardowski
  0 siblings, 1 reply; 14+ messages in thread
From: Luiz Augusto von Dentz @ 2012-10-15 14:43 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: Michał Poczwardowski, linux-bluetooth

Hi Michal,

On Tue, Oct 9, 2012 at 8:34 PM, Marcel Holtmann <marcel@holtmann.org> wrote:
> Hi Michal,
>
>>  Makefile.am  |    9 +++++++++
>>  configure.ac |   15 +++++++++++++++
>>  2 files changed, 24 insertions(+), 0 deletions(-)
>>
>> diff --git a/Makefile.am b/Makefile.am
>> index 724dd5d..95b99a6 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/gobexfuse
>
> I rather call this obexfuse or similar. I don't want to have any "g"
> prefixes in the future anymore.

Are you looking into this? I will probably need more time to look in
detail what you have done, but at least the binary name should be
changed as Marcel suggested.

-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [RFC obexd 02/11] build: Add --enable-fuse for gobexfuse
  2012-10-15 14:43     ` Luiz Augusto von Dentz
@ 2012-10-15 15:37       ` Michał Poczwardowski
  0 siblings, 0 replies; 14+ messages in thread
From: Michał Poczwardowski @ 2012-10-15 15:37 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Luiz Augusto von Dentz

I will change that :)

On 15 October 2012 16:43, Luiz Augusto von Dentz <luiz.dentz@gmail.com> wrote:
> Hi Michal,
>
> On Tue, Oct 9, 2012 at 8:34 PM, Marcel Holtmann <marcel@holtmann.org> wrote:
>> Hi Michal,
>>
>>>  Makefile.am  |    9 +++++++++
>>>  configure.ac |   15 +++++++++++++++
>>>  2 files changed, 24 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/Makefile.am b/Makefile.am
>>> index 724dd5d..95b99a6 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/gobexfuse
>>
>> I rather call this obexfuse or similar. I don't want to have any "g"
>> prefixes in the future anymore.
>
> Are you looking into this? I will probably need more time to look in
> detail what you have done, but at least the binary name should be
> changed as Marcel suggested.
>
> --
> Luiz Augusto von Dentz
> --
> 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

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2012-10-15 15:37 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-09 18:15 [RFC obexd 01/11] fuse: Add initial gobexfuse files, fuse main and options parse Michał Poczwardowski
2012-10-09 18:15 ` [RFC obexd 02/11] build: Add --enable-fuse for gobexfuse Michał Poczwardowski
2012-10-09 18:34   ` Marcel Holtmann
2012-10-15 14:43     ` Luiz Augusto von Dentz
2012-10-15 15:37       ` Michał Poczwardowski
2012-10-09 18:15 ` [RFC obexd 03/11] fuse: Add gobexhlp_connect/disconnect functions with helpers Michał Poczwardowski
2012-10-09 18:15 ` [RFC obexd 04/11] fuse: Add request helpers and setpath operation Michał Poczwardowski
2012-10-09 18:15 ` [RFC obexd 05/11] fuse: Add readdir operation Michał Poczwardowski
2012-10-09 18:15 ` [RFC obexd 06/11] fuse: Add getattr operation Michał Poczwardowski
2012-10-09 18:15 ` [RFC obexd 07/11] fuse: Add open and read operations plus location helpers Michał Poczwardowski
2012-10-09 18:15 ` [RFC obexd 08/11] fuse: Add write operation Michał Poczwardowski
2012-10-09 18:15 ` [RFC obexd 09/11] fuse: Add touch operation Michał Poczwardowski
2012-10-09 18:15 ` [RFC obexd 10/11] fuse: Add unlink/rmdir operation Michał Poczwardowski
2012-10-09 18:15 ` [RFC obexd 11/11] fuse: Add rename operation Michał Poczwardowski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).