Skip to content

Commit

Permalink
Better heuristic to get FUSE options
Browse files Browse the repository at this point in the history
  • Loading branch information
astrada committed Apr 20, 2024
1 parent d38ba9c commit f579949
Showing 1 changed file with 54 additions and 8 deletions.
62 changes: 54 additions & 8 deletions lib/Fuse_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@
02111-1307 USA
Alessandro Strada
Warning: this main() contains a hack that's requested for compatibility
with OCaml version 5 and later. The new Multicore runtime prohibits
calling a fork() from C after caml_main() is called. So, I'm calling
fuse_daemonize() before caml_main(), and I try to detect any option that
keeps the process in foreground. But there are a couple of problems with this
hack: First, if the foreground option is injected by caml_main(), I will miss
it. Also, fuse_daemonize() redirects stdout and stderr to /dev/null, so it
gobbles up any error message produced by caml_main().
See
https://discuss.ocaml.org/t/multicore-and-fork-called-from-c-bindings/13993/2
for further details.
*/

#include <caml/version.h>
Expand All @@ -41,17 +54,34 @@
char **insert_foreground_option(int argc, char **argv);
void free_fuse_argv(int n, char **fuse_argv);
void start_program(int argc, char **argv, char *mountpoint, int foreground);
void parse_fuse_args(int argc, char **argv, struct fuse_args *args);
bool is_fuse_arg(char *arg, char *prev);
void parse_fuse_args(int argc, char **argv, struct fuse_args *args,
bool *debug);
bool is_fuse_arg(char *arg, char *prev, bool is_last);
bool is_debug(char *arg);
int main_ocaml5(int argc, char **argv);
int main_ocaml4(int argc, char **argv);

/* https://v2.ocaml.org/releases/5.1/htmlman/intfc.html#ss:main-c */
int main(int argc, char **argv) {
#if OCAML_VERSION < 50000
main_ocaml4(argc, argv);
#else
main_ocaml5(argc, argv);
#endif
}

/* https://v2.ocaml.org/releases/5.1/htmlman/intfc.html#ss:main-c */
int main_ocaml5(int argc, char **argv) {
struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
char *mountpoint;
int foreground;
bool debug;

parse_fuse_args(argc, argv, &args);
parse_fuse_args(argc, argv, &args, &debug);
if (fuse_parse_cmdline(&args, &mountpoint, NULL, &foreground) != -1) {
if (debug) {
foreground = 1;
}
start_program(argc, argv, mountpoint, foreground);

fuse_opt_free_args(&args);
Expand All @@ -62,19 +92,25 @@ int main(int argc, char **argv) {
return 1;
}

void parse_fuse_args(int argc, char **argv, struct fuse_args *args) {
int main_ocaml4(int argc, char **argv) { caml_main(argv); }

void parse_fuse_args(int argc, char **argv, struct fuse_args *args,
bool *debug) {
int i = 1;

fuse_opt_add_arg(args, argv[0]);
while (i < argc) {
if (is_fuse_arg(argv[i], argv[i - 1])) {
if (is_fuse_arg(argv[i], argv[i - 1], i == argc - 1)) {
fuse_opt_add_arg(args, argv[i]);
}
if (is_debug(argv[i])) {
*debug = true;
}
++i;
}
}

bool is_fuse_arg(char *arg, char *prev) {
bool is_fuse_arg(char *arg, char *prev, bool is_last) {
if (strcmp(arg, "--help") == 0) {
return true;
}
Expand All @@ -95,19 +131,29 @@ bool is_fuse_arg(char *arg, char *prev) {
if (prev != NULL && strcmp(prev, "-o") == 0) {
return true;
} else {
if (access(arg, F_OK) == 0) {
if (is_last && access(arg, F_OK) == 0) {
return true;
}
}
}
return false;
}

bool is_debug(char *arg) {
if (strcmp(arg, "--debug") == 0) {
return true;
}
if (strcmp(arg, "-debug") == 0) {
return true;
}
return false;
}

void start_program(int argc, char **argv, char *mountpoint, int foreground) {
char **fuse_argv = argv;

if (mountpoint != NULL) {
/* https://github.com/libfuse/libfuse/blob/d04687923194d906fe5ad82dcd546c9807bf15b6/include/fuse_common.h#L246
/* https://github.com/libfuse/libfuse/blob/fuse-2.9.9/include/fuse_common.h#L246
*/
if (fuse_daemonize(foreground) == -1) {
perror("fuse_daemonize");
Expand Down

0 comments on commit f579949

Please sign in to comment.