fork usmb 20130204 to susmb - susmb - mounting of SMB/CIFS shares via FUSE
(HTM) git clone git://git.codemadness.org/susmb
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
(DIR) commit af92f1402be85b1819f2ba2dda8cae9ff5381b69
(DIR) parent aa94e132c12faf1a00f547ea4a96b5728612dea6
(HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org>
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.tar.gz
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(-)
---
(DIR) 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
(DIR) 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.
-
(DIR) diff --git a/COPYING b/LICENSE
(DIR) 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-self -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations
+
+# 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} ${SUSMB_LDFLAGS}
+
+.c.o:
+ ${CC} -o $@ -c $< ${SUSMB_CPPFLAGS} ${SMBCLIENT_CFLAGS} ${FUSE_CFLAGS} ${SUSMB_CFLAGS} ${SUSMB_CPPFLAGS}
+
+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"; done
+ # 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"; done
+ # 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
(DIR) 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.h \
- 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:%cD' | head -n1 )" "+%Y%m%d%H%M%S")~$(ARCHIVE)
-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@/version.h \
- @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
-
(DIR) 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.tar.gz
+(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 overhead.
+- 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 root:
+ (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 smbclient
+ 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 credentials
+ 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 nowadays anyway.
+- 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 done via a
+ 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 Makefile.
+- Man page rewritten from roff to mandoc.
(DIR) 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 <scott@netsplit.com>.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 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 $1[]_CFLAGS
-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" 2>&1`
- 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
(DIR) 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)) break;
-
- 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;
-}
-
(DIR) 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
(DIR) 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>
-
(DIR) 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 -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations"
-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 termios.h unistd.h utime.h])
-
-# 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
-
(DIR) 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,'^Version: ',, -e 's,-.*,,')
-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).changes
-
-#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 release $(VERSION). )
- # Remove requirements for preparing the release tarball
- # from the Debian control file
- sed -i -e '/^ autoconf/d' -e '/^ devscripts/d' $(unpack_dir)/debian/control
-
-$(tar_gz): tar
-
-$(orig_tar_gz): $(tar_gz) debclean
- mkdir $(pkg_deb_dir)
- [ $(PACKAGE) = $(deb_package) ]
- ln -s ../$(tar_gz) $(orig_tar_gz)
-
-
-
(DIR) diff --git a/debian/changelog b/debian/changelog
@@ -1,5 +0,0 @@
-usmb (20090411-1) UNRELEASED; urgency=low
-
- * Initial release. (Closes: #572703)
-
- -- Michal Suchanek <hramrach@centrum.cz> Wed, 10 Mar 2010 11:59:09 +0100
(DIR) diff --git a/debian/compat b/debian/compat
@@ -1 +0,0 @@
-7
(DIR) 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 <hramrach@centrum.cz>
-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.
(DIR) diff --git a/debian/copyright b/debian/copyright
@@ -1,25 +0,0 @@
-Authors:
- Geoff Johnstone <qwerty@acm.org>
-Download: http://ametros.net/code.html#usmb
-
-Files: *
-Copyright:
- (C) 2006-2013 Geoff Johnstone <qwerty@acm.org>
- Debian packaging (C) 2010 Michal Suchanek <hramrach@centrum.cz>
-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.
-
(DIR) diff --git a/debian/rules b/debian/rules
@@ -1,3 +0,0 @@
-#!/usr/bin/make -f
-%:
- dh $@
(DIR) diff --git a/debian/usmb.docs b/debian/usmb.docs
@@ -1,2 +0,0 @@
-README
-usmb.conf
(DIR) 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 time)
- -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:
(DIR) 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
-}
-
(DIR) 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
(DIR) 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);
-}
-
(DIR) 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
(DIR) 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 size)
-{
- /* 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;
-}
-
(DIR) 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;
-}
-
(DIR) 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;
-}
-
(DIR) 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
-
(DIR) 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\\someuser@192.168.1.1/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://domain\\someuser@192.168.1.1/Storage" /mnt/share
+.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 hiltjo@codemadness.org
+.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
(DIR) 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 : 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;
+}
+
+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 dev)
+{
+ 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)) ? -errno : 0;
+ 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 : 0;
+ 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 : 0;
+ 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_, file))) {
+ 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 error */
+ 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) ? -errno : 0;
+ 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 : 0;
+ 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 portability */
+
+ 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 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 (*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) + 2;
+ 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 hiltjo@codemadness.org\n");
+}
+
+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://domain\\user@server/sharename> <mountpoint>\n"
+ "\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" -> "Sharename". */
+ 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, opt_nofork, &fuse_argc, &fuse_argv);
+ ret = usmb_fuse_main(fuse_argc, fuse_argv, &fuse_ops, sizeof(fuse_ops), NULL);
+ 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;
+}
(DIR) 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>.
(DIR) 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;
-}
-
(DIR) 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>
-
(DIR) 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
(DIR) 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 size)
-{
- 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 : 0;
- 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;
-}
-
(DIR) 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
(DIR) 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);
-}
-
(DIR) 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 off,
- 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
(DIR) 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;
-}
-
(DIR) 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
(DIR) 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());
-}
-
(DIR) 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
(DIR) 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])
-
(DIR) 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;
-}
-
(DIR) 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