in src/s3fs.cpp [4774:5176]
int main(int argc, char* argv[])
{
int ch;
int fuse_res;
int option_index = 0;
struct fuse_operations s3fs_oper;
time_t incomp_abort_time = (24 * 60 * 60);
S3fsLog singletonLog;
static const struct option long_opts[] = {
{"help", no_argument, NULL, 'h'},
{"version", no_argument, 0, 0},
{"debug", no_argument, NULL, 'd'},
{"incomplete-mpu-list", no_argument, NULL, 'u'},
{"incomplete-mpu-abort", optional_argument, NULL, 'a'}, // 'a' is only identifier and is not option.
{NULL, 0, NULL, 0}
};
// init xml2
xmlInitParser();
LIBXML_TEST_VERSION
init_sysconf_vars();
// get program name - emulate basename
program_name = argv[0];
size_t found = program_name.find_last_of('/');
if(found != std::string::npos){
program_name.replace(0, found+1, "");
}
// set credential object
//
ps3fscred = new S3fsCred();
if(!ps3fscred) {
S3FS_PRN_EXIT("Failed to new S3fsCred.");
exit(EXIT_FAILURE);
}
if(!S3fsCurl::InitCredentialObject(ps3fscred)){
S3FS_PRN_EXIT("Failed to setup credential object to ossfs curl.");
delete ps3fscred;
exit(EXIT_FAILURE);
}
printf("[NOTICE] OSS signature V1 service will not be available for new uids since March 1st, 2025. It is recommended to mount with OSS signature V4:\n\t ossfs [oss-bucket] [mount-path] [options] -osigv4 -oregion=[your-region-id]\n");
while((ch = getopt_long(argc, argv, "dho:fsu", long_opts, &option_index)) != -1){
switch(ch){
case 0:
if(strcmp(long_opts[option_index].name, "version") == 0){
show_version();
delete ps3fscred;
exit(EXIT_SUCCESS);
}
break;
case 'h':
show_help();
delete ps3fscred;
exit(EXIT_SUCCESS);
case 'o':
break;
case 'd':
break;
case 'f':
foreground = true;
break;
case 's':
break;
case 'u': // --incomplete-mpu-list
if(NO_UTILITY_MODE != utility_mode){
S3FS_PRN_EXIT("already utility mode option is specified.");
delete ps3fscred;
exit(EXIT_FAILURE);
}
utility_mode = INCOMP_TYPE_LIST;
break;
case 'a': // --incomplete-mpu-abort
if(NO_UTILITY_MODE != utility_mode){
S3FS_PRN_EXIT("already utility mode option is specified.");
delete ps3fscred;
exit(EXIT_FAILURE);
}
utility_mode = INCOMP_TYPE_ABORT;
// check expire argument
if(NULL != optarg && 0 == strcasecmp(optarg, "all")){ // all is 0s
incomp_abort_time = 0;
}else if(NULL != optarg){
if(!convert_unixtime_from_option_arg(optarg, incomp_abort_time)){
S3FS_PRN_EXIT("--incomplete-mpu-abort option argument is wrong.");
delete ps3fscred;
exit(EXIT_FAILURE);
}
}
// if optarg is null, incomp_abort_time is 24H(default)
break;
default:
delete ps3fscred;
exit(EXIT_FAILURE);
}
}
// print launch message
print_launch_message(argc, argv);
// Load SSE environment
if(!S3fsCurl::LoadEnvSse()){
S3FS_PRN_EXIT("something wrong about SSE environment.");
delete ps3fscred;
exit(EXIT_FAILURE);
}
// ssl init
if(!s3fs_init_global_ssl()){
S3FS_PRN_EXIT("could not initialize for ssl libraries.");
delete ps3fscred;
exit(EXIT_FAILURE);
}
// mutex for xml
if(!init_parser_xml_lock()){
S3FS_PRN_EXIT("could not initialize mutex for xml parser.");
s3fs_destroy_global_ssl();
delete ps3fscred;
exit(EXIT_FAILURE);
}
// init curl (without mime types)
//
// [NOTE]
// The curl initialization here does not load mime types.
// The mime types file parameter are dynamic values according
// to the user's environment, and are analyzed by the my_fuse_opt_proc
// function.
// The my_fuse_opt_proc function is executed after this curl
// initialization. Because the curl method is used in the
// my_fuse_opt_proc function, then it must be called here to
// initialize. Fortunately, the processing using mime types
// is only PUT/POST processing, and it is not used until the
// call of my_fuse_opt_proc function is completed. Therefore,
// the mime type is loaded just after calling the my_fuse_opt_proc
// function.
//
if(!S3fsCurl::InitS3fsCurl()){
S3FS_PRN_EXIT("Could not initiate curl library.");
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
// clear this structure
memset(&s3fs_oper, 0, sizeof(s3fs_oper));
// This is the fuse-style parser for the arguments
// after which the bucket name and mountpoint names
// should have been set
struct fuse_args custom_args = FUSE_ARGS_INIT(argc, argv);
if(0 != fuse_opt_parse(&custom_args, NULL, NULL, my_fuse_opt_proc)){
S3fsCurl::DestroyS3fsCurl();
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
if (S3fsCurl::GetSignatureType() == V4_ONLY && !is_specified_region) {
S3FS_PRN_EXIT("Using OSSV4 signature requires specifying the region");
S3fsCurl::DestroyS3fsCurl();
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
// init mime types for curl
if(!S3fsCurl::InitMimeType(mimetype_file)){
S3FS_PRN_WARN("Missing MIME types prevents setting Content-Type on uploaded objects.");
}
// [NOTE]
// exclusive option check here.
//
if(strcasecmp(S3fsCurl::GetStorageClass().c_str(), "REDUCED_REDUNDANCY") == 0 && !S3fsCurl::IsSseDisable()){
S3FS_PRN_EXIT("use_sse option could not be specified with storage class reduced_redundancy.");
S3fsCurl::DestroyS3fsCurl();
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
if(!S3fsCurl::FinalCheckSse()){
S3FS_PRN_EXIT("something wrong about SSE options.");
S3fsCurl::DestroyS3fsCurl();
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
if(S3fsCurl::GetSignatureType() == V1_ONLY && S3fsCurl::GetUnsignedPayload()){
S3FS_PRN_WARN("Ignoring enable_unsigned_payload with sigv1");
}
if(!FdEntity::GetNoMixMultipart() && max_dirty_data != -1){
S3FS_PRN_WARN("Setting max_dirty_data to -1 when nomixupload is enabled");
max_dirty_data = -1;
}
//
// Check the combination of parameters for credential
//
if(!ps3fscred->CheckAllParams()){
S3fsCurl::DestroyS3fsCurl();
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
// The second plain argument is the mountpoint
// if the option was given, we all ready checked for a
// readable, non-empty directory, this checks determines
// if the mountpoint option was ever supplied
if(NO_UTILITY_MODE == utility_mode){
if(mountpoint.empty()){
S3FS_PRN_EXIT("missing MOUNTPOINT argument.");
show_usage();
S3fsCurl::DestroyS3fsCurl();
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
}
// check tmp dir permission
if(!FdManager::CheckTmpDirExist()){
S3FS_PRN_EXIT("temporary directory doesn't exists.");
S3fsCurl::DestroyS3fsCurl();
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
// check cache dir permission
if(!FdManager::CheckCacheDirExist() || !FdManager::CheckCacheTopDir() || !CacheFileStat::CheckCacheFileStatTopDir()){
S3FS_PRN_EXIT("could not allow cache directory permission, check permission of cache directories.");
S3fsCurl::DestroyS3fsCurl();
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
// set fake free disk space
if(-1 != fake_diskfree_size){
FdManager::InitFakeUsedDiskSize(fake_diskfree_size);
}
// set user agent
S3fsCurl::InitUserAgent();
// There's room for more command line error checking
// Check to see if the bucket name contains periods and https (SSL) is
// being used. This is a known limitation:
// https://docs.amazonwebservices.com/AmazonS3/latest/dev/
// The Developers Guide suggests that either use HTTP of for us to write
// our own certificate verification logic.
// For now, this will be unsupported unless we get a request for it to
// be supported. In that case, we have a couple of options:
// - implement a command line option that bypasses the verify host
// but doesn't bypass verifying the certificate
// - write our own host verification (this might be complex)
// See issue #128strncasecmp
/*
if(1 == S3fsCurl::GetSslVerifyHostname()){
found = S3fsCred::GetBucket().find_first_of('.');
if(found != std::string::npos){
found = s3host.find("https:");
if(found != std::string::npos){
S3FS_PRN_EXIT("Using https and a bucket name with periods is unsupported.");
exit(1);
}
}
}
*/
if(NO_UTILITY_MODE != utility_mode){
int exitcode = s3fs_utility_processing(incomp_abort_time);
S3fsCurl::DestroyS3fsCurl();
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
delete ps3fscred;
exit(exitcode);
}
// Check multipart / copy api for mix multipart uploading
if(nomultipart || nocopyapi || norenameapi){
FdEntity::SetNoMixMultipart();
max_dirty_data = -1;
}
// check free disk space
if(!FdManager::IsSafeDiskSpace(NULL, S3fsCurl::GetMultipartSize() * S3fsCurl::GetMaxParallelCount())){
// clean cache dir and retry
S3FS_PRN_WARN("No enough disk space for ossfs, try to clean cache dir");
FdManager::get()->CleanupCacheDir();
if(!FdManager::IsSafeDiskSpaceWithLog(nullptr, S3fsCurl::GetMultipartSize() * S3fsCurl::GetMaxParallelCount())){
S3fsCurl::DestroyS3fsCurl();
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
}
// check readdir_optimize
if(is_readdir_optimize){
if(is_use_xattr){
S3FS_PRN_EXIT("readdir_optimize option could not be specified with use_xattr option.");
S3fsCurl::DestroyS3fsCurl();
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
delete ps3fscred;
exit(EXIT_FAILURE);
}
is_refresh_fakemeta = true;
StatCache::getStatCacheData()->SetNoExtendedMeta(true, readdir_check_size);
S3FS_PRN_INFO("Readdir optimize, flag(%d, %lld)", is_refresh_fakemeta, static_cast<long long int>(readdir_check_size));
}
// try to check s3fs service
if (EXIT_SUCCESS != s3fs_check_service()) {
exit(EXIT_FAILURE);
}
s3fs_oper.getattr = s3fs_getattr;
s3fs_oper.readlink = s3fs_readlink;
s3fs_oper.mknod = s3fs_mknod;
s3fs_oper.mkdir = s3fs_mkdir;
s3fs_oper.unlink = s3fs_unlink;
s3fs_oper.rmdir = s3fs_rmdir;
s3fs_oper.symlink = s3fs_symlink;
s3fs_oper.rename = s3fs_rename;
s3fs_oper.link = s3fs_link;
if(!nocopyapi){
s3fs_oper.chmod = s3fs_chmod;
s3fs_oper.chown = s3fs_chown;
s3fs_oper.utimens = s3fs_utimens;
}else{
s3fs_oper.chmod = s3fs_chmod_nocopy;
s3fs_oper.chown = s3fs_chown_nocopy;
s3fs_oper.utimens = s3fs_utimens_nocopy;
}
s3fs_oper.truncate = s3fs_truncate;
s3fs_oper.open = s3fs_open;
s3fs_oper.read = s3fs_read;
s3fs_oper.write = s3fs_write;
s3fs_oper.statfs = s3fs_statfs;
s3fs_oper.flush = s3fs_flush;
s3fs_oper.fsync = s3fs_fsync;
s3fs_oper.release = s3fs_release;
s3fs_oper.opendir = s3fs_opendir;
s3fs_oper.readdir = s3fs_readdir;
s3fs_oper.init = s3fs_init;
s3fs_oper.destroy = s3fs_destroy;
s3fs_oper.access = s3fs_access;
s3fs_oper.create = s3fs_create;
// extended attributes
if(is_use_xattr){
s3fs_oper.setxattr = s3fs_setxattr;
s3fs_oper.getxattr = s3fs_getxattr;
s3fs_oper.listxattr = s3fs_listxattr;
s3fs_oper.removexattr = s3fs_removexattr;
}
s3fs_oper.flag_utime_omit_ok = true;
// now passing things off to fuse, fuse will finish evaluating the command line args
fuse_res = fuse_main(custom_args.argc, custom_args.argv, &s3fs_oper, NULL);
if(fuse_res == 0){
fuse_res = s3fs_init_deferred_exit_status;
}
fuse_opt_free_args(&custom_args);
// Destroy curl
if(!S3fsCurl::DestroyS3fsCurl()){
S3FS_PRN_WARN("Could not release curl library.");
}
s3fs_destroy_global_ssl();
destroy_parser_xml_lock();
delete ps3fscred;
// cleanup xml2
xmlCleanupParser();
S3FS_MALLOCTRIM(0);
exit(fuse_res);
}