#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <locale.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <pthread.h>
#include <libsmbclient.h>
#include <pwd.h>
#include "common.h"
#include "smbitem.h"
#include "auth.h"
#include "auth-libsecret.h"
#include "process.h"
#include "samba.h"
#include "function.h"
#include "event.h"
#include "reconfigure.h"
static void check_samba_version(void){
const char *samba_version;
int major, minor;
samba_version = smbc_version();
if (sscanf(samba_version, "%d.%d.%*d", &major, &minor) != 2){
fprintf(stderr, "ERROR: Can't parse libsmbclient version: %s\n",
samba_version);
exit(EXIT_FAILURE);
}
if (major >= 5) goto to_new;
if (major == 4) goto ok;
if (major == 3){
if (minor >= 2) goto ok;
else goto unsupported;
}
unsupported:
fprintf(stderr, "ERROR: Unsupported libsmbclient version: %s\n"
" Please consider upgrade to libsmbclient >= 3.2\n"
"\n",
samba_version);
exit(EXIT_FAILURE);
ok:
/* libsmbclient >= 3.2 is perfectly OK */
return;
to_new:
fprintf(stderr, "WARNING: Unknown libsmbclient version: %s\n"
" " PACKAGE_NAME " may not work as expected.\n"
"\n",
samba_version);
/* Hm... libsmbclient version is too new, trying to continue anyway. */
return;
}
static inline size_t get_default_rw_block_size(void){
return (strncmp(smbc_version(), "3.0.", 4) == 0) ? 48 : 128;
}
static void sig_handler(int signum){
fprintf(stderr, "%d->%s: signal %d received\n",
getpid(), __FUNCTION__, signum);
common_print_backtrace();
exit(signum);
}
static void set_signal_reactions(void){
struct{
int signum;
char *name;
} sig[] = { {SIGILL, "SIGILL" },
{SIGSEGV, "SIGSEGV"},
{SIGABRT, "SIGABRT"} };
int i;
struct sigaction action;
sigemptyset(&action.sa_mask);
action.sa_handler = sig_handler;
action.sa_flags = SA_RESTART;
for(i = 0; i < 3; i++){
if (sigaction(sig[i].signum, &action, NULL) < 0){
fprintf(stderr, "Can't set %s handler\n", sig[i].name);
exit(EXIT_FAILURE);
}
}
sigemptyset(&action.sa_mask);
sigaddset(&action.sa_mask, SIGHUP);
sigaddset(&action.sa_mask, SIGCHLD);
if (pthread_sigmask(SIG_BLOCK, &action.sa_mask, NULL) != 0){
fprintf(stderr, "Can't block SIGHUP and SIGCHLD signals.\n");
exit(EXIT_FAILURE);
}
}
static void print_help(struct fuse_args *outargs){
fprintf(stderr,
"usage: %s mountpoint [options]\n"
"\n"
"general options:\n"
" -o opt,[opt...] mount options\n"
" -h --help print help\n"
" -V --version print version\n"
"\n"
"SMBNetFS options:\n"
"%s"
"\n", outargs->argv[0], smbnetfs_option_list);
fuse_opt_add_arg(outargs, "-ho");
fuse_main(outargs->argc, outargs->argv, &smb_oper, NULL);
}
static int smbnetfs_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs){
const char *value;
char *name;
int result;
(void) data;
(void) key;
if ((strcmp(arg, "--version") == 0) || (strcmp(arg, "-V") == 0)){
fprintf(stderr, "SMBNetFS version " PACKAGE_VERSION "\n");
fprintf(stderr, "libsmbclient version %s\n", smbc_version());
fuse_opt_add_arg(outargs, "--version");
fuse_main(outargs->argc, outargs->argv, &smb_oper, NULL);
exit(EXIT_SUCCESS);
}
if ((strcmp(arg, "--help") == 0) || (strcmp(arg, "-h") == 0)){
print_help(outargs);
exit(EXIT_FAILURE);
}
if ((value = strchr(arg, '=')) == NULL) return 1;
if (value++ == arg) return 1;
if (strlen(value) == 0) return 1;
if ((name = strndup(arg, value - arg - 1)) == NULL) return 1;
/* check for specific SMBNetFS options */
result = reconfigure_analyse_cmdline_option(name, (char*) value);
free(name);
return result ? 0 : 1;
}
int main(int argc, char *argv[]){
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
setlocale(LC_ALL, "");
check_samba_version();
set_signal_reactions();
/* init all subsystems with their default values */
common_init();
reconfigure_set_default_login_and_configdir();
#ifdef HAVE_LIBSECRET
libsecret_init();
#endif /* HAVE_LIBSECRET */
smbitem_init();
process_init();
samba_init(1024 * get_default_rw_block_size());
event_set_event_handler(&smb_oper);
/* parse command line options */
if (fuse_opt_parse(&args, NULL, NULL, smbnetfs_opt_proc) == -1){
fprintf(stderr, "Can't parse command line, please verify it.\n");
exit(EXIT_FAILURE);
}
reconfigure_read_config(CONFIG_OPT_STARTUP);
samba_allocate_ctxs();
fuse_main(args.argc, args.argv, &smb_oper, NULL);
samba_destroy_unused_ctxs();
smbitem_delete_obsolete(time(NULL) + 10, SMBITEM_SAMBA_TREE);
smbitem_delete_obsolete(time(NULL) + 10, SMBITEM_USER_TREE);
auth_delete_obsolete(time(NULL) + 10);
smbitem_done();
process_cleanup_from_zombies();
#ifdef HAVE_LIBSECRET
libsecret_done();
#endif /* HAVE_LIBSECRET */
return 0;
}