2014-05-13 00:41:46 +08:00
|
|
|
/*
|
2016-01-15 05:50:22 +08:00
|
|
|
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
|
|
|
|
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
2014-05-13 00:41:46 +08:00
|
|
|
*/
|
|
|
|
|
2023-01-29 12:15:10 +08:00
|
|
|
#define FMT_HEADER_ONLY
|
|
|
|
|
2014-05-13 00:41:46 +08:00
|
|
|
#include "config.hpp"
|
2019-09-24 22:27:46 +08:00
|
|
|
#include "ef.hpp"
|
2018-10-08 10:28:58 +08:00
|
|
|
#include "errno.hpp"
|
2023-01-29 12:15:10 +08:00
|
|
|
#include "fmt/core.h"
|
2018-09-12 04:45:17 +08:00
|
|
|
#include "fs_glob.hpp"
|
2018-12-12 23:08:17 +08:00
|
|
|
#include "fs_statvfs_cache.hpp"
|
2019-09-24 22:27:46 +08:00
|
|
|
#include "hw_cpu.hpp"
|
2015-09-28 18:39:16 +08:00
|
|
|
#include "num.hpp"
|
2014-05-13 00:41:46 +08:00
|
|
|
#include "policy.hpp"
|
2015-09-28 18:39:16 +08:00
|
|
|
#include "str.hpp"
|
|
|
|
#include "version.hpp"
|
2014-05-13 00:41:46 +08:00
|
|
|
|
2020-12-20 04:06:08 +08:00
|
|
|
#include "fuse.h"
|
2019-01-09 13:01:52 +08:00
|
|
|
|
2019-09-24 22:27:46 +08:00
|
|
|
#include <fstream>
|
2019-01-09 13:01:52 +08:00
|
|
|
#include <iomanip>
|
|
|
|
#include <iostream>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2014-06-01 05:54:18 +08:00
|
|
|
using std::string;
|
|
|
|
using std::vector;
|
2014-05-13 00:41:46 +08:00
|
|
|
|
2015-09-28 18:39:16 +08:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
MERGERFS_OPT_HELP,
|
|
|
|
MERGERFS_OPT_VERSION
|
|
|
|
};
|
|
|
|
|
2019-09-24 22:27:46 +08:00
|
|
|
|
2015-03-12 06:14:05 +08:00
|
|
|
static
|
|
|
|
void
|
2020-12-20 04:06:08 +08:00
|
|
|
set_option(const std::string &option_,
|
|
|
|
fuse_args *args_)
|
2015-03-12 06:14:05 +08:00
|
|
|
{
|
|
|
|
|
2020-12-20 04:06:08 +08:00
|
|
|
fuse_opt_add_arg(args_,"-o");
|
|
|
|
fuse_opt_add_arg(args_,option_.c_str());
|
2015-03-12 06:14:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
void
|
2020-12-20 04:06:08 +08:00
|
|
|
set_kv_option(const std::string &key_,
|
|
|
|
const std::string &val_,
|
|
|
|
fuse_args *args_)
|
2015-03-12 06:14:05 +08:00
|
|
|
{
|
|
|
|
std::string option;
|
|
|
|
|
2020-12-20 04:06:08 +08:00
|
|
|
option = key_ + '=' + val_;
|
2015-03-12 06:14:05 +08:00
|
|
|
|
2020-12-20 04:06:08 +08:00
|
|
|
set_option(option,args_);
|
2015-03-12 06:14:05 +08:00
|
|
|
}
|
|
|
|
|
2019-09-24 22:27:46 +08:00
|
|
|
static
|
|
|
|
void
|
2022-11-30 07:24:09 +08:00
|
|
|
set_fuse_threads(Config::Write &cfg_,
|
|
|
|
fuse_args *args_)
|
2019-09-24 22:27:46 +08:00
|
|
|
{
|
2022-11-30 07:24:09 +08:00
|
|
|
set_kv_option("read-thread-count",cfg_->fuse_read_thread_count.to_string(),args_);
|
|
|
|
set_kv_option("process-thread-count",cfg_->fuse_process_thread_count.to_string(),args_);
|
2023-03-20 11:15:11 +08:00
|
|
|
set_kv_option("pin-threads",cfg_->fuse_pin_threads.to_string(),args_);
|
2019-09-24 22:27:46 +08:00
|
|
|
}
|
|
|
|
|
2015-03-12 06:14:05 +08:00
|
|
|
static
|
|
|
|
void
|
2020-12-20 04:06:08 +08:00
|
|
|
set_fsname(Config::Write &cfg_,
|
|
|
|
fuse_args *args_)
|
2015-03-12 06:14:05 +08:00
|
|
|
{
|
2020-12-20 04:06:08 +08:00
|
|
|
if(cfg_->fsname->empty())
|
2015-03-12 06:14:05 +08:00
|
|
|
{
|
2020-12-20 04:06:08 +08:00
|
|
|
vector<string> paths;
|
2015-03-12 06:14:05 +08:00
|
|
|
|
2020-12-20 04:06:08 +08:00
|
|
|
cfg_->branches->to_paths(paths);
|
2015-03-12 06:14:05 +08:00
|
|
|
|
2020-12-20 04:06:08 +08:00
|
|
|
if(paths.size() > 0)
|
|
|
|
cfg_->fsname = str::remove_common_prefix_and_join(paths,':');
|
2015-03-12 06:14:05 +08:00
|
|
|
}
|
2019-05-13 02:07:21 +08:00
|
|
|
|
2020-12-20 04:06:08 +08:00
|
|
|
set_kv_option("fsname",cfg_->fsname,args_);
|
2015-03-12 06:14:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
void
|
2020-12-20 04:06:08 +08:00
|
|
|
set_subtype(fuse_args *args_)
|
2015-03-12 06:14:05 +08:00
|
|
|
{
|
2020-12-20 04:06:08 +08:00
|
|
|
set_kv_option("subtype","mergerfs",args_);
|
2015-03-12 06:14:05 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
void
|
2020-12-20 04:06:08 +08:00
|
|
|
set_default_options(fuse_args *args_)
|
2015-03-12 06:14:05 +08:00
|
|
|
{
|
2020-12-20 04:06:08 +08:00
|
|
|
set_option("default_permissions",args_);
|
2015-03-12 06:14:05 +08:00
|
|
|
}
|
|
|
|
|
2023-01-17 12:33:36 +08:00
|
|
|
static
|
|
|
|
bool
|
|
|
|
should_ignore(const std::string &key_)
|
|
|
|
{
|
|
|
|
static const std::set<std::string> IGNORED_KEYS =
|
|
|
|
{
|
2023-02-23 06:52:46 +08:00
|
|
|
"allow_other",
|
2023-01-17 12:33:36 +08:00
|
|
|
"atomic_o_trunc",
|
|
|
|
"big_writes",
|
|
|
|
"cache.open",
|
|
|
|
"defaults",
|
|
|
|
"hard_remove",
|
2023-02-23 06:52:46 +08:00
|
|
|
"no_splice_move",
|
|
|
|
"no_splice_read",
|
|
|
|
"no_splice_write",
|
2023-01-17 12:33:36 +08:00
|
|
|
"nonempty",
|
2023-02-23 06:52:46 +08:00
|
|
|
"splice_move",
|
|
|
|
"splice_read",
|
|
|
|
"splice_write",
|
2023-03-20 11:15:11 +08:00
|
|
|
"use_ino",
|
2023-01-17 12:33:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
return (IGNORED_KEYS.find(key_) != IGNORED_KEYS.end());
|
|
|
|
}
|
|
|
|
|
2019-05-31 06:59:18 +08:00
|
|
|
static
|
|
|
|
int
|
2020-12-20 04:06:08 +08:00
|
|
|
parse_and_process_kv_arg(Config::Write &cfg_,
|
|
|
|
Config::ErrVec *errs_,
|
2019-09-24 22:27:46 +08:00
|
|
|
const std::string &key_,
|
|
|
|
const std::string &val_)
|
2019-05-31 06:59:18 +08:00
|
|
|
{
|
|
|
|
int rv;
|
2019-09-24 22:27:46 +08:00
|
|
|
std::string key(key_);
|
|
|
|
std::string val(val_);
|
|
|
|
|
|
|
|
rv = 0;
|
|
|
|
if(key == "config")
|
2020-12-20 04:06:08 +08:00
|
|
|
return ((cfg_->from_file(val_,errs_) < 0) ? 1 : 0);
|
2019-09-24 22:27:46 +08:00
|
|
|
ef(key == "attr_timeout")
|
|
|
|
key = "cache.attr";
|
|
|
|
ef(key == "entry_timeout")
|
|
|
|
key = "cache.entry";
|
|
|
|
ef(key == "negative_entry")
|
|
|
|
key = "cache.negative_entry";
|
|
|
|
ef(key == "direct_io" && val.empty())
|
|
|
|
val = "true";
|
|
|
|
ef(key == "kernel_cache" && val.empty())
|
|
|
|
val = "true";
|
|
|
|
ef(key == "auto_cache" && val.empty())
|
|
|
|
val = "true";
|
|
|
|
ef(key == "async_read" && val.empty())
|
|
|
|
val = "true";
|
|
|
|
ef(key == "sync_read" && val.empty())
|
|
|
|
{key = "async_read", val = "false";}
|
2023-01-17 12:33:36 +08:00
|
|
|
ef(::should_ignore(key_))
|
2023-01-17 02:55:01 +08:00
|
|
|
return 0;
|
2019-05-24 11:22:36 +08:00
|
|
|
|
2020-12-20 04:06:08 +08:00
|
|
|
if(cfg_->has_key(key) == false)
|
2019-05-24 11:22:36 +08:00
|
|
|
return 1;
|
|
|
|
|
2020-12-20 04:06:08 +08:00
|
|
|
rv = cfg_->set_raw(key,val);
|
2019-09-24 22:27:46 +08:00
|
|
|
if(rv)
|
2020-12-20 04:06:08 +08:00
|
|
|
errs_->push_back({rv,key+'='+val});
|
2018-10-08 10:28:58 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-11-02 22:23:56 +08:00
|
|
|
static
|
|
|
|
int
|
2020-12-20 04:06:08 +08:00
|
|
|
process_opt(Config::Write &cfg_,
|
|
|
|
Config::ErrVec *errs_,
|
2019-09-24 22:27:46 +08:00
|
|
|
const std::string &arg_)
|
2018-11-02 22:23:56 +08:00
|
|
|
{
|
2019-09-24 22:27:46 +08:00
|
|
|
std::string key;
|
|
|
|
std::string val;
|
2018-11-02 22:23:56 +08:00
|
|
|
|
2019-09-24 22:27:46 +08:00
|
|
|
str::splitkv(arg_,'=',&key,&val);
|
2020-12-20 04:06:08 +08:00
|
|
|
key = str::trim(key);
|
|
|
|
val = str::trim(val);
|
2018-11-02 22:23:56 +08:00
|
|
|
|
2020-12-20 04:06:08 +08:00
|
|
|
return parse_and_process_kv_arg(cfg_,errs_,key,val);
|
2018-11-02 22:23:56 +08:00
|
|
|
}
|
|
|
|
|
2019-01-07 01:52:55 +08:00
|
|
|
static
|
|
|
|
int
|
2020-12-20 04:06:08 +08:00
|
|
|
process_branches(Config::Write &cfg_,
|
|
|
|
Config::ErrVec *errs_,
|
|
|
|
const char *arg_)
|
2018-12-12 23:08:17 +08:00
|
|
|
{
|
|
|
|
int rv;
|
2019-09-24 22:27:46 +08:00
|
|
|
string arg;
|
2018-12-12 23:08:17 +08:00
|
|
|
|
2019-09-24 22:27:46 +08:00
|
|
|
arg = arg_;
|
2020-12-20 04:06:08 +08:00
|
|
|
rv = cfg_->set_raw("branches",arg);
|
2019-09-24 22:27:46 +08:00
|
|
|
if(rv)
|
2020-12-20 04:06:08 +08:00
|
|
|
errs_->push_back({rv,"branches="+arg});
|
2018-12-12 23:08:17 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
int
|
2020-12-20 04:06:08 +08:00
|
|
|
process_mount(Config::Write &cfg_,
|
|
|
|
Config::ErrVec *errs_,
|
|
|
|
const char *arg_)
|
2014-05-13 00:41:46 +08:00
|
|
|
{
|
2015-03-12 06:14:05 +08:00
|
|
|
int rv;
|
2019-09-24 22:27:46 +08:00
|
|
|
string arg;
|
2014-05-13 00:41:46 +08:00
|
|
|
|
2019-09-24 22:27:46 +08:00
|
|
|
arg = arg_;
|
2020-12-20 04:06:08 +08:00
|
|
|
rv = cfg_->set_raw("mount",arg);
|
2019-09-24 22:27:46 +08:00
|
|
|
if(rv)
|
2020-12-20 04:06:08 +08:00
|
|
|
errs_->push_back({rv,"mount="+arg});
|
2014-06-01 05:54:18 +08:00
|
|
|
|
2014-08-04 03:50:28 +08:00
|
|
|
return 1;
|
2014-06-01 05:54:18 +08:00
|
|
|
}
|
|
|
|
|
2015-09-28 18:39:16 +08:00
|
|
|
static
|
|
|
|
void
|
|
|
|
usage(void)
|
|
|
|
{
|
|
|
|
std::cout <<
|
2019-05-24 11:22:36 +08:00
|
|
|
"Usage: mergerfs [options] <branches> <destpath>\n"
|
2015-09-28 18:39:16 +08:00
|
|
|
"\n"
|
|
|
|
" -o [opt,...] mount options\n"
|
|
|
|
" -h --help print help\n"
|
|
|
|
" -v --version print version\n"
|
|
|
|
"\n"
|
|
|
|
"mergerfs options:\n"
|
2019-05-24 11:22:36 +08:00
|
|
|
" <branches> ':' delimited list of directories. Supports\n"
|
2015-09-28 18:39:16 +08:00
|
|
|
" shell globbing (must be escaped in shell)\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o config=FILE Read options from file in key=val format\n"
|
|
|
|
" -o func.FUNC=POLICY Set function FUNC to policy POLICY\n"
|
|
|
|
" -o category.CAT=POLICY Set functions in category CAT to POLICY\n"
|
|
|
|
" -o fsname=STR Sets the name of the filesystem.\n"
|
|
|
|
" -o cache.open=INT 'open' policy cache timeout in seconds.\n"
|
2019-01-07 01:52:55 +08:00
|
|
|
" default = 0 (disabled)\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o cache.statfs=INT 'statfs' cache timeout in seconds. Used by\n"
|
2018-12-12 23:08:17 +08:00
|
|
|
" policies. default = 0 (disabled)\n"
|
2019-05-24 11:22:36 +08:00
|
|
|
" -o cache.files=libfuse|off|partial|full|auto-full\n"
|
|
|
|
" * libfuse: Use direct_io, kernel_cache, auto_cache\n"
|
|
|
|
" values directly\n"
|
|
|
|
" * off: Disable page caching\n"
|
|
|
|
" * partial: Clear page cache on file open\n"
|
|
|
|
" * full: Keep cache on file open\n"
|
|
|
|
" * auto-full: Keep cache if mtime & size not changed\n"
|
|
|
|
" default = libfuse\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o cache.writeback=BOOL\n"
|
2020-02-08 03:05:03 +08:00
|
|
|
" Enable kernel writeback caching (if supported)\n"
|
2020-07-20 19:01:33 +08:00
|
|
|
" cache.files must be enabled as well.\n"
|
2020-02-08 03:05:03 +08:00
|
|
|
" default = false\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o cache.symlinks=BOOL\n"
|
2019-05-24 11:22:36 +08:00
|
|
|
" Enable kernel caching of symlinks (if supported)\n"
|
|
|
|
" default = false\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o cache.readdir=BOOL\n"
|
2019-05-24 11:22:36 +08:00
|
|
|
" Enable kernel caching readdir (if supported)\n"
|
2019-05-22 11:23:26 +08:00
|
|
|
" default = false\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o cache.attr=INT File attribute cache timeout in seconds.\n"
|
2019-02-04 11:38:57 +08:00
|
|
|
" default = 1\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o cache.entry=INT File name lookup cache timeout in seconds.\n"
|
2019-02-04 11:38:57 +08:00
|
|
|
" default = 1\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o cache.negative_entry=INT\n"
|
2019-05-24 11:22:36 +08:00
|
|
|
" Negative file name lookup cache timeout in\n"
|
2019-02-04 11:38:57 +08:00
|
|
|
" seconds. default = 0\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o inodecalc=passthrough|path-hash|devino-hash|hybrid-hash\n"
|
|
|
|
" Selects the inode calculation algorithm.\n"
|
|
|
|
" default = hybrid-hash\n"
|
|
|
|
" -o minfreespace=INT Minimum free space needed for certain policies.\n"
|
2018-10-01 07:47:44 +08:00
|
|
|
" default = 4G\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o moveonenospc=BOOL Try to move file to another drive when ENOSPC\n"
|
2018-10-01 07:47:44 +08:00
|
|
|
" on write. default = false\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o dropcacheonclose=BOOL\n"
|
2017-04-24 18:57:29 +08:00
|
|
|
" When a file is closed suggest to OS it drop\n"
|
2019-05-24 11:22:36 +08:00
|
|
|
" the file's cache. This is useful when using\n"
|
|
|
|
" 'cache.files'. default = false\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o symlinkify=BOOL Read-only files, after a timeout, will be turned\n"
|
2017-04-24 18:57:29 +08:00
|
|
|
" into symlinks. Read docs for limitations and\n"
|
2018-10-01 07:47:44 +08:00
|
|
|
" possible issues. default = false\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o symlinkify_timeout=INT\n"
|
2019-05-24 11:22:36 +08:00
|
|
|
" Timeout in seconds before files turn to symlinks.\n"
|
2018-10-01 07:47:44 +08:00
|
|
|
" default = 3600\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o nullrw=BOOL Disables reads and writes. For benchmarking.\n"
|
2018-10-03 02:22:37 +08:00
|
|
|
" default = false\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o ignorepponrename=BOOL\n"
|
2017-06-30 11:57:15 +08:00
|
|
|
" Ignore path preserving when performing renames\n"
|
2017-07-03 02:39:59 +08:00
|
|
|
" and links. default = false\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o link_cow=BOOL Delink/clone file on open to simulate CoW.\n"
|
2018-10-08 10:28:58 +08:00
|
|
|
" default = false\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o nfsopenhack=off|git|all\n"
|
|
|
|
" A workaround for exporting mergerfs over NFS\n"
|
|
|
|
" where there are issues with creating files for\n"
|
|
|
|
" write while setting the mode to read-only.\n"
|
|
|
|
" default = off\n"
|
|
|
|
" -o security_capability=BOOL\n"
|
2018-10-01 07:47:44 +08:00
|
|
|
" When disabled return ENOATTR when the xattr\n"
|
|
|
|
" security.capability is queried. default = true\n"
|
2018-11-20 12:30:39 +08:00
|
|
|
" -o xattr=passthrough|noattr|nosys\n"
|
2018-10-08 10:28:58 +08:00
|
|
|
" Runtime control of xattrs. By default xattr\n"
|
|
|
|
" requests will pass through to the underlying\n"
|
|
|
|
" filesystems. notattr will short circuit as if\n"
|
2018-11-20 12:30:39 +08:00
|
|
|
" nothing exists. nosys will respond as if not\n"
|
2018-10-08 10:28:58 +08:00
|
|
|
" supported or disabled. default = passthrough\n"
|
2018-11-02 22:23:56 +08:00
|
|
|
" -o statfs=base|full When set to 'base' statfs will use all branches\n"
|
|
|
|
" when performing statfs calculations. 'full' will\n"
|
|
|
|
" only include branches on which that path is\n"
|
|
|
|
" available. default = base\n"
|
|
|
|
" -o statfs_ignore=none|ro|nc\n"
|
|
|
|
" 'ro' will cause statfs calculations to ignore\n"
|
|
|
|
" available space for branches mounted or tagged\n"
|
|
|
|
" as 'read only' or 'no create'. 'nc' will ignore\n"
|
|
|
|
" available space for branches tagged as\n"
|
|
|
|
" 'no create'. default = none\n"
|
2020-07-31 01:54:29 +08:00
|
|
|
" -o posix_acl=BOOL Enable POSIX ACL support. default = false\n"
|
|
|
|
" -o async_read=BOOL If disabled or unavailable the kernel will\n"
|
2019-05-29 03:15:18 +08:00
|
|
|
" ensure there is at most one pending read \n"
|
|
|
|
" request per file and will attempt to order\n"
|
|
|
|
" requests by offset. default = true\n"
|
2015-09-28 18:39:16 +08:00
|
|
|
<< std::endl;
|
|
|
|
}
|
|
|
|
|
2014-05-13 00:41:46 +08:00
|
|
|
static
|
|
|
|
int
|
2019-09-24 22:27:46 +08:00
|
|
|
option_processor(void *data_,
|
|
|
|
const char *arg_,
|
|
|
|
int key_,
|
|
|
|
fuse_args *outargs_)
|
2014-05-13 00:41:46 +08:00
|
|
|
{
|
2020-12-20 04:06:08 +08:00
|
|
|
Config::Write cfg;
|
|
|
|
Config::ErrVec *errs = (Config::ErrVec*)data_;
|
2014-05-13 00:41:46 +08:00
|
|
|
|
2019-09-24 22:27:46 +08:00
|
|
|
switch(key_)
|
2014-05-13 00:41:46 +08:00
|
|
|
{
|
|
|
|
case FUSE_OPT_KEY_OPT:
|
2020-12-20 04:06:08 +08:00
|
|
|
return process_opt(cfg,errs,arg_);
|
2014-05-13 00:41:46 +08:00
|
|
|
|
|
|
|
case FUSE_OPT_KEY_NONOPT:
|
2020-12-20 04:06:08 +08:00
|
|
|
if(cfg->branches->empty())
|
|
|
|
return process_branches(cfg,errs,arg_);
|
2019-09-24 22:27:46 +08:00
|
|
|
else
|
2020-12-20 04:06:08 +08:00
|
|
|
return process_mount(cfg,errs,arg_);
|
2014-05-13 00:41:46 +08:00
|
|
|
|
2015-09-28 18:39:16 +08:00
|
|
|
case MERGERFS_OPT_HELP:
|
|
|
|
usage();
|
2020-09-11 09:58:23 +08:00
|
|
|
exit(0);
|
2015-09-28 18:39:16 +08:00
|
|
|
|
|
|
|
case MERGERFS_OPT_VERSION:
|
2018-03-10 09:48:36 +08:00
|
|
|
std::cout << "mergerfs version: "
|
|
|
|
<< (MERGERFS_VERSION[0] ? MERGERFS_VERSION : "unknown")
|
|
|
|
<< std::endl;
|
2020-09-11 09:58:23 +08:00
|
|
|
exit(0);
|
2015-09-28 18:39:16 +08:00
|
|
|
|
2014-05-13 00:41:46 +08:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2019-09-24 22:27:46 +08:00
|
|
|
return 0;
|
2014-05-13 00:41:46 +08:00
|
|
|
}
|
|
|
|
|
2023-01-29 12:15:10 +08:00
|
|
|
static
|
|
|
|
void
|
|
|
|
check_for_mount_loop(Config::Write &cfg_,
|
|
|
|
Config::ErrVec *errs_)
|
|
|
|
{
|
|
|
|
fs::Path mount;
|
|
|
|
fs::PathVector branches;
|
|
|
|
std::error_code ec;
|
|
|
|
|
2023-02-02 12:05:45 +08:00
|
|
|
mount = (std::string)cfg_->mountpoint;
|
2023-01-29 12:15:10 +08:00
|
|
|
branches = cfg_->branches->to_paths();
|
|
|
|
for(const auto &branch : branches)
|
|
|
|
{
|
|
|
|
if(ghc::filesystem::equivalent(branch,mount,ec))
|
|
|
|
{
|
|
|
|
std::string errstr;
|
|
|
|
|
|
|
|
errstr = fmt::format("branches can not include the mountpoint: {}",branch.string());
|
|
|
|
errs_->push_back({0,errstr});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-25 20:03:46 +08:00
|
|
|
namespace options
|
2014-05-13 00:41:46 +08:00
|
|
|
{
|
2019-01-25 20:03:46 +08:00
|
|
|
void
|
2020-12-20 04:06:08 +08:00
|
|
|
parse(fuse_args *args_,
|
|
|
|
Config::ErrVec *errs_)
|
2014-05-13 00:41:46 +08:00
|
|
|
{
|
2020-12-20 04:06:08 +08:00
|
|
|
Config::Write cfg;
|
2019-01-25 20:03:46 +08:00
|
|
|
const struct fuse_opt opts[] =
|
|
|
|
{
|
|
|
|
FUSE_OPT_KEY("-h",MERGERFS_OPT_HELP),
|
|
|
|
FUSE_OPT_KEY("--help",MERGERFS_OPT_HELP),
|
|
|
|
FUSE_OPT_KEY("-v",MERGERFS_OPT_VERSION),
|
|
|
|
FUSE_OPT_KEY("-V",MERGERFS_OPT_VERSION),
|
|
|
|
FUSE_OPT_KEY("--version",MERGERFS_OPT_VERSION),
|
|
|
|
{NULL,-1U,0}
|
|
|
|
};
|
|
|
|
|
2019-05-13 02:07:21 +08:00
|
|
|
fuse_opt_parse(args_,
|
2020-12-20 04:06:08 +08:00
|
|
|
errs_,
|
2019-01-25 20:03:46 +08:00
|
|
|
opts,
|
|
|
|
::option_processor);
|
|
|
|
|
2020-12-20 04:06:08 +08:00
|
|
|
if(cfg->branches->empty())
|
|
|
|
errs_->push_back({0,"branches not set"});
|
2023-02-02 12:05:45 +08:00
|
|
|
if(cfg->mountpoint->empty())
|
2020-12-20 04:06:08 +08:00
|
|
|
errs_->push_back({0,"mountpoint not set"});
|
2020-09-11 09:58:23 +08:00
|
|
|
|
2023-01-29 12:15:10 +08:00
|
|
|
check_for_mount_loop(cfg,errs_);
|
2023-02-23 06:52:46 +08:00
|
|
|
|
2019-05-13 02:07:21 +08:00
|
|
|
set_default_options(args_);
|
2020-12-20 04:06:08 +08:00
|
|
|
set_fsname(cfg,args_);
|
2019-05-13 02:07:21 +08:00
|
|
|
set_subtype(args_);
|
2022-11-30 07:24:09 +08:00
|
|
|
set_fuse_threads(cfg,args_);
|
2023-03-20 11:15:11 +08:00
|
|
|
|
|
|
|
cfg->finish_initializing();
|
2014-05-13 00:41:46 +08:00
|
|
|
}
|
|
|
|
}
|