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