#include <captive/client-vfs.h>
#include <captive/macros.h>
+#include <captive/client.h>
+#include <captive/captivemodid.h>
#include "main.h" /* self */
#include "op_statfs.h"
/* FIXME: Dupe with libcaptive/client/options.c */
#define DEFAULT_SYSLOG_FACILITY LOG_DAEMON
/* Each element must be preceded by a comma (',')! */
-#define LIBFUSE_ADDONS ",default_permissions,kernel_cache"
+#define LIBFUSE_ADDONS ",default_permissions,allow_other,kernel_cache"
CaptiveVfsObject *capfuse_captive_vfs_object;
&capfuse_mountpoint, /* mountpoint */
&capfuse_multithreaded, /* multithreaded */
&capfuse_fd))) /* fd */
- g_error(_("FUSE fuse_setup() failed"));
+ g_error(_(
+ "FUSE fuse_setup() failed!\n"
+ "You may need Linux kernel 2.6.14 or higher with its 'fuse.ko' enabled.\n"
+ "You may also need to install or upgrade 'fuse' package to your system."));
if (fuse_loop(capfuse_fuse)) {
/* Do not: g_error(_("FUSE fuse_loop() error"));
* as it is caused on each umount(8).
int main(int argc,char **argv)
{
-poptContext context;
-int errint;
-int rest_argc,i;
+poptContext context=NULL; /* Valid if: opt_o; '= NULL' to shut up GCC. */
+int rest_argc;
const char **rest_argv,**csp;
struct captive_options options;
+int capfuse_argc;
const char **capfuse_argv;
const char *program_name=argv[0];
const char *sandbox_server_argv0=G_STRINGIFY(LIBEXECDIR) "/captive-sandbox-server";
-const char *image_filename;
-
- g_log_set_always_fatal(~(0
- |G_LOG_LEVEL_MESSAGE
- |G_LOG_LEVEL_INFO
- |G_LOG_LEVEL_DEBUG
- ));
-
- /* Prevent output block buffering if redirecting stdout to file. */
- setvbuf(stdout,(char *)NULL,_IONBF,0);
- setvbuf(stderr,(char *)NULL,_IONBF,0);
+const char *image_filename=NULL;
+gboolean opt_n=FALSE;
+gboolean opt_v=FALSE;
+const char *opt_o=NULL;
+const char *mountpoint=NULL;
+char **argv_sp;
+int opt_o_argc; /* Valid if: opt_o */
+const char **opt_o_argv=NULL; /* Valid if: opt_o */
+
+#if 0
+{
+char **sp;
+ for (sp=argv;*sp;sp++)
+ fprintf(stderr,"argv: \"%s\"\n",*sp);
+}
+#endif
- /* Initialize the i18n stuff */
- setlocale(LC_ALL,"");
- bindtextdomain(PACKAGE,LOCALEDIR);
- textdomain(PACKAGE);
+ /* Do not set g_log_set_always_fatal() here as we would not be able
+ * to restart failed children due to communication-failure alarms.
+ */
- /* Initialize GObject subsystem of GLib. */
- g_type_init();
+ captive_standalone_init();
+ /* poptGetNextOpt() below requires valid: captive_options */
captive_options_init(&options);
captive_options=&options; /* for parsing by 'CAPTIVE_POPT_INCLUDE' */
+ argv_sp=argv+1;
+ if (*argv_sp && (*argv_sp)[0]!='-')
+ image_filename=*argv_sp++;
+ if (*argv_sp && (*argv_sp)[0]!='-')
+ mountpoint=*argv_sp++;
+ if (*argv_sp && !strcmp(*argv_sp,"-n")) {
+ opt_n=TRUE;
+ argv_sp++;
+ }
+ if (*argv_sp && !strcmp(*argv_sp,"-v")) {
+ opt_v=TRUE;
+ argv_sp++;
+ }
+ if (argv_sp[0] && argv_sp[1] && !strcmp(argv_sp[0],"-o")) {
+ argv_sp++;
+ opt_o=*argv_sp++;
+ }
+ if (*argv_sp) {
+ /* Lethal path but still give chance for "--help" etc. */
+ /* Do not: POPT_CONTEXT_POSIXMEHARDER
+ * as mount(8) puts there first un-pre-dashed "ro"/"rw" etc. */
+ /* poptGetNextOpt() requires valid: captive_options */
+ if ((context=poptGetContext(
+ PACKAGE, /* name */
+ argc,(/*en-const*/const char **)argv, /* argc,argv */
+ popt_table, /* options */
+ 0))) /* flags; && !POPT_CONTEXT_KEEP_FIRST */
+ while (0<=poptGetNextOpt(context));
+ g_error(_("Excessive argument: %s"),*argv_sp);
+ }
+
+ if (opt_o) {
+char *opt_o_spaced=(char */* de-const; length is not changed */)captive_strdup_alloca(opt_o);
+char *s,quote;
+
+ quote=0;
+ for (s=opt_o_spaced;*s;s++) {
+ /* Be compatible with: poptParseArgvString()
+ * which also does not differentiate '"' and "'" */
+ if (*s=='\\' && s[1]) {
+ s++;
+ continue;
+ }
+ if (quote) {
+ if (*s==quote)
+ quote=0;
+ continue;
+ }
+ switch (*s) {
+ case '"':
+ case '\'':
+ quote=*s;
+ continue;
+ case ',':
+ *s=' ';
+ continue;
+ }
+ }
+ if (poptParseArgvString(opt_o_spaced,&opt_o_argc,&opt_o_argv))
+ g_error(_("Error splitting arguments of the space-reparsed '-o': %s"),opt_o_spaced);
+ /* Adjust the options for all the subsystems eating the same string vector. */
+ for (csp=opt_o_argv;*csp;csp++) {
+ /* Unsupported mount(8) options not valid for fusermount(8) and causing:
+ * fusermount: mount failed: Invalid argument */
+ if (0
+ || !strcmp(*csp,"defaults")
+ || !strcmp(*csp, "auto")
+ || !strcmp(*csp,"noauto")) {
+ memmove(csp,csp+1,(opt_o_argv+opt_o_argc+1-(csp+1))*sizeof(*csp));
+ opt_o_argc--;
+ csp--;
+ continue;
+ }
+ /* Pre-dash "ro"/"rw" to let libcaptive to be aware of the mode.
+ * We will put the final "ro"/"rw" there again from 'captive_options.rwmode' later. */
+ if (!strcmp(*csp,"ro"))
+ *csp="--ro";
+ if (!strcmp(*csp,"rw"))
+ *csp="--rw";
+ /* LUFS "uid" and "gid" options should map to FUSE well, I hope. */
+#define STRNCMP_CONST(mem,string) strncmp((mem),(string),strlen((string)))
+ if (0
+ || !STRNCMP_CONST(*csp,"fmask=")
+ || !STRNCMP_CONST(*csp,"dmask=")
+ || !STRNCMP_CONST(*csp,"channels=")
+ || !STRNCMP_CONST(*csp,"root=")
+ || !strcmp(*csp,"own_fs")
+ || !strcmp(*csp,"quiet")
+ || !STRNCMP_CONST(*csp,"dir_cache_ttl=")
+ )
+ g_error(_("Seen obsolete LUFS option \"%s\" - please update your \"/etc/fstab\" for FUSE options instead"),
+ *csp);
+#undef STRNCMP_CONST
+ }
+ }
+
g_assert(!options.sandbox_server_argv);
g_assert(!options.sandbox_server_ior);
/* captive_options_free(&options) will: g_free(options.sandbox_server_argv); */
options.syslog_facility=DEFAULT_SYSLOG_FACILITY;
- context=poptGetContext(
- PACKAGE, /* name */
- argc,(/*en-const*/const char **)argv, /* argc,argv */
- popt_table, /* options */
- POPT_CONTEXT_POSIXMEHARDER); /* flags; && !POPT_CONTEXT_KEEP_FIRST */
- if (context==NULL) {
- g_error(_("Error parsing command-line arguments"));
- return EXIT_FAILURE;
- }
- errint=poptReadDefaultConfig(context,
- TRUE); /* useEnv */
- if (errint!=0)
- g_warning(_("Error reading default popt configuration"));
- errint=poptGetNextOpt(context);
- if (errint!=-1) {
- g_error(_("Error parsing (dash-prefixed) command-line argument"));
- return EXIT_FAILURE;
+ if (opt_o) {
+ /* Do not: POPT_CONTEXT_POSIXMEHARDER
+ * as mount(8) puts there first un-pre-dashed "ro"/"rw" etc. */
+ if (!(context=poptGetContext(
+ PACKAGE, /* name */
+ opt_o_argc,opt_o_argv, /* argc,argv */
+ popt_table, /* options */
+ POPT_CONTEXT_KEEP_FIRST))) /* flags */
+ g_error(_("Error parsing command-line arguments from pre-parsed '-o': %s"),opt_o);
+ if (poptReadDefaultConfig(context,
+ TRUE)) /* useEnv */
+ g_warning(_("Error reading default popt configuration"));
+ while (0<=poptGetNextOpt(context));
+ rest_argv=poptGetArgs(context);
}
- rest_argv=poptGetArgs(context);
- for (csp=rest_argv,rest_argc=0;csp && *csp;csp++)
+ else
+ rest_argv=NULL;
+ rest_argc=0;
+ for (csp=rest_argv;csp && *csp;csp++)
rest_argc++;
- captive_options=NULL; /* already parsed by 'CAPTIVE_POPT_INCLUDE' */
-
- /* Override the (default) Captive options with mount(8) supplied "-o" argument. */
- /* rest_argv[0] is the device now. */
- /* rest_argv[1] is the mountpoint now. */
- if (rest_argc>=4 && !strcmp(rest_argv[2],"-o")) {
-const char *cs=rest_argv[3];
-
- while (cs&&*cs) {
- if ((!strncmp(cs,"ro",2) || !strncmp(cs,"rw",2)) && (cs[2]==',' || !cs[2])) {
- if (!strncmp(cs,"ro",2))
- options.rwmode=CAPTIVE_OPTION_RWMODE_RO;
- if (!strncmp(cs,"rw",2))
- options.rwmode=CAPTIVE_OPTION_RWMODE_RW;
- }
- if ((cs=strchr(cs,',')))
- cs++;
- }
- }
+ if (!image_filename || !mountpoint)
+ g_error(_("File/device disk image pathname and mountpoint command-line arguments required"));
/* image_iochannel */
- if (rest_argc<1) {
- g_error(_("File/device disk image pathname command-line argument required"));
- return EXIT_FAILURE;
- }
g_assert(options.image_iochannel==NULL);
- image_filename=rest_argv[0];
- rest_argc--;
- rest_argv++;
if (!(options.image_iochannel=g_io_channel_new_file(
image_filename, /* filename */
(options.rwmode==CAPTIVE_OPTION_RWMODE_RW ? "r+" : "r"), /* mode */
g_error(_("image_iochannel failed open of: %s"),image_filename);
return EXIT_FAILURE;
}
+
+ if (!options.captivemodid)
+ options.captivemodid=captive_captivemodid_load_default(FALSE);
if (options.filesystem.type==CAPTIVE_OPTIONS_MODULE_TYPE_EMPTY) {
const char *self_prefix="mount.captive-";
options.load_module=g_list_append(options.load_module,options_module);
}
+ /* It is still required for: captive_options_module_load() */
+ captive_options=NULL; /* already parsed by 'CAPTIVE_POPT_INCLUDE' */
+
if (GNOME_VFS_OK!=captive_vfs_new(&capfuse_captive_vfs_object,&options)) {
g_error(_("captive_vfs_new() failed"));
return EXIT_FAILURE;
captive_options_free(&options);
/* Simulate argv[0] there as it got cut by popt. */
- captive_newn_alloca(capfuse_argv,1+rest_argc+1+2);
- capfuse_argv[0]=argv[0];
- memcpy(capfuse_argv+1,rest_argv,sizeof(*rest_argv)*(rest_argc+1));
-
- for (i=1;capfuse_argv[i];i++) {
- if (strcmp(capfuse_argv[i],"-o"))
- continue;
- capfuse_argv[i+1]=captive_printf_alloca("fsname=%s" LIBFUSE_ADDONS ",%s",image_filename,capfuse_argv[i+1]);
- break;
- }
- if (!capfuse_argv[i]) {
- capfuse_argv[i ]="-o";
- capfuse_argv[i+1]=captive_printf_alloca("fsname=%s" LIBFUSE_ADDONS,image_filename);
- capfuse_argv[i+2]=NULL;
- }
+ capfuse_argc=4+2*rest_argc;
+ captive_newn_alloca(capfuse_argv,capfuse_argc+1);
+ csp=capfuse_argv;
+ *csp++=argv[0];
+ *csp++=mountpoint;
+ *csp++="-o";
+ *csp++=captive_printf_alloca("fsname=%s" LIBFUSE_ADDONS ",%s",
+ image_filename,(options.rwmode==CAPTIVE_OPTION_RWMODE_RO ? "ro" : "rw"));
+ if (rest_argv)
+ while (*rest_argv) {
+ *csp++="-o";
+ *csp++=*rest_argv++;
+ }
+ *csp=NULL;
+#if 0
+{
+const char **csp;
+ for (csp=capfuse_argv;*csp;csp++)
+ fprintf(stderr,"capfuse_argv: \"%s\"\n",*csp);
+}
+#endif
/* FIXFUSE: fuse_main()/fuse_main_real() would be enough for Captive fuse but
* the public interface of fuse_main() is too broken.
*/
- capfuse_run(1+rest_argc,capfuse_argv);
+ capfuse_run(capfuse_argc,capfuse_argv);
/* 'rest_argv' gets cleared by 'poptFreeContext(context);' below */
- poptFreeContext(context);
+ if (opt_o)
+ poptFreeContext(context);
if (capfuse_captive_vfs_object) {
g_object_unref(capfuse_captive_vfs_object);