feat: add support for sshfs

This commit is contained in:
Glenn Y. Rolland 2023-10-24 15:53:28 +02:00
parent 002db7026b
commit 67cd9ae964
6 changed files with 117 additions and 30 deletions

View file

@ -67,7 +67,7 @@ module GX
def run()
@config.load_from_file
names_display = {} of String => NamedTuple(filesystem: GoCryptFS, ansi_name: String)
names_display = {} of String => NamedTuple(filesystem: Filesystem, ansi_name: String)
@config.filesystems.each do |filesystem|
result_name = filesystem.mounted? ? "#{filesystem.name} [open]" : filesystem.name
ansi_name = filesystem.mounted? ? "#{filesystem.name} [#{ "open".colorize(:green) }]" : filesystem.name

View file

@ -1,5 +1,5 @@
require "./filesystems/gocryptfs"
require "./filesystems"
module GX
class Config
@ -13,7 +13,7 @@ module GX
record AddArgs, name : String, path : String
record DelArgs, name : String
getter filesystems : Array(GoCryptFS)
getter filesystems : Array(Filesystem)
getter home_dir : String
property mode : Mode
property path : String
@ -28,30 +28,31 @@ module GX
@home_dir = ENV["HOME"]
@mode = Mode::Run
@filesystems = [] of GoCryptFS
@filesystems = [] of Filesystem
@path = File.join(@home_dir, ".config", DEFAULT_CONFIG_PATH)
@args = NoArgs
end
def load_from_file
@filesystems = [] of GoCryptFS
@filesystems = [] of Filesystem
if !File.exists? @path
STDERR.puts "Error: file #{@path} does not exist!".colorize(:red)
exit(1)
end
load_vaults(@path)
load_filesystems(@path)
end
private def load_vaults(config_path : String)
private def load_filesystems(config_path : String)
yaml_data = YAML.parse(File.read(config_path))
vaults_data = yaml_data["filesystems"].as_a
vaults_data.each do |vault_data|
type = vault_data["type"].as_s
name = vault_data["name"].as_s
encrypted_path = vault_data["encrypted_path"].as_s
@filesystems << GoCryptFS.new(name, encrypted_path, "#{name}.Open")
vaults_data.each do |filesystem_data|
type = filesystem_data["type"].as_s
name = filesystem_data["name"].as_s
# encrypted_path = filesystem_data["encrypted_path"].as_s
@filesystems << Filesystem.from_yaml(filesystem_data.to_yaml)
# @filesystems << Filesystem.new(name, encrypted_path, "#{name}.Open")
end
end
end

3
src/filesystems.cr Normal file
View file

@ -0,0 +1,3 @@
require "./filesystems/gocryptfs"
require "./filesystems/filesystem"

View file

@ -0,0 +1,38 @@
require "yaml"
module GX
abstract class Filesystem
include YAML::Serializable
use_yaml_discriminator "type", {
gocryptfs: GoCryptFS,
sshfs: SshFS
}
property type : String
end
module GenericFilesystem
def unmount
system("fusermount -u #{mount_dir.shellescape}")
puts "Filesystem #{name} is now closed.".colorize(:green)
end
def mount(&block)
Dir.mkdir_p(mount_dir) unless Dir.exists?(mount_dir)
if mounted?
puts "Already mounted. Skipping.".colorize(:yellow)
return
end
yield
puts "Filesystem #{name} is now available on #{mount_dir}".colorize(:green)
end
end
end
require "./gocryptfs"
require "./sshfs"

View file

@ -1,14 +1,19 @@
require "shellwords"
require "./filesystem"
module GX
class GoCryptFS
getter name : String
getter encrypted_path : String
getter mount_dir : String
class GoCryptFS < Filesystem
getter name : String = ""
getter encrypted_path : String = ""
def initialize(@name, @encrypted_path, mount_name : String)
@[YAML::Field(key: "mount_dir", ignore: true)]
getter mount_dir : String = ""
include GenericFilesystem
def after_initialize()
home_dir = ENV["HOME"] || raise "Home directory not found"
@mount_dir = File.join(home_dir, "mnt/#{mount_name}")
@mount_dir = File.join(home_dir, "mnt/#{@name}")
end
def mounted? : Bool
@ -16,26 +21,22 @@ module GX
end
def mount
Dir.mkdir_p(mount_dir) unless Dir.exists?(mount_dir)
if mounted?
puts "Already mounted. Skipping.".colorize(:yellow)
else
super do
input = STDIN
output = STDOUT
error = STDERR
process = Process.new("gocryptfs", ["-idle", "15m", encrypted_path, mount_dir], input: input, output: output, error: error)
process = Process.new(
"gocryptfs",
["-idle", "15m", encrypted_path, mount_dir],
input: input,
output: output,
error: error
)
unless process.wait.success?
puts "Error mounting the vault".colorize(:red)
return
end
puts "GoCryptFS #{name} is now available on #{mount_dir}".colorize(:green)
end
end
def unmount
system("fusermount -u #{mount_dir.shellescape}")
puts "GoCryptFS #{name} is now closed.".colorize(:green)
end
end
end

44
src/filesystems/sshfs.cr Normal file
View file

@ -0,0 +1,44 @@
require "shellwords"
require "./filesystem"
module GX
class SshFS < Filesystem
getter name : String = ""
getter remote_path : String = ""
getter remote_user : String = ""
getter remote_host : String = ""
@[YAML::Field(key: "mount_dir", ignore: true)]
getter mount_dir : String = ""
include GenericFilesystem
def after_initialize()
home_dir = ENV["HOME"] || raise "Home directory not found"
@mount_dir = File.join(home_dir, "mnt/#{@name}")
end
def mounted? : Bool
`mount`.includes?("#{remote_user}@#{remote_host}:#{remote_path} on #{mount_dir}")
end
def mount
super do
input = STDIN
output = STDOUT
error = STDERR
process = Process.new(
"sshfs",
["#{remote_user}@#{remote_host}:#{remote_path}", mount_dir],
input: input,
output: output,
error: error
)
unless process.wait.success?
puts "Error mounting the filesystem".colorize(:red)
return
end
end
end
end
end