예제 #1
0
파일: main.c 프로젝트: bjb/vdev
// run! 
int main( int argc, char** argv ) {
   
   int rc = 0;
   pid_t pid = 0;
   struct vdevfs vdev;
   
   memset( &vdev, 0, sizeof(struct vdevfs) );
   
   // set up global vdev state
   rc = vdevfs_init( &vdev, argc, argv );
   if( rc != 0 ) {
      
      vdev_error("vdevfs_init rc = %d\n", rc );
      
      exit(1);
   }
   
   // run!
   rc = vdevfs_main( &vdev, vdev.fuse_argc, vdev.fuse_argv );
   
   vdevfs_shutdown( &vdev );
   
   return rc;
}
예제 #2
0
파일: fs.cpp 프로젝트: 8l/vdev
// initialize the filesystem front-end 
// call after vdev_init
// return 0 on success
// return -ENOMEM on OOM
// return negative on error
int vdevfs_init( struct vdevfs* vdev, int argc, char** argv ) {
   
   int rc = 0;
   int rh = 0;
   struct fskit_core* core = NULL;
   int fuse_argc = 0;
   char** fuse_argv = NULL;
   int dirfd = 0;
   
   // library setup 
   vdev_setup_global();
   
   struct fskit_fuse_state* fs = VDEV_CALLOC( struct fskit_fuse_state, 1 );
   
   if( fs == NULL ) {
      return -ENOMEM;
   }
   
   fuse_argv = VDEV_CALLOC( char*, argc + 5 );
   
   if( fuse_argv == NULL ) {
      
      free( fs );
      return -ENOMEM;
   }
   
   // load config 
   vdev->config = VDEV_CALLOC( struct vdev_config, 1 );
   if( vdev->config == NULL ) {
      
      free( fs );
      free( fuse_argv );
      return -ENOMEM;
   }
   
   // init config 
   rc = vdev_config_init( vdev->config );
   if( rc != 0 ) {
      
      vdev_error("vdev_config_init rc = %d\n", rc );
      
      vdevfs_shutdown( vdev );
      free( fs );
      free( fuse_argv );
      return rc;
   }
   
   // parse opts 
   rc = vdev_config_load_from_args( vdev->config, argc, argv, &fuse_argc, fuse_argv );
   if( rc != 0 ) {
      
      vdev_error("vdev_opts_parse rc = %d\n", rc );
      
      vdev_config_usage( argv[0] );
      
      free( fs );
      free( fuse_argv );
      vdevfs_shutdown( vdev );
      return rc;
   }
   
   // get the mountpoint, but from FUSE 
   if( vdev->config->mountpoint != NULL ) {
      free( vdev->config->mountpoint );
   }
   
   rc = vdev_get_mountpoint( fuse_argc, fuse_argv, &vdev->config->mountpoint );
   if( rc != 0 ) {
      
      vdev_error("vdev_get_mountpoint rc = %d\n", rc );
      
      vdev_config_usage( argv[0] );
      
      free( fs );
      free( fuse_argv );
      return rc;
   }
   
   vdev_set_debug_level( vdev->config->debug_level );
   vdev_set_error_level( vdev->config->error_level );
   
   vdev_debug("Config file: %s\n", vdev->config->config_path );
   
   rc = vdev_config_load( vdev->config->config_path, vdev->config );
   if( rc != 0 ) {
      
      vdev_error("vdev_config_load('%s') rc = %d\n", vdev->config->config_path, rc );
      
      vdevfs_shutdown( vdev );
      free( fs );
      free( fuse_argv );
      return rc;
   }
   
   vdev_debug("vdev ACLs dir:    %s\n", vdev->config->acls_dir );
   
   // force -odev, since we'll create device nodes 
   fuse_argv[fuse_argc] = (char*)vdev_fuse_odev;
   fuse_argc++;
   
   // force -oallow_other, since we'll want to expose this to everyone 
   fuse_argv[fuse_argc] = (char*)vdev_fuse_allow_other;
   fuse_argc++;
   
   // force -ononempty, since we'll want to import the underlying filesystem
   fuse_argv[fuse_argc] = (char*)vdev_fuse_ononempty;
   fuse_argc++;
   
   vdev->mountpoint = vdev_strdup_or_null( vdev->config->mountpoint );
   
   if( vdev->mountpoint == NULL ) {
      
      vdev_error("Failed to set mountpoint, config.mountpount = '%s'\n", vdev->config->mountpoint );
      
      vdevfs_shutdown( vdev );
      free( fuse_argv );
      free( fs );
      return -EINVAL;
   }
   else {
      
      vdev_debug("mountpoint:       %s\n", vdev->mountpoint );
   }
   
   vdev->argc = argc;
   vdev->argv = argv;
   vdev->fuse_argc = fuse_argc;
   vdev->fuse_argv = fuse_argv;
   
   fskit_set_debug_level( vdev->config->debug_level );
   fskit_set_error_level( vdev->config->error_level );
   
   // get mountpoint directory 
   dirfd = open( vdev->mountpoint, O_DIRECTORY );
   if( dirfd < 0 ) {
      
      rc = -errno;
      vdev_error("open('%s') rc = %d\n", vdev->mountpoint, rc );
      
      free( fs );
      vdevfs_shutdown( vdev );
      return rc;
   }
   
   vdev->mountpoint_dirfd = dirfd;
   
   // set up fskit
   rc = fskit_fuse_init( fs, vdev );
   if( rc != 0 ) {
      
      vdev_error("fskit_fuse_init rc = %d\n", rc );
      free( fs );
      vdevfs_shutdown( vdev );
      return rc;
   }
   
   // load ACLs 
   rc = vdev_acl_load_all( vdev->config->acls_dir, &vdev->acls, &vdev->num_acls );
   if( rc != 0 ) {
      
      vdev_error("vdev_acl_load_all('%s') rc = %d\n", vdev->config->acls_dir, rc );
      
      fskit_fuse_shutdown( fs, NULL );
      free( fs );
      vdevfs_shutdown( vdev );
      return rc;
   }
   
   // make sure the fs can access its methods through the VFS
   fskit_fuse_setting_enable( fs, FSKIT_FUSE_SET_FS_ACCESS );
   
   core = fskit_fuse_get_core( fs );
   
   // add handlers.
   rh = fskit_route_readdir( core, FSKIT_ROUTE_ANY, vdevfs_readdir, FSKIT_CONCURRENT );
   if( rh < 0 ) {
      
      vdev_error("fskit_route_readdir(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
      goto vdev_route_fail;
   }
   
   rh = fskit_route_stat( core, FSKIT_ROUTE_ANY, vdevfs_stat, FSKIT_CONCURRENT );
   if( rh < 0 ) {
      
      vdev_error("fskit_route_stat(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
      goto vdev_route_fail;
   }
   
   rh = fskit_route_mknod( core, FSKIT_ROUTE_ANY, vdevfs_mknod, FSKIT_CONCURRENT );
   if( rc < 0 ) {
      
      vdev_error("fskit_route_mknod(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
      goto vdev_route_fail;
   }
   
   rh = fskit_route_mkdir( core, FSKIT_ROUTE_ANY, vdevfs_mkdir, FSKIT_CONCURRENT );
   if( rh < 0 ) {
      
      vdev_error("fskit_route_mkdir(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
      goto vdev_route_fail;
   }
   
   rh = fskit_route_create( core, FSKIT_ROUTE_ANY, vdevfs_create, FSKIT_CONCURRENT );
   if( rh < 0 ) {
      
      vdev_error("fskit_route_create(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
      goto vdev_route_fail;
   }
   
   rh = fskit_route_open( core, FSKIT_ROUTE_ANY, vdevfs_open, FSKIT_CONCURRENT );
   if( rh < 0 ) {
      
      vdev_error("fskit_route_open(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
      goto vdev_route_fail;
   }
   
   rh = fskit_route_read( core, FSKIT_ROUTE_ANY, vdevfs_read, FSKIT_CONCURRENT );
   if( rh < 0 ) {
      
      vdev_error("fskit_route_read(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
      goto vdev_route_fail;
   }
   
   rh = fskit_route_write( core, FSKIT_ROUTE_ANY, vdevfs_write, FSKIT_CONCURRENT );
   if( rh < 0 ) {
      
      vdev_error("fskit_route_write(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
      goto vdev_route_fail;
   }
   
   rh = fskit_route_close( core, FSKIT_ROUTE_ANY, vdevfs_close, FSKIT_CONCURRENT );
   if( rh < 0 ) {
      
      vdev_error("fskit_route_close(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
      goto vdev_route_fail;
   }
   
   rh = fskit_route_sync( core, FSKIT_ROUTE_ANY, vdevfs_sync, FSKIT_CONCURRENT );
   if( rh < 0 ) {
      
      vdev_error("fskit_route_sync(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
      goto vdev_route_fail;
   }
   
   rh = fskit_route_detach( core, FSKIT_ROUTE_ANY, vdevfs_detach, FSKIT_CONCURRENT );
   if( rh < 0 ) {
      
      vdev_error("fskit_route_detach(%s) rc = %d\n", FSKIT_ROUTE_ANY, rh );
      goto vdev_route_fail;
   }
   
   vdev->fs = fs;
   vdev->close_rh = rh;
   
   // set the root to be owned by the effective UID and GID of user
   fskit_chown( core, "/", 0, 0, geteuid(), getegid() );
   
   // import the underlying filesystem once we're mounted, but before taking requests.
   rc = fskit_fuse_postmount_callback( fs, vdevfs_dev_import, vdev );
   if( rc != 0 ) {
      
      vdev_error("fskit_fuse_postmount_callback() rc = %d\n", rc );
      
      vdev->fs = NULL;
      goto vdev_route_fail;
   }
   
   return 0;

vdev_route_fail:

   fskit_fuse_shutdown( fs, NULL );
   free( fs );
   vdevfs_shutdown( vdev );
   return rh;
}