Introduction
Introduction Statistics Contact Development Disclaimer Help
fork usmb 20130204 to susmb - susmb - mounting of SMB/CIFS shares via FUSE
git clone git://git.codemadness.org/susmb
Log
Files
Refs
README
LICENSE
---
commit af92f1402be85b1819f2ba2dda8cae9ff5381b69
parent aa94e132c12faf1a00f547ea4a96b5728612dea6
Author: Hiltjo Posthuma <[email protected]>
Date: Wed, 5 Mar 2025 19:23:52 +0100
fork usmb 20130204 to susmb
Based off git commit aa94e132c12faf1a00f547ea4a96b5728612dea6
http://repo.or.cz/w/usmb.git/snapshot/aa94e132c12faf1a00f547ea4a96b5728612dea6.…
See the README for a summary of the most important changes.
Diffstat:
D .gitignore | 10 ----------
D INSTALL | 35 -----------------------------…
R COPYING -> LICENSE | 0
A Makefile | 102 +++++++++++++++++++++++++++++…
D Makefile.in | 134 -----------------------------…
M README | 133 ++++++++++++++++++-----------…
D aclocal.m4 | 155 -----------------------------…
D conffile.c | 237 -----------------------------…
D conffile.h | 27 ---------------------------
D config.rng | 48 -----------------------------…
D configure.ac | 96 -----------------------------…
D debian/Makefile.pkgdeb | 43 ------------------------------
D debian/changelog | 5 -----
D debian/compat | 1 -
D debian/control | 29 -----------------------------
D debian/copyright | 25 -------------------------
D debian/rules | 3 ---
D debian/usmb.docs | 2 --
D install-sh | 519 -----------------------------…
D options.c | 192 -----------------------------…
D options.h | 26 --------------------------
D password.c | 86 ------------------------------
D password.h | 24 ------------------------
D samba30_compat.c | 72 -----------------------------…
D samba32_compat.c | 40 -----------------------------…
D samba33_compat.c | 49 -----------------------------…
D samba3x-compat.h | 283 -----------------------------…
A susmb.1 | 86 ++++++++++++++++++++++++++++++
A susmb.c | 1377 +++++++++++++++++++++++++++++…
D usmb.1 | 156 -----------------------------…
D usmb.c | 336 -----------------------------…
D usmb.conf | 61 -----------------------------…
D usmb.h | 43 ------------------------------
D usmb_dir.c | 217 -----------------------------…
D usmb_dir.h | 36 -----------------------------…
D usmb_file.c | 339 -----------------------------…
D usmb_file.h | 43 ------------------------------
D utils.c | 216 -----------------------------…
D utils.h | 47 -----------------------------…
D version.c | 72 -----------------------------…
D version.h | 25 -------------------------
D version.m4 | 5 -----
D xml.c | 187 -----------------------------…
D xml.h | 34 -----------------------------…
44 files changed, 1642 insertions(+), 4014 deletions(-)
---
diff --git a/.gitignore b/.gitignore
@@ -1,10 +0,0 @@
-Makefile
-autom4te.cache
-config.h
-config.h.in
-config.log
-config.status
-configure
-config.rng.h
-usmb
-*.o
diff --git a/INSTALL b/INSTALL
@@ -1,35 +0,0 @@
-usmb - Unprivileged mounting of SMB/CIFS shares via FUSE
-========================================================
-
-Pre-Requisites
---------------
-
-glib 2.6 or later - www.gtk.org.
-libxml2 - ftp.gnome.org.
-FUSE 2.6 or later - fuse.sourgeforge.net.
-libsmbclient 3.0 (part of Samba) - www.samba.org.
-
-You need GNU sed to build usmb.
-
-If you aren't using a usmb release tarball (e.g if you're using a development
-snapshot or a git clone) then you need a recent (post-2.63) version of GNU
-autoconf to be installed.
-
-
-Installation
-------------
-
-[ -x ./configure ] || autoreconf
-./configure
-make
-make install # Maybe as root, depending on your installation prefix.
-
-If the configure script says "Cannot find libsmbclient" then use
---with-samba=xxx to tell it where Samba is installed.
-
-
-Configuration etc.
-------------------
-
-Please see the README.
-
diff --git a/COPYING b/LICENSE
diff --git a/Makefile b/Makefile
@@ -0,0 +1,102 @@
+.POSIX:
+
+NAME = susmb
+VERSION = 0.9
+
+# paths
+PREFIX = /usr/local
+MANPREFIX = ${PREFIX}/man
+DOCPREFIX = ${PREFIX}/share/doc/${NAME}
+
+# use system flags.
+SUSMB_CFLAGS = ${CFLAGS}
+SUSMB_LDFLAGS = ${LDFLAGS}
+SUSMB_CPPFLAGS = -D_DEFAULT_SOURCE
+
+# test: debug
+#SUSMB_CFLAGS = -O0 -g -ggdb -Wall -Wextra -pedantic -Wformat-security -Winit-…
+
+# Linux
+#SUSMB_CFLAGS += -D_GNU_SOURCE
+# Linux: use libbsd (arc4random, etc).
+#SUSMB_LDFLAGS += -lbsd
+
+# pkg-config --cflags smbclient
+SMBCLIENT_CFLAGS = -I/usr/local/include/samba-4.0
+# Linux:
+#SMBCLIENT_CFLAGS = -I/usr/include/samba-4.0
+# pkg-config --libs smbclient
+SMBCLIENT_LDFLAGS = -L/usr/local/lib -lsmbclient
+# Linux:
+#SMBCLIENT_LDFLAGS = -lsmbclient
+
+# pkg-config --cflags fuse
+FUSE_CFLAGS = -I/usr/local/include
+# Linux:
+#FUSE_CFLAGS = -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse
+
+# pkg-config --libs fuse
+FUSE_LDFLAGS = -lfuse
+# Linux:
+#FUSE_LDFLAGS = -lfuse -pthread
+
+BIN = ${NAME}
+SCRIPTS =
+SRC = ${BIN:=.c}
+HDR =
+MAN1 = ${BIN:=.1}\
+ ${SCRIPTS:=.1}
+DOC = \
+ LICENSE\
+ README
+
+all: ${BIN}
+
+${BIN}: ${@:=.o}
+
+OBJ = ${SRC:.c=.o}
+
+${OBJ}: ${HDR}
+
+.o:
+ ${CC} -o $@ $< ${SUSMB_LDFLAGS} ${SMBCLIENT_LDFLAGS} ${FUSE_LDFLAGS} $…
+
+.c.o:
+ ${CC} -o $@ -c $< ${SUSMB_CPPFLAGS} ${SMBCLIENT_CFLAGS} ${FUSE_CFLAGS}…
+
+dist:
+ rm -rf "${NAME}-${VERSION}"
+ mkdir -p "${NAME}-${VERSION}"
+ cp -f ${MAN1} ${DOC} ${HDR} ${SCRIPTS} \
+ ${SRC} Makefile "${NAME}-${VERSION}"
+ # make tarball
+ tar cf - "${NAME}-${VERSION}" | gzip -c > "${NAME}-${VERSION}.tar.gz"
+ rm -rf "${NAME}-${VERSION}"
+
+clean:
+ rm -f ${BIN} ${OBJ}
+
+install: all
+ # installing executable files and scripts.
+ mkdir -p "${DESTDIR}${PREFIX}/bin"
+ cp -f ${BIN} ${SCRIPTS} "${DESTDIR}${PREFIX}/bin"
+ for f in ${BIN} ${SCRIPTS}; do chmod 755 "${DESTDIR}${PREFIX}/bin/$$f"…
+ # installing example files.
+ mkdir -p "${DESTDIR}${DOCPREFIX}"
+ cp -f ${DOC} "${DESTDIR}${DOCPREFIX}"
+ for d in ${DOC}; do chmod 644 "${DESTDIR}${DOCPREFIX}/$$d"; done
+ # installing manual pages for general commands: section 1.
+ mkdir -p "${DESTDIR}${MANPREFIX}/man1"
+ cp -f ${MAN1} "${DESTDIR}${MANPREFIX}/man1"
+ for m in ${MAN1}; do chmod 644 "${DESTDIR}${MANPREFIX}/man1/$$m"; done
+
+uninstall:
+ # removing executable files and scripts.
+ for f in ${BIN} ${SCRIPTS}; do rm -f "${DESTDIR}${PREFIX}/bin/$$f"; do…
+ # removing example files.
+ for d in ${DOC}; do rm -f "${DESTDIR}${DOCPREFIX}/$$d"; done
+ -rmdir "${DESTDIR}${DOCPREFIX}"
+ # removing manual pages.
+ for m in ${MAN1}; do rm -f "${DESTDIR}${MANPREFIX}/man1/$$m"; done
+
+.PHONY: all clean dist install uninstall
diff --git a/Makefile.in b/Makefile.in
@@ -1,134 +0,0 @@
-# usmb - mount SMB shares via FUSE and Samba
-#
-# @configure_input@
-#
-# Copyright (C) 2006-2013 Geoff Johnstone
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 3 as
-# published by the Free Software Foundation.
-#
-# 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, see <http://www.gnu.org/licenses/>.
-
-CC = @CC@
-
-prefix = ${DESTDIR}@prefix@
-exec_prefix = @exec_prefix@
-bindir = @bindir@
-datarootdir = @datarootdir@
-mandir = @mandir@
-man1dir = $(mandir)/man1
-
-CFLAGS = @CFLAGS@ -I@srcdir@ -I@builddir@ -Werror
-LDFLAGS = @LDFLAGS@
-LIBS = @LIBS@
-
-CFLAGS += @LIBXML2_CFLAGS@ @GLIB_CFLAGS@ @FUSE_CFLAGS@
-LIBS += @LIBXML2_LIBS@ @GLIB_LIBS@ @FUSE_LIBS@
-
-SOURCES = conffile.c options.c password.c usmb.c usmb_dir.c usmb_file.c \
- utils.c version.c xml.c samba@SAMBA_VERSION@_compat.c
-OBJECTS = $(SOURCES:.c=.o)
-
-PROGRAM = @PACKAGE_NAME@
-MANPAGE = $(PROGRAM).1
-
-
-all: $(PROGRAM)
-
-
-$(PROGRAM): $(OBJECTS)
- $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
-
-
-clean:
- $(RM) $(PROGRAM) $(OBJECTS)
-
-
-distclean: clean
- $(RM) -r core usmb-*.tar.bz2 usmb-*.tar.gz doc/*.mdzip.bak config.rng.…
- autom4te.cache config.h.in~ config.status config.log config.h \
- Makefile
-
-
-allclean: distclean
- $(RM) configure config.h.in autom4te.cache
-
-
-install-strip: STRIPFLAGS = -s
-install install-strip: $(PROGRAM)
- @MKDIR_P@ $(bindir) $(man1dir)
- @INSTALL@ -m 755 $(STRIPFLAGS) $(PROGRAM) $(bindir)/
- @INSTALL@ -m 644 $(MANPAGE) $(man1dir)/
-
-
-uninstall:
- $(RM) $(bindir)/$(PROGRAM) $(man1dir)/$(MANPAGE)
- rmdir -p $(bindir) $(man1dir)
- @echo Please delete ~/.usmb.conf manually.
-
-
-dist: tar
-
-
-PACKAGE = @PACKAGE_NAME@
-ifeq ($(SNAPSHOT),)
- VERSION = @PACKAGE_VERSION@
- ARCHIVE = $(VERSION)
-else
- ARCHIVE = $(shell git show $(SNAPSHOT) '--pretty=format:%h' | head -n1 )
- VERSION = $(shell date -ud "$(shell git show $(SNAPSHOT) '--pretty=format:%c…
-endif
-
-
-tar: STAGING=/tmp/usmb-$(VERSION)
-tar:
- mkdir $(STAGING)
- git archive $(ARCHIVE) | tar -C $(STAGING) -x -f -
- git log > $(STAGING)/Changelog
- (cd $(STAGING) && \
- autoreconf && \
- rm -rf autom4te.cache)
- (cd $(STAGING)/.. && \
- tar jcf $(PWD)/$(PACKAGE)-$(VERSION).tar.bz2 $(PACKAGE)-$(VERSION) &&…
- tar zcf $(PWD)/$(PACKAGE)-$(VERSION).tar.gz $(PACKAGE)-$(VERSION))
- rm -rf $(STAGING)
-
-include debian/Makefile.pkgdeb
-
-
-config.rng.h: @srcdir@/config.rng
- @SED@ -e 's/"/\\"/g' -e 's/\(.*\)/ "\1" \\/' \
- -e '1istatic const char *rng_$(@:.rng.h=) =' $^ > config.rng.h
- echo ' "";' >> config.rng.h
-
-
-%.o: @srcdir@/%.c
- $(CC) $(CFLAGS) -c -o $@ $<
-
-
-.PHONY: all debug dist install install-strip uninstall clean distclean tar
-
-conffile.o: @srcdir@/conffile.c @srcdir@/utils.h @srcdir@/xml.h \
- @builddir@/config.rng.h
-options.o: @srcdir@/options.c @srcdir@/options.h @srcdir@/utils.h \
- @srcdir@/version.h
-password.o: @srcdir@/password.c @srcdir@/password.h @srcdir@/utils.h
-usmb.o: @srcdir@/usmb.c @srcdir@/conffile.h @srcdir@/options.h \
- @srcdir@/usmb.h @srcdir@/usmb_dir.h @srcdir@/usmb_file.h \
- @srcdir@/utils.h @srcdir@/password.h @srcdir@/…
- @srcdir@/samba3x-compat.h
-usmb_dir.o: @srcdir@/samba3x-compat.h @srcdir@/usmb_dir.c @srcdir@/usmb_dir.h \
- @srcdir@/usmb.h @srcdir@/utils.h
-usmb_file.o: @srcdir@/samba3x-compat.h @srcdir@/usmb_file.c \
- @srcdir@/usmb_file.h @srcdir@/usmb.h @srcdir@/utils.h
-utils.o: @srcdir@/utils.c @srcdir@/utils.h
-version.o: @srcdir@/version.c @srcdir@/version.h
-xml.o: @srcdir@/xml.c @srcdir@/xml.h @srcdir@/utils.h
-
diff --git a/README b/README
@@ -1,26 +1,10 @@
-usmb - Unprivileged mounting of SMB/CIFS shares via FUSE
-========================================================
-
-Acknowledgements
-----------------
-
-Jonathan Schultz (Email <firstname> at imatix.com) provided a patch
-to fix the display of file modification times.
-
-Stijn Hoop (Email <firstname> at sandcat.nl) provided a patch to fix
-a compilation problem on 64-bit platforms.
-
-Nigel Smith (Email me at <firstname>.<surname>.name) contributed the
-port to Samba 3.2.
-
-Michal Suchanek (Email hramrach at centrum dot cz) contributed the
-Debian packaging and the initial implementation of ~-expansion.
-
+susmb - Unprivileged mounting of SMB/CIFS shares via FUSE
+=========================================================
Introduction
------------
-usmb lets you mount SMB/CIFS shares via FUSE, in the vein of the Map Network
+susmb lets you mount SMB/CIFS shares via FUSE, in the vein of the Map Network
Drive functionality in Windows.
The two existing FUSE filesystems that I know of (SMB for FUSE and fusesmb)
@@ -46,56 +30,93 @@ in/out of the user process' context. Mitigating factors are:
4. The client filesystem code can be upgraded/fixed without kernel changes.
-Pre-Requisites and Installation
--------------------------------
-
-Please see INSTALL.
-
+Dependencies
+------------
-Configuration
--------------
+- FUSE 2.6 or later (and probably <3).
+- libsmbclient 4.20+ (part of Samba) - www.samba.org (samba 3.3+ required).
-You need an XML configuration file - ${HOME}/.usmb.conf by default. There's an
-example in usmb.conf.
-There are two main elements: credentials and mounts.
+Installation
+------------
-Credentials:
+make
+make install # Maybe as root, depending on your installation prefix.
- <credentials id="some_id">
- <domain>mydomain</domain>
- <username>username</username>
- <password>password</password>
- </credentials>
-Each credentials element gives authentication details. You can have multiple
-credentials elements; each must have a distinct id attribute. If you omit
-the <password> element then usmb will prompt you for a password.
+Configuration and usage
+-----------------------
-A mount element describes an SMB share:
+See the man page.
- <mount id="mount_id" credentials="some_id">
- <server>1.2.3.4</server>
- <share>sharename</share>
- <mountpoint>/tmp/share</mountpoint>
- </mount>
-The credentials attribute identifies the id of the credentials element that
-provides authentication details for the share. The server, share and
-mountpoint should be self-explanatory. The id is given on the usmb command
-line to identify the SMB share to mount.
+Acknowledgements
+----------------
-You can specify multiple mount elements; each must have a distinct id
-(though credentials and mount IDs can be the same).
+Geoff Johnstone, the main author of the original usmb program.
-The whole file is wrapped in a <usmbconfig> element.
+Jonathan Schultz (Email <firstname> at imatix.com) provided a patch
+to fix the display of file modification times.
+Stijn Hoop (Email <firstname> at sandcat.nl) provided a patch to fix
+a compilation problem on 64-bit platforms.
-Usage
------
+Nigel Smith (Email me at <firstname>.<surname>.name) contributed the
+port to Samba 3.2.
-$ usmb [options] mount_ID
+Michal Suchanek (Email hramrach at centrum dot cz) contributed the
+Debian packaging and the initial implementation of ~-expansion.
-Use usmb --help for a list of options.
-Mount IDs are defined in the configuration file.
+Changes
+-------
+
+This is a fork of usmb 20130204
+http://repo.or.cz/w/usmb.git/snapshot/aa94e132c12faf1a00f547ea4a96b5728612dea6…
+(git commit aa94e132c12faf1a00f547ea4a96b5728612dea6)
+
+It has the patches applied from OpenBSD ports 7.6:
+https://cvsweb.openbsd.org/cgi-bin/cvsweb/ports/sysutils/usmb/
+
+It is mainly tested on OpenBSD (Linux has a SMB/CIFS driver anyway).
+
+Below is a summary of the most important changes:
+
+Performance:
+
+- Set struct stat st.st_blksiz to a higher number for more efficient buffering
+ for programs using the standard FILE* stdio interfaces. Huge improvement for
+ reads and writes.
+ On OpenBSD the default block size for FUSE is 512 bytes.
+ This cripples network performance.
+ On OpenBSD there is no FUSE caching layer, so each read call had more overhe…
+- Remove the hardcoded FUSE mount option max_read=N.
+ This cripples network performance.
+
+
+Security:
+- Many code simplifications and deletions (attack surface and easier to review…
+- Use unveil(2) syscall to lock down much of the filesystem except the
+ mountpoint and required FUSE devices.
+- Optional priviledge dropping support: on OpenBSD FUSE would need to run as r…
+ (sysctl kern.usermount was removed around July 2016, around
+ commit 65c8a8a0394483b41de8f02c862e65fb529cf538).
+ After mounting the filesystem and acquiring access to the FUSE driver
+ priviledges are dropped. This is not perfect, but at least now the Samba smb…
+ code runs as a user again.
+- Remove support for reading the password from the terminal. This can be
+ insecure and caused issues when running as a daemon and the network credenti…
+ changed.
+
+
+Cleanups:
+- Merge everything into one C file for easier code review.
+- Remove Samba < 3.3 compatibility layer and code. This is hard to test nowada…
+- Use getopt for option parsing: remove dependences on glib which was used for
+ option parsing only.
+ Remove long option support.
+- Remove libxml2 dependency and configuration via XML. Configuration is now do…
+ simpler syntax as a URI from the command-line. This was also listed in the
+ man page under the BUGS section as a wanted feature.
+- Remove autoconf and files specific to Debian packaging. Use a simple Makefil…
+- Man page rewritten from roff to mandoc.
diff --git a/aclocal.m4 b/aclocal.m4
@@ -1,155 +0,0 @@
-# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
-#
-# Copyright © 2004 Scott James Remnant <[email protected]>.
-#
-# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that program.
-
-# PKG_PROG_PKG_CONFIG([MIN-VERSION])
-# ----------------------------------
-AC_DEFUN([PKG_PROG_PKG_CONFIG],
-[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
-m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
-AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
-if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
- AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
-fi
-if test -n "$PKG_CONFIG"; then
- _pkg_min_version=m4_default([$1], [0.9.0])
- AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
- if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
- AC_MSG_RESULT([yes])
- else
- AC_MSG_RESULT([no])
- PKG_CONFIG=""
- fi
-
-fi[]dnl
-])# PKG_PROG_PKG_CONFIG
-
-# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
-#
-# Check to see whether a particular set of modules exists. Similar
-# to PKG_CHECK_MODULES(), but does not set variables or print errors.
-#
-#
-# Similar to PKG_CHECK_MODULES, make sure that the first instance of
-# this or PKG_CHECK_MODULES is called, or make sure to call
-# PKG_CHECK_EXISTS manually
-# --------------------------------------------------------------
-AC_DEFUN([PKG_CHECK_EXISTS],
-[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
-if test -n "$PKG_CONFIG" && \
- AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
- m4_ifval([$2], [$2], [:])
-m4_ifvaln([$3], [else
- $3])dnl
-fi])
-
-
-# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
-# ---------------------------------------------
-m4_define([_PKG_CONFIG],
-[if test -n "$$1"; then
- pkg_cv_[]$1="$$1"
- elif test -n "$PKG_CONFIG"; then
- PKG_CHECK_EXISTS([$3],
- [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
- [pkg_failed=yes])
- else
- pkg_failed=untried
-fi[]dnl
-])# _PKG_CONFIG
-
-# _PKG_SHORT_ERRORS_SUPPORTED
-# -----------------------------
-AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
-[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
- _pkg_short_errors_supported=yes
-else
- _pkg_short_errors_supported=no
-fi[]dnl
-])# _PKG_SHORT_ERRORS_SUPPORTED
-
-
-# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
-# [ACTION-IF-NOT-FOUND])
-#
-#
-# Note that if there is a possibility the first call to
-# PKG_CHECK_MODULES might not happen, you should be sure to include an
-# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
-#
-#
-# --------------------------------------------------------------
-AC_DEFUN([PKG_CHECK_MODULES],
-[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
-AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
-AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
-
-pkg_failed=no
-AC_MSG_CHECKING([for $1])
-
-_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
-_PKG_CONFIG([$1][_LIBS], [libs], [$2])
-
-m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $…
-and $1[]_LIBS to avoid the need to call pkg-config.
-See the pkg-config man page for more details.])
-
-if test $pkg_failed = yes; then
- _PKG_SHORT_ERRORS_SUPPORTED
- if test $_pkg_short_errors_supported = yes; then
- $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2…
- else
- $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1`
- fi
- # Put the nasty error message in config.log where it belongs
- echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
-
- ifelse([$4], , [AC_MSG_ERROR(dnl
-[Package requirements ($2) were not met:
-
-$$1_PKG_ERRORS
-
-Consider adjusting the PKG_CONFIG_PATH environment variable if you
-installed software in a non-standard prefix.
-
-_PKG_TEXT
-])],
- [AC_MSG_RESULT([no])
- $4])
-elif test $pkg_failed = untried; then
- ifelse([$4], , [AC_MSG_FAILURE(dnl
-[The pkg-config script could not be found or is too old. Make sure it
-is in your PATH or set the PKG_CONFIG environment variable to the full
-path to pkg-config.
-
-_PKG_TEXT
-
-To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
- [$4])
-else
- $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
- $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
- AC_MSG_RESULT([yes])
- ifelse([$3], , :, [$3])
-fi[]dnl
-])# PKG_CHECK_MODULES
diff --git a/conffile.c b/conffile.c
@@ -1,237 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2013 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <pwd.h>
-#include <unistd.h>
-#include "utils.h"
-#include "xml.h"
-#include "conffile.h"
-#include "config.rng.h"
-
-
-static bool check_conf_perms (const char *conffile, int fd)
-{
- struct stat buf;
-
- if (0 == fstat (fd, &buf))
- {
- if (getuid() != buf.st_uid)
- {
- fprintf (stderr, "You do not own the configuration file %s.\n", conffile…
- return false;
- }
-
- if (buf.st_mode & (S_IRWXG | S_IRWXO))
- {
- fprintf (stderr, "Configuration file %s is accessible to non-owner.\n",
- conffile);
- return false;
- }
- }
-
- else
- {
- fprintf (stderr, "Cannot stat configuration file %s: %s.\n",
- conffile, strerror (errno));
- return false;
- }
-
- return true;
-}
-
-
-static bool conffile_read (const char *filename,
- xmlDocPtr *doc,
- xmlXPathContextPtr *ctx)
-{
- int fd = open (filename, O_RDONLY);
- if (-1 == fd)
- {
- fprintf (stderr, "Cannot open %s: %s.\n", filename, strerror (errno));
- return false;
- }
-
- if (!check_conf_perms (filename, fd))
- {
- (void)close (fd);
- return false;
- }
-
- *doc = xmlReadFd (fd, NULL, NULL, XML_PARSE_NONET);
- (void)close (fd);
-
- if (NULL == *doc)
- {
- fprintf (stderr, "Cannot parse %s.\n", filename);
- return false;
- }
-
- if (!xml_validate_relaxng (*doc, rng_config))
- {
- fprintf (stderr, "%s isn't a valid USMB configuration.\n", filename);
- xmlFreeDoc (*doc);
- return false;
- }
-
- *ctx = xmlXPathNewContext (*doc);
- if (NULL == *ctx)
- {
- fputs ("Cannot create XPath context.\n", stderr);
- xmlFreeDoc (*doc);
- return false;
- }
-
- return true;
-}
-
-
-static bool do_xpath_text (xmlXPathContextPtr ctx,
- const char *parent, const char *id,
- const char *child, char **out)
-{
- char xpath[2048];
-
- if (!bsnprintf (xpath, sizeof (xpath),
- "/usmbconfig/%s[@id='%s']/%s/text()", parent, id, child))
- return false;
-
- return xml_xpath_text (ctx, xpath, (void *)out);
-}
-
-
-// Expand ~ in *mountpoint.
-static bool expand_tilde (char **mountpoint)
-{
- assert (NULL != mountpoint);
- assert (NULL != *mountpoint);
-
- if ('~' != **mountpoint)
- return true;
-
- // Extract the username.
- char * const username = (*mountpoint) + 1;
- char * const end = strchr (username, '/');
-
- const char *dir = NULL;
-
- if (('\0' == *username) || (end == username)) // No username => use HOME.
- {
- dir = getenv ("HOME");
- }
- else // Else look up the user's home directory.
- {
- if (NULL != end)
- *end = '\0';
-
- struct passwd * const pwd = getpwnam (username);
- if (NULL != pwd)
- dir = pwd->pw_dir;
-
- if (NULL != end)
- *end = '/';
- }
-
- if (NULL == dir)
- {
- fputs ("Failed to expand tilde in mount point.\n", stderr);
- return false;
- }
-
- char *result;
- if (!baprintf (&result, "%s%s", dir, (NULL == end) ? "" : end))
- {
- perror ("Failed to expand tilde in mount point");
- return false;
- }
-
- free (*mountpoint);
- *mountpoint = result;
- return true;
-}
-
-
-bool conffile_get_mount (const char *filename, const char *key,
- char **server, char **share,
- char **mountpoint, char **options,
- char **domain, char **username,
- char **password)
-{
- xmlDocPtr doc;
- xmlXPathContextPtr ctx;
- char xp[2048];
- char *creds = NULL;
-
- *server = *share = *mountpoint = *options = NULL;
- *domain = *username = *password = NULL;
-
- if (strchr (key, '\''))
- {
- fprintf (stderr, "Invalid share name: %s.\n", key);
- return false;
- }
-
- if (!conffile_read (filename, &doc, &ctx))
- return false;
-
- do {
- if (!do_xpath_text (ctx, "mount", key, "server", server)) break;
- if (!do_xpath_text (ctx, "mount", key, "share", share)) break;
- if (!do_xpath_text (ctx, "mount", key, "mountpoint", mountpoint)) break;
- if (!expand_tilde (mountpoint)) break;
- (void)do_xpath_text (ctx, "mount", key, "options", options);
-
- if (!snprintf (xp, sizeof (xp), "/usmbconfig/mount[@id='%s']", key)) break;
- if (!xml_xpath_attr_value (ctx, xp, "credentials", &creds)) break;
-
- (void)do_xpath_text (ctx, "credentials", creds, "domain", domain);
- if (!do_xpath_text (ctx, "credentials", creds, "username", username)) brea…
-
- if (!do_xpath_text (ctx, "credentials", creds, "password", password))
- *password = NULL;
-
- xmlXPathFreeContext (ctx);
- xmlFreeDoc (doc);
-
- return true;
- /*NOTREACHED*/
- } while (false /*CONSTCOND*/);
-
- fputs ("Invalid configuration.\n", stderr);
-
- xfree (*username);
- clear_and_free (*password);
- xfree (*domain);
- xfree (creds);
- xfree (*options);
- xfree (*mountpoint);
- xfree (*share);
- xfree (*server);
-
- xmlXPathFreeContext (ctx);
- xmlFreeDoc (doc);
-
- return false;
-}
-
diff --git a/conffile.h b/conffile.h
@@ -1,27 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2009 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef CONFFILE_H
- #define CONFFILE_H
-
- #include <stdbool.h>
-
- bool conffile_get_mount (const char *filename, const char *key,
- char **server, char **share,
- char **mountpoint, char **options,
- char **domain, char **username,
- char **password) MUSTCHECK;
-#endif
diff --git a/config.rng b/config.rng
@@ -1,48 +0,0 @@
-<grammar xmlns="http://relaxng.org/ns/structure/1.0">
-
- <start>
- <ref name="usmbconfig" />
- </start>
-
-
- <define name="usmbconfig">
- <element name="usmbconfig">
- <zeroOrMore>
- <choice>
- <ref name="credentials" />
- <ref name="mount" />
- </choice>
- </zeroOrMore>
- </element>
- </define>
-
-
- <define name="credentials">
- <element name="credentials">
- <attribute name="id" />
- <optional>
- <element name="domain"> <text /> </element>
- </optional>
- <element name="username"> <text /> </element>
- <optional>
- <element name="password"> <text /> </element>
- </optional>
- </element>
- </define>
-
-
- <define name="mount">
- <element name="mount">
- <attribute name="id" />
- <attribute name="credentials" />
- <element name="server"> <text /> </element>
- <element name="share"> <text /> </element>
- <element name="mountpoint"> <text /> </element>
- <optional>
- <element name="options"> <text /> </element>
- </optional>
- </element>
- </define>
-
-</grammar>
-
diff --git a/configure.ac b/configure.ac
@@ -1,96 +0,0 @@
-m4_include([version.m4])
-
-AC_PREREQ([2.63])
-AC_INIT([usmb], VERSION_)
-AC_CONFIG_SRCDIR([usmb.c])
-AC_CONFIG_HEADERS([config.h])
-
-AC_DEFINE([USMB_VERSION],[0x]VERSION_,[usmb version])
-AC_DEFINE([USMB_VERSION_STATUS],'[VERSION_STATUS_]',[Version status])
-
-AC_ARG_ENABLE([debug],
- [AS_HELP_STRING([--enable-debug],
- [Build in debug mode (default no)])],
- [AC_DEFINE([DEBUG], [], [Define to build in debug mode])])
-
-AC_ARG_WITH([samba],
- [AS_HELP_STRING([--with-samba=prefix],
- [Location of Samba (i.e. libsmbclient)])],
- [if test no = $withval ; then
- AC_MSG_ERROR(Samba is required for building AC_PACKAGE_NAME)
- else
- CFLAGS="$CFLAGS -I$withval/include"
- LDFLAGS="$LDFLAGS -L$withval/lib"
- fi])
-
-# Checks for programs.
-AC_PROG_CC_C99([gcc])
-AC_PROG_INSTALL
-AC_PROG_MKDIR_P
-AC_PROG_SED
-
-AC_DEFINE([_BSD_SOURCE], [], [Define to use BSD APIs (mandatory)])
-AC_DEFINE([FUSE_USE_VERSION], [26], [Required FUSE API version])
-
-m4_define([UNUSED_],[])
-m4_define([MUSTCHECK_],[])
-
-if test "$GCC" = yes ; then
- m4_define([UNUSED_], [__attribute__ ((unused))])
- m4_define([MUSTCHECK_], [__attribute__ ((warn_unused_result))])
- CFLAGS="$CFLAGS -Wall -Wextra -pedantic -Wformat-security -Winit-self -Wwrit…
-fi
-
-AC_DEFINE([UNUSED], [UNUSED_], [Marks unused parameters])
-AC_DEFINE([MUSTCHECK], [MUSTCHECK_],
- [Marks functions whose result values must not be ignored])
-
-# Checks for libraries.
-AC_CHECK_LIB([smbclient], [smbc_init], [],
- [AC_MSG_ERROR(Cannot find libsmbclient.)])
-
-AC_CHECK_LIB([smbclient], [smbc_getFunctionStatVFS],
- [AC_DEFINE([HAVE_SAMBA33], [],
- [Whether we have Samba 3.3 or later])
- SAMBA_VERSION=33])
-
-AC_CHECK_LIB([smbclient], [smbc_getFunctionOpen],
- [AC_DEFINE([HAVE_SAMBA32], [],
- [Whether we have Samba 3.2 or later])
- if test "$SAMBA_VERSION" = "" ; then
- SAMBA_VERSION=32
- fi])
-
-if test "$SAMBA_VERSION" = '' ; then
- SAMBA_VERSION=30
-fi
-
-AC_SUBST(SAMBA_VERSION,[$SAMBA_VERSION])
-
-PKG_PROG_PKG_CONFIG
-PKG_CHECK_MODULES([LIBXML2], [libxml-2.0])
-PKG_CHECK_MODULES([GLIB], [glib-2.0])
-PKG_CHECK_MODULES([FUSE], [fuse])
-
-
-# Checks for header files.
-AC_CHECK_HEADERS([fcntl.h limits.h stddef.h stdlib.h string.h sys/time.h termi…
-
-# Checks for typedefs, structures, and compiler characteristics.
-AC_HEADER_STDBOOL
-AC_C_INLINE
-AC_TYPE_MODE_T
-AC_TYPE_OFF_T
-AC_TYPE_SIZE_T
-AC_TYPE_UID_T
-AC_TYPE_UINT64_T
-AC_CHECK_TYPES([ptrdiff_t])
-
-# Checks for library functions.
-AC_FUNC_MALLOC
-AC_FUNC_REALLOC
-AC_CHECK_FUNCS([memset strchr strerror])
-
-AC_CONFIG_FILES([Makefile])
-AC_OUTPUT
-
diff --git a/debian/Makefile.pkgdeb b/debian/Makefile.pkgdeb
@@ -1,43 +0,0 @@
-deb_package = $(shell dpkg-parsechangelog | grep ^Source: | sed -e s,'^Source:…
-deb_version = $(shell dpkg-parsechangelog | grep ^Version: | sed -e s,'^Versio…
-revision = $(shell dpkg-parsechangelog | grep ^Version: | sed -e -e 's,.*-,,')
-architecture = $(shell dpkg --print-architecture)
-tar_dir = $(PACKAGE)-$(VERSION)
-tar_gz = $(tar_dir).tar.gz
-pkg_deb_dir = pkgdeb
-unpack_dir = $(pkg_deb_dir)/$(tar_dir)
-orig_tar_gz = $(pkg_deb_dir)/$(PACKAGE)_$(VERSION).orig.tar.gz
-pkg_deb_src = $(pkg_deb_dir)/$(PACKAGE)_$(VERSION)-$(revision)_source.changes
-pkg_deb_bin = $(pkg_deb_dir)/$(PACKAGE)_$(VERSION)-$(revision)_$(architecture)…
-
-#deb_pkg_key = -kCB8C5858
-deb_pkg_key = -us -uc
-
-debclean:
- rm -rf $(pkg_deb_dir)
-
-deb: debsrc debbin
-
-debbin: $(unpack_dir)
- cd $(unpack_dir) && dpkg-buildpackage -b $(deb_pkg_key)
-
-debsrc: $(unpack_dir)
- cd $(unpack_dir) && dpkg-buildpackage -S $(deb_pkg_key)
-
-$(unpack_dir): $(orig_tar_gz)
- tar -zxf $(orig_tar_gz) -C $(pkg_deb_dir)
- [ $(VERSION) = $(deb_version) ] || \
- ( cd $(unpack_dir) && debchange -m -v $(VERSION)-1 New upstream rele…
- # Remove requirements for preparing the release tarball
- # from the Debian control file
- sed -i -e '/^ autoconf/d' -e '/^ devscripts/d' $(unpack_dir)/debian/co…
-
-$(tar_gz): tar
-
-$(orig_tar_gz): $(tar_gz) debclean
- mkdir $(pkg_deb_dir)
- [ $(PACKAGE) = $(deb_package) ]
- ln -s ../$(tar_gz) $(orig_tar_gz)
-
-
-
diff --git a/debian/changelog b/debian/changelog
@@ -1,5 +0,0 @@
-usmb (20090411-1) UNRELEASED; urgency=low
-
- * Initial release. (Closes: #572703)
-
- -- Michal Suchanek <[email protected]> Wed, 10 Mar 2010 11:59:09 +0100
diff --git a/debian/compat b/debian/compat
@@ -1 +0,0 @@
-7
diff --git a/debian/control b/debian/control
@@ -1,29 +0,0 @@
-Source: usmb
-Section: otherosfs
-Priority: optional
-Build-Depends:
- debhelper,
- autoconf (>= 2.63),
- devscripts,
- libfuse-dev (>= 2.6),
- libglib2.0-dev,
- libsmbclient-dev (>= 3),
- libxml2-dev,
- pkg-config
-Standards-Version: 3.8.4
-Maintainer: Michal Suchanek <[email protected]>
-Homepage: http://repo.or.cz/w/usmb.git
-
-Package: usmb
-Recommends: fuse-utils
-Architecture: any
-Depends:
- ${shlibs:Depends},
- ${misc:Depends},
-Description: samba (CIFS) FUSE module
- usmb mounts samba (CIFS, Windows, NetBIOS) shares just like smbfs does,
- but uses FUSE to allow users other than root to mount shares.
- .
- Previously smbfs allowed the same by making mount.cifs setuid root but
- this was recently disabled in the smbfs package due to security
- concerns.
diff --git a/debian/copyright b/debian/copyright
@@ -1,25 +0,0 @@
-Authors:
- Geoff Johnstone <[email protected]>
-Download: http://ametros.net/code.html#usmb
-
-Files: *
-Copyright:
- (C) 2006-2013 Geoff Johnstone <[email protected]>
- Debian packaging (C) 2010 Michal Suchanek <[email protected]>
-License: GPL-3
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- version 3 as published by the Free Software Foundation.
- .
- 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
- .
- On Debian systems, the complete text of the GNU General Public License
- can be found in /usr/share/common-licenses/GPL-3 file.
-
diff --git a/debian/rules b/debian/rules
@@ -1,3 +0,0 @@
-#!/usr/bin/make -f
-%:
- dh $@
diff --git a/debian/usmb.docs b/debian/usmb.docs
@@ -1,2 +0,0 @@
-README
-usmb.conf
diff --git a/install-sh b/install-sh
@@ -1,519 +0,0 @@
-#!/bin/sh
-# install - install a program, script, or datafile
-
-scriptversion=2006-12-25.00
-
-# This originates from X11R5 (mit/util/scripts/install.sh), which was
-# later released in X11R6 (xc/config/util/install.sh) with the
-# following copyright and license.
-#
-# Copyright (C) 1994 X Consortium
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
-# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-# Except as contained in this notice, the name of the X Consortium shall not
-# be used in advertising or otherwise to promote the sale, use or other deal-
-# ings in this Software without prior written authorization from the X Consor-
-# tium.
-#
-#
-# FSF changes to this file are in the public domain.
-#
-# Calling this script install-sh is preferred over install.sh, to prevent
-# `make' implicit rules from creating a file called install from it
-# when there is no Makefile.
-#
-# This script is compatible with the BSD install script, but was written
-# from scratch.
-
-nl='
-'
-IFS=" "" $nl"
-
-# set DOITPROG to echo to test this script
-
-# Don't use :- since 4.3BSD and earlier shells don't like it.
-doit=${DOITPROG-}
-if test -z "$doit"; then
- doit_exec=exec
-else
- doit_exec=$doit
-fi
-
-# Put in absolute file names if you don't have them in your path;
-# or use environment vars.
-
-chgrpprog=${CHGRPPROG-chgrp}
-chmodprog=${CHMODPROG-chmod}
-chownprog=${CHOWNPROG-chown}
-cmpprog=${CMPPROG-cmp}
-cpprog=${CPPROG-cp}
-mkdirprog=${MKDIRPROG-mkdir}
-mvprog=${MVPROG-mv}
-rmprog=${RMPROG-rm}
-stripprog=${STRIPPROG-strip}
-
-posix_glob='?'
-initialize_posix_glob='
- test "$posix_glob" != "?" || {
- if (set -f) 2>/dev/null; then
- posix_glob=
- else
- posix_glob=:
- fi
- }
-'
-
-posix_mkdir=
-
-# Desired mode of installed file.
-mode=0755
-
-chgrpcmd=
-chmodcmd=$chmodprog
-chowncmd=
-mvcmd=$mvprog
-rmcmd="$rmprog -f"
-stripcmd=
-
-src=
-dst=
-dir_arg=
-dst_arg=
-
-copy_on_change=false
-no_target_directory=
-
-usage="\
-Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
- or: $0 [OPTION]... SRCFILES... DIRECTORY
- or: $0 [OPTION]... -t DIRECTORY SRCFILES...
- or: $0 [OPTION]... -d DIRECTORIES...
-
-In the 1st form, copy SRCFILE to DSTFILE.
-In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
-In the 4th, create DIRECTORIES.
-
-Options:
- --help display this help and exit.
- --version display version info and exit.
-
- -c (ignored)
- -C install only if different (preserve the last data modification…
- -d create directories instead of installing files.
- -g GROUP $chgrpprog installed files to GROUP.
- -m MODE $chmodprog installed files to MODE.
- -o USER $chownprog installed files to USER.
- -s $stripprog installed files.
- -t DIRECTORY install into DIRECTORY.
- -T report an error if DSTFILE is a directory.
-
-Environment variables override the default commands:
- CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
- RMPROG STRIPPROG
-"
-
-while test $# -ne 0; do
- case $1 in
- -c) ;;
-
- -C) copy_on_change=true;;
-
- -d) dir_arg=true;;
-
- -g) chgrpcmd="$chgrpprog $2"
- shift;;
-
- --help) echo "$usage"; exit $?;;
-
- -m) mode=$2
- case $mode in
- *' '* | *' '* | *'
-'* | *'*'* | *'?'* | *'['*)
- echo "$0: invalid mode: $mode" >&2
- exit 1;;
- esac
- shift;;
-
- -o) chowncmd="$chownprog $2"
- shift;;
-
- -s) stripcmd=$stripprog;;
-
- -t) dst_arg=$2
- shift;;
-
- -T) no_target_directory=true;;
-
- --version) echo "$0 $scriptversion"; exit $?;;
-
- --) shift
- break;;
-
- -*) echo "$0: invalid option: $1" >&2
- exit 1;;
-
- *) break;;
- esac
- shift
-done
-
-if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
- # When -d is used, all remaining arguments are directories to create.
- # When -t is used, the destination is already specified.
- # Otherwise, the last argument is the destination. Remove it from $@.
- for arg
- do
- if test -n "$dst_arg"; then
- # $@ is not empty: it contains at least $arg.
- set fnord "$@" "$dst_arg"
- shift # fnord
- fi
- shift # arg
- dst_arg=$arg
- done
-fi
-
-if test $# -eq 0; then
- if test -z "$dir_arg"; then
- echo "$0: no input file specified." >&2
- exit 1
- fi
- # It's OK to call `install-sh -d' without argument.
- # This can happen when creating conditional directories.
- exit 0
-fi
-
-if test -z "$dir_arg"; then
- trap '(exit $?); exit' 1 2 13 15
-
- # Set umask so as not to create temps with too-generous modes.
- # However, 'strip' requires both read and write access to temps.
- case $mode in
- # Optimize common cases.
- *644) cp_umask=133;;
- *755) cp_umask=22;;
-
- *[0-7])
- if test -z "$stripcmd"; then
- u_plus_rw=
- else
- u_plus_rw='% 200'
- fi
- cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
- *)
- if test -z "$stripcmd"; then
- u_plus_rw=
- else
- u_plus_rw=,u+rw
- fi
- cp_umask=$mode$u_plus_rw;;
- esac
-fi
-
-for src
-do
- # Protect names starting with `-'.
- case $src in
- -*) src=./$src;;
- esac
-
- if test -n "$dir_arg"; then
- dst=$src
- dstdir=$dst
- test -d "$dstdir"
- dstdir_status=$?
- else
-
- # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
- # might cause directories to be created, which would be especially bad
- # if $src (and thus $dsttmp) contains '*'.
- if test ! -f "$src" && test ! -d "$src"; then
- echo "$0: $src does not exist." >&2
- exit 1
- fi
-
- if test -z "$dst_arg"; then
- echo "$0: no destination specified." >&2
- exit 1
- fi
-
- dst=$dst_arg
- # Protect names starting with `-'.
- case $dst in
- -*) dst=./$dst;;
- esac
-
- # If destination is a directory, append the input filename; won't work
- # if double slashes aren't ignored.
- if test -d "$dst"; then
- if test -n "$no_target_directory"; then
- echo "$0: $dst_arg: Is a directory" >&2
- exit 1
- fi
- dstdir=$dst
- dst=$dstdir/`basename "$src"`
- dstdir_status=0
- else
- # Prefer dirname, but fall back on a substitute if dirname fails.
- dstdir=`
- (dirname "$dst") 2>/dev/null ||
- expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
- X"$dst" : 'X\(//\)[^/]' \| \
- X"$dst" : 'X\(//\)$' \| \
- X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
- echo X"$dst" |
- sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
- s//\1/
- q
- }
- /^X\(\/\/\)[^/].*/{
- s//\1/
- q
- }
- /^X\(\/\/\)$/{
- s//\1/
- q
- }
- /^X\(\/\).*/{
- s//\1/
- q
- }
- s/.*/./; q'
- `
-
- test -d "$dstdir"
- dstdir_status=$?
- fi
- fi
-
- obsolete_mkdir_used=false
-
- if test $dstdir_status != 0; then
- case $posix_mkdir in
- '')
- # Create intermediate dirs using mode 755 as modified by the umask.
- # This is like FreeBSD 'install' as of 1997-10-28.
- umask=`umask`
- case $stripcmd.$umask in
- # Optimize common cases.
- *[2367][2367]) mkdir_umask=$umask;;
- .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
-
- *[0-7])
- mkdir_umask=`expr $umask + 22 \
- - $umask % 100 % 40 + $umask % 20 \
- - $umask % 10 % 4 + $umask % 2
- `;;
- *) mkdir_umask=$umask,go-w;;
- esac
-
- # With -d, create the new directory with the user-specified mode.
- # Otherwise, rely on $mkdir_umask.
- if test -n "$dir_arg"; then
- mkdir_mode=-m$mode
- else
- mkdir_mode=
- fi
-
- posix_mkdir=false
- case $umask in
- *[123567][0-7][0-7])
- # POSIX mkdir -p sets u+wx bits regardless of umask, which
- # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
- ;;
- *)
- tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
- trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
-
- if (umask $mkdir_umask &&
- exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
- then
- if test -z "$dir_arg" || {
- # Check for POSIX incompatibilities with -m.
- # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
- # other-writeable bit of parent directory when it shouldn't.
- # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
- ls_ld_tmpdir=`ls -ld "$tmpdir"`
- case $ls_ld_tmpdir in
- d????-?r-*) different_mode=700;;
- d????-?--*) different_mode=755;;
- *) false;;
- esac &&
- $mkdirprog -m$different_mode -p -- "$tmpdir" && {
- ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
- test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
- }
- }
- then posix_mkdir=:
- fi
- rmdir "$tmpdir/d" "$tmpdir"
- else
- # Remove any dirs left behind by ancient mkdir implementations.
- rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
- fi
- trap '' 0;;
- esac;;
- esac
-
- if
- $posix_mkdir && (
- umask $mkdir_umask &&
- $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
- )
- then :
- else
-
- # The umask is ridiculous, or mkdir does not conform to POSIX,
- # or it failed possibly due to a race condition. Create the
- # directory the slow way, step by step, checking for races as we go.
-
- case $dstdir in
- /*) prefix='/';;
- -*) prefix='./';;
- *) prefix='';;
- esac
-
- eval "$initialize_posix_glob"
-
- oIFS=$IFS
- IFS=/
- $posix_glob set -f
- set fnord $dstdir
- shift
- $posix_glob set +f
- IFS=$oIFS
-
- prefixes=
-
- for d
- do
- test -z "$d" && continue
-
- prefix=$prefix$d
- if test -d "$prefix"; then
- prefixes=
- else
- if $posix_mkdir; then
- (umask=$mkdir_umask &&
- $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
- # Don't fail if two instances are running concurrently.
- test -d "$prefix" || exit 1
- else
- case $prefix in
- *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
- *) qprefix=$prefix;;
- esac
- prefixes="$prefixes '$qprefix'"
- fi
- fi
- prefix=$prefix/
- done
-
- if test -n "$prefixes"; then
- # Don't fail if two instances are running concurrently.
- (umask $mkdir_umask &&
- eval "\$doit_exec \$mkdirprog $prefixes") ||
- test -d "$dstdir" || exit 1
- obsolete_mkdir_used=true
- fi
- fi
- fi
-
- if test -n "$dir_arg"; then
- { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
- { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
- { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
- test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
- else
-
- # Make a couple of temp file names in the proper directory.
- dsttmp=$dstdir/_inst.$$_
- rmtmp=$dstdir/_rm.$$_
-
- # Trap to clean up those temp files at exit.
- trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
-
- # Copy the file name to the temp name.
- (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
-
- # and set any options; do chmod last to preserve setuid bits.
- #
- # If any of these fail, we abort the whole thing. If we want to
- # ignore errors from any of these, just make sure not to ignore
- # errors from the above "$doit $cpprog $src $dsttmp" command.
- #
- { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
- { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
- { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
- { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
-
- # If -C, don't bother to copy if it wouldn't change the file.
- if $copy_on_change &&
- old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
- new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
-
- eval "$initialize_posix_glob" &&
- $posix_glob set -f &&
- set X $old && old=:$2:$4:$5:$6 &&
- set X $new && new=:$2:$4:$5:$6 &&
- $posix_glob set +f &&
-
- test "$old" = "$new" &&
- $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
- then
- rm -f "$dsttmp"
- else
- # Rename the file to the real destination.
- $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
-
- # The rename failed, perhaps because mv can't rename something else
- # to itself, or perhaps because mv is so ancient that it does not
- # support -f.
- {
- # Now remove or move aside any old file at destination location.
- # We try this two ways since rm can't unlink itself on some
- # systems and the destination file might be busy for other
- # reasons. In this case, the final cleanup might fail but the new
- # file should still install successfully.
- {
- test ! -f "$dst" ||
- $doit $rmcmd -f "$dst" 2>/dev/null ||
- { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
- { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
- } ||
- { echo "$0: cannot unlink or rename $dst" >&2
- (exit 1); exit 1
- }
- } &&
-
- # Now rename the file to the real destination.
- $doit $mvcmd "$dsttmp" "$dst"
- }
- fi || exit 1
-
- trap '' 0
- fi
-done
-
-# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
-# time-stamp-start: "scriptversion="
-# time-stamp-format: "%:y-%02m-%02d.%02H"
-# time-stamp-end: "$"
-# End:
diff --git a/options.c b/options.c
@@ -1,192 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2013 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <assert.h>
-#include <glib.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "options.h"
-#include "utils.h"
-#include "version.h"
-
-
-static gboolean version = FALSE;
-static gchar *conffile = NULL;
-static gboolean debug = FALSE;
-static gboolean nofork = FALSE;
-static gboolean umount = FALSE;
-static gchar **remaining = NULL;
-
-
-static GOptionEntry entries[] = {
- { .long_name = "version",
- .short_name = 'v',
- .flags = 0,
- .arg = G_OPTION_ARG_NONE,
- .arg_data = &version,
- .description = "Show usmb, FUSE and Samba versions" },
-
- { .long_name = "version",
- .short_name = 'V',
- .flags = G_OPTION_FLAG_HIDDEN,
- .arg = G_OPTION_ARG_NONE,
- .arg_data = &version,
- .description = NULL },
-
- { .long_name = "config",
- .short_name = 'c',
- .flags = 0,
- .arg = G_OPTION_ARG_FILENAME,
- .arg_data = &conffile,
- .description = "usmb configuration file" },
-
- { .long_name = "debug",
- .short_name = 'd',
- .arg = G_OPTION_ARG_NONE,
- .arg_data = &debug,
- .description = "Debug mode" },
-
- { .long_name = "nofork",
- .short_name = 'f',
- .arg = G_OPTION_ARG_NONE,
- .arg_data = &nofork,
- .description = "Foreground operation" },
-
- { .long_name = "unmount",
- .short_name = 'u',
- .arg = G_OPTION_ARG_NONE,
- .arg_data = &umount,
- .description = "Unmount the given filesystem" },
-
- { .long_name = G_OPTION_REMAINING,
- .short_name = 0,
- .arg = G_OPTION_ARG_STRING_ARRAY,
- .arg_data = &remaining,
- .description = NULL },
-
- { .long_name = NULL }
-};
-
-
-bool parse_args (int *argc, char ***argv,
- const char **mountid, const char **out_conffile,
- bool *out_umount)
-{
- GError *error = NULL;
-
- GOptionContext *context =
- g_option_context_new ("- mount SMB shares via FUSE and Samba");
- g_option_context_add_main_entries (context, entries, NULL);
- bool ret = g_option_context_parse (context, argc, argv, &error);
- g_option_context_free (context);
-
- if (false == ret)
- {
- fprintf (stderr, "Try `%s --help' for more information\n", (*argv)[0]);
- return false;
- }
-
- if (version)
- {
- show_version (stdout);
- exit (EXIT_SUCCESS);
- }
-
- if ((NULL == remaining) || (NULL == remaining[0]))
- {
- fputs ("No share ID given.\n", stderr);
- return false;
- }
-
- if (NULL != remaining[1])
- {
- fputs ("Too many arguments.\n", stderr);
- return false;
- }
-
- *out_umount = umount;
- *mountid = remaining[0];
- g_free (remaining);
- DEBUG (fprintf (stderr, "Mount ID: %s\n", *mountid));
-
- if (NULL != conffile)
- *out_conffile = conffile;
-
- return ret;
-}
-
-
-/* FUSE args are:
- *
- * argv[0]
- * -s
- * -d -- if debug mode requested
- * -f -- if foreground mode requested
- * -o ... -- if any mount options in the config file
- * mount point
- */
-#define MAXARGS 12
-void build_fuse_args (const char *options, const char *mountpoint,
- int *out_argc, char ***out_argv)
-{
- static char USMB[] = "usmb";
- static char MINUS_S[] = "-s";
- static char MINUS_D[] = "-d";
- static char MINUS_F[] = "-f";
- static char MINUS_O[] = "-o";
- static char MAX_READ[] = "max_read=32768";
-
- assert (NULL != mountpoint);
- static char *argv[MAXARGS];
-
- int argc = 0;
-
- argv[argc++] = USMB;
- argv[argc++] = MINUS_S;
-
- if (debug)
- argv[argc++] = MINUS_D;
-
- // force -f in debug mode
-#ifndef DEBUGON
- if (nofork)
-#endif
- argv[argc++] = MINUS_F;
-
- argv[argc++] = MINUS_O;
- argv[argc++] = MAX_READ;
-
- if ((NULL != options) && ('\0' != options[0]))
- {
- argv[argc++] = MINUS_O;
- argv[argc++] = (char *)options;
- }
-
- argv[argc++] = (char *)mountpoint;
- argv[argc] = NULL; // for good measure...
-
- assert (argc < MAXARGS);
- *out_argc = argc;
- *out_argv = argv;
-
- #ifdef DEBUGON
- for (int i = 0; i < argc; ++i)
- fprintf (stderr, "%d: %s\n", i, argv[i]);
- #endif
-}
-
diff --git a/options.h b/options.h
@@ -1,26 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2009 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef OPTIONS_H
- #define OPTIONS_H
-
- bool parse_args (int *argc, char ***argv,
- const char **mountid, const char **out_conffile,
- bool *out_umount) MUSTCHECK;
- void build_fuse_args (const char *options, const char *mountpoint,
- int *out_argc, char ***out_argv);
-
-#endif
diff --git a/password.c b/password.c
@@ -1,86 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2009 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <assert.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-#include "password.h"
-#include "utils.h"
-
-
-bool password_read (char **out)
-{
- struct termios attr, new;
-
- assert (NULL != out);
- *out = NULL;
-
- if (0 != tcgetattr (STDIN_FILENO, &attr))
- {
- perror ("tcgetattr");
- fputs ("Cannot configure terminal to read password securely.\n", stderr);
- return false;
- }
-
- new = attr;
- new.c_lflag &= ~ECHO;
-
- if (0 != tcsetattr (STDIN_FILENO, TCSAFLUSH, &new))
- {
- perror ("tcsetattr");
- fputs ("Cannot configure terminal to read password securely.\n", stderr);
- return false;
- }
-
- char buff[1024];
-
- fputs ("\nPassword: ", stdout);
- fflush (stdout);
- const bool ok = (buff == fgets (buff, sizeof (buff), stdin));
- fputc ('\n', stdout);
-
- if (0 != tcsetattr (STDIN_FILENO, TCSAFLUSH, &attr))
- {
- perror ("tcsetattr");
- fputs ("Failed to reset terminal.\n", stderr);
- }
-
- if (!ok)
- {
- return false;
- }
-
- // strip a trailing '\n'.
- {
- size_t len = strlen (buff);
-
- if ((0 < len) && ('\n' == buff[len - 1]))
- buff[len - 1] = '\0';
- }
-
- *out = xstrdup (buff);
- memset (buff, 0, sizeof (buff));
-
- DEBUG (fprintf (stderr, "Password: %s\n", *out));
-
- return (NULL != *out);
-}
-
diff --git a/password.h b/password.h
@@ -1,24 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2009 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef PASSWORD_H
- #define PASSWORD_H
-
- #include <stdbool.h>
-
- bool password_read (char **out) MUSTCHECK;
-
-#endif
diff --git a/samba30_compat.c b/samba30_compat.c
@@ -1,72 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2009 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "samba3x-compat.h"
-#include "usmb.h"
-#include "usmb_file.h"
-#include "utils.h"
-
-
-int usmb_statfs (const char *path UNUSED, struct statvfs *vfs UNUSED)
-{
- (void)path;
- (void)vfs;
- return -ENOSYS;
-}
-
-
-int compat_truncate (const char *path UNUSED, SMBCFILE *file UNUSED, off_t siz…
-{
- /* Windows doesn't support truncation so we implement a limited version:
- * 0 == size => create a new file for writing.
- * current size == size => succeed.
- * else return -ENOSYS.
- */
-
- if (0 == size)
- {
- char *url = make_url (path);
- if (NULL == url)
- return -ENOMEM;
-
- SMBCFILE *file_ = smbc_getFunctionOpen (ctx) (ctx, url,
- O_WRONLY | O_TRUNC, 0);
- if (NULL == file_)
- {
- free_errno (url);
- return -errno;
- }
-
- smbc_getFunctionClose (ctx) (ctx, file_);
- free (url);
-
- return 0;
- }
-
- struct stat st;
- int ret = usmb_getattr (path, &st);
-
- if (0 != ret)
- return ret;
-
- return (size == st.st_size) ? 0 : -ENOSYS;
-}
-
diff --git a/samba32_compat.c b/samba32_compat.c
@@ -1,40 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2009 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "samba3x-compat.h"
-#include "usmb.h"
-#include "utils.h"
-
-
-int usmb_statfs (const char *path, struct statvfs *vfs)
-{
- (void)path;
- (void)vfs;
- return -ENOSYS;
-}
-
-
-
-int compat_truncate (const char *path UNUSED, SMBCFILE *file, off_t size)
-{
- return (0 > smbc_getFunctionFtruncate (ctx) (ctx, file, size)) ? -errno : 0;
-}
-
diff --git a/samba33_compat.c b/samba33_compat.c
@@ -1,49 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2009 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "samba3x-compat.h"
-#include "usmb.h"
-#include "utils.h"
-
-
-int usmb_statfs (const char *path, struct statvfs *vfs)
-{
- if ((NULL == path) || (NULL == vfs))
- return -EINVAL;
-
- char *url = make_url (path);
- if (NULL == url)
- return -ENOMEM;
-
- DEBUG (fprintf (stderr, "statfs (%s, %p)\n", url, (void *)vfs));
- memset (vfs, 0, sizeof (*vfs));
-
- int ret = (0 > smbc_getFunctionStatVFS (ctx) (ctx, url, vfs)) ? -errno : 0;
- free (url);
- return ret;
-}
-
-
-int compat_truncate (const char *path UNUSED, SMBCFILE *file, off_t size)
-{
- return (0 > smbc_getFunctionFtruncate (ctx) (ctx, file, size)) ? -errno : 0;
-}
-
diff --git a/samba3x-compat.h b/samba3x-compat.h
@@ -1,283 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2009 Geoff Johnstone
- *
- * Portions of this file are taken from Samba 3.2's libsmbclient.h:
- * Copyright (C) Andrew Tridgell 1998
- * Copyright (C) Richard Sharpe 2000
- * Copyright (C) John Terpsra 2000
- * Copyright (C) Tom Jansen (Ninja ISD) 2002
- * Copyright (C) Derrell Lipman 2003-2008
- *
- * 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 3 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef SAMBA_30_COMPAT_H
- #define SAMBA_30_COMPAT_H
-
- #include "config.h"
- #include <libsmbclient.h>
- #include <sys/statvfs.h>
-
-
- int usmb_statfs (const char *path UNUSED, struct statvfs *vfs UNUSED);
- int compat_truncate (const char *path, SMBCFILE *file, off_t size);
-
-
- #ifndef HAVE_SAMBA32
-
- typedef int (*smbc_chmod_fn) (SMBCCTX *c, const char *fname, mode_t mode);
-
- static inline smbc_chmod_fn smbc_getFunctionChmod (SMBCCTX *c)
- {
- return c->chmod;
- }
-
-
- typedef int (*smbc_close_fn) (SMBCCTX *c, SMBCFILE *file);
-
- static inline smbc_close_fn smbc_getFunctionClose (SMBCCTX *c)
- {
- return c->close_fn;
- }
-
-
- typedef int (*smbc_closedir_fn) (SMBCCTX *c, SMBCFILE *dir);
-
- static inline smbc_closedir_fn smbc_getFunctionClosedir (SMBCCTX *c)
- {
- return c->closedir;
- }
-
-
- typedef SMBCFILE * (*smbc_creat_fn) (SMBCCTX *c,
- const char *path,
- mode_t mode);
-
- static inline smbc_creat_fn smbc_getFunctionCreat (SMBCCTX *c)
- {
- return c->creat;
- }
-
-
- typedef int (*smbc_fstat_fn) (SMBCCTX *c, SMBCFILE *file, struct stat *st);
-
- static inline smbc_fstat_fn smbc_getFunctionFstat (SMBCCTX *c)
- {
- return c->fstat;
- }
-
-
- typedef int (*smbc_getxattr_fn) (SMBCCTX *context,
- const char *fname,
- const char *name,
- const void *value,
- size_t size);
-
- static inline smbc_getxattr_fn smbc_getFunctionGetxattr (SMBCCTX *c)
- {
- return c->getxattr;
- }
-
-
- typedef int (*smbc_listxattr_fn) (SMBCCTX *context,
- const char *fname,
- char *list,
- size_t size);
-
- static inline smbc_listxattr_fn smbc_getFunctionListxattr (SMBCCTX *c)
- {
- return c->listxattr;
- }
-
-
- typedef off_t (*smbc_lseek_fn) (SMBCCTX *c,
- SMBCFILE *file,
- off_t offset,
- int whence);
-
- static inline smbc_lseek_fn smbc_getFunctionLseek (SMBCCTX *c)
- {
- return c->lseek;
- }
-
-
- typedef int (*smbc_mkdir_fn) (SMBCCTX *c, const char *fname, mode_t mode);
-
- static inline smbc_mkdir_fn smbc_getFunctionMkdir (SMBCCTX *c)
- {
- return c->mkdir;
- }
-
-
- typedef SMBCFILE * (*smbc_open_fn) (SMBCCTX *c,
- const char *fname,
- int flags,
- mode_t mode);
-
- static inline smbc_open_fn smbc_getFunctionOpen (SMBCCTX *c)
- {
- return c->open;
- }
-
-
- typedef SMBCFILE * (*smbc_opendir_fn) (SMBCCTX *c, const char *fname);
-
- static inline smbc_opendir_fn smbc_getFunctionOpendir (SMBCCTX *c)
- {
- return c->opendir;
- }
-
-
- typedef ssize_t (*smbc_read_fn) (SMBCCTX *c,
- SMBCFILE *file,
- void *buf,
- size_t count);
-
- static inline smbc_read_fn smbc_getFunctionRead (SMBCCTX *c)
- {
- return c->read;
- }
-
-
- typedef struct smbc_dirent * (*smbc_readdir_fn) (SMBCCTX *c, SMBCFILE *dir…
-
- static inline smbc_readdir_fn smbc_getFunctionReaddir (SMBCCTX *c)
- {
- return c->readdir;
- }
-
-
- typedef int (*smbc_removexattr_fn) (SMBCCTX *context,
- const char *fname,
- const char *name);
-
- static inline smbc_removexattr_fn smbc_getFunctionRemovexattr (SMBCCTX *c)
- {
- return c->removexattr;
- }
-
-
- typedef int (*smbc_rename_fn) (SMBCCTX *ocontext,
- const char *oname,
- SMBCCTX *ncontext,
- const char *nname);
-
- static inline smbc_rename_fn smbc_getFunctionRename (SMBCCTX *c)
- {
- return c->rename;
- }
-
-
- typedef int (*smbc_rmdir_fn) (SMBCCTX *c, const char *fname);
-
- static inline smbc_rmdir_fn smbc_getFunctionRmdir (SMBCCTX *c)
- {
- return c->rmdir;
- }
-
-
- typedef int (*smbc_lseekdir_fn)(SMBCCTX *c,
- SMBCFILE *dir,
- off_t offset);
-
- static inline smbc_lseekdir_fn smbc_getFunctionLseekdir (SMBCCTX *c)
- {
- return c->lseekdir;
- }
-
-
- typedef int (*smbc_setxattr_fn) (SMBCCTX *context,
- const char *fname,
- const char *name,
- const void *value,
- size_t size,
- int flags);
-
- static inline smbc_setxattr_fn smbc_getFunctionSetxattr (SMBCCTX *c)
- {
- return c->setxattr;
- }
-
-
- typedef int (*smbc_stat_fn) (SMBCCTX *c, const char *fname, struct stat *s…
-
- static inline smbc_stat_fn smbc_getFunctionStat (SMBCCTX *c)
- {
- return c->stat;
- }
-
-
- typedef int (*smbc_unlink_fn) (SMBCCTX *c, const char *fname);
-
- static inline smbc_unlink_fn smbc_getFunctionUnlink (SMBCCTX *c)
- {
- return c->unlink;
- }
-
-
- typedef int (*smbc_utimes_fn) (SMBCCTX *c,
- const char *fname,
- struct timeval *tbuf);
-
- static inline smbc_utimes_fn smbc_getFunctionUtimes (SMBCCTX *c)
- {
- return c->utimes;
- }
-
-
- typedef ssize_t (*smbc_write_fn) (SMBCCTX *c,
- SMBCFILE *file,
- void *buf,
- size_t count);
-
- static inline smbc_write_fn smbc_getFunctionWrite (SMBCCTX *c)
- {
- return c->write;
- }
-
-
- typedef void (*smbc_get_auth_fn) (const char *srv,
- const char *shr,
- char *wg, int wglen,
- char *un, int unlen,
- char *pw, int pwlen);
-
- static inline void smbc_setFunctionAuthData (SMBCCTX *c,
- smbc_get_auth_data_fn fn)
- {
- c->callbacks.auth_fn = fn;
- }
-
-
- static inline void smbc_setTimeout (SMBCCTX *c, int timeout)
- {
- c->timeout = timeout;
- }
-
-
- static inline void smbc_setUser (SMBCCTX *c, char *user)
- {
- c->user = user;
- }
-
-
- static inline void smbc_setWorkgroup (SMBCCTX *c, char *workgroup)
- {
- c->workgroup = workgroup;
- }
-
- #endif
-
-#endif
-
diff --git a/susmb.1 b/susmb.1
@@ -0,0 +1,86 @@
+.Dd March 5, 2025
+.Dt SUSMB 1
+.Os
+.Sh NAME
+.Nm susmb
+.Nd Mount SMB/CIFS shares via FUSE
+.Sh SYNOPSIS
+.Nm
+.Op Fl d
+.Op Fl f
+.Op Fl v
+.Op Fl o Ar options
+.Op Fl u Ar user
+.Op Fl g Ar gid
+.Ar URI
+.Ar mountpoint
+.Pp
+.Ar URI
+is in the format: smb://domain\\[email protected]/Storage
+.Pp
+The password should be specified with the environment variable
+.Ev SMB_PASS .
+.Sh DESCRIPTION
+.Nm
+mounts SMB and CIFS shares through FUSE, including Samba shares and
+Windows shared folders.
+Unlike some other such filesystems,
+.Nm
+can mount
+shares from any server, including those not browsable or advertised on the
+network.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl d
+Debug mode.
+.It Fl f
+Foreground operation (i.e. don't daemonise).
+.It Fl v
+Show
+.Nm ,
+FUSE and Samba versions and exit.
+.It Fl o Ar options
+Additional list of FUSE options as a comma-separated list.
+These options are platform-specific, see the man page of your FUSE
+implementation for the supported options.
+.It Fl u Ar user
+Privdrop to user.
+When a name is given then the uid and gid is read from the password
+database entry.
+Otherwise the option is interpreted as an uid number.
+.It Fl g Ar gid
+Privdrop to group.
+This option is interpreted as an gid number.
+.El
+.Pp
+Both a uid and gid should be specified or resolved to be able to use privdrop.
+.Sh EXIT STATUS
+.Ex -std
+.Sh EXAMPLES
+.Bd -literal
+SMB_PASS="password" susmb -u hiltjo -f -o 'uid=1000,gid=1000,allow_other' "smb…
+.Ed
+.Sh SEE ALSO
+.Xr fusermount 1 ,
+.Xr fuse_mount 3 ,
+.Xr mount.cifs 8 ,
+.Xr umount.cifs 8
+.Sh AUTHORS
+.An Hiltjo Posthuma Aq Mt [email protected]
+.Pp
+usmb authors:
+.Pp
+Geoff Johnstone, with contributions from Jonathan Schultz, Stijn Hoop, Nigel
+Smith and Michal Suchanek.
+.Sh CAVEATS
+.Bl -item
+.It
+When running
+.Nm
+as a privilege-dropped user on Linux there may be issues unmounting the
+network share in a clean manner.
+A workaround could be a shellscript wrapper that does something like:
+.Pp
+trap 'umount /mnt/testshare' INT TERM EXIT
+.El
diff --git a/susmb.c b/susmb.c
@@ -0,0 +1,1377 @@
+/* susmb - mount SMB shares via FUSE and Samba
+ * Copyright (C) 2025 Hiltjo Posthuma
+ * Copyright (C) 2006-2013 Geoff Johnstone
+ *
+ * Portions of this file are taken from Samba 3.2's libsmbclient.h:
+ * Copyright (C) Andrew Tridgell 1998
+ * Copyright (C) Richard Sharpe 2000
+ * Copyright (C) John Terpsra 2000
+ * Copyright (C) Tom Jansen (Ninja ISD) 2002
+ * Copyright (C) Derrell Lipman 2003-2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Marks unused parameters */
+#define UNUSED __attribute__ ((unused))
+
+#define SUSMB_VERSION "0.9"
+
+#include <libsmbclient.h>
+
+/* Required FUSE API version */
+#define FUSE_USE_VERSION 26
+
+#include <fuse.h>
+
+#include <sys/types.h>
+#include <sys/statvfs.h>
+
+/* struct timeval needed by libsmbclient.h */
+#include <sys/time.h>
+
+#include <dirent.h>
+#include <err.h>
+#include <errno.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* use libbsd stdlib.h for arc4random() */
+#ifdef __linux__
+#include <bsd/stdlib.h>
+#endif
+
+#ifndef __OpenBSD__
+#define unveil(p1,p2) 0
+#endif
+
+/* ctype-like macros, but always compatible with ASCII / UTF-8 */
+#define ISALPHA(c) ((((unsigned)c) | 32) - 'a' < 26)
+#define ISCNTRL(c) ((c) < ' ' || (c) == 0x7f)
+#define ISDIGIT(c) (((unsigned)c) - '0' < 10)
+#define ISSPACE(c) ((c) == ' ' || ((((unsigned)c) - '\t') < 5))
+#define TOLOWER(c) ((((unsigned)c) - 'A' < 26) ? ((c) | 32) : (c))
+
+/* URI */
+struct uri {
+ char proto[48]; /* scheme including ":" or "://" */
+ char userinfo[256]; /* username [:password] */
+ char host[256];
+ char port[6]; /* numeric port */
+ char path[1024];
+ char query[1024];
+ char fragment[1024];
+};
+
+int uri_parse(const char *s, struct uri *u);
+
+char * make_url(const char *path);
+bool create_smb_context(SMBCCTX **pctx);
+void destroy_smb_context(SMBCCTX *ctx_, int shutdown);
+
+int usmb_statfs(const char *path UNUSED, struct statvfs *vfs UNUSED);
+int compat_truncate(const char *path, SMBCFILE *file, off_t size);
+
+void show_about(FILE *fp);
+void show_version(FILE *fp);
+void usage(void);
+
+void build_fuse_args(const char *options, const char *mountpoint,
+ int debug, int nofork,
+ int *out_argc, char ***out_argv);
+
+int usmb_fuse_main(int argc, char *argv[],
+ const struct fuse_operations *op, size_t op_size,
+ void *user_data);
+
+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_unlink(const char *filename);
+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);
+int usmb_mknod(const char *filename, mode_t mode, dev_t dev);
+int usmb_create(const char *filename, mode_t mode,
+ struct fuse_file_info *fi);
+int usmb_rename(const char *from, const char *to);
+int usmb_utime(const char *filename, struct utimbuf *utb);
+int usmb_truncate(const char *filename, off_t newsize);
+int usmb_chmod(const char *filename, mode_t mode);
+int usmb_ftruncate(const char *path, off_t size,
+ struct fuse_file_info *fi);
+
+/* directory operations */
+
+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);
+int usmb_setxattr(const char *path, const char *name, const char *value,
+ size_t size, int flags);
+int usmb_getxattr(const char *path, const char *name, char *value,
+ size_t size);
+int usmb_listxattr(const char *path, char *list, size_t size);
+int usmb_removexattr(const char *path, const char *name);
+
+void *emalloc(size_t size);
+void *erealloc(void *ptr, size_t size);
+char *estrdup(const char *s);
+
+char * xstrdup(const char *in);
+void clear_and_free(char *ptr);
+void free_errno(void *ptr);
+
+/* globals */
+
+static SMBCCTX *ctx;
+static int opt_debug, opt_nofork;
+static char *opt_server, *opt_share, *opt_mountpoint, *opt_options,
+ *opt_domain, *opt_username, *opt_password;
+static int disconnect;
+static char *sharename;
+static const char *argv0 = "susmb";
+
+/* for privdrop */
+static uid_t opt_uid;
+static gid_t opt_gid;
+static int opt_privdrop;
+
+/* fuse_file_info uses a uint64_t for a "File handle" */
+static inline uint64_t
+smbcfile_to_fd(SMBCFILE *file)
+{
+ return (uint64_t)(uintptr_t)file;
+}
+
+static inline SMBCFILE *
+fd_to_smbcfile(uint64_t fd)
+{
+ return (SMBCFILE *)(uintptr_t)fd;
+}
+
+void *
+emalloc(size_t size)
+{
+ void *p;
+
+ p = malloc(size);
+ if (p == NULL)
+ err(1, "malloc");
+ return p;
+}
+
+void *
+erealloc(void *ptr, size_t size)
+{
+ void *p;
+
+ p = realloc(ptr, size);
+ if (p == NULL)
+ err(1, "realloc");
+ return p;
+}
+
+char *
+estrdup(const char *s)
+{
+ char *p;
+
+ p = strdup(s);
+ if (p == NULL)
+ err(1, "strdup");
+ return p;
+}
+
+/* Parse URI string `s` into an uri structure `u`.
+ * Returns 0 on success or -1 on failure */
+int
+uri_parse(const char *s, struct uri *u)
+{
+ const char *p = s;
+ char *endptr;
+ size_t i;
+ long l;
+
+ u->proto[0] = u->userinfo[0] = u->host[0] = u->port[0] = '\0';
+ u->path[0] = u->query[0] = u->fragment[0] = '\0';
+
+ /* protocol-relative */
+ if (*p == '/' && *(p + 1) == '/') {
+ p += 2; /* skip "//" */
+ goto parseauth;
+ }
+
+ /* scheme / protocol part */
+ for (; ISALPHA((unsigned char)*p) || ISDIGIT((unsigned char)*p) ||
+ *p == '+' || *p == '-' || *p == '.'; p++)
+ ;
+ /* scheme, except if empty and starts with ":" then it is a path */
+ if (*p == ':' && p != s) {
+ if (*(p + 1) == '/' && *(p + 2) == '/')
+ p += 3; /* skip "://" */
+ else
+ p++; /* skip ":" */
+
+ if ((size_t)(p - s) >= sizeof(u->proto))
+ return -1; /* protocol too long */
+ memcpy(u->proto, s, p - s);
+ u->proto[p - s] = '\0';
+
+ if (*(p - 1) != '/')
+ goto parsepath;
+ } else {
+ p = s; /* no scheme format, reset to start */
+ goto parsepath;
+ }
+
+parseauth:
+ /* userinfo (username:password) */
+ i = strcspn(p, "@/?#");
+ if (p[i] == '@') {
+ if (i >= sizeof(u->userinfo))
+ return -1; /* userinfo too long */
+ memcpy(u->userinfo, p, i);
+ u->userinfo[i] = '\0';
+ p += i + 1;
+ }
+
+ /* IPv6 address */
+ if (*p == '[') {
+ /* bracket not found, host too short or too long */
+ i = strcspn(p, "]");
+ if (p[i] != ']' || i < 3)
+ return -1;
+ i++; /* including "]" */
+ } else {
+ /* domain / host part, skip until port, path or end. */
+ i = strcspn(p, ":/?#");
+ }
+ if (i >= sizeof(u->host))
+ return -1; /* host too long */
+ memcpy(u->host, p, i);
+ u->host[i] = '\0';
+ p += i;
+
+ /* port */
+ if (*p == ':') {
+ p++;
+ if ((i = strcspn(p, "/?#")) >= sizeof(u->port))
+ return -1; /* port too long */
+ memcpy(u->port, p, i);
+ u->port[i] = '\0';
+ /* check for valid port: range 1 - 65535, may be empty */
+ errno = 0;
+ l = strtol(u->port, &endptr, 10);
+ if (i && (errno || *endptr || l <= 0 || l > 65535))
+ return -1;
+ p += i;
+ }
+
+parsepath:
+ /* path */
+ if ((i = strcspn(p, "?#")) >= sizeof(u->path))
+ return -1; /* path too long */
+ memcpy(u->path, p, i);
+ u->path[i] = '\0';
+ p += i;
+
+ /* query */
+ if (*p == '?') {
+ p++;
+ if ((i = strcspn(p, "#")) >= sizeof(u->query))
+ return -1; /* query too long */
+ memcpy(u->query, p, i);
+ u->query[i] = '\0';
+ p += i;
+ }
+
+ /* fragment */
+ if (*p == '#') {
+ p++;
+ if ((i = strlen(p)) >= sizeof(u->fragment))
+ return -1; /* fragment too long */
+ memcpy(u->fragment, p, i);
+ u->fragment[i] = '\0';
+ }
+
+ return 0;
+}
+
+char *
+xstrdup(const char *in)
+{
+ if (in != NULL)
+ return estrdup(in);
+ return NULL;
+}
+
+void
+clear_and_free(char *ptr)
+{
+ if (ptr != NULL) {
+ explicit_bzero(ptr, strlen(ptr));
+ free(ptr);
+ }
+}
+
+void
+free_errno(void *ptr)
+{
+ int saved_errno = errno;
+ free(ptr);
+ errno = saved_errno;
+}
+
+int
+usmb_statfs(const char *path, struct statvfs *vfs)
+{
+ if (path == NULL || vfs == NULL)
+ return -EINVAL;
+
+ char *url = make_url(path);
+ if (url == NULL)
+ return -ENOMEM;
+
+ memset(vfs, 0, sizeof(*vfs));
+
+ int ret = (0 > smbc_getFunctionStatVFS(ctx) (ctx, url, vfs)) ? -errno …
+ free(url);
+
+ return ret;
+}
+
+int
+compat_truncate(const char *path UNUSED, SMBCFILE *file, off_t size)
+{
+ return (0 > smbc_getFunctionFtruncate(ctx) (ctx, file, size)) ? -errno…
+}
+
+static bool
+change_blksiz(struct stat *st)
+{
+ if (st == NULL)
+ return false;
+
+ /* change block size to improve performance of stdio FILE * operations,
+ only for regular files to be on the safe side. */
+ if (S_ISREG(st->st_mode)) {
+ st->st_blksize = 32768;
+ return true;
+ }
+
+ return false;
+}
+
+/* Samba gets st_nlink wrong for directories. */
+/* still wrong in 2025-03-03 with Samba 4.20 */
+static bool
+fix_nlink(const char *url, struct stat *st)
+{
+ if (!S_ISDIR(st->st_mode))
+ return true;
+
+ SMBCFILE *file = smbc_getFunctionOpendir(ctx) (ctx, url);
+ if (file == NULL)
+ return false;
+
+ st->st_nlink = 0;
+ errno = ERANGE;
+
+ struct smbc_dirent *dirent;
+ while (NULL != (dirent = smbc_getFunctionReaddir(ctx) (ctx, file))) {
+ if (SMBC_DIR == dirent->smbc_type) {
+ if (INT_MAX == st->st_nlink++) {
+ break;
+ }
+ }
+ }
+
+ (void)smbc_getFunctionClosedir(ctx) (ctx, file);
+
+ return (dirent == NULL);
+}
+
+int
+usmb_getattr(const char *filename, struct stat *st)
+{
+ char *url = make_url(filename);
+ if (url == NULL)
+ return -ENOMEM;
+
+ int ret = smbc_getFunctionStat(ctx) (ctx, url, st);
+
+ if ((0 > ret) || !fix_nlink(url, st))
+ ret = -errno;
+
+ change_blksiz(st);
+
+ free(url);
+
+ return ret;
+}
+
+int
+usmb_fgetattr(const char *filename UNUSED, struct stat *st,
+ struct fuse_file_info *fi)
+{
+ SMBCFILE *file = fd_to_smbcfile(fi->fh);
+
+ if (0 > smbc_getFunctionFstat(ctx) (ctx, file, st))
+ return -errno;
+
+ if (S_ISDIR(st->st_mode)) {
+ char *url = make_url(filename);
+ if (url == NULL)
+ return -ENOMEM;
+
+ bool ok = fix_nlink(url, st);
+ free_errno(url);
+
+ if (!ok)
+ return -errno;
+ }
+
+ change_blksiz(st);
+
+ return 0;
+}
+
+int
+usmb_unlink(const char *filename)
+{
+ char *url = make_url(filename);
+ if (url == NULL)
+ return -ENOMEM;
+
+ int ret = (0 > smbc_getFunctionUnlink(ctx) (ctx, url)) ? -errno : 0;
+ free(url);
+
+ return ret;
+}
+
+int
+usmb_open(const char *filename, struct fuse_file_info *fi)
+{
+ char *url = make_url(filename);
+
+ if (url == NULL)
+ return -ENOMEM;
+
+ SMBCFILE *file = smbc_getFunctionOpen(ctx) (ctx, url, fi->flags, 0);
+
+ int ret = (file == NULL) ? -errno : 0;
+ free(url);
+ fi->fh = smbcfile_to_fd(file);
+
+ return ret;
+}
+
+int
+usmb_release(const char *filename UNUSED, struct fuse_file_info *fi)
+{
+ SMBCFILE *file = fd_to_smbcfile(fi->fh);
+ return (0 > smbc_getFunctionClose(ctx) (ctx, file)) ? -errno : 0;
+}
+
+int
+usmb_read(const char *filename UNUSED, char *buff, size_t len, off_t off,
+ struct fuse_file_info *fi)
+{
+ SMBCFILE *file = fd_to_smbcfile(fi->fh);
+
+ if (0 > smbc_getFunctionLseek(ctx) (ctx, file, off, SEEK_SET)) {
+ return -errno;
+ }
+
+ int bytes = smbc_getFunctionRead(ctx) (ctx, file, buff, len);
+
+ return (0 > bytes) ? -errno : (int)bytes;
+}
+
+int
+usmb_write(const char *filename UNUSED, const char *buff, size_t len,
+ off_t off, struct fuse_file_info *fi)
+{
+ SMBCFILE *file = fd_to_smbcfile(fi->fh);
+ size_t written = 0;
+ int bytes = 0;
+
+ if (0 > smbc_getFunctionLseek(ctx)(ctx, file, off, SEEK_SET))
+ return -errno;
+
+ const smbc_write_fn write_fn = smbc_getFunctionWrite(ctx);
+ while (written < len) {
+ bytes = write_fn(ctx, file, (char *)buff, len);
+ if (0 > bytes)
+ break;
+
+ written += bytes;
+ buff += bytes;
+
+ /* avoids infinite loops. */
+ if (bytes == 0)
+ break;
+ }
+
+ return (0 > bytes) ? -errno : (int)written;
+}
+
+/* File systems must support mknod on OpenBSD */
+int
+usmb_mknod(const char *filename, mode_t mode, __attribute__((unused)) dev_t de…
+{
+ char *url = make_url(filename);
+ if (url == NULL)
+ return -ENOMEM;
+
+ if (S_ISCHR(mode) || S_ISBLK(mode) || S_ISFIFO(mode) || S_ISSOCK(mode))
+ return -EPERM;
+
+ SMBCFILE *file = smbc_getFunctionCreat(ctx) (ctx, url, mode);
+ int ret = (file == NULL) ? -errno : 0;
+
+ /* File must not be open when mknod returns. */
+ if (ret == 0)
+ smbc_getFunctionClose(ctx) (ctx, file);
+ free(url);
+
+ return ret;
+}
+
+int
+usmb_create(const char *filename, mode_t mode, struct fuse_file_info *fi)
+{
+ char *url = make_url(filename);
+ if (url == NULL)
+ return -ENOMEM;
+
+ SMBCFILE *file = smbc_getFunctionCreat(ctx) (ctx, url, mode);
+
+ int ret = (file == NULL) ? -errno : 0;
+ fi->fh = smbcfile_to_fd(file);
+
+ free(url);
+
+ return ret;
+}
+
+int
+usmb_rename(const char *from, const char *to)
+{
+ char *fromurl = make_url(from);
+ if (fromurl == NULL)
+ return -ENOMEM;
+
+ char *tourl = make_url(to);
+ if (tourl == NULL) {
+ free(fromurl);
+ return -ENOMEM;
+ }
+
+ int ret =
+ (0 > smbc_getFunctionRename(ctx)(ctx, fromurl, ctx, tourl)) ? -err…
+ free(tourl);
+ free(fromurl);
+
+ return ret;
+}
+
+int
+usmb_utime(const char *filename, struct utimbuf *utb)
+{
+ struct utimbuf tmp_utb;
+
+ if (utb == NULL) {
+ for (;;) {
+ time_t now = time(NULL);
+ if (now != (time_t)-1) {
+ tmp_utb.actime = tmp_utb.modtime = now;
+ break;
+ }
+
+ if (EINTR != errno)
+ return -errno;
+
+ usleep(1000); /* sleep a bit to not hog the CPU */
+ }
+ utb = &tmp_utb;
+ }
+
+ char *url = make_url(filename);
+ if (url == NULL)
+ return -ENOMEM;
+
+ struct timeval tv[2] = {
+ { .tv_sec = utb->actime, .tv_usec = 0 },
+ { .tv_sec = utb->modtime, .tv_usec = 0 },
+ };
+
+ int ret = (0 > smbc_getFunctionUtimes (ctx) (ctx, url, tv)) ? -errno :…
+ free(url);
+
+ return ret;
+}
+
+int
+usmb_chmod(const char *filename, mode_t mode)
+{
+ char *url = make_url(filename);
+
+ if (url == NULL)
+ return -ENOMEM;
+
+ int ret = (0 > smbc_getFunctionChmod(ctx) (ctx, url, mode)) ? -errno :…
+ free(url);
+
+ return ret;
+}
+
+int
+usmb_truncate(const char *filename, off_t newsize)
+{
+ char *url = make_url(filename);
+ if (url == NULL)
+ return -ENOMEM;
+
+ SMBCFILE *file = smbc_getFunctionOpen(ctx) (ctx, url, O_WRONLY, 0);
+ if (file == NULL) {
+ int ret = -errno;
+ free(url);
+ return ret;
+ }
+
+ int ret = compat_truncate(filename, file, newsize);
+
+ smbc_getFunctionClose(ctx) (ctx, file);
+ free(url);
+
+ return ret;
+}
+
+int
+usmb_ftruncate(const char *path, off_t size,
+ struct fuse_file_info *fi)
+{
+ return compat_truncate(path, fd_to_smbcfile(fi->fh), size);
+}
+
+/* directory operations below */
+
+int
+usmb_mkdir(const char *dirname, mode_t mode)
+{
+ char *url = make_url(dirname);
+
+ if (url == NULL)
+ return -ENOMEM;
+
+ int ret = smbc_getFunctionMkdir(ctx) (ctx, url, mode) ? -errno : 0;
+ free(url);
+
+ return ret;
+}
+
+int
+usmb_rmdir(const char *dirname)
+{
+ char *url = make_url(dirname);
+ if (url == NULL)
+ return -ENOMEM;
+
+ int ret = smbc_getFunctionRmdir(ctx) (ctx, url) ? -errno : 0;
+ free(url);
+
+ return ret;
+}
+
+int
+usmb_opendir(const char *dirname, struct fuse_file_info *fi)
+{
+ char *url = make_url(dirname);
+ if (url == NULL)
+ return -ENOMEM;
+
+ SMBCFILE *file = smbc_getFunctionOpendir(ctx) (ctx, url);
+
+ int ret = (file == NULL) ? -errno : 0;
+ free(url);
+
+ fi->fh = smbcfile_to_fd(file);
+
+ return ret;
+}
+
+int
+usmb_readdir(const char *path, void *h, fuse_fill_dir_t filler,
+ off_t offset UNUSED, struct fuse_file_info *fi UNUSED)
+{
+ SMBCCTX *ctx_ = NULL;
+ SMBCFILE *file = NULL;
+ char *url = NULL;
+ struct smbc_dirent *dirent;
+ struct stat stbuf;
+ int ret = 0;
+
+ if (!create_smb_context(&ctx_))
+ return -errno;
+
+ do {
+ url = make_url(path);
+ if (url == NULL) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ file = smbc_getFunctionOpendir(ctx_) (ctx_, url);
+ if (file == NULL) {
+ ret = -errno;
+ break;
+ }
+
+ smbc_getFunctionLseekdir(ctx_) (ctx_, file, 0);
+
+ while (NULL != (dirent = smbc_getFunctionReaddir(ctx_) (ctx_, …
+ memset(&stbuf, 0, sizeof(stbuf));
+ stbuf.st_ino = arc4random();
+
+ switch (dirent->smbc_type) {
+ case SMBC_DIR:
+ stbuf.st_mode = S_IFDIR;
+ break;
+ case SMBC_FILE:
+ stbuf.st_mode = S_IFREG;
+ break;
+ case SMBC_LINK:
+ stbuf.st_mode = S_IFLNK;
+ break;
+ default:
+ break;
+ }
+
+ if (1 == filler(h, dirent->name, &stbuf, 0)) { /* if e…
+ ret = -1;
+ break;
+ }
+ }
+ } while (false /*CONSTCOND*/);
+
+ if (file != NULL)
+ (void)smbc_getFunctionClosedir(ctx_) (ctx_, file);
+
+ free(url);
+ destroy_smb_context(ctx_, 0);
+
+ return ret;
+}
+
+int
+usmb_releasedir(const char *path UNUSED, struct fuse_file_info *fi)
+{
+ SMBCFILE *file = fd_to_smbcfile(fi->fh);
+
+ return (0 > smbc_getFunctionClosedir(ctx) (ctx, file)) ? -errno : 0;
+}
+
+int
+usmb_setxattr(const char *path, const char *name, const char *value,
+ size_t size, int flags)
+{
+ char *url = make_url(path);
+ if (url == NULL)
+ return -ENOMEM;
+
+ int ret = smbc_getFunctionSetxattr(ctx) (ctx, url, name,
+ value, size, flags) ? -errno : 0;
+ free(url);
+
+ return ret;
+}
+
+int
+usmb_getxattr(const char *path, const char *name, char *value, size_t size)
+{
+ char *url = make_url(path);
+ if (url == NULL)
+ return -ENOMEM;
+
+ int ret = smbc_getFunctionGetxattr(ctx) (ctx, url, name,
+ value, size) ? -errno : 0;
+ free(url);
+
+ return ret;
+}
+
+int
+usmb_listxattr(const char *path, char *list, size_t size)
+{
+ char *url = make_url(path);
+ if (url == NULL)
+ return -ENOMEM;
+
+ int ret = smbc_getFunctionListxattr(ctx) (ctx, url, list, size) ? -err…
+ free(url);
+
+ return ret;
+}
+
+int
+usmb_removexattr(const char *path, const char *name)
+{
+ char *url = make_url(path);
+ if (url == NULL)
+ return -ENOMEM;
+
+ int ret = smbc_getFunctionRemovexattr(ctx) (ctx, url, name) ? -errno :…
+ free(url);
+
+ return ret;
+}
+
+char *
+make_url(const char *path)
+{
+ size_t len;
+ char *p;
+
+ /* no path or path is empty */
+ if ((path == NULL) || (path[0] == '\0')) {
+ return xstrdup(sharename);
+ } else {
+ len = strlen(sharename) + strlen(path) + 1;
+ p = emalloc(len);
+ snprintf(p, len, "%s%s", sharename, path);
+ return p;
+ }
+}
+
+static void
+auth_fn(const char *srv UNUSED, const char *shr UNUSED,
+ char *wg, int wglen, char *un, int unlen,
+ char *pw, int pwlen)
+{
+ /* snprintf is used in this way to behave similar to strlcpy(), for po…
+
+ if (opt_domain != NULL)
+ snprintf(wg, wglen, "%s", opt_domain);
+ else if (wglen)
+ wg[0] = '\0'; /* no domain */
+
+ snprintf(un, unlen, "%s", opt_username);
+ snprintf(pw, pwlen, "%s", opt_password);
+}
+
+void
+destroy_smb_context(SMBCCTX *ctx_, int shutdown)
+{
+ /* Samba frees the workgroup and user strings but we want to persist t…
+ smbc_setWorkgroup(ctx_, NULL);
+ smbc_setUser(ctx_, NULL);
+ smbc_free_context(ctx_, shutdown);
+}
+
+bool
+create_smb_context(SMBCCTX **pctx)
+{
+ *pctx = smbc_new_context();
+
+ if (*pctx == NULL) {
+ perror("Cannot create SMB context");
+ return false;
+ }
+
+ smbc_setWorkgroup(*pctx, opt_domain);
+ smbc_setUser(*pctx, opt_username);
+ smbc_setTimeout(*pctx, 5000);
+ smbc_setFunctionAuthData(*pctx, auth_fn);
+
+ if (smbc_init_context(*pctx) == NULL) {
+ perror("Cannot initialise SMB context");
+ destroy_smb_context(*pctx, 1);
+ return false;
+ }
+
+ return true;
+}
+
+static void *
+usmb_init(struct fuse_conn_info *conn UNUSED)
+{
+ return NULL;
+}
+
+static void
+usmb_destroy(void *unused UNUSED)
+{
+}
+
+// probably won't (can't ?) implement these:
+// readlink symlink flush fsync
+
+// no easy way of implementing these:
+// access
+
+#define SET_ELEMENT(name,value) name = value
+
+static struct fuse_operations fuse_ops = {
+ SET_ELEMENT (.getattr, usmb_getattr),
+ SET_ELEMENT (.readlink, NULL),
+ SET_ELEMENT (.getdir, NULL),
+ SET_ELEMENT (.mknod, usmb_mknod),
+ SET_ELEMENT (.mkdir, usmb_mkdir),
+ SET_ELEMENT (.unlink, usmb_unlink),
+ SET_ELEMENT (.rmdir, usmb_rmdir),
+ SET_ELEMENT (.symlink, NULL),
+ SET_ELEMENT (.rename, usmb_rename),
+ SET_ELEMENT (.link, NULL),
+ SET_ELEMENT (.chmod, usmb_chmod),
+ SET_ELEMENT (.chown, NULL), // usmb_chown, --not implemented in libsmbclient
+ SET_ELEMENT (.truncate, usmb_truncate),
+ SET_ELEMENT (.utime, usmb_utime),
+ SET_ELEMENT (.open, usmb_open),
+ SET_ELEMENT (.read, usmb_read),
+ SET_ELEMENT (.write, usmb_write),
+ SET_ELEMENT (.statfs, usmb_statfs),
+ SET_ELEMENT (.flush, NULL),
+ SET_ELEMENT (.release, usmb_release),
+ SET_ELEMENT (.fsync, NULL),
+ SET_ELEMENT (.setxattr, usmb_setxattr),
+ SET_ELEMENT (.getxattr, usmb_getxattr),
+ SET_ELEMENT (.listxattr, usmb_listxattr),
+ SET_ELEMENT (.removexattr, usmb_removexattr),
+ SET_ELEMENT (.opendir, usmb_opendir),
+ SET_ELEMENT (.readdir, usmb_readdir),
+ SET_ELEMENT (.releasedir, usmb_releasedir),
+ SET_ELEMENT (.fsyncdir, NULL),
+ SET_ELEMENT (.init, usmb_init),
+ SET_ELEMENT (.destroy, usmb_destroy),
+ SET_ELEMENT (.access, NULL),
+ SET_ELEMENT (.create, usmb_create),
+ SET_ELEMENT (.ftruncate, usmb_ftruncate),
+ SET_ELEMENT (.fgetattr, usmb_fgetattr),
+ SET_ELEMENT (.lock, NULL), // TODO: implement
+ SET_ELEMENT (.utimens, NULL), // TODO: implement
+ SET_ELEMENT (.bmap, NULL), // TODO: implement
+};
+
+static char *
+create_share_name(const char *server_, const char *sharename)
+{
+ /* len: + 2 for "/" and NUL terminator */
+ size_t len = strlen("smb://") + strlen(server_) + strlen(sharename) + …
+ char *p;
+
+ p = emalloc(len);
+ snprintf(p, len, "smb://%s/%s", server_, sharename);
+
+ return p;
+}
+
+static bool
+check_credentials(void)
+{
+ char *url = make_url("");
+ if (url == NULL) {
+ errno = ENOMEM;
+ return false;
+ }
+
+ struct stat stat_;
+ bool ret = (0 == (smbc_getFunctionStat(ctx) (ctx, url, &stat_)));
+
+ free_errno(url);
+
+ return ret;
+}
+
+static bool
+get_context(void)
+{
+ ctx = NULL;
+
+ if (disconnect)
+ return false;
+
+ disconnect = 1;
+ if (!create_smb_context(&ctx))
+ return false;
+
+ if (!check_credentials()) {
+ perror("Connection failed");
+ destroy_smb_context(ctx, 1);
+ ctx = NULL;
+ return NULL;
+ }
+
+ disconnect = 0;
+
+ return (ctx != NULL);
+}
+
+void
+show_about(FILE *fp)
+{
+ fprintf(fp, "susmb - mount SMB shares via FUSE and Samba\n"
+ "\n"
+ "Copyright (C) 2025 Hiltjo Posthuma.\n"
+ "Copyright (C) 2006-2013 Geoff Johnstone.\n"
+ "\n"
+ "Licensed under the GNU General Public License.\n"
+ "susmb comes with ABSOLUTELY NO WARRANTY; "
+ "for details please see\n"
+ "http://www.gnu.org/licenses/gpl.txt\n"
+ "\n"
+ "Please send bug reports, patches etc. to [email protected]…
+}
+
+void
+show_version(FILE *fp)
+{
+ show_about(fp);
+ fputc('\n', fp);
+ fprintf(fp, "susmb version: %s\n"
+ "FUSE version: %d.%d\n"
+ "Samba version: %s\n",
+ SUSMB_VERSION,
+ FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION,
+ smbc_version());
+}
+
+void
+usage(void)
+{
+ fprintf(stdout,
+ "Usage: %s [-dfv] [-o options] [-u user] [-g gid] <smb://domai…
+ "\n"
+ "Options:\n"
+ " -d Debug mode\n"
+ " -f Foreground operation\n"
+ " -o Additional FUSE options\n"
+ " -u Privdrop to user and its group or uid\n"
+ " -g Privdrop to group id\n"
+ " -v Show program, FUSE and Samba versions\n", argv0);
+ exit(1);
+}
+
+/* FUSE args are:
+ *
+ * argv[0]
+ * -s
+ * -d -- if debug mode requested
+ * -f -- if foreground mode requested
+ * -o ... -- if any mount options in the config file
+ * mount point
+ */
+#define MAXARGS 12
+void build_fuse_args(const char *options, const char *mountpoint,
+ int debug, int nofork,
+ int *out_argc, char ***out_argv)
+{
+ static char SUSMB[] = "susmb";
+ static char MINUS_S[] = "-s";
+ static char MINUS_D[] = "-d";
+ static char MINUS_F[] = "-f";
+ static char MINUS_O[] = "-o";
+ static char *argv[MAXARGS];
+ int argc = 0;
+
+ argv[argc++] = SUSMB;
+ argv[argc++] = MINUS_S;
+
+ if (debug)
+ argv[argc++] = MINUS_D;
+
+ if (nofork)
+ argv[argc++] = MINUS_F;
+
+ if ((options != NULL) && (options[0] != '\0')) {
+ argv[argc++] = MINUS_O;
+ argv[argc++] = (char *)options;
+ }
+
+ argv[argc++] = (char *)mountpoint;
+ argv[argc] = NULL;
+
+ *out_argc = argc;
+ *out_argv = argv;
+}
+
+int usmb_fuse_main(int argc, char *argv[],
+ const struct fuse_operations *op, size_t op_size,
+ void *user_data)
+{
+ struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+ struct fuse *fuse = NULL;
+ struct fuse_chan *chan = NULL;
+ struct fuse_session *session = NULL;
+ int fd, res = 1;
+ int fflag = 0, sflag = 0;
+ char *mountpoint = NULL;
+
+ if (fuse_parse_cmdline(&args, &mountpoint, &sflag, &fflag) != 0)
+ return 1;
+
+ if (mountpoint == NULL || *mountpoint == '\0') {
+ warnx("error: no mountpoint specified");
+ res = 2;
+ goto out1;
+ }
+
+ chan = fuse_mount(mountpoint, &args);
+ if (chan == NULL) {
+ res = 4;
+ goto out2;
+ }
+
+ fuse = fuse_new(chan, &args, op, op_size, user_data);
+ if (fuse == NULL) {
+ res = 3;
+ goto out1;
+ }
+
+ /* daemonize */
+ if (!fflag) {
+ switch (fork()) {
+ case -1:
+ res = 5;
+ warn("fork");
+ goto out3;
+ case 0:
+ break;
+ default:
+ _exit(0);
+ }
+
+ if (setsid() == -1) {
+ res = 5;
+ warn("setsid");
+ goto out3;
+ }
+
+ (void)chdir("/"); /* nochdir */
+
+ /* noclose */
+ if ((fd = open("/dev/null", O_RDWR)) != -1) {
+ (void)dup2(fd, STDIN_FILENO);
+ (void)dup2(fd, STDOUT_FILENO);
+ (void)dup2(fd, STDERR_FILENO);
+ if (fd > 2)
+ (void)close(fd);
+ }
+ }
+
+ /* setup signal handlers: can only be used if privdrop is not used */
+ if (!opt_privdrop) {
+ session = fuse_get_session(fuse);
+ if (fuse_set_signal_handlers(session) != 0) {
+ res = 6;
+ goto out3;
+ }
+ }
+
+ /* privdrop */
+ if (opt_privdrop) {
+ if (setresgid(opt_uid, opt_uid, opt_uid) == -1)
+ err(1, "setresgid");
+ if (setresuid(opt_gid, opt_gid, opt_gid) == -1)
+ err(1, "setresuid");
+ }
+
+ res = fuse_loop(fuse);
+ if (res)
+ res = 8;
+
+ if (!opt_privdrop) {
+ if (session)
+ fuse_remove_signal_handlers(session);
+ }
+
+out3:
+ if (chan)
+ fuse_unmount(mountpoint, chan);
+out2:
+ if (fuse)
+ fuse_destroy(fuse);
+out1:
+ return res;
+}
+
+int
+main(int argc, char **argv)
+{
+ struct uri u;
+ struct passwd *pw;
+ char *tmp, *p;
+ char **fuse_argv;
+ int fuse_argc;
+ int ch, ret = 1;
+ long l;
+
+ while ((ch = getopt(argc, argv, "hvVdfo:u:g:")) != -1) {
+ switch (ch) {
+ case 'd':
+ opt_debug = 1;
+ break;
+ case 'f':
+ opt_nofork = 1;
+ break;
+ case 'o':
+ opt_options = xstrdup(optarg);
+ break;
+ case 'h':
+ usage();
+ break;
+ case 'u':
+ opt_privdrop = 1;
+ /* by username: use uid and gid from passwd entry */
+ if ((pw = getpwnam(optarg)) != NULL) {
+ opt_uid = pw->pw_uid;
+ opt_gid = pw->pw_gid;
+ } else {
+ /* try to parse number */
+ errno = 0;
+ l = strtol(optarg, NULL, 10);
+ if (l <= 0 || errno)
+ usage();
+ opt_uid = (uid_t)l;
+ }
+ break;
+ case 'g':
+ opt_privdrop = 1;
+ /* parse gid as number */
+ errno = 0;
+ l = strtol(optarg, NULL, 10);
+ if (l <= 0 || errno)
+ usage();
+ opt_gid = (gid_t)l;
+ break;
+ case 'v':
+ case 'V':
+ show_version(stdout);
+ exit(0);
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (opt_privdrop && (opt_uid == 0 || opt_gid == 0))
+ usage();
+
+ /* password is read from enviroment variable.
+ It is assumed the environment is secure */
+ if ((tmp = getenv("SMB_PASS")) != NULL)
+ opt_password = xstrdup(tmp);
+
+ /* options were succesfully parsed */
+ if (ch == '?' || ch == ':') {
+ usage();
+ return 0;
+ }
+
+ if (argc != 2)
+ usage();
+
+ /* parse URI */
+ tmp = xstrdup(argv[0]);
+ if (uri_parse(tmp, &u) == -1)
+ usage();
+
+ /* check required options and format */
+ if (strcmp(u.proto, "smb://") ||
+ u.userinfo[0] == '\0' ||
+ u.host[0] == '\0' ||
+ u.path[0] != '/') {
+ usage();
+ }
+
+ /* password in userinfo field is not allowed */
+ if (strchr(u.userinfo, ':')) {
+ fprintf(stderr, "password must be specified via $SMB_PASS\n\n"…
+ usage();
+ }
+
+ /* split domain\user if '\' is found */
+ if ((p = strchr(u.userinfo, '\\'))) {
+ *p = '\0';
+ opt_domain = xstrdup(u.userinfo);
+ opt_username = xstrdup(p + 1);
+ } else {
+ opt_domain = xstrdup("");
+ opt_username = xstrdup(u.userinfo);
+ }
+
+ opt_server = xstrdup(u.host);
+ opt_share = xstrdup(u.path + 1); /* share name, "/Sharename" -> "Share…
+ free(tmp);
+
+ opt_mountpoint = xstrdup(argv[1]);
+
+ if (opt_mountpoint == NULL || opt_mountpoint[0] == '\0' ||
+ opt_server == NULL || opt_server[0] == '\0' ||
+ opt_share == NULL || opt_share[0] == '\0' ||
+ opt_username == NULL || opt_username[0] == '\0' ||
+ opt_password == NULL) {
+ usage();
+ }
+
+ if (unveil("/", "") == -1)
+ err(1, "unveil");
+ /* required for daemonize mode and ignoring output */
+ if (unveil("/dev/null", "rw") == -1)
+ err(1, "unveil");
+ /* read-write permissions to OpenBSD FUSE driver */
+ if (unveil("/dev/fuse0", "rw") == -1)
+ err(1, "unveil");
+ /* (r)ead, (w)rite, e(x)ecute, (c)reate permissions to mountpoint */
+ if (unveil(opt_mountpoint, "rwxc") == -1)
+ err(1, "unveil");
+ /* lock further unveil calls */
+ if (unveil(NULL, NULL) == -1)
+ err(1, "unveil");
+
+ sharename = create_share_name(opt_server, opt_share);
+ if (sharename != NULL) {
+ if (get_context()) {
+ build_fuse_args(opt_options, opt_mountpoint, opt_debug…
+ ret = usmb_fuse_main(fuse_argc, fuse_argv, &fuse_ops, …
+ destroy_smb_context(ctx, 1);
+ }
+ }
+
+ free(sharename);
+ clear_and_free(opt_password);
+ free(opt_username);
+ free(opt_domain);
+ free(opt_options);
+ free(opt_mountpoint);
+ free(opt_share);
+ free(opt_server);
+
+ return ret;
+}
diff --git a/usmb.1 b/usmb.1
@@ -1,156 +0,0 @@
-.\" Copyright (C) 2010 Geoff Johnstone.
-.\" See section COPYING for conditions for redistribution.
-.TH usmb 1 "April 2010" "usmb" "User Commands"
-.fp 0 CR
-.SH NAME
-usmb \- Mount SMB/CIFS shares via FUSE
-.SH SYNOPSIS
-usmb [\-c \fIfile\fR] [\-d] [\-f] \fImount_id\fR
-.br
-usmb [\-c \fIfile\fR] \-u \fImount_id\fR
-.SH DESCRIPTION
-.P
-usmb mounts SMB and CIFS shares through FUSE, including Samba shares and
-Windows shared folders. Unlike some other such filesystems, usmb can mount
-shares from any server, including those not browsable or advertised on the
-network.
-.P
-Shares, usernames and other details are defined in a configuration file, by
-default ${HOME}/.usmb.conf.
-.SH OPTIONS
-.TP
-\fB\-c\fR \fIfile\fR, \fB\-\-config\fR=\fIfile\fR
-Use \fIfile\fR rather than ${HOME}/.usmb.conf as the configuration file.
-.TP
-\fB\-d\fR, \fB\-\-debug\fR
-Debug mode.
-.TP
-\fB\-f\fR, \fB\-\-nofork\fR
-Foreground operation (i.e. don't daemonise).
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-Show usage information and exit.
-.TP
-\fB\-u\fR, \fB\-\-unmount\fR
-Unmount the given filesystem.
-.TP
-\fB\-v\fR, \fB\-\-version\fR
-Show usmb, FUSE and Samba versions and exit.
-.P
-.SH CONFIGURATION
-.P
-usmb uses the configuration file ${HOME}/.usmb.conf to define shares and the
-credentials used to access them. The configuration file is an XML file with
-two main elements: credentials and mounts. The file can contain any number of
-credentials and mounts elements; the whole file is wrapped in a usmbconfig
-element.
-.SS Credentials
-.P
-.ft CR
- <credentials id="\fIID used in mount elements\f(CR">
- <domain>\fIdomain or workgroup\f(CR</domain>
- <username>\fIusername\f(CR</username>
- <password>\fIpassword (optional)\f(CR</password>
- </credentials>
-.P
-Each credentials element defines a domain/username/password triple. If you
-omit the <password> element then usmb will prompt for a password when the
-credentials are used.
-.SS Mounts
-.P
-.ft CR
- <mount id="\fImount_id\f(CR" credentials="\fIID of credentials to use\f(CR">
- <server>\fIhostname or IP address of server\f(CR</server>
- <share>\fIshare name\f(CR</share>
- <mountpoint>\fI/path/to/mount/point\f(CR</mountpoint>
- <options>\fImount options\f(CR</options>
- </mount>
-.P
-A mount element describes a share. The id attribute is given on the usmb
-command line to identify the share to mount. The credentials attribute
-identified the id of the credentials element to use. The (optional) options
-element gives a comma-separated list of FUSE mount options:
-.TP
-\fBhard_remove\fR
-Immediate removal (don't hide files)
-.TP
-\fBumask=M\fR
-Set file permissions (octal)
-.TP
-\fBuid=N\fR
-Set file owner
-.TP
-\fBgid=N\fR
-Set file group
-.TP
-\fBallow_other\fR
-Allow access to other users
-.TP
-\fBallow_root\fR
-Allow access to root
-.TP
-\fBnonempty\fR
-Allow mount over non-empty directory
-.SS Example
-.P
-.ft CR
-<?xml version="1.0" encoding="ISO-8859-1"?>
-.br
-<usmbconfig>
-
- <credentials id="cred1">
- <domain>WORKGROUP</domain>
- <username>user</username>
- <password>pass</password>
- </credentials>
-
- <credentials id="cred2">
- <domain>mydomain</domain>
- <username>anotheruser</username>
- <!-- No password element => prompt for password at runtime. -->
- </credentials>
-
- <mount id="home" credentials="cred1">
- <server>192.168.0.5</server>
- <share>myshare</share>
- <mountpoint>/tmp/smb</mountpoint>
- </mount>
-
- <mount id="music" credentials="cred2">
- <server>winbox</server>
- <share>music</share>
-
- <!-- You can use ~/xyz or ~user/xyz for the mountpoint. -->
- <mountpoint>~/music</mountpoint>
- <options>allow_root</options>
- </mount>
-
-</usmbconfig>
-.P
-This defines two shares:
-.RS 2
-\\\\192.168.0.5\\myshare on /tmp/smb authenticating as WORKGROUP\\user
-.br
-\\\\winbox\\music on ${HOME}/music authenticating as mydomain\\anotheruser
-.RE
-.P
-These can be mounted using "usmb home" or "usmb music".
-.SH AUTHOR
-Geoff Johnstone, with contributions from Jonathan Schultz, Stijn Hoop, Nigel
-Smith and Michal Suchanek.
-.SH FILES
-${HOME}/.usmb.conf
-.SH BUGS
-.P
-usmb should not require a configuration file. The configuration file can
-provide defaults but you should be able to specify everything necessary on
-the command line.
-.P
-usmb does not support Kerberos / GSSAPI authentication, although a development
-branch exists with preliminary support.
-.SH "SEE ALSO"
-fusermount(1), mount.cifs(8), umount.cifs(8).
-.SH COPYING
-Copyright \(co 2006-2013 Geoff Johnstone.
-.br
-Licence: GNU GPL version 3 <http://gnu.org/licenses/gpl.html>.
diff --git a/usmb.c b/usmb.c
@@ -1,336 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2013 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <sys/time.h> // struct timeval needed by libsmbclient.h
-#include <unistd.h>
-#include <libsmbclient.h>
-#include "samba3x-compat.h"
-#include <fuse.h>
-#include <assert.h>
-#include <limits.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "conffile.h"
-#include "options.h"
-#include "password.h"
-#include "usmb.h"
-#include "usmb_dir.h"
-#include "usmb_file.h"
-#include "utils.h"
-#include "version.h"
-
-
-SMBCCTX *ctx;
-static char *server, *share, *mountpoint, *options,
- *domain, *username, *password;
-
-
-char * make_url (const char *path)
-{
- assert (NULL != share);
-
- if ((NULL == path) || ('\0' == path[0]))
- return xstrdup (share);
- else
- return concat_strings (2, share, path);
-}
-
-
-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 UNUSED, const char *shr UNUSED,
- char *wg, int wglen, char *un, int unlen,
- char *pw, int pwlen)
-{
- DEBUG (fprintf (stderr, "Authenticating for \\\\%s\\%s\n", srv, shr));
- DEBUG (fprintf (stderr, "Domain: %s; User: %s; Password: %s\n",
- domain, username, password));
-
- if (NULL != domain)
- do_strncpy (wg, domain, wglen);
-
- do_strncpy (un, username, unlen);
- do_strncpy (pw, password, pwlen);
-}
-
-
-void destroy_smb_context (SMBCCTX *ctx_, int shutdown)
-{
- // Samba frees the workgroup and user strings but we want to persist them.
- smbc_setWorkgroup (ctx_, NULL);
- smbc_setUser (ctx_, NULL);
- smbc_free_context (ctx_, shutdown);
-}
-
-
-bool create_smb_context (SMBCCTX **pctx)
-{
- *pctx = smbc_new_context();
-
- if (NULL == *pctx)
- {
- perror ("Cannot create SMB context");
- return false;
- }
-
- smbc_setWorkgroup (*pctx, domain);
- smbc_setUser (*pctx, username);
- smbc_setTimeout (*pctx, 5000);
- smbc_setFunctionAuthData (*pctx, auth_fn);
-
- if (NULL == smbc_init_context (*pctx))
- {
- perror ("Cannot initialise SMB context");
- destroy_smb_context (*pctx, 1);
- return false;
- }
-
- return true;
-}
-
-
-static void * usmb_init (struct fuse_conn_info *conn UNUSED)
-{
- DEBUG (fputs ("usmb_init()\n", stderr));
- return NULL;
-}
-
-
-static void usmb_destroy (void *unused UNUSED)
-{
- DEBUG (fputs ("usmb_destroy()\n", stderr));
-}
-
-
-// probably won't (can't ?) implement these:
-// readlink mknod symlink flush fsync
-
-// no easy way of implementing these:
-// access
-
-#ifdef __lint
-#define SET_ELEMENT(name,value) value
-#else
-#define SET_ELEMENT(name,value) name = value
-#endif
-static struct fuse_operations fuse_ops = {
- SET_ELEMENT (.getattr, usmb_getattr),
- SET_ELEMENT (.readlink, NULL),
- SET_ELEMENT (.getdir, NULL),
- SET_ELEMENT (.mknod, NULL),
- SET_ELEMENT (.mkdir, usmb_mkdir),
- SET_ELEMENT (.unlink, usmb_unlink),
- SET_ELEMENT (.rmdir, usmb_rmdir),
- SET_ELEMENT (.symlink, NULL),
- SET_ELEMENT (.rename, usmb_rename),
- SET_ELEMENT (.link, NULL),
- SET_ELEMENT (.chmod, usmb_chmod),
- SET_ELEMENT (.chown, NULL), // usmb_chown, --not implemented in libsmbclient
- SET_ELEMENT (.truncate, usmb_truncate),
- SET_ELEMENT (.utime, usmb_utime),
- SET_ELEMENT (.open, usmb_open),
- SET_ELEMENT (.read, usmb_read),
- SET_ELEMENT (.write, usmb_write),
- SET_ELEMENT (.statfs, usmb_statfs),
- SET_ELEMENT (.flush, NULL),
- SET_ELEMENT (.release, usmb_release),
- SET_ELEMENT (.fsync, NULL),
- SET_ELEMENT (.setxattr, usmb_setxattr),
- SET_ELEMENT (.getxattr, usmb_getxattr),
- SET_ELEMENT (.listxattr, usmb_listxattr),
- SET_ELEMENT (.removexattr, usmb_removexattr),
- SET_ELEMENT (.opendir, usmb_opendir),
- SET_ELEMENT (.readdir, usmb_readdir),
- SET_ELEMENT (.releasedir, usmb_releasedir),
- SET_ELEMENT (.fsyncdir, NULL),
- SET_ELEMENT (.init, usmb_init),
- SET_ELEMENT (.destroy, usmb_destroy),
- SET_ELEMENT (.access, NULL),
- SET_ELEMENT (.create, usmb_create),
- SET_ELEMENT (.ftruncate, usmb_ftruncate),
- SET_ELEMENT (.fgetattr, usmb_fgetattr),
- SET_ELEMENT (.lock, NULL), // TODO: implement
- SET_ELEMENT (.utimens, NULL), // TODO: implement
- SET_ELEMENT (.bmap, NULL), // TODO: implement
-};
-
-
-static bool create_share_name (const char *server_, const char *sharename)
-{
- size_t len = strlen ("smb:///") +
- strlen (server_) +
- strlen (sharename) + 1;
-
- if (NULL == (share = malloc (len)))
- {
- perror ("Cannot allocate share name");
- return false;
- }
-
- if (!bsnprintf (share, len, "smb://%s/%s", server_, sharename))
- {
- fputs ("Share server and/or name are too long.\n", stderr);
- free (share);
- return false;
- }
-
- DEBUG (fprintf (stderr, "Share URL: %s\n", share));
- return true;
-}
-
-
-static void free_strings (char *sharename)
-{
- xfree (sharename);
- clear_and_free (password);
- xfree (username);
- xfree (domain);
- xfree (options);
- xfree (mountpoint);
- xfree (share);
- xfree (server);
-}
-
-
-static bool check_credentials (void)
-{
- char *url = make_url ("");
- if (NULL == url)
- {
- errno = ENOMEM;
- return false;
- }
-
- DEBUG (fprintf (stderr, "URL: %s\n", url));
-
- struct stat stat_;
- bool ret = (0 == (smbc_getFunctionStat (ctx) (ctx, url, &stat_)));
-
- free_errno (url);
- return ret;
-}
-
-
-static bool get_context (void)
-{
- ctx = NULL;
-
- unsigned attempts = 3;
-
- while (0 != attempts--)
- {
- if ((NULL == password) && !password_read (&password))
- break;
-
- if (!create_smb_context (&ctx))
- {
- clear_and_free (password);
- password = NULL;
- ctx = NULL;
- break;
- }
-
- if (check_credentials())
- break;
-
- perror ("Connection failed");
- clear_and_free (password);
- password = NULL;
-
- destroy_smb_context (ctx, 1);
- ctx = NULL;
- }
-
- return (NULL != ctx);
-}
-
-
-int main (int argc, char **argv)
-{
- const char *conffile, *mountid;
- bool umount;
- char *sharename = NULL;
- int ret = EXIT_FAILURE;
-
- if (sizeof (uint64_t) < sizeof (uintptr_t))
- {
- fputs ("usmb is not supported on this platform.\n", stderr);
- return EXIT_FAILURE;
- }
-
- {
- static char conf[PATH_MAX];
- const char * const HOME = getenv ("HOME");
- if (NULL == HOME)
- {
- fputs ("Please set the HOME environment variable.\n", stderr);
- return EXIT_FAILURE;
- }
-
- if (!bsnprintf (conf, sizeof (conf), "%s/.usmb.conf", HOME))
- {
- fputs ("Configuration file path is too long.\n", stderr);
- return EXIT_FAILURE;
- }
-
- conffile = conf;
- }
-
- if (!parse_args (&argc, &argv, &mountid, &conffile, &umount))
- return EXIT_FAILURE;
-
- if (!umount)
- show_about (stdout);
-
- if (!conffile_get_mount (conffile, mountid,
- &server, &sharename, &mountpoint, &options,
- &domain, &username, &password))
- return EXIT_FAILURE;
-
- DEBUG (fprintf (stderr, "Mountpoint: %s\n", mountpoint));
-
- if (umount)
- {
- execlp ("fusermount", "fusermount", "-u", mountpoint, NULL);
- perror ("Failed to execute fusermount");
- }
-
- else if (create_share_name (server, sharename) && get_context())
- {
- DEBUG (fprintf (stderr, "Username: %s\\%s\n", domain, username));
-
- int fuse_argc;
- char **fuse_argv;
- build_fuse_args (options, mountpoint, &fuse_argc, &fuse_argv);
- ret = fuse_main (fuse_argc, fuse_argv, &fuse_ops, NULL);
- destroy_smb_context (ctx, 1);
- }
-
- free_strings (sharename);
- return ret;
-}
-
diff --git a/usmb.conf b/usmb.conf
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1"?>
-
-<!--
- Example usmb.conf
- =================
-
- This defines two shares:
-
- \\192.168.0.5\myshare on /tmp/smb authenticating as WORKGROUP\user
- \\winbox\music on ${HOME}/music authenticating as mydomain\anotheruser
-
- These can be mounted using
-
- usmb home
- usmb music
-
- Mount options are comma-separated. Useful options:
-
- hard_remove - immediate removal (don't hide files)
- umask=M - set file permissions (octal)
- uid=N - set file owner
- gid=N - set file group
- allow_other - allow access to other users
- allow_root - allow access to root
- nonempty - allow mount over non-empty directory
-
--->
-
-<usmbconfig>
-
- <credentials id="cred1">
- <domain>WORKGROUP</domain>
- <username>user</username>
- <password>pass</password>
- </credentials>
-
- <credentials id="cred2">
- <domain>mydomain</domain>
- <username>anotheruser</username>
- <!-- No password element => prompt for password at runtime.
- <password>secret</password>
- -->
- </credentials>
-
- <mount id="home" credentials="cred1">
- <server>192.168.0.5</server>
- <share>myshare</share>
- <mountpoint>/tmp/smb</mountpoint>
- </mount>
-
- <mount id="music" credentials="cred2">
- <server>winbox</server>
- <share>music</share>
-
- <!-- You can use ~/xyz or ~user/xyz for the mountpoint. -->
- <mountpoint>~/music</mountpoint>
- <options>allow_root</options>
- </mount>
-
-</usmbconfig>
-
diff --git a/usmb.h b/usmb.h
@@ -1,43 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2009 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef USMB_H
- #define USMB_H
-
- #include <stdbool.h>
- #include <stdint.h>
- #include <libsmbclient.h>
-
- extern SMBCCTX *ctx;
-
- char * make_url (const char *path) MUSTCHECK;
-
- bool create_smb_context (SMBCCTX **pctx) MUSTCHECK;
- void destroy_smb_context (SMBCCTX *ctx, int shutdown);
-
- /* fuse_file_info uses a uint64_t for a "File handle" */
- static inline uint64_t smbcfile_to_fd (SMBCFILE *file)
- {
- return (uint64_t)(uintptr_t)file;
- }
-
-
- static inline SMBCFILE * fd_to_smbcfile (uint64_t fd)
- {
- return (SMBCFILE *)(uintptr_t)fd;
- }
-
-#endif
diff --git a/usmb_dir.c b/usmb_dir.c
@@ -1,217 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2013 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <sys/time.h> // struct timeval needed by libsmbclient.h
-#include <libsmbclient.h>
-#include "samba3x-compat.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"
-#include "utils.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_getFunctionMkdir (ctx) (ctx, url, 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, "rmdir (%s)\n", url));
- int ret = smbc_getFunctionRmdir (ctx) (ctx, url) ? -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)", url));
- SMBCFILE *file = smbc_getFunctionOpendir (ctx) (ctx, url);
- DEBUG (fprintf (stderr, " = %p\n", (void *)file));
-
- int ret = (NULL == file) ? -errno : 0;
- free (url);
- fi->fh = smbcfile_to_fd (file);
-
- return ret;
-}
-
-
-int usmb_readdir (const char *path, void *h, fuse_fill_dir_t filler,
- off_t offset UNUSED, struct fuse_file_info *fi UNUSED)
-{
- SMBCCTX *ctx_ = NULL;
- SMBCFILE *file = NULL;
- char *url = NULL;
- struct smbc_dirent *dirent;
- int ret = 0;
-
- DEBUG (fprintf (stderr, "readdir (%s)\n", path));
-
- if (!create_smb_context (&ctx_))
- return -errno;
-
- do
- {
- url = make_url (path);
- if (NULL == url)
- {
- ret = -ENOMEM;
- break;
- }
-
- file = smbc_getFunctionOpendir (ctx_) (ctx_, url);
- if (NULL == file)
- {
- ret = -errno;
- break;
- }
-
- smbc_getFunctionLseekdir (ctx_) (ctx_, file, 0);
-
- while (NULL != (dirent = smbc_getFunctionReaddir (ctx_) (ctx_, file)))
- {
- 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;
- }
-
- DEBUG (fprintf (stderr, " %s\n", dirent->name));
- if (1 == filler (h, dirent->name, &stbuf, 0)) /* if error */
- {
- ret = -1;
- break;
- }
- }
- } while (false /*CONSTCOND*/);
-
- if (NULL != file)
- (void)smbc_getFunctionClosedir (ctx_) (ctx_, file);
-
- if (NULL != url)
- free (url);
-
- destroy_smb_context (ctx_, 0);
- return ret;
-}
-
-
-int usmb_releasedir (const char *path UNUSED, struct fuse_file_info *fi)
-{
- SMBCFILE *file = fd_to_smbcfile (fi->fh);
- DEBUG (fprintf (stderr, "releasedir (%s, %p)\n", path, (void *)file));
- return (0 > smbc_getFunctionClosedir (ctx) (ctx, file)) ? -errno : 0;
-}
-
-
-int usmb_setxattr (const char *path, const char *name, const char *value,
- size_t size, int flags)
-{
- char *url = make_url (path);
- if (NULL == url)
- return -ENOMEM;
-
- DEBUG (fprintf (stderr, "setxattr (%s, %s, %p, %llu, %x)\n",
- path, url, value, (unsigned long long)size, flags));
- int ret = smbc_getFunctionSetxattr (ctx) (ctx, url, name,
- value, size, flags) ? -errno : 0;
- free (url);
- return ret;
-}
-
-
-int usmb_getxattr (const char *path, const char *name, char *value, size_t siz…
-{
- char *url = make_url (path);
- if (NULL == url)
- return -ENOMEM;
-
- DEBUG (fprintf (stderr, "getxattr (%s, %s, %p, %llu)\n",
- path, url, value, (unsigned long long)size));
- int ret = smbc_getFunctionGetxattr (ctx) (ctx, url, name,
- value, size) ? -errno : 0;
- free (url);
- return ret;
-}
-
-
-int usmb_listxattr (const char *path, char *list, size_t size)
-{
- char *url = make_url (path);
- if (NULL == url)
- return -ENOMEM;
-
- DEBUG (fprintf (stderr, "listxattr (%s, %p, %llu)\n",
- url, list, (unsigned long long)size));
- int ret = smbc_getFunctionListxattr (ctx) (ctx, url, list, size) ? -errno : …
- free (url);
- return ret;
-}
-
-
-int usmb_removexattr (const char *path, const char *name)
-{
- char *url = make_url (path);
- if (NULL == url)
- return -ENOMEM;
-
- DEBUG (fprintf (stderr, "removexattr (%s, %s)\n", url, name));
- int ret = smbc_getFunctionRemovexattr (ctx) (ctx, url, name) ? -errno : 0;
- free (url);
- return ret;
-}
-
diff --git a/usmb_dir.h b/usmb_dir.h
@@ -1,36 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2009 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#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);
- int usmb_setxattr (const char *path, const char *name, const char *value,
- size_t size, int flags);
- int usmb_getxattr (const char *path, const char *name, char *value,
- size_t size);
- int usmb_listxattr (const char *path, char *list, size_t size);
- int usmb_removexattr (const char *path, const char *name);
-
-#endif
diff --git a/usmb_file.c b/usmb_file.c
@@ -1,339 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2009 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <sys/time.h> // struct timeval needed by libsmbclient.h
-#include <libsmbclient.h>
-#include "samba3x-compat.h"
-#include <limits.h>
-#include <assert.h>
-#include <fuse.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "usmb_file.h"
-#include "usmb.h"
-#include "utils.h"
-
-
-// Samba gets st_nlink wrong for directories.
-static bool fix_nlink (const char *url, struct stat *st)
-{
- assert (NULL != url);
- assert (NULL != st);
-
- if (!S_ISDIR (st->st_mode))
- return true;
-
- SMBCFILE *file = smbc_getFunctionOpendir (ctx) (ctx, url);
- if (NULL == file)
- return false;
-
- // st->st_nlink = 2;
- st->st_nlink = 0;
- errno = ERANGE;
-
- struct smbc_dirent *dirent;
-
- while (NULL != (dirent = smbc_getFunctionReaddir (ctx) (ctx, file)))
- if (SMBC_DIR == dirent->smbc_type)
- if (INT_MAX == st->st_nlink++)
- break;
-
- (void)smbc_getFunctionClosedir (ctx) (ctx, file);
- return (NULL == dirent);
-}
-
-
-int usmb_getattr (const char *filename, struct stat *st)
-{
- char *url = make_url (filename);
- if (NULL == url)
- return -ENOMEM;
-
- DEBUG (fprintf (stderr, "stat (%s)\n", url));
-
- int ret = smbc_getFunctionStat (ctx) (ctx, url, st);
-
- if ((0 > ret) || !fix_nlink (url, st))
- ret = -errno;
-
- free (url);
- return ret;
-}
-
-
-int usmb_fgetattr (const char *filename UNUSED, struct stat *st,
- struct fuse_file_info *fi)
-{
- SMBCFILE *file = fd_to_smbcfile (fi->fh);
- DEBUG (fprintf (stderr, "fgetattr (%s, %p)\n", filename, (void *)file));
-
- if (0 > smbc_getFunctionFstat (ctx) (ctx, file, st))
- return -errno;
-
- if (S_ISDIR (st->st_mode))
- {
- char *url = make_url (filename);
- if (NULL == url)
- return -ENOMEM;
-
- bool ok = fix_nlink (url, st);
- free_errno (url);
-
- if (!ok)
- return -errno;
- }
-
- return 0;
-}
-
-
-int usmb_unlink (const char *filename)
-{
- char *url = make_url (filename);
- if (NULL == url)
- return -ENOMEM;
-
- DEBUG (fprintf (stderr, "unlink (%s)\n", url));
- int ret = (0 > smbc_getFunctionUnlink (ctx) (ctx, url)) ? -errno : 0;
- free (url);
- return ret;
-}
-
-
-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, %d)", url, fi->flags));
- SMBCFILE *file = smbc_getFunctionOpen (ctx) (ctx, url, fi->flags, 0);
- DEBUG (fprintf (stderr, " = %p\n", (void *)file));
-
- int ret = (NULL == file) ? -errno : 0;
- free (url);
- fi->fh = smbcfile_to_fd (file);
-
- return ret;
-}
-
-
-int usmb_release (const char *filename UNUSED, struct fuse_file_info *fi)
-{
- SMBCFILE *file = fd_to_smbcfile (fi->fh);
- DEBUG (fprintf (stderr, "release (%s, %p)\n", filename, (void *)file));
- return (0 > smbc_getFunctionClose (ctx) (ctx, file)) ? -errno : 0;
-}
-
-
-int usmb_read (const char *filename UNUSED, char *buff, size_t len, off_t off,
- struct fuse_file_info *fi)
-{
- assert (32768 >= len);
-
- SMBCFILE *file = fd_to_smbcfile (fi->fh);
- DEBUG (fprintf (stderr, "read (%p, %p, %llu, %lld) ",
- (void *)file, buff, (unsigned long long)len, (long long)off)…
-
- if (0 > smbc_getFunctionLseek (ctx) (ctx, file, off, SEEK_SET))
- {
- fprintf (stderr, "- seek failed: %d\n", -errno);
- return -errno;
- }
-
- int bytes = smbc_getFunctionRead (ctx) (ctx, file, buff, len);
- DEBUG (fprintf (stderr, "= %d\n", bytes));
- return (0 > bytes) ? -errno : (int)bytes;
-}
-
-
-int usmb_write (const char *filename UNUSED, const char *buff, size_t len,
- off_t off, struct fuse_file_info *fi)
-{
- SMBCFILE *file = fd_to_smbcfile (fi->fh);
- DEBUG (fprintf (stderr, "write (%p, %p, len=%llu, off=%lld) ",
- (void *)file, buff, (unsigned long long)len, (long long)off)…
-
- if (0 > smbc_getFunctionLseek (ctx) (ctx, file, off, SEEK_SET))
- return -errno;
-
- size_t written = 0;
- int bytes = 0;
-
- // No idea whether Windows servers don't like > 32768 byte writes
- // (cf. usmb_read), but taking no chances...
-
- const smbc_write_fn write_fn = smbc_getFunctionWrite (ctx);
-
- while (written < len)
- {
- bytes = write_fn (ctx, file, (char *)buff, (len > 32768) ? 32768 : len);
- if (0 > bytes)
- break;
-
- written += bytes;
- buff += bytes;
-
- // avoids infinite loops
- if (0 == bytes)
- break;
- }
-
- DEBUG (fprintf (stderr, "= %d\n", (0 > bytes) ? -errno : (int)written));
- return (0 > bytes) ? -errno : (int)written;
-}
-
-
-int usmb_create (const char *filename, mode_t mode, struct fuse_file_info *fi)
-{
- char *url = make_url (filename);
- if (NULL == url)
- return -ENOMEM;
-
- DEBUG (fprintf (stderr, "creat (%s)", url));
-
- SMBCFILE *file = smbc_getFunctionCreat (ctx) (ctx, url, mode);
- DEBUG (fprintf (stderr, " = %p\n", (void *)file));
- int ret = (NULL == file) ? -errno : 0;
- fi->fh = smbcfile_to_fd (file);
-
- free (url);
- return ret;
-}
-
-
-int usmb_rename (const char *from, const char *to)
-{
- char *fromurl = make_url (from);
- if (NULL == fromurl)
- return -ENOMEM;
-
- char *tourl = make_url (to);
- if (NULL == tourl)
- {
- free (fromurl);
- return -ENOMEM;
- }
-
- DEBUG (fprintf (stderr, "rename (%s, %s)\n", fromurl, tourl));
- int ret =
- (0 > smbc_getFunctionRename (ctx) (ctx, fromurl, ctx, tourl)) ? -errno : 0;
- free (tourl);
- free (fromurl);
- return ret;
-}
-
-
-int usmb_utime (const char *filename, struct utimbuf *utb)
-{
- struct utimbuf tmp_utb;
-
- if (NULL == utb)
- {
- for (;;)
- {
- time_t now = time (NULL);
- if ((time_t)-1 != now)
- {
- tmp_utb.actime = tmp_utb.modtime = now;
- break;
- }
-
- if (EINTR != errno)
- return -errno;
- }
-
- utb = &tmp_utb;
- }
-
- char *url = make_url (filename);
- if (NULL == url)
- return -ENOMEM;
-
- struct timeval tv[2] = {
- { .tv_sec = utb->actime, .tv_usec = 0 },
- { .tv_sec = utb->modtime, .tv_usec = 0 },
- };
-
- DEBUG (fprintf (stderr, "utime (%s)\n", url));
- int ret = (0 > smbc_getFunctionUtimes (ctx) (ctx, url, tv)) ? -errno : 0;
- free (url);
- return ret;
-}
-
-
-#if 0
-Samba defines utimes as taking struct timevals rather than timespecs.
-int usmb_utimes (const char *filename, const struct timespec ts[2])
-{
- char *url = make_url (filename);
- if (NULL == url)
- return -ENOMEM;
-
- DEBUG (fprintf (stderr, "utimes (%s)\n", url));
- int ret = (0 > ctx->utimes (ctx, url, ts)) ? -errno : 0;
- free (url);
- return ret;
-}
-#endif
-
-
-int usmb_chmod (const char *filename, mode_t mode)
-{
- char *url = make_url (filename);
- if (NULL == url)
- return -ENOMEM;
-
- DEBUG (fprintf (stderr, "chmod (%s, %u)\n", url, mode));
- int ret = (0 > smbc_getFunctionChmod (ctx) (ctx, url, mode)) ? -errno : 0;
- free (url);
- return ret;
-}
-
-
-int usmb_truncate (const char *filename, off_t offset)
-{
- char *url = make_url (filename);
- if (NULL == url)
- return -ENOMEM;
-
- SMBCFILE *file = smbc_getFunctionOpen (ctx) (ctx, url, O_WRONLY, 0);
- if (NULL == file)
- {
- int ret = -errno;
- free (url);
- return ret;
- }
-
- int ret = compat_truncate (filename, file, offset);
-
- smbc_getFunctionClose (ctx) (ctx, file);
- free (url);
- return ret;
-}
-
-
-int usmb_ftruncate (const char *path, off_t size,
- struct fuse_file_info *fi)
-{
- return compat_truncate (path, fd_to_smbcfile (fi->fh), size);
-}
-
diff --git a/usmb_file.h b/usmb_file.h
@@ -1,43 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2009 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#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_unlink (const char *filename);
- 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 of…
- struct fuse_file_info *fi);
- int usmb_create (const char *filename, mode_t mode,
- struct fuse_file_info *fi);
- int usmb_rename (const char *from, const char *to);
- int usmb_utime (const char *filename, struct utimbuf *utb);
- int usmb_truncate (const char *filename, off_t newsize);
- int usmb_chmod (const char *filename, mode_t mode);
- int usmb_ftruncate (const char *path, off_t size,
- struct fuse_file_info *fi);
-
-#endif
diff --git a/utils.c b/utils.c
@@ -1,216 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2013 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <assert.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdio.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);
- /*LINTED*/
- 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);
- va_end (ap);
- return NULL;
- }
-
- buff_size = dbl_len;
- }
-
- /*LINTED*/
- ptrdiff_t diff = out - base;
-
- char *newbase = realloc (base, buff_size);
- if (NULL == newbase)
- {
- free (base);
- va_end (ap);
- return NULL;
- }
-
- base = newbase;
- out = base + diff;
- }
-
- memcpy (out, next, next_len);
- out += next_len;
- }
- va_end (ap);
-
- *out = '\0';
- return base;
-}
-
-
-char * xstrdup (const char *in)
-{
- char *out = NULL;
-
- if (NULL != in)
- {
- size_t len = strlen (in) + 1;
-
- if ((out = malloc (len)))
- memcpy (out, in, len);
- }
-
- return out;
-}
-
-
-// the const here lets us pass a pointer to const
-void xfree (const void *ptr)
-{
- if (NULL != ptr)
- free ((void *)ptr);
-}
-
-
-void clear_and_free (char *ptr)
-{
- if (NULL != ptr)
- {
- for (char *pch = ptr; '\0' != *pch; ++pch)
- *pch = '\0';
-
- free (ptr);
- }
-}
-
-
-void free_errno (const void *ptr)
-{
- int err = errno;
- free ((void *)ptr);
- errno = err;
-}
-
-
-void xfree_errno (const void *ptr)
-{
- int err = errno;
- xfree (ptr);
- errno = err;
-}
-
-
-bool bsnprintf (char *str, size_t size, const char *format, ...)
-{
- va_list ap;
- bool ret;
-
- va_start (ap, format);
- ret = bvsnprintf (str, size, format, ap);
- va_end (ap);
-
- return ret;
-}
-
-
-bool bvsnprintf (char *str, size_t size, const char *format, va_list ap)
-{
- int ret;
-
- assert (NULL != str);
- assert (NULL != format);
-
- ret = vsnprintf (str, size, format, ap);
-
- return ((ret >= 0) && ((size_t)ret < size));
-}
-
-
-bool baprintf (char **out, const char *format, ...)
-{
- va_list ap;
- bool ret;
-
- va_start (ap, format);
- ret = bvaprintf (out, format, ap);
- va_end (ap);
-
- return ret;
-}
-
-
-bool bvaprintf (char **out, const char *format, va_list ap)
-{
- assert (NULL != out);
- assert (NULL != format);
- *out = NULL;
-
- va_list ap2;
- va_copy (ap2, ap);
- int bytes = vsnprintf (NULL, 0, format, ap2);
- va_end (ap2);
-
- if ((1 > bytes) || (INT_MAX == bytes))
- return false;
-
- ++bytes; // '\0'.
-
- if (bytes != (int)(size_t)bytes)
- return false;
-
- *out = malloc ((size_t)bytes);
- if (NULL == *out)
- return false;
-
- if (!bvsnprintf (*out, bytes, format, ap))
- {
- free (*out);
- *out = NULL;
- return false;
- }
-
- return true;
-}
-
diff --git a/utils.h b/utils.h
@@ -1,47 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2009 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef UTILS_H
- #define UTILS_H
-
- #include <stdarg.h>
- #include <stdbool.h>
- #include <stddef.h>
-
- #ifdef DEBUG
- #undef DEBUG
- #define DEBUG(x) (x)
- #define DEBUGON
- #else
- #define DEBUG(x) ((void)0)
- #endif
-
- char * concat_strings (int num, ...) MUSTCHECK;
- char * xstrdup (const char *in) MUSTCHECK;
- void xfree (const void *ptr);
- void clear_and_free (char *ptr);
- void free_errno (const void *ptr);
- void xfree_errno (const void *ptr);
- bool bsnprintf (char *str, size_t size, const char *format, ...)
- __attribute__ ((format (printf, 3, 4))) MUSTCHECK;
- bool bvsnprintf (char *str, size_t size,
- const char *format,
- va_list ap) MUSTCHECK;
- bool baprintf (char **out, const char *format, ...)
- __attribute__ ((format (printf, 2, 3))) MUSTCHECK;
- bool bvaprintf (char **out, const char *format, va_list ap) MUSTCHECK;
-
-#endif
diff --git a/version.c b/version.c
@@ -1,72 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2009 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <stdio.h>
-#include <sys/time.h>
-#include <libsmbclient.h>
-#include <fuse.h>
-#include "version.h"
-
-
-#if ((USMB_VERSION_STATUS != 'a') && \
- (USMB_VERSION_STATUS != 'b') && \
- (USMB_VERSION_STATUS != 'p') && \
- (USMB_VERSION_STATUS != 's'))
- #error Unsupported USMB_VERSION_STATUS
-#endif
-
-
-void show_about (FILE *fp)
-{
- fprintf (fp, "usmb - mount SMB shares via FUSE and Samba\n"
- "\n"
- "Copyright (C) 2006-2013 Geoff Johnstone.\n"
- "Licensed under the GNU General Public License.\n"
- "usmb comes with ABSOLUTELY NO WARRANTY; "
- "for details please see\n"
- "http://www.gnu.org/licenses/gpl.txt\n"
- "\n"
- "Please send bug reports, patches etc. to %s@%s.org\n",
- "geoffjohnstone", "acm"); // anti-spam.
-}
-
-
-static inline const char * get_status (char ch)
-{
- switch (ch)
- {
- case 'a': return "alpha";
- case 'b': return "beta";
- case 'p': return "pre-release";
- case 's': return "stable";
- default: return "unofficial";
- }
-}
-
-
-void show_version (FILE *fp)
-{
- show_about (fp);
- fputc ('\n', fp);
- fprintf (fp, "usmb version: %08x (%s)\n"
- "FUSE version: %d.%d\n"
- "Samba version: %s\n",
- USMB_VERSION, get_status (USMB_VERSION_STATUS),
- FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION,
- smbc_version());
-}
-
diff --git a/version.h b/version.h
@@ -1,25 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2009 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef VERSION_H
- #define VERSION_H
-
- #include <stdio.h>
-
- void show_about (FILE *fp);
- void show_version (FILE *fp);
-
-#endif
diff --git a/version.m4 b/version.m4
@@ -1,5 +0,0 @@
-m4_define([VERSION_],[20130204])
-
-# a - alpha, b - beta, p - pre-release, s - stable
-m4_define([VERSION_STATUS_],[s])
-
diff --git a/xml.c b/xml.c
@@ -1,187 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2013 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <libxml/xmlreader.h>
-#include <libxml/xpath.h>
-#include <libxml/xpathInternals.h>
-#include <assert.h>
-#include <stdbool.h>
-#include <string.h>
-#include "xml.h"
-#include "utils.h"
-
-
-bool xml_validate_relaxng (xmlDocPtr doc, const char *schema)
-{
- xmlRelaxNGParserCtxtPtr rngpcptr = NULL;
- xmlRelaxNGPtr rngptr = NULL;
- xmlRelaxNGValidCtxtPtr rngvptr = NULL;
- bool ret = false;
-
- assert (NULL != doc);
-
- do
- {
- rngpcptr = xmlRelaxNGNewMemParserCtxt (schema, strlen (schema));
- if (NULL == rngpcptr)
- break;
-
- rngptr = xmlRelaxNGParse (rngpcptr);
- if (NULL == rngptr)
- break;
-
- rngvptr = xmlRelaxNGNewValidCtxt (rngptr);
- if (NULL == rngvptr)
- break;
-
- ret = (0 == xmlRelaxNGValidateDoc (rngvptr, doc));
- } while (false /*CONSTCOND*/);
-
- if (NULL != rngvptr)
- xmlRelaxNGFreeValidCtxt (rngvptr);
-
- if (NULL != rngptr)
- xmlRelaxNGFree (rngptr);
-
- if (NULL != rngpcptr)
- xmlRelaxNGFreeParserCtxt (rngpcptr);
-
- return ret;
-}
-
-
-bool xml_xpath_attr_value (xmlXPathContextPtr ctx,
- char *xpath,
- const char *attr,
- char **out)
-{
- xmlXPathObjectPtr obj;
- xmlChar *tmp;
-
- assert (NULL != ctx);
- assert (NULL != xpath);
- assert (NULL != out);
-
- *out = NULL;
-
- obj = xmlXPathEval (BAD_CAST xpath, ctx);
- if (NULL == obj)
- {
- DEBUG (fputs ("XPath evaluation error\n", stderr));
- return false;
- }
-
- do
- {
- if (XPATH_NODESET != obj->type)
- {
- DEBUG (fputs ("XPath evaluation didn't return a nodeset\n", stderr));
- break;
- }
-
- if (NULL == obj->nodesetval)
- {
- DEBUG (fputs ("nodesetval is NULL\n", stderr));
- break;
- }
-
- if (1 != obj->nodesetval->nodeNr)
- {
- DEBUG (fprintf (stderr, "Nodeset has %d elements\n",
- obj->nodesetval->nodeNr));
- break;
- }
-
- tmp = xmlGetProp (obj->nodesetval->nodeTab[0], BAD_CAST attr);
- if (NULL == tmp)
- break;
-
- *out = xstrdup ((char *)tmp);
- if (NULL == *out)
- break;
-
- xmlXPathFreeObject (obj);
- return true;
- /*NOTREACHED*/
- } while (false /*CONSTCOND*/);
-
- *out = NULL;
- xmlXPathFreeObject (obj);
- return false;
-}
-
-
-bool xml_xpath_text (xmlXPathContextPtr ctx, char *xpath, char **out)
-{
- xmlXPathObjectPtr obj;
-
- assert (NULL != ctx);
- assert (NULL != xpath);
- assert (NULL != out);
-
- *out = NULL;
-
- DEBUG (fprintf (stderr, "xml_xpath_text (%s)\n", xpath));
-
- obj = xmlXPathEval (BAD_CAST xpath, ctx);
- if (NULL == obj)
- {
- DEBUG (fputs ("XPath evaluation error\n", stderr));
- return false;
- }
-
- do
- {
- if (XPATH_NODESET != obj->type)
- {
- DEBUG (fputs ("XPath evaluation didn't return a nodeset\n", stderr));
- break;
- }
-
- if (NULL == obj->nodesetval)
- {
- DEBUG (fputs ("nodesetval is NULL\n", stderr));
- break;
- }
-
- if (1 != obj->nodesetval->nodeNr)
- {
- DEBUG (fprintf (stderr, "Nodeset has %d elements\n",
- obj->nodesetval->nodeNr));
- break;
- }
-
- if (NULL == obj->nodesetval->nodeTab[0]->content)
- {
- DEBUG (fputs ("Node has no text\n", stderr));
- break;
- }
-
- *out = xstrdup ((char *)obj->nodesetval->nodeTab[0]->content);
- if (NULL == *out)
- break;
-
- xmlXPathFreeObject (obj);
- return true;
- /*NOTREACHED*/
- } while (false /*CONSTCOND*/);
-
- *out = NULL;
- xmlXPathFreeObject (obj);
- return false;
-}
-
diff --git a/xml.h b/xml.h
@@ -1,34 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006-2009 Geoff Johnstone
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 as
- * published by the Free Software Foundation.
- *
- * 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef XML_H
- #define XML_H
-
- #include <libxml/xmlreader.h>
- #include <libxml/xpath.h>
- #include <libxml/xpathInternals.h>
- #include <stdbool.h>
-
-
- bool xml_validate_relaxng (xmlDocPtr doc, const char *schema) MUSTCHECK;
- bool xml_xpath_attr_value (xmlXPathContextPtr ctx,
- char *xpath,
- const char *attribute,
- char **out) MUSTCHECK;
- bool xml_xpath_text (xmlXPathContextPtr ctx,
- char *xpath, char **out) MUSTCHECK;
-
-#endif
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.