diff options
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | client/Makefile.am | 30 | ||||
-rw-r--r-- | configure.ac | 71 | ||||
-rw-r--r-- | daemon/.gitignore | 3 | ||||
-rw-r--r-- | daemon/Makefile.am | 7 | ||||
-rw-r--r-- | daemon/gvfsbackend.c | 2 | ||||
-rw-r--r-- | daemon/gvfsbackendsmb.c | 570 | ||||
-rw-r--r-- | daemon/gvfsbackendsmb.h | 46 | ||||
-rw-r--r-- | daemon/smb.c | 54 |
9 files changed, 786 insertions, 1 deletions
@@ -2,6 +2,10 @@ Makefile Makefile.in *~ *.o +*.la +*.lo +.deps +.libs test aclocal.m4 autom4te.cache diff --git a/client/Makefile.am b/client/Makefile.am new file mode 100644 index 00000000..4bd74aa6 --- /dev/null +++ b/client/Makefile.am @@ -0,0 +1,30 @@ +NULL = + +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/gvfs \ + -I$(top_srcdir)/daemon \ + $(GLIB_CFLAGS) $(DBUS_CFLAGS) \ + -DG_LOG_DOMAIN=\"GVFS\" -DG_DISABLE_DEPRECATED \ + -DDBUS_API_SUBJECT_TO_CHANGE + +module_flags = -export_dynamic -avoid-version -module -no-undefined +modulesdir = $(libdir)/gio/gvfs-modules + +modules_LTLIBRARIES = libgvfsdbus.la + +libgvfsdbus_la_LDFLAGS = $(module_flags) +libgvfsdbus_la_SOURCES = \ + gsysutils.c gsysutils.h \ + gdbusutils.c gdbusutils.h \ + gvfsimpldaemon.c gvfsimpldaemon.h \ + gfiledaemon.c gfiledaemon.h \ + gfiledaemonlocal.c gfiledaemonlocal.h \ + gvfsuriutils.c gvfsuriutils.h \ + gfileinputstreamdaemon.c gfileinputstreamdaemon.h \ + gfileenumeratordaemon.c gfileenumeratordaemon.h \ + gvfsdaemondbus.c \ + $(NULL) + +libgvfsdbus_la_LIBADD = \ + $(top_builddir)/gio/libgio.la \ + $(DBUS_LIBS) \ + $(GLIB_LIBS) diff --git a/configure.ac b/configure.ac index a1d0a615..ae966945 100644 --- a/configure.ac +++ b/configure.ac @@ -101,11 +101,82 @@ fi AC_SUBST(XATTR_LIBS) dnl ========================================================================== +dnl Samba 3.0 + +AC_ARG_ENABLE(samba, [ --disable-samba build without samba support]) +msg_samba="no" +if test "x$enable_samba" != "xno"; then + AC_ARG_WITH(samba-includes, [ --with-samba-includes=PREFIX Location of samba includes.], + with_samba_includes="$withval", with_samba_includes="/usr/include") + have_samba_includes="no" + if test "x${with_samba_includes}" != "xno"; then + CPPFLAGS_save="$CPPFLAGS" + + echo "before test, samba_includes: ${samba_includes}" + + CPPFLAGS="$CPPFLAGS -I$with_samba_includes" + AC_CHECK_HEADER(libsmbclient.h, [ samba_includes="yes" ]) + CPPFLAGS="$CPPFLAGS_save" + + if test "x{samba_includes}" != "xno" -a "x${samba_includes}" != "x"; then + have_samba_includes="yes" + if test "${with_samba_includes}" != "/usr/include" ; then + SAMBA_CFLAGS="-I$with_samba_includes" + else + SAMBA_CFLAGS="" + fi + + CPPFLAGS="$CPPFLAGS -I$with_samba_includes" + AC_CHECK_MEMBER(SMBCCTX.flags, + [AC_DEFINE(HAVE_SAMBA_FLAGS,, [Defined if flags availible in SMBCCTXT])],, + [#include <libsmbclient.h>]) + AC_CHECK_MEMBER(SMBCCTX.close, + [AC_DEFINE(HAVE_SAMBA_OLD_CLOSE, , [Defined if old close is available in SMBCCTXT])],, + [#include <libsmbclient.h>]) + CPPFLAGS="$CPPFLAGS_save" + else + SAMBA_CFLAGS="" + fi + fi + echo "have_samba_includes: ${have_samba_includes}" + AC_ARG_WITH(samba-libs, [ --with-samba-libs=PREFIX Location of Samba libs.], + with_samba_libs="$withval", with_samba_libs="/usr/lib") + if test "x${with_samba_libs}" != "xno" -a "x${have_samba_includes}" != "xno"; then + LDFLAGS_save="$LDFLAGS" + + LDFLAGS="$LDFLAGS -L$with_samba_libs" + AC_CHECK_LIB(smbclient, smbc_new_context,samba_libs="yes", samba_libs="no") + LDFLAGS="$LDFLAGS_save" + if test "x${samba_libs}" != "xno"; then + AC_DEFINE(HAVE_SAMBA,, [Define to 1 if you have the samba 3.0 libraries]) + msg_samba="yes" + if test x$with_samba_libs != x/usr/lib; then + SAMBA_LIBS="-L$with_samba_libs -lsmbclient" + else + SAMBA_LIBS="-lsmbclient" + fi + else + SAMBA_CFLAGS="" + SAMBA_LIBS="" + fi + fi + AC_MSG_CHECKING(for Samba 3.0 libraries) + AC_MSG_RESULT($msg_samba) +fi +AM_CONDITIONAL(HAVE_SAMBA, test $msg_samba = yes) +AC_SUBST(SAMBA_CFLAGS) +AC_SUBST(SAMBA_LIBS) + +dnl ========================================================================== dnl Globally define_GNU_SOURCE and therefore enable the GNU extensions AC_DEFINE(_GNU_SOURCE, 1, [Enable GNU Extensions]) dnl ========================================================================== + +AC_DEFINE(_FILE_OFFSET_BITS, 64, [Enable LFS]) + +dnl ========================================================================== AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal) diff --git a/daemon/.gitignore b/daemon/.gitignore index bcc5ada5..3df41a58 100644 --- a/daemon/.gitignore +++ b/daemon/.gitignore @@ -7,3 +7,6 @@ Makefile Makefile.in gvfs-daemon +gvfs-daemon-smb +gvfs-daemon-test + diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 059ea34c..7241e757 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -18,6 +18,7 @@ libraries = \ noinst_PROGRAMS = \ gvfs-daemon \ gvfs-daemon-test \ + gvfs-daemon-smb \ $(NULL) libdaemon_la_SOURCES = \ @@ -48,3 +49,9 @@ gvfs_daemon_test_SOURCES = \ test.c gvfs_daemon_test_LDADD = $(libraries) + +gvfs_daemon_smb_SOURCES = \ + gvfsbackendsmb.c gvfsbackendsmb.h \ + smb.c + +gvfs_daemon_smb_LDADD = $(libraries) $(SAMBA_LIBS) diff --git a/daemon/gvfsbackend.c b/daemon/gvfsbackend.c index bf96bcc2..f2263368 100644 --- a/daemon/gvfsbackend.c +++ b/daemon/gvfsbackend.c @@ -307,7 +307,7 @@ void g_vfs_backend_register_with_daemon (GVfsBackend *backend, GVfsDaemon *daemon) { - g_print ("registering %s\n", backend->object_path); + g_print ("registering %s with %p\n", backend->object_path, daemon); g_vfs_daemon_add_job_source (daemon, G_VFS_JOB_SOURCE (backend)); g_vfs_daemon_register_path (daemon, backend->object_path, backend_dbus_handler, backend); diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c new file mode 100644 index 00000000..d284b8b7 --- /dev/null +++ b/daemon/gvfsbackendsmb.c @@ -0,0 +1,570 @@ +#include <config.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> + +#include <glib/gstdio.h> +#include <glib/gi18n.h> +#include <gio/gvfserror.h> +#include <gio/gfile.h> +#include <gio/gfilelocal.h> + +#include "gvfsbackendsmb.h" +#include "gvfsjobopenforread.h" +#include "gvfsjobread.h" +#include "gvfsjobseekread.h" +#include "gvfsjobgetinfo.h" +#include "gvfsjobenumerate.h" +#include "gvfsdaemonprotocol.h" + +G_DEFINE_TYPE (GVfsBackendSmb, g_vfs_backend_smb, G_TYPE_VFS_BACKEND); + +static GVfsBackendSmb *smb_backend = NULL; + +static void +g_vfs_backend_smb_finalize (GObject *object) +{ + GVfsBackendSmb *backend; + + backend = G_VFS_BACKEND_SMB (object); + + if (G_OBJECT_CLASS (g_vfs_backend_smb_parent_class)->finalize) + (*G_OBJECT_CLASS (g_vfs_backend_smb_parent_class)->finalize) (object); +} + +static void +g_vfs_backend_smb_init (GVfsBackendSmb *backend) +{ +} + +/* Authentication callback function type (traditional method) + * + * Type for the the authentication function called by the library to + * obtain authentication credentals + * + * @param srv Server being authenticated to + * @param shr Share being authenticated to + * @param wg Pointer to buffer containing a "hint" for the + * workgroup to be authenticated. Should be filled in + * with the correct workgroup if the hint is wrong. + * @param wglen The size of the workgroup buffer in bytes + * @param un Pointer to buffer containing a "hint" for the + * user name to be use for authentication. Should be + * filled in with the correct workgroup if the hint is + * wrong. + * @param unlen The size of the username buffer in bytes + * @param pw Pointer to buffer containing to which password + * copied + * @param pwlen The size of the password buffer in bytes + * + */ +static void +auth_callback (const char *server_name, const char *share_name, + char *domain_out, int domainmaxlen, + char *username_out, int unmaxlen, + char *password_out, int pwmaxlen) +{ + g_print ("auth_callback: %s %s\n", server_name, share_name); +} + +/* Add a server to the cache system + * + * @param c pointer to smb context + * @param srv pointer to server to add + * @param server server name + * @param share share name + * @param workgroup workgroup used to connect + * @param username username used to connect + * @return 0 on success. 1 on failure. + * + */ +static int +add_cached_server (SMBCCTX *context, SMBCSRV *new, + const char *server_name, const char *share_name, + const char *domain, const char *username) +{ + g_print ("add_cached_server\n"); + if (smb_backend->server != NULL) + return 1; + + smb_backend->server_name = g_strdup (server_name); + smb_backend->share_name = g_strdup (share_name); + smb_backend->domain = g_strdup (domain); + smb_backend->username = g_strdup (username); + smb_backend->server = new; + + return 0; +} + +/* Remove cached server + * + * @param c pointer to smb context + * @param srv pointer to server to remove + * @return 0 when found and removed. 1 on failure. + * + */ +static int +remove_cached_server(SMBCCTX * context, SMBCSRV * server) +{ + g_print ("remove_cached_server\n"); + if (smb_backend->server == server) + { + g_free (smb_backend->server_name); + smb_backend->server_name = NULL; + g_free (smb_backend->share_name); + smb_backend->share_name = NULL; + g_free (smb_backend->domain); + smb_backend->domain = NULL; + g_free (smb_backend->username); + smb_backend->username = NULL; + smb_backend->server = NULL; + return 0; + } + return 1; +} + + +/* Look up a server in the cache system + * + * @param c pointer to smb context + * @param server server name to match + * @param share share name to match + * @param workgroup workgroup to match + * @param username username to match + * @return pointer to SMBCSRV on success. NULL on failure. + * + */ +static SMBCSRV * +get_cached_server (SMBCCTX * context, + const char *server_name, const char *share_name, + const char *domain, const char *username) +{ + if (smb_backend->server != NULL && + strcmp (smb_backend->server_name, server_name) == 0 && + strcmp (smb_backend->share_name, server_name) == 0 && + strcmp (smb_backend->domain, domain) == 0 && + strcmp (smb_backend->username, username) == 0) + return smb_backend->server; + + return NULL; +} + +/* Try to remove all servers from the cache system and disconnect + * + * @param c pointer to smb context + * + * @return 0 when found and removed. 1 on failure. + * + */ +static int +purge_cached (SMBCCTX * context) +{ + if (smb_backend->server) + remove_cached_server(context, smb_backend->server); + + return 0; +} + +#define SUB_DELIM_CHARS "!$&'()*+,;=" + +static gboolean +is_valid (char c, const char *reserved_chars_allowed) +{ + if (g_ascii_isalnum (c) || + c == '-' || + c == '.' || + c == '_' || + c == '~') + return TRUE; + + if (reserved_chars_allowed && + strchr (reserved_chars_allowed, c) != NULL) + return TRUE; + + return FALSE; +} + +static void +g_string_append_encoded (GString *string, + const char *encoded, + const char *reserved_chars_allowed) +{ + char c; + static const gchar hex[16] = "0123456789ABCDEF"; + + while ((c = *encoded++) != 0) + { + if (is_valid (c, reserved_chars_allowed)) + g_string_append_c (string, c); + else + { + g_string_append_c (string, '%'); + g_string_append_c (string, hex[((guchar)c) >> 4]); + g_string_append_c (string, hex[((guchar)c) & 0xf]); + } + } +} + +static char * +create_smb_uri (const char *server, + const char *share, + const char *path) +{ + GString *uri; + + uri = g_string_new ("smb://"); + g_string_append_encoded (uri, server, NULL); + g_string_append_c (uri, '/'); + g_string_append_encoded (uri, share, NULL); + if (path != NULL) + { + if (*path != '/') + g_string_append_c (uri, '/'); + g_string_append_encoded (uri, path, SUB_DELIM_CHARS ":@/"); + } + return g_string_free (uri, FALSE); +} + + +GVfsBackendSmb * +g_vfs_backend_smb_new (const char *server, + const char *share) +{ + GVfsBackendSmb *backend; + char *obj_path, *bus_name; + SMBCCTX *smb_context; + int res; + char *uri; + struct stat st; + + g_assert (smb_backend == NULL); + + smb_context = smbc_new_context (); + if (smb_context == NULL) + return NULL; + + smb_context->debug = 0; + smb_context->callbacks.auth_fn = auth_callback; + + smb_context->callbacks.add_cached_srv_fn = add_cached_server; + smb_context->callbacks.get_cached_srv_fn = get_cached_server; + smb_context->callbacks.remove_cached_srv_fn = remove_cached_server; + smb_context->callbacks.purge_cached_fn = purge_cached; + +#if defined(HAVE_SAMBA_FLAGS) +#if defined(SMB_CTX_FLAG_USE_KERBEROS) && defined(SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS) + smb_context->flags |= SMB_CTX_FLAG_USE_KERBEROS | SMB_CTX_FLAG_FALLBACK_AFTER_KERBEROS; +#endif +#if defined(SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON) + //smb_context->flags |= SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON; +#endif +#endif + + if (0) + smbc_option_set(smb_context, "debug_stderr", (void *) 1); + + + if (!smbc_init_context (smb_context)) + { + g_print ("init context failed\n"); + smbc_free_context (smb_context, FALSE); + return NULL; + } + + obj_path = g_strdup_printf (G_VFS_DBUS_MOUNTPOINT_PATH"smbshare/h_%s/f_%s", server, share); + bus_name = g_strdup_printf (G_VFS_DBUS_MOUNTPOINT_NAME"smbshare.h_%s.f_%s", server, share); + + backend = g_object_new (G_TYPE_VFS_BACKEND_SMB, + "object-path", obj_path, + "bus-name", bus_name, + NULL); + smb_backend = backend; + backend->smb_context = smb_context; + + uri = create_smb_uri (server, share, NULL); + res = smb_context->stat (smb_context, uri, &st); + g_free (uri); + if (res != 0) + { + g_object_unref (backend); + return NULL; + } + + return backend; +} + +static gboolean +open_idle_cb (gpointer data) +{ + GVfsJobOpenForRead *job = data; + int fd; + + if (g_vfs_job_is_cancelled (G_VFS_JOB (job))) + { + g_vfs_job_failed (G_VFS_JOB (job), G_VFS_ERROR, + G_VFS_ERROR_CANCELLED, + _("Operation was cancelled")); + return FALSE; + } + + fd = g_open (job->filename, O_RDONLY); + if (fd == -1) + { + g_vfs_job_failed (G_VFS_JOB (job), G_FILE_ERROR, + g_file_error_from_errno (errno), + "Error opening file %s: %s", + job->filename, g_strerror (errno)); + } + else + { + g_vfs_job_open_for_read_set_can_seek (job, TRUE); + g_vfs_job_open_for_read_set_handle (job, GINT_TO_POINTER (fd)); + g_vfs_job_succeeded (G_VFS_JOB (job)); + } + return FALSE; +} + +static void +open_read_cancelled_cb (GVfsJob *job, gpointer data) +{ + guint tag = GPOINTER_TO_INT (data); + + g_print ("open_read_cancelled_cb\n"); + + if (g_source_remove (tag)) + g_vfs_job_failed (job, G_VFS_ERROR, + G_VFS_ERROR_CANCELLED, + _("Operation was cancelled")); +} + +static gboolean +do_open_for_read (GVfsBackend *backend, + GVfsJobOpenForRead *job, + char *filename) +{ + GError *error; + + g_print ("open_for_read (%s)\n", filename); + + if (strcmp (filename, "/fail") == 0) + { + error = g_error_new (G_FILE_ERROR, G_FILE_ERROR_IO, "Smb error"); + g_vfs_job_failed_from_error (G_VFS_JOB (job), error); + return TRUE; + } + else + { + guint tag = g_timeout_add (0, open_idle_cb, job); + g_signal_connect (job, "cancelled", (GCallback)open_read_cancelled_cb, GINT_TO_POINTER (tag)); + return TRUE; + } +} + +static gboolean +read_idle_cb (gpointer data) +{ + GVfsJobRead *job = data; + int fd; + ssize_t res; + + fd = GPOINTER_TO_INT (job->handle); + + res = read (fd, job->buffer, job->bytes_requested); + + if (res == -1) + { + g_vfs_job_failed (G_VFS_JOB (job), G_FILE_ERROR, + g_file_error_from_errno (errno), + "Error reading from file: %s", + g_strerror (errno)); + } + else + { + g_vfs_job_read_set_size (job, res); + g_vfs_job_succeeded (G_VFS_JOB (job)); + } + + return FALSE; +} + +static void +read_cancelled_cb (GVfsJob *job, gpointer data) +{ + guint tag = GPOINTER_TO_INT (job->backend_data); + + g_source_remove (tag); + g_vfs_job_failed (job, G_VFS_ERROR, + G_VFS_ERROR_CANCELLED, + _("Operation was cancelled")); +} + +static gboolean +do_read (GVfsBackend *backend, + GVfsJobRead *job, + GVfsBackendHandle handle, + char *buffer, + gsize bytes_requested) +{ + guint tag; + + g_print ("read (%d)\n", bytes_requested); + + tag = g_timeout_add (0, read_idle_cb, job); + G_VFS_JOB (job)->backend_data = GINT_TO_POINTER (tag); + g_signal_connect (job, "cancelled", (GCallback)read_cancelled_cb, NULL); + + return TRUE; +} + +static gboolean +do_seek_on_read (GVfsBackend *backend, + GVfsJobSeekRead *job, + GVfsBackendHandle handle, + goffset offset, + GSeekType type) +{ + int whence; + int fd; + off_t final_offset; + + g_print ("seek_on_read (%d, %d)\n", (int)offset, type); + + switch (type) + { + default: + case G_SEEK_SET: + whence = SEEK_SET; + break; + case G_SEEK_CUR: + whence = SEEK_CUR; + break; + case G_SEEK_END: + whence = SEEK_END; + break; + } + + + fd = GPOINTER_TO_INT (handle); + + final_offset = lseek (fd, offset, whence); + + if (final_offset == (off_t)-1) + { + g_vfs_job_failed (G_VFS_JOB (job), G_FILE_ERROR, + g_file_error_from_errno (errno), + "Error seeking in file: %s", + g_strerror (errno)); + } + else + { + g_vfs_job_seek_read_set_offset (job, offset); + g_vfs_job_succeeded (G_VFS_JOB (job)); + } + + return TRUE; +} + +static gboolean +do_close_read (GVfsBackend *backend, + GVfsJobCloseRead *job, + GVfsBackendHandle handle) +{ + int fd; + + g_print ("close ()\n"); + + fd = GPOINTER_TO_INT (handle); + close(fd); + + g_vfs_job_succeeded (G_VFS_JOB (job)); + + return TRUE; +} + +static gboolean +do_get_info (GVfsBackend *backend, + GVfsJobGetInfo *job, + char *filename, + GFileInfoRequestFlags requested, + const char *attributes, + gboolean follow_symlinks) +{ + GFile *file; + GFileInfo *info; + GError *error; + + file = g_file_local_new (filename); + + error = NULL; + info = g_file_get_info (file, requested, attributes, follow_symlinks, + NULL, &error); + + if (info) + { + g_vfs_job_get_info_set_info (job, requested, info); + g_vfs_job_succeeded (G_VFS_JOB (job)); + } + else + g_vfs_job_failed_from_error (G_VFS_JOB (job), error); + + g_object_unref (info); + g_object_unref (file); + + return TRUE; +} + +static gboolean +do_enumerate (GVfsBackend *backend, + GVfsJobEnumerate *job, + char *filename, + GFileInfoRequestFlags requested, + const char *attributes, + gboolean follow_symlinks) +{ + GFileInfo *info1, *info2;; + GList *l; + + g_vfs_job_enumerate_set_result (job, requested); + g_vfs_job_succeeded (G_VFS_JOB (job)); + + info1 = g_file_info_new (); + info2 = g_file_info_new (); + g_file_info_set_name (info1, "file1"); + g_file_info_set_file_type (info1, G_FILE_TYPE_REGULAR); + g_file_info_set_name (info2, "file2"); + g_file_info_set_file_type (info2, G_FILE_TYPE_REGULAR); + + l = NULL; + l = g_list_append (l, info1); + l = g_list_append (l, info2); + + g_vfs_job_enumerate_add_info (job, l); + + g_list_free (l); + g_object_unref (info1); + g_object_unref (info2); + + g_vfs_job_enumerate_done (job); + + return TRUE; +} + +static void +g_vfs_backend_smb_class_init (GVfsBackendSmbClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass); + + gobject_class->finalize = g_vfs_backend_smb_finalize; + + backend_class->open_for_read = do_open_for_read; + backend_class->read = do_read; + backend_class->seek_on_read = do_seek_on_read; + backend_class->close_read = do_close_read; + backend_class->get_info = do_get_info; + backend_class->enumerate = do_enumerate; +} diff --git a/daemon/gvfsbackendsmb.h b/daemon/gvfsbackendsmb.h new file mode 100644 index 00000000..99a967e3 --- /dev/null +++ b/daemon/gvfsbackendsmb.h @@ -0,0 +1,46 @@ +#ifndef __G_VFS_BACKEND_SMB_H__ +#define __G_VFS_BACKEND_SMB_H__ + +#include <gvfsbackend.h> + +#include <libsmbclient.h> + +G_BEGIN_DECLS + +#define G_TYPE_VFS_BACKEND_SMB (g_vfs_backend_smb_get_type ()) +#define G_VFS_BACKEND_SMB(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_VFS_BACKEND_SMB, GVfsBackendSmb)) +#define G_VFS_BACKEND_SMB_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_VFS_BACKEND_SMB, GVfsBackendSmbClass)) +#define G_IS_VFS_BACKEND_SMB(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_VFS_BACKEND_SMB)) +#define G_IS_VFS_BACKEND_SMB_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_VFS_BACKEND_SMB)) +#define G_VFS_BACKEND_SMB_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_VFS_BACKEND_SMB, GVfsBackendSmbClass)) + +typedef struct _GVfsBackendSmb GVfsBackendSmb; +typedef struct _GVfsBackendSmbClass GVfsBackendSmbClass; + +struct _GVfsBackendSmb +{ + GVfsBackend parent_instance; + + SMBCCTX *smb_context; + + /* Cache */ + char *server_name; + char *share_name; + char *domain; + char *username; + SMBCSRV *server; +}; + +struct _GVfsBackendSmbClass +{ + GVfsBackendClass parent_class; +}; + +GType g_vfs_backend_smb_get_type (void) G_GNUC_CONST; + +GVfsBackendSmb *g_vfs_backend_smb_new (const char *server, + const char *share); + +G_END_DECLS + +#endif /* __G_VFS_BACKEND_SMB_H__ */ diff --git a/daemon/smb.c b/daemon/smb.c new file mode 100644 index 00000000..5f3c6416 --- /dev/null +++ b/daemon/smb.c @@ -0,0 +1,54 @@ +#include <config.h> + +#include <stdlib.h> + +#include <glib.h> +#include <dbus/dbus.h> +#include <dbus-gmain.h> +#include "gvfsdaemon.h" +#include "gvfsbackendsmb.h" +#include <gvfsdaemonprotocol.h> + +int +main (int argc, char *argv[]) +{ + GMainLoop *loop; + GVfsDaemon *daemon; + GVfsBackendSmb *backend; + const char *server, *share; + + if (argc < 3) + { + g_print ("Args: server share\n"); + return 0; + } + + server = argv[1]; + share = argv[2]; + + g_thread_init (NULL); + + g_type_init (); + + daemon = g_vfs_daemon_new (FALSE, FALSE); + if (daemon == NULL) + return 1; + + backend = g_vfs_backend_smb_new (server, share); + + if (backend == NULL) + { + g_print ("Failed instantiating backend\n"); + return 1; + } + + g_vfs_backend_register_with_daemon (G_VFS_BACKEND (backend), daemon); + g_object_unref (backend); + + loop = g_main_loop_new (NULL, FALSE); + + g_print ("Entering mainloop\n"); + g_main_loop_run (loop); + + return 0; +} |