|
|
@@ -0,0 +1,236 @@ |
|
|
|
// FUSE file system for vlbi_streamer style recordings |
|
|
|
#define FUSE_USE_VERSION 26 |
|
|
|
#include <fuse.h> |
|
|
|
|
|
|
|
#include <evlbidebug.h> |
|
|
|
|
|
|
|
#include <iostream> |
|
|
|
#include <cstddef> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
using namespace std; |
|
|
|
|
|
|
|
/////////////////////////////////////////////// |
|
|
|
// Keep state of the FUSE file system in |
|
|
|
// a struct of this type. It's a global |
|
|
|
// variable. |
|
|
|
/////////////////////////////////////////////// |
|
|
|
const string defaultRootDir = "/mnt"; |
|
|
|
|
|
|
|
struct vbs_state_type { |
|
|
|
string rootDir; |
|
|
|
|
|
|
|
vbs_state_type() {} |
|
|
|
}; |
|
|
|
|
|
|
|
vbs_state_type* vbs_state = 0; |
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////// |
|
|
|
// Here follow the implementations |
|
|
|
// of the file system functions |
|
|
|
// that we support |
|
|
|
/////////////////////////////////////////////// |
|
|
|
void* vbs_init(struct fuse_conn_info* /*conn*/) { |
|
|
|
DEBUG(-1, "vbs_init" << endl); |
|
|
|
return (void*)vbs_state; |
|
|
|
} |
|
|
|
|
|
|
|
void vbs_destroy(void* ptr) { |
|
|
|
DEBUG(-1, "vbs_destroy" << endl); |
|
|
|
if( ptr==(void*)vbs_state ) |
|
|
|
DEBUG(-1, "Yes, it was our global pointer" << endl); |
|
|
|
delete (vbs_state_type*)ptr; |
|
|
|
vbs_state = 0; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////// |
|
|
|
// A filesystem must define a set |
|
|
|
// of operations with callback functions |
|
|
|
// on the file system objects it |
|
|
|
// represents. All callbacks are |
|
|
|
// registered in the fuse_operations struct |
|
|
|
/////////////////////////////////////////////// |
|
|
|
struct vbs_fuse_operations : |
|
|
|
public fuse_operations { |
|
|
|
|
|
|
|
vbs_fuse_operations() { |
|
|
|
init = &vbs_init; |
|
|
|
destroy = &vbs_destroy; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
vbs_fuse_operations vbs_oper; |
|
|
|
#if 0 |
|
|
|
struct fuse_operations vbs_oper = { |
|
|
|
//.getattr = vbs_getattr, |
|
|
|
//.readdir = vbs_readdir, |
|
|
|
//.open = vbs_open, |
|
|
|
//.read = vbs_read, |
|
|
|
//.readlink = vbs_readlink, |
|
|
|
// no .getdir -- that's deprecated |
|
|
|
//.getdir = NULL, |
|
|
|
//.mknod = vbs_mknod, |
|
|
|
//.mkdir = vbs_mkdir, |
|
|
|
//.unlink = vbs_unlink, |
|
|
|
//.rmdir = vbs_rmdir, |
|
|
|
//.symlink = vbs_symlink, |
|
|
|
//.rename = vbs_rename, |
|
|
|
//.link = vbs_link, |
|
|
|
//.chmod = vbs_chmod, |
|
|
|
//.chown = vbs_chown, |
|
|
|
//.truncate = vbs_truncate, |
|
|
|
//.utime = vbs_utime, |
|
|
|
//.write = vbs_write, |
|
|
|
/** Just a placeholder, don't set */ // huh??? |
|
|
|
//.statfs = vbs_statfs, |
|
|
|
//.flush = vbs_flush, |
|
|
|
//.release = vbs_release, |
|
|
|
//.fsync = vbs_fsync, |
|
|
|
//.setxattr = vbs_setxattr, |
|
|
|
//.getxattr = vbs_getxattr, |
|
|
|
//.listxattr = vbs_listxattr, |
|
|
|
//.removexattr = vbs_removexattr, |
|
|
|
//.opendir = vbs_opendir, |
|
|
|
//.releasedir = vbs_releasedir, |
|
|
|
//.fsyncdir = vbs_fsyncdir, |
|
|
|
.init = vbs_init, |
|
|
|
.destroy = vbs_destroy, |
|
|
|
//.access = vbs_access, |
|
|
|
//.create = vbs_create, |
|
|
|
//.ftruncate = vbs_ftruncate, |
|
|
|
}; |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////// |
|
|
|
// Command line handling |
|
|
|
// There's only a few options |
|
|
|
// that we support |
|
|
|
// -m <int> setting debug level |
|
|
|
// -r <path> set root dir for disks |
|
|
|
// -f FUSE 'foreground' flag |
|
|
|
/////////////////////////////////////////////// |
|
|
|
struct vbs_settings { |
|
|
|
int debug_level; |
|
|
|
bool help; |
|
|
|
bool foreground; |
|
|
|
char const* root_dir; |
|
|
|
|
|
|
|
// Initialize with defaults |
|
|
|
vbs_settings(): |
|
|
|
debug_level( 0 ), help( false ), foreground( false ), root_dir( 0 ) |
|
|
|
{} |
|
|
|
}; |
|
|
|
|
|
|
|
ostream& operator<<(ostream& os, const vbs_settings& vbo) { |
|
|
|
os << "-m " << vbo.debug_level << " "; |
|
|
|
if( vbo.root_dir ) |
|
|
|
os << "-r " << vbo.root_dir << " "; |
|
|
|
if( vbo.help ) |
|
|
|
os << "-h" << " "; |
|
|
|
if( vbo.foreground ) |
|
|
|
os << "-f" << " "; |
|
|
|
return os; |
|
|
|
} |
|
|
|
|
|
|
|
#define KEY_FOREGROUND 42 |
|
|
|
#define KEY_HELP 666 |
|
|
|
#define VBSFS_OPT(t, p, v) { t, offsetof(struct vbs_settings, p), v } |
|
|
|
struct fuse_opt vbs_options[] = { |
|
|
|
VBSFS_OPT("-m %i", debug_level, 0), |
|
|
|
VBSFS_OPT("-r %s", root_dir, 0), |
|
|
|
// The FUSE_OPT_KEY() ones are handled |
|
|
|
// by vbs_option_proc() |
|
|
|
//FUSE_OPT_KEY("-f", KEY_FOREGROUND), |
|
|
|
//FUSE_OPT_KEY("-h", KEY_HELP), |
|
|
|
FUSE_OPT_END |
|
|
|
}; |
|
|
|
|
|
|
|
int vbs_option_proc(void* data, const char* arg, int key, struct fuse_args* /*outargs*/) { |
|
|
|
int rv = 1; |
|
|
|
const string arg_s( arg ); |
|
|
|
vbs_settings* settingsptr = (vbs_settings*)data; |
|
|
|
|
|
|
|
|
|
|
|
if( key==KEY_FOREGROUND ) { |
|
|
|
rv = 0; |
|
|
|
settingsptr->foreground = true; |
|
|
|
} else if( key==KEY_HELP ) { |
|
|
|
rv = 0; |
|
|
|
settingsptr->help = true; |
|
|
|
} else { |
|
|
|
DEBUG(-1, "vbs_option_proc/Unrecognized arg=" << arg << " (key=" << key << ")" << endl); |
|
|
|
} |
|
|
|
if( arg_s=="-h" ) |
|
|
|
settingsptr->help = true; |
|
|
|
return rv; |
|
|
|
} |
|
|
|
|
|
|
|
void Usage( void ) { |
|
|
|
cout << "VBS specific command line arguments:" << endl |
|
|
|
#if 0 |
|
|
|
<< " -h print this message" << endl |
|
|
|
<< " -f run FUSE in the foreground, not as daemon" << endl |
|
|
|
#endif |
|
|
|
<< " -m <int> set VBS_FS debug print level to <n>" << endl |
|
|
|
<< " higher <n> => more output, default 0 (no output)" << endl |
|
|
|
<< " -r <path> path to vbs_fs 'root' directory; assume all disks" << endl |
|
|
|
<< " are mounted under <path>/disk<n> with <n> being" << endl |
|
|
|
<< " a non-negative integer" << endl; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////// |
|
|
|
// |
|
|
|
// The main function |
|
|
|
// |
|
|
|
/////////////////////////////////////////////// |
|
|
|
int main(int argc, char** argv) { |
|
|
|
// Before doing _anything_ check if we're not root/suid root |
|
|
|
if( ::getuid()==0 || ::geteuid()==0 ) { |
|
|
|
DEBUG(-1, "Running vbs_fuse as root opens unnacceptable security holes" << endl); |
|
|
|
return -11; |
|
|
|
} |
|
|
|
|
|
|
|
// Now we can safely start parsing |
|
|
|
int fuse_stat; |
|
|
|
vbs_settings settings; |
|
|
|
struct fuse_args args = FUSE_ARGS_INIT(argc, argv); |
|
|
|
|
|
|
|
vbs_state = new vbs_state_type(); |
|
|
|
|
|
|
|
// Do command line parsing |
|
|
|
::fuse_opt_parse(&args, (void*)&settings, &vbs_options[0], vbs_option_proc); |
|
|
|
DEBUG(1, "fuse_opt_arg done [" << settings << "]" << endl); |
|
|
|
|
|
|
|
#if 0 |
|
|
|
// Append to FUSE 'command line' |
|
|
|
if( settings.foreground && ::fuse_opt_add_arg(&args, "-f")!=0 ) { |
|
|
|
DEBUG(-1, "fuse_opt_add_arg(.., \"-f\") fails?!" << endl); |
|
|
|
return -12; |
|
|
|
} |
|
|
|
if( settings.help && ::fuse_opt_add_arg(&args, "-h")!=0 ) { |
|
|
|
DEBUG(-1, "fuse_opt_add_arg(.., \"-h\") fails?!" << endl); |
|
|
|
return -13; |
|
|
|
} |
|
|
|
#endif |
|
|
|
if( settings.help ) |
|
|
|
Usage(); |
|
|
|
// If no root dir given, default to "/mnt" |
|
|
|
if( settings.root_dir==0 ) |
|
|
|
DEBUG(-1, "WARN: No root dir specified for disks, defaulting to " << defaultRootDir << endl); |
|
|
|
vbs_state->rootDir = (settings.root_dir==0?defaultRootDir:string(settings.root_dir)); |
|
|
|
|
|
|
|
|
|
|
|
// Now it's about time to drop into FUSE's main loop |
|
|
|
DEBUG(3, "dropping into fuse_main" << endl); |
|
|
|
fuse_stat = fuse_main(args.argc, args.argv, &vbs_oper, vbs_state); |
|
|
|
|
|
|
|
DEBUG(3, "fuse_stat returned " << fuse_stat << endl); |
|
|
|
return fuse_stat; |
|
|
|
} |