Initial commit of prototype. - susmb - mounting of SMB/CIFS shares via FUSE
HTML git clone git://git.codemadness.org/susmb
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
DIR commit 5f2b4da911cafeff284a07cb31b8bdca77e84ac8
DIR parent d1d535c39adce75ac738e897f932070ff8966e6a
HTML Author: geoff <devnull@localhost>
Date: Sat, 6 May 2006 22:02:40 +0000
Initial commit of prototype.
Diffstat:
A Makefile | 19 +++++++++++++++++++
A usmb.c | 211 +++++++++++++++++++++++++++++++
A usmb.h | 13 +++++++++++++
A usmb_dir.c | 104 +++++++++++++++++++++++++++++++
A usmb_dir.h | 14 ++++++++++++++
A usmb_file.c | 78 +++++++++++++++++++++++++++++++
A usmb_file.h | 18 ++++++++++++++++++
A utils.c | 66 +++++++++++++++++++++++++++++++
A utils.h | 6 ++++++
9 files changed, 529 insertions(+), 0 deletions(-)
---
DIR diff --git a/Makefile b/Makefile
@@ -0,0 +1,19 @@
+SAMBA = /opt/samba
+CC = gcc
+CFLAGS = -Wall -W -std=c99 -pedantic -O $(shell pkg-config --cflags fuse) \
+ -I$(SAMBA)/include -D_BSD_SOURCE -DFUSE_USE_VERSION=25 # -DDEBUG
+LDLIBS = $(shell pkg-config --libs-only-l fuse) -lsmbclient
+LDFLAGS = $(shell pkg-config --libs-only-L fuse) -L$(SAMBA)/lib
+
+SOURCES = usmb.c usmb_dir.c usmb_file.c utils.c
+OBJECTS = $(SOURCES:.c=.o)
+
+PROGRAM = usmb
+
+all: $(PROGRAM)
+
+$(PROGRAM): $(OBJECTS)
+ $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
+
+clean:
+ $(RM) $(PROGRAM) $(OBJECTS)
DIR diff --git a/usmb.c b/usmb.c
@@ -0,0 +1,211 @@
+#include <sys/time.h> // struct timeval needed by libsmbclient.h
+#include <libsmbclient.h>
+#include <fuse.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "usmb.h"
+#include "usmb_dir.h"
+#include "usmb_file.h"
+
+
+
+#define INIT_LEN 256
+static char * concat_strings (int num, ...)
+{
+ va_list ap;
+
+ char *base, *out;
+
+ base = out = malloc (INIT_LEN);
+ if (NULL == base)
+ return NULL;
+
+ size_t buff_size = INIT_LEN;
+
+ va_start (ap, num);
+ for (int i = 0; i < num; ++i)
+ {
+ const char *next = va_arg (ap, const char *);
+ assert (NULL != next);
+
+ size_t next_len = strlen (next);
+ size_t required = (out - base) + next_len + 1;
+
+ if (buff_size < required)
+ {
+ while (buff_size < required)
+ {
+ size_t dbl_len = buff_size * 2;
+ if (dbl_len < buff_size)
+ {
+ free (base);
+ return NULL;
+ }
+
+ buff_size = dbl_len;
+ }
+
+ ptrdiff_t diff = out - base;
+
+ char *newbase = realloc (base, buff_size);
+ if (NULL == newbase)
+ {
+ free (base);
+ return NULL;
+ }
+
+ base = newbase;
+ out = base + diff;
+ }
+
+ memcpy (out, next, next_len);
+ out += next_len;
+ }
+ va_end (ap);
+
+ *out = '\0';
+ return base;
+}
+
+
+static const char *share = "//127.0.0.1/geoff";
+
+char * make_url (const char *path)
+{
+ DEBUG (fprintf (stderr, "make_url (%s)\n", path));
+ if ((NULL == path) || ('\0' == path[0]))
+ return concat_strings (2, "smb:", share);
+ else
+ return concat_strings (3, "smb:", share, path);
+}
+
+#if 0
+static void dump_dirent (struct smbc_dirent *dirent)
+{
+ switch (dirent->smbc_type)
+ {
+ case SMBC_WORKGROUP: fputs (" Workgroup", stdout); break;
+ case SMBC_SERVER: fputs (" Server", stdout); break;
+ case SMBC_FILE_SHARE: fputs (" File Share", stdout); break;
+ case SMBC_PRINTER_SHARE: fputs ("Printer Share", stdout); break;
+ case SMBC_COMMS_SHARE: fputs (" Comms Share", stdout); break;
+ case SMBC_IPC_SHARE: fputs (" IPC Share", stdout); break;
+ case SMBC_DIR: fputs (" Directory", stdout); break;
+ case SMBC_FILE: fputs (" File", stdout); break;
+ case SMBC_LINK: fputs (" Link", stdout); break;
+ default: fputs (" Unknown", stdout); break;
+ }
+
+ fputs (" - ", stdout);
+
+ puts (dirent->name);
+}
+#endif
+
+
+static inline void do_strncpy (char *to, const char *from, int tolen)
+{
+ strncpy (to, from, tolen);
+ to[tolen - 1] = '\0';
+}
+
+
+static void auth_fn (const char *srv, const char *shr, char *wg, int wglen,
+ char *un, int unlen, char *pw, int pwlen)
+{
+ DEBUG (fprintf (stderr, "Authenticating for \\\\%s\\%s\n", srv, shr));
+
+ do_strncpy (wg, "WORKGROUP", wglen);
+ do_strncpy (un, "geoff", unlen);
+ do_strncpy (pw, "ze]T72%5V", pwlen);
+}
+
+
+static void * usmb_init (void)
+{
+ return NULL;
+}
+
+
+static void usmb_destroy (void *unused)
+{
+ (void)unused;
+}
+
+
+#define usmb_readlink NULL
+#define usmb_mknod NULL
+#define usmb_unlink NULL
+#define usmb_symlink NULL
+#define usmb_rename NULL
+#define usmb_chmod NULL
+#define usmb_chown NULL
+#define usmb_truncate NULL
+#define usmb_utime NULL
+#define usmb_statfs NULL
+#define usmb_flush NULL
+#define usmb_release NULL
+#define usmb_fsync NULL
+#define usmb_access NULL
+#define usmb_create NULL
+#define usmb_ftruncate NULL
+
+
+static struct fuse_operations fuse_ops = {
+ .getattr = usmb_getattr,
+ .readlink = usmb_readlink,
+ .getdir = NULL,
+ .mknod = usmb_mknod,
+ .mkdir = usmb_mkdir,
+ .unlink = usmb_unlink,
+ .rmdir = usmb_rmdir,
+ .symlink = usmb_symlink,
+ .rename = usmb_rename,
+ .link = NULL,
+ .chmod = usmb_chmod,
+ .chown = usmb_chown,
+ .truncate = usmb_truncate,
+ .utime = usmb_utime,
+ .open = usmb_open,
+ .read = usmb_read,
+ .write = usmb_write,
+ .statfs = usmb_statfs,
+ .flush = usmb_flush,
+ .release = usmb_release,
+ .fsync = usmb_fsync,
+#ifdef SETXATTR
+ .setxattr = usmb_setxattr,
+ .getxattr = usmb_getxattr,
+ .listxattr = usmb_listxattr,
+ .removexattr = usmb_removexattr,
+#endif
+ .opendir = usmb_opendir,
+ .readdir = usmb_readdir,
+ .releasedir = usmb_releasedir,
+ .fsyncdir = NULL,
+ .init = usmb_init,
+ .destroy = usmb_destroy,
+ .access = usmb_access,
+ .create = usmb_create,
+ .ftruncate = usmb_ftruncate,
+ .fgetattr = usmb_fgetattr
+};
+
+
+
+int main (int argc, char **argv)
+{
+ if (0 != smbc_init (auth_fn, 0))
+ {
+ perror ("Cannot initialise SMB library");
+ return EXIT_FAILURE;
+ }
+
+ return fuse_main (argc, argv, &fuse_ops);
+}
+
DIR diff --git a/usmb.h b/usmb.h
@@ -0,0 +1,13 @@
+#ifndef USMB_H
+ #define USMB_H
+
+ #ifdef DEBUG
+ #undef DEBUG
+ #define DEBUG(x) (x)
+ #else
+ #define DEBUG(x) ((void)0)
+ #endif
+
+ char * make_url (const char *path);
+
+#endif
DIR diff --git a/usmb_dir.c b/usmb_dir.c
@@ -0,0 +1,104 @@
+#include <sys/time.h> // struct timeval needed by libsmbclient.h
+#include <libsmbclient.h>
+#include <fuse.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "usmb_dir.h"
+#include "usmb.h"
+
+
+int usmb_mkdir (const char *dirname, mode_t mode)
+{
+ char *url = make_url (dirname);
+ if (NULL == url)
+ return -ENOMEM;
+
+ DEBUG (fprintf (stderr, "mkdir (%s)\n", url));
+ int ret = smbc_mkdir (dirname, mode) ? -errno : 0;
+ free (url);
+ return ret;
+}
+
+
+int usmb_rmdir (const char *dirname)
+{
+ char *url = make_url (dirname);
+ if (NULL == url)
+ return -ENOMEM;
+
+ DEBUG (fprintf (stderr, "mkdir (%s)\n", url));
+ int ret = smbc_rmdir (dirname) ? -errno : 0;
+ free (url);
+ return ret;
+}
+
+
+int usmb_opendir (const char *dirname, struct fuse_file_info *fi)
+{
+ char *url = make_url (dirname);
+ if (NULL == url)
+ return -ENOMEM;
+
+ DEBUG (fprintf (stderr, "opendir (%s)\n", url));
+ int fd = smbc_opendir (url);
+ fi->fh = fd;
+
+ int ret = (fd < 0) ? -errno : 0;
+ free (url);
+ return ret;
+}
+
+
+int usmb_readdir (const char *path, void *h, fuse_fill_dir_t filler,
+ off_t offset, struct fuse_file_info *fi)
+{
+ (void)path;
+ (void)offset;
+
+ DEBUG (fprintf (stderr, "readdir (%s)\n", path));
+
+ struct smbc_dirent *dirent;
+ errno = 0;
+ while (NULL != (dirent = smbc_readdir (fi->fh)))
+ {
+ struct stat stbuf;
+
+ switch (dirent->smbc_type)
+ {
+ case SMBC_DIR:
+ stbuf.st_mode = DT_DIR << 12;
+ break;
+
+ case SMBC_FILE:
+ stbuf.st_mode = DT_REG << 12;
+ break;
+
+ case SMBC_LINK:
+ stbuf.st_mode = DT_LNK << 12;
+ break;
+
+ default:
+ break;
+ }
+
+ if (1 == filler (h, dirent->name, &stbuf, 0)) /* if error */
+ return -1;
+ }
+
+ return -errno;
+}
+
+
+int usmb_releasedir (const char *path, struct fuse_file_info *fi)
+{
+ (void)path;
+
+ DEBUG (fprintf (stderr, "releasedir (%s)\n", path));
+ return (smbc_closedir (fi->fh) < 0) ? -errno : 0;
+}
+
DIR diff --git a/usmb_dir.h b/usmb_dir.h
@@ -0,0 +1,14 @@
+#ifndef USMB_DIR_H
+ #define USMB_DIR_H
+
+ #include <sys/types.h>
+ #include <fuse.h>
+
+ int usmb_mkdir (const char *dirname, mode_t mode);
+ int usmb_rmdir (const char *dirname);
+ int usmb_opendir (const char *dirname, struct fuse_file_info *fi);
+ int usmb_readdir (const char *path, void *h, fuse_fill_dir_t filler,
+ off_t offset, struct fuse_file_info *fi);
+ int usmb_releasedir (const char *path, struct fuse_file_info *fi);
+
+#endif
DIR diff --git a/usmb_file.c b/usmb_file.c
@@ -0,0 +1,78 @@
+#include <sys/time.h> // struct timeval needed by libsmbclient.h
+#include <libsmbclient.h>
+#include <fuse.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "usmb_file.h"
+#include "usmb.h"
+
+
+int usmb_getattr (const char *filename, struct stat *st)
+{
+ char *url = make_url (filename);
+ DEBUG (fprintf (stderr, "stat (%s)\n", url));
+
+ int ret = smbc_stat (url, st);
+ free (url);
+ return (ret < 0) ? -errno : 0;
+}
+
+
+int usmb_fgetattr (const char *filename, struct stat *st,
+ struct fuse_file_info *fi)
+{
+ (void)filename;
+ return (smbc_fstat (fi->fh, st) < 0) ? -errno : 0;
+}
+
+
+int usmb_open (const char *filename, struct fuse_file_info *fi)
+{
+ char *url = make_url (filename);
+ if (NULL == url)
+ return -ENOMEM;
+
+ DEBUG (fprintf (stderr, "open (%s)\n", url));
+
+ int fd = smbc_open (url, 0, 0);
+ int ret = (fd < 0) ? -errno : 0;
+ fi->fh = fd;
+
+ free (url);
+ return ret;
+}
+
+
+int usmb_release (const char *filename, struct fuse_file_info *fi)
+{
+ (void)filename;
+ return (smbc_close (fi->fh) < 0) ? -errno : 0;
+}
+
+
+int usmb_read (const char *filename, char *buff, size_t len, off_t off,
+ struct fuse_file_info *fi)
+{
+ (void)filename;
+ (void)off;
+
+ /* TODO: this may be WRONG: do we need to consider the offset */
+ DEBUG (fprintf (stderr, "read (%p, %u)\n", buff, len));
+ return smbc_read (fi->fh, buff, len);
+}
+
+
+int usmb_write (const char *filename, const char *buff, size_t len, off_t off,
+ struct fuse_file_info *fi)
+{
+ (void)filename;
+ (void)off;
+
+ /* TODO: this may be WRONG: do we need to consider the offset */
+ DEBUG (fprintf (stderr, "write (%p, %u)\n", buff, len));
+ return smbc_write (fi->fh, (char *)buff, len) ? -errno : 0;
+}
+
DIR diff --git a/usmb_file.h b/usmb_file.h
@@ -0,0 +1,18 @@
+#ifndef USMB_FILE_H
+ #define USMB_FILE_H
+
+ #include <fuse.h>
+ #include <stddef.h>
+ #include <sys/types.h>
+
+ int usmb_getattr (const char *filename, struct stat *st);
+ int usmb_fgetattr (const char *filename, struct stat *st,
+ struct fuse_file_info *fi);
+ int usmb_open (const char *filename, struct fuse_file_info *fi);
+ int usmb_release (const char *filename, struct fuse_file_info *fi);
+ int usmb_read (const char *filename, char *buff, size_t len, off_t off,
+ struct fuse_file_info *fi);
+ int usmb_write (const char *filename, const char *buff, size_t len, off_t off,
+ struct fuse_file_info *fi);
+
+#endif
DIR diff --git a/utils.c b/utils.c
@@ -0,0 +1,66 @@
+#include <assert.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include "utils.h"
+
+
+#define INIT_LEN 256
+char * concat_strings (int num, ...)
+{
+ va_list ap;
+
+ char *base, *out;
+
+ base = out = malloc (INIT_LEN);
+ if (NULL == base)
+ return NULL;
+
+ size_t buff_size = INIT_LEN;
+
+ va_start (ap, num);
+ for (int i = 0; i < num; ++i)
+ {
+ const char *next = va_arg (ap, const char *);
+ assert (NULL != next);
+
+ size_t next_len = strlen (next);
+ size_t required = (out - base) + next_len + 1;
+
+ if (buff_size < required)
+ {
+ while (buff_size < required)
+ {
+ size_t dbl_len = buff_size * 2;
+ if (dbl_len < buff_size)
+ {
+ free (base);
+ return NULL;
+ }
+
+ buff_size = dbl_len;
+ }
+
+ ptrdiff_t diff = out - base;
+
+ char *newbase = realloc (base, buff_size);
+ if (NULL == newbase)
+ {
+ free (base);
+ return NULL;
+ }
+
+ base = newbase;
+ out = base + diff;
+ }
+
+ memcpy (out, next, next_len);
+ out += next_len;
+ }
+ va_end (ap);
+
+ *out = '\0';
+ return base;
+}
+
DIR diff --git a/utils.h b/utils.h
@@ -0,0 +1,6 @@
+#ifndef UTILS_H
+ #define UTILS_H
+
+ char * concat_strings (int num, ...);
+
+#endif