You actually have to do very little command-line parsing: FUSE
understands a large number of command-line arguments, and parses
them itself. Most importantly, FUSE expects the mountpoint to be one
of the members of the argv[] array.
However, if there are arguments that your code needs to parse and
understand, you need to parse them before starting FUSE. We can see
an example of this in BBFS: the underlying directory that is being
watched is interacted with by BBFS, not by FUSE. Consequently, I need to
examine the command-line arguments and find that file. Borrowing from
the mount command, I decided that the underlying
directory should be the first argument on the line that didn't have a
dash in front of it. The
code for this is in main(); it looks like this:
for (i = 1; (i < argc) && (argv[i][0] == '-'); i++)
if (argv[i][1] == 'o') i++; // -o takes a parameter; need to
// skip it too. This doesn't
// handle "squashed" parameters
if ((argc - i) != 2) bb_usage();
bb_data->rootdir = realpath(argv[i], NULL);
argv[i] = argv[i+1];
argc--;
fprintf(stderr, "about to call fuse_main\n");
fuse_stat = fuse_main(argc, argv, &bb_oper, bb_data);
The for-loop goes past any options, assuming
libfuse will know what to do with them. If I
had any options interpreted by my code (for instance, if I allowed the
user to change the name of the log file), this is where I'd parse
them. For that matter, if the parsing were even slightly more
complicated than this I'd use getopt()).
Once I'm past the options, I should have exactly two arguments left:
the root directory and the mountpoint. If I don't, I print a usage
message and exit. If I do, I call the C library
realpath() function to canonicalize the directory name,
and point bb_data->rootdir to it (of course,
bb_data has been calloc()ed before
this code is reached).
After I've done that, I remove the root directory from the argument vector and reduce the argument count. I don't need to look for the mountpoint, since FUSE will find that for itself.
Once I'm ready to start the filesystem, I call
fuse_main(). Its parameters are argc and
argv (as modified by my main() function),
the bb_oper struct containing pointers to my
re-implementations of the POSIX file operations, and a
struct bb_data, used for storing private data.
Private data will be discussed in the next section.
fuse_main() parses the rest of the command line,
mounts the directory specified on the command line, and performs other
initializations. Then, it calls an initialization function to
perform any initialization defined by my code. bb_oper->init
points to my bb_init() function, so it is called next.
My bb_init() function is really small; all it does is
calls a function called log_open() and then log the fact
that it has been called. log_open() depends heavily on
the private data I passed in bb_data, so we'll wait to
duscuss it until the next section.