All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.