rfusefs 1.0.3 → 1.1.0.rc202009.34
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.yardopts +2 -0
- data/CHANGES.md +40 -0
- data/LICENSE +24 -0
- data/README.md +83 -0
- data/TODO.md +7 -0
- metadata +17 -41
- data/.gitignore +0 -9
- data/Gemfile +0 -6
- data/History.rdoc +0 -34
- data/README.rdoc +0 -106
- data/Rakefile +0 -22
- data/TODO.txt +0 -6
- data/lib/fuse/fusedir.rb +0 -328
- data/lib/fuse/rfusefs-fuse.rb +0 -540
- data/lib/fusefs/dirlink.rb +0 -46
- data/lib/fusefs/metadir.rb +0 -287
- data/lib/fusefs/pathmapper.rb +0 -442
- data/lib/fusefs/sqlitemapper.rb +0 -120
- data/lib/rfusefs/version.rb +0 -3
- data/rfusefs.gemspec +0 -31
- data/samples/demo.rb +0 -57
- data/samples/dictfs.rb +0 -74
- data/samples/hello.rb +0 -20
- data/samples/openurifs.rb +0 -53
- data/samples/railsfs.rb +0 -77
- data/samples/sqlfs.rb +0 -134
- data/samples/yamlfs.rb +0 -168
- data/spec-fusefs/fusefs_spec.rb +0 -12
- data/spec/metadir_spec.rb +0 -369
- data/spec/mount_unmount_spec.rb +0 -21
- data/spec/pathmapper_spec.rb +0 -417
- data/spec/rfusefs_spec.rb +0 -505
- data/spec/sample_spec.rb +0 -33
- data/spec/spec_helper.rb +0 -42
- data/spec/sqlitemapper_spec.rb +0 -135
data/lib/fusefs/sqlitemapper.rb
DELETED
@@ -1,120 +0,0 @@
|
|
1
|
-
require 'fusefs/pathmapper'
|
2
|
-
require 'sqlite3'
|
3
|
-
require 'thread'
|
4
|
-
|
5
|
-
module FuseFS
|
6
|
-
|
7
|
-
class SqliteMapperFS < PathMapperFS
|
8
|
-
|
9
|
-
# The database file
|
10
|
-
attr_reader :db_path
|
11
|
-
|
12
|
-
# The database connection
|
13
|
-
attr_reader :db
|
14
|
-
|
15
|
-
# Maintains a count of the number of times through the scan loop
|
16
|
-
attr_reader :scan_id
|
17
|
-
|
18
|
-
#
|
19
|
-
#
|
20
|
-
# @param [String] db_path Path to Sqlite database
|
21
|
-
# @param [String] sql query
|
22
|
-
# @param [Hash] options see {PathMapperFS#initialize}
|
23
|
-
# @yieldparam [Row] row to map
|
24
|
-
# @yieldreturn [String,String,Hash<Symbol,Object>] newpath, realpath, options
|
25
|
-
# * newpath - the mapped path
|
26
|
-
# * realpath - path to the real file
|
27
|
-
# * options - additional information to store with this path
|
28
|
-
def initialize(db_path,sql,options = { },&row_mapper)
|
29
|
-
@db_path = db_path.to_s
|
30
|
-
@sql = sql.to_s
|
31
|
-
define_singleton_method(:map_row,row_mapper) if block_given?
|
32
|
-
super(options)
|
33
|
-
end
|
34
|
-
|
35
|
-
# Maps a row into a new filepath
|
36
|
-
#
|
37
|
-
# @param [Hash] row sqlite result hash for a row
|
38
|
-
# @return [String,String,Hash<Symbol,Object>] newpath, realpath, options
|
39
|
-
# * newpath - the mapped path
|
40
|
-
# * realpath - path to the real file
|
41
|
-
# * options - additional information to store with this path
|
42
|
-
# @abstract
|
43
|
-
def map_row(row)
|
44
|
-
raise NotImplementedError, "abstract method #{__method__} not implemented"
|
45
|
-
end
|
46
|
-
|
47
|
-
# FuseFS callback when the filesystem is mounted
|
48
|
-
# Starts the scanning loop and performs the initial scan
|
49
|
-
# @api FuseFS
|
50
|
-
def mounted()
|
51
|
-
@mounted = true
|
52
|
-
@mutex = Mutex.new
|
53
|
-
@cv = ConditionVariable.new
|
54
|
-
@scan_thread = Thread.new() { scan_loop() }
|
55
|
-
end
|
56
|
-
|
57
|
-
# FuseFS callback when filesystem is unmounted
|
58
|
-
#
|
59
|
-
# Stops the database watching threads
|
60
|
-
# @api FuseFS
|
61
|
-
def unmounted()
|
62
|
-
@mounted = false
|
63
|
-
@mutex.synchronize { @cv.signal() }
|
64
|
-
@scan_thread.join
|
65
|
-
end
|
66
|
-
|
67
|
-
|
68
|
-
# Trigger a rescan of the database
|
69
|
-
def rescan()
|
70
|
-
@mutex.synchronize { @cv.signal() }
|
71
|
-
end
|
72
|
-
|
73
|
-
# Executes the sql query and passes each row to map_row (or the block passed in {#initialize})
|
74
|
-
#
|
75
|
-
# Subclasses can override this method for pre/post scan processing, calling super as required
|
76
|
-
def scan()
|
77
|
-
db.execute(@sql) do |row|
|
78
|
-
new_path, real_path, options = map_row(row)
|
79
|
-
options ||= {}
|
80
|
-
options[:sqlite_scan_id] = @scan_id
|
81
|
-
begin
|
82
|
-
map_file(new_path, real_path, options)
|
83
|
-
rescue StandardError => e
|
84
|
-
puts e
|
85
|
-
puts e.backtrace.join("\n")
|
86
|
-
end
|
87
|
-
end
|
88
|
-
cleanup() { |file_node| file_node.options[:sqlite_scan_id] != @scan_id }
|
89
|
-
end
|
90
|
-
|
91
|
-
# Rescan on HUP signal
|
92
|
-
def sighup
|
93
|
-
rescan()
|
94
|
-
end
|
95
|
-
|
96
|
-
private
|
97
|
-
|
98
|
-
def scan_loop()
|
99
|
-
@mutex.synchronize() do
|
100
|
-
@scan_id = 0
|
101
|
-
while @mounted
|
102
|
-
begin
|
103
|
-
@db = SQLite3::Database.new(@db_path,:readonly => true)
|
104
|
-
@db.results_as_hash = true
|
105
|
-
@db.busy_timeout(10000)
|
106
|
-
@scan_id = @scan_id + 1
|
107
|
-
scan()
|
108
|
-
rescue StandardError => e
|
109
|
-
puts e
|
110
|
-
puts e.backtrace.join("\n")
|
111
|
-
ensure
|
112
|
-
@db.close unless @db.closed?
|
113
|
-
@db = nil
|
114
|
-
end
|
115
|
-
@cv.wait(@mutex)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
data/lib/rfusefs/version.rb
DELETED
data/rfusefs.gemspec
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "rfusefs/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |s|
|
6
|
-
s.name = "rfusefs"
|
7
|
-
s.version = RFuseFS::VERSION
|
8
|
-
s.platform = Gem::Platform::RUBY
|
9
|
-
s.authors = ["Grant Gardner"]
|
10
|
-
s.email = ["grant@lastweekend.com.au"]
|
11
|
-
s.homepage = "http://rubygems.org/gems/rfusefs"
|
12
|
-
s.summary = %q{Filesystem in Ruby Userspace}
|
13
|
-
s.description = %q{A more Ruby like way to write FUSE filesystems - inspired by (compatible with) FuseFS, implemented over RFuse}
|
14
|
-
|
15
|
-
s.files = `git ls-files`.split("\n")
|
16
|
-
s.test_files = `git ls-files -- {test,spec,spec-fusefs}/*`.split("\n")
|
17
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
-
s.require_paths = ["lib"]
|
19
|
-
|
20
|
-
s.has_rdoc = 'yard'
|
21
|
-
s_extra_rdoc_files = 'History.rdoc'
|
22
|
-
|
23
|
-
s.add_dependency("rfuse", "~> 1.1")
|
24
|
-
s.add_development_dependency("rake")
|
25
|
-
s.add_development_dependency("rspec","~> 3")
|
26
|
-
s.add_development_dependency("yard")
|
27
|
-
s.add_development_dependency("redcarpet")
|
28
|
-
s.add_development_dependency("sqlite3")
|
29
|
-
s.add_development_dependency("sys-filesystem")
|
30
|
-
s.add_development_dependency("ffi-xattr", ">= 0.1.1")
|
31
|
-
end
|
data/samples/demo.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require "rubygems"
|
2
|
-
require 'rfusefs'
|
3
|
-
require 'fusefs/metadir'
|
4
|
-
require 'fusefs/dirlink'
|
5
|
-
|
6
|
-
include FuseFS
|
7
|
-
|
8
|
-
root = MetaDir.new
|
9
|
-
root.stats.max_space = 1024*1024
|
10
|
-
root.stats.max_nodes = 1024
|
11
|
-
root.stats.strict = true
|
12
|
-
|
13
|
-
class Counter
|
14
|
-
def initialize
|
15
|
-
@counter = 0
|
16
|
-
end
|
17
|
-
def to_s
|
18
|
-
@counter += 1
|
19
|
-
@counter.to_s + "\n"
|
20
|
-
end
|
21
|
-
def size
|
22
|
-
@counter.to_s.size
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class Randwords
|
27
|
-
def initialize(*ary)
|
28
|
-
@ary = ary.flatten
|
29
|
-
end
|
30
|
-
def to_s
|
31
|
-
@ary[rand(@ary.size)].to_s + "\n"
|
32
|
-
end
|
33
|
-
def size
|
34
|
-
@size ||= @ary.map{|v| v.size}.max
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
root.write_to('/hello',"Hello, World!\n")
|
39
|
-
|
40
|
-
progress = '.'
|
41
|
-
|
42
|
-
root.write_to('/progress',progress)
|
43
|
-
|
44
|
-
Thread.new do
|
45
|
-
20.times do
|
46
|
-
sleep 5
|
47
|
-
progress << '.'
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
root.write_to('/counter',Counter.new)
|
52
|
-
root.write_to('/color',Randwords.new('red','blue','green','purple','yellow','bistre','burnt sienna','jade'))
|
53
|
-
root.write_to('/animal',Randwords.new('duck','dog','cat','duck billed platypus','silly fella'))
|
54
|
-
|
55
|
-
root.mkdir("/#{ENV['USER']}",FuseFS::DirLink.new(ENV['HOME']))
|
56
|
-
|
57
|
-
FuseFS.main(ARGV) { | options | root }
|
data/samples/dictfs.rb
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
# dictfs.rb
|
2
|
-
|
3
|
-
require "rubygems"
|
4
|
-
require 'fusefs'
|
5
|
-
include FuseFS
|
6
|
-
|
7
|
-
#TODO: GG Don't know which "dict" this was referring to
|
8
|
-
require 'dict'
|
9
|
-
|
10
|
-
class DictFS < FuseFS::FuseDir
|
11
|
-
def initialize
|
12
|
-
@servers = ['dict.org','alt0.dict.org']
|
13
|
-
@database = DICT::ALL_DATABASES
|
14
|
-
@strategy = 'exact'
|
15
|
-
@match_strategy = DICT::DEFAULT_MATCH_STRATEGY
|
16
|
-
@port = DICT::DEFAULT_PORT
|
17
|
-
|
18
|
-
@dict = DICT.new(@servers, @port, false, false)
|
19
|
-
@dict.client("%s v%s" % ["Dictionary","1.0"])
|
20
|
-
end
|
21
|
-
def contents(path)
|
22
|
-
# The 'readme' file
|
23
|
-
['readme']
|
24
|
-
end
|
25
|
-
def file?(path)
|
26
|
-
base, rest = split_path(path)
|
27
|
-
rest.nil? # DictFS doesn't have subdirs.
|
28
|
-
end
|
29
|
-
def read_file(path)
|
30
|
-
word, rest = split_path(path)
|
31
|
-
word.downcase!
|
32
|
-
if word == "readme"
|
33
|
-
return %Q[
|
34
|
-
DictFS: You may not see the files, but if you cat any file here, it will look
|
35
|
-
that file up on dict.org!
|
36
|
-
].lstrip
|
37
|
-
end
|
38
|
-
puts "Looking up #{word}"
|
39
|
-
m = @dict.match(@database, @strategy, word)
|
40
|
-
if m
|
41
|
-
contents = []
|
42
|
-
m.each do |db,words|
|
43
|
-
words.each do |w|
|
44
|
-
defs = @dict.define(db,w)
|
45
|
-
str = []
|
46
|
-
defs.each do |d|
|
47
|
-
str << "Definition of '#{w}' (by #{d.description})"
|
48
|
-
d.definition.each do |line|
|
49
|
-
str << " #{line.strip}"
|
50
|
-
end
|
51
|
-
contents << str.join("\n")
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
contents << ''
|
56
|
-
contents.join("\n")
|
57
|
-
else
|
58
|
-
"No dictionary definitions found\n"
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
if (File.basename($0) == File.basename(__FILE__))
|
64
|
-
unless (ARGV.length > 0 && File.directory?(ARGV[0]))
|
65
|
-
puts "Usage: #{$0} <mountpoint> <mount_options>"
|
66
|
-
exit
|
67
|
-
end
|
68
|
-
|
69
|
-
root = DictFS.new
|
70
|
-
|
71
|
-
# Set the root FuseFS
|
72
|
-
FuseFS.start(root,*ARGV)
|
73
|
-
|
74
|
-
end
|
data/samples/hello.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
class HelloDir
|
2
|
-
def contents(path)
|
3
|
-
['hello.txt']
|
4
|
-
end
|
5
|
-
|
6
|
-
def file?(path)
|
7
|
-
path == '/hello.txt'
|
8
|
-
end
|
9
|
-
|
10
|
-
def read_file(path)
|
11
|
-
"Hello, World!\n"
|
12
|
-
end
|
13
|
-
|
14
|
-
end
|
15
|
-
|
16
|
-
if __FILE__ == $0
|
17
|
-
require 'rfusefs'
|
18
|
-
hellodir = HelloDir.new
|
19
|
-
FuseFS.start(hellodir,*ARGV)
|
20
|
-
end
|
data/samples/openurifs.rb
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
# openurifs.rb
|
2
|
-
#
|
3
|
-
|
4
|
-
require "rubygems"
|
5
|
-
require 'fusefs'
|
6
|
-
include FuseFS
|
7
|
-
|
8
|
-
require 'open-uri'
|
9
|
-
|
10
|
-
class OpenUriFS < FuseFS::FuseDir
|
11
|
-
def contents(path)
|
12
|
-
# The 'readme' file
|
13
|
-
[]
|
14
|
-
end
|
15
|
-
def directory?(path)
|
16
|
-
uri = scan_path(path)
|
17
|
-
fn = uri.pop
|
18
|
-
return true if fn =~ /\.(com|org|net|us|de|jp|ru|uk|biz|info)$/
|
19
|
-
return true if fn =~ /^\d+\.\d+\.\d+\.\d+$/
|
20
|
-
! (fn =~ /\./) # Does the last item doesn't contain a '.' ?
|
21
|
-
end
|
22
|
-
def file?(path)
|
23
|
-
!directory?(path)
|
24
|
-
end
|
25
|
-
def read_file(path)
|
26
|
-
proto, rest = split_path(path)
|
27
|
-
uri = "#{proto}://#{rest}"
|
28
|
-
open(uri).read
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
if (File.basename($0) == File.basename(__FILE__))
|
33
|
-
if (ARGV.size != 1)
|
34
|
-
puts "Usage: #{$0} <directory>"
|
35
|
-
exit
|
36
|
-
end
|
37
|
-
|
38
|
-
dirname = ARGV.shift
|
39
|
-
|
40
|
-
unless File.directory?(dirname)
|
41
|
-
puts "Usage: #{dirname} is not a directory."
|
42
|
-
exit
|
43
|
-
end
|
44
|
-
|
45
|
-
root = OpenUriFS.new
|
46
|
-
|
47
|
-
# Set the root FuseFS
|
48
|
-
FuseFS.set_root(root)
|
49
|
-
|
50
|
-
FuseFS.mount_under(dirname)
|
51
|
-
|
52
|
-
FuseFS.run # This doesn't return until we're unmounted.
|
53
|
-
end
|
data/samples/railsfs.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# RailsFS, as written by _why_the_lucky_stiff
|
4
|
-
#
|
5
|
-
# Full instructions:
|
6
|
-
# http://redhanded.hobix.com/inspect/railsfsAfterACoupleMinutesOfToolingWithFuseWhoa.html
|
7
|
-
#
|
8
|
-
=begin
|
9
|
-
Instructions cut and paste from _why's blog:
|
10
|
-
|
11
|
-
Save the railfs.rb script as script/filesys in your Rails app. (If you'd
|
12
|
-
rather not cut-and-paste the above, it's here.)
|
13
|
-
|
14
|
-
Now, run mkdir ~/railsmnt. Then, script/filesys ~/railsmnt. The rules are as
|
15
|
-
follows:
|
16
|
-
|
17
|
-
* ls ~/railsmnt will give you a list of tables.
|
18
|
-
* ls ~/railsmnt/table will list IDs from the table.
|
19
|
-
* cat ~/railsmnt/table/id will display a record in YAML.
|
20
|
-
* vim ~/railsmnt/table/id to edit the record in YAML!
|
21
|
-
|
22
|
-
=end
|
23
|
-
|
24
|
-
require "rubygems"
|
25
|
-
require 'fusefs'
|
26
|
-
require File.dirname(__FILE__) + '/../config/environment'
|
27
|
-
|
28
|
-
class RailsFS < FuseFS::FuseDir
|
29
|
-
def initialize
|
30
|
-
@classes = {}
|
31
|
-
require 'find'
|
32
|
-
Find.find( File.join(RAILS_ROOT, 'app/models') ) do |model|
|
33
|
-
if /(\w+)\.rb$/ =~ model
|
34
|
-
model = $1
|
35
|
-
( @classes[model] = Kernel::const_get( Inflector.classify( model ) ) ).
|
36
|
-
find :first rescue @classes.delete( model )
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
def directory? path
|
41
|
-
tname, key = scan_path path
|
42
|
-
table = @classes[tname]
|
43
|
-
if table.nil?; false # /table
|
44
|
-
elsif key; false # /table/id
|
45
|
-
else; true end
|
46
|
-
end
|
47
|
-
def file? path
|
48
|
-
tname, key = scan_path path
|
49
|
-
table = @classes[tname]
|
50
|
-
key and table and table.find( key )
|
51
|
-
end
|
52
|
-
def can_delete?; true end
|
53
|
-
def can_write? path; file? path end
|
54
|
-
def contents path
|
55
|
-
tname, key = scan_path path
|
56
|
-
table = @classes[tname]
|
57
|
-
if tname.nil?; @classes.keys.sort # /
|
58
|
-
else; table.find( :all ).map { |o| o.id.to_s } end # /table
|
59
|
-
end
|
60
|
-
def write_to path, body
|
61
|
-
obj = YAML::load( body )
|
62
|
-
obj.save
|
63
|
-
end
|
64
|
-
def read_file path
|
65
|
-
tname, key = scan_path path
|
66
|
-
table = @classes[tname]
|
67
|
-
YAML::dump( table.find( key ) )
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
if (File.basename($0) == File.basename(__FILE__))
|
72
|
-
root = RailsFS.new
|
73
|
-
FuseFS.set_root(root)
|
74
|
-
FuseFS.mount_under(ARGV[0])
|
75
|
-
FuseFS.run # This doesn't return until we're unmounted.
|
76
|
-
end
|
77
|
-
|
data/samples/sqlfs.rb
DELETED
@@ -1,134 +0,0 @@
|
|
1
|
-
# sqlfs.rb
|
2
|
-
#
|
3
|
-
# The SQL-db proof of concept for FuseFS
|
4
|
-
#
|
5
|
-
# Author: Greg Millam
|
6
|
-
|
7
|
-
require "rubygems"
|
8
|
-
require 'fusefs'
|
9
|
-
|
10
|
-
require 'mysql'
|
11
|
-
|
12
|
-
class SqlFS < FuseFS::FuseDir
|
13
|
-
class DBTable
|
14
|
-
attr_accessor :name, :key, :fields
|
15
|
-
end
|
16
|
-
def initialize(host,user,pass,db)
|
17
|
-
@sql = Mysql.connect(host,user,pass,db)
|
18
|
-
@tables = Hash.new(nil)
|
19
|
-
|
20
|
-
tables = @sql.query('show tables')
|
21
|
-
|
22
|
-
tables.each do |i,|
|
23
|
-
table = DBTable.new
|
24
|
-
table.name = i
|
25
|
-
table.fields = {}
|
26
|
-
res = @sql.query("describe #{i}")
|
27
|
-
res.each do |field,type,null,key,default,extra|
|
28
|
-
table.fields[field] = type
|
29
|
-
if (key =~ /pri/i)
|
30
|
-
table.key = field
|
31
|
-
end
|
32
|
-
end
|
33
|
-
@tables[i] = table if table.key
|
34
|
-
end
|
35
|
-
end
|
36
|
-
def directory?(path)
|
37
|
-
tname, key, field = scan_path(path)
|
38
|
-
table = @tables[tname]
|
39
|
-
case
|
40
|
-
when tname.nil?
|
41
|
-
true # This means "/"
|
42
|
-
when table.nil?
|
43
|
-
false
|
44
|
-
when field
|
45
|
-
false # Always a file
|
46
|
-
when key
|
47
|
-
res = @sql.query("SELECT #{table.key}, 1 FROM #{table.name} WHERE #{table.key} = '#{Mysql.escape_string(key)}'")
|
48
|
-
res.num_rows > 0 # If there was a result, it exists.
|
49
|
-
else
|
50
|
-
true # It's just a table.
|
51
|
-
end
|
52
|
-
end
|
53
|
-
def file?(path)
|
54
|
-
tname, key, field = scan_path(path)
|
55
|
-
table = @tables[tname]
|
56
|
-
case
|
57
|
-
when field.nil?
|
58
|
-
false # Only field entries are files.
|
59
|
-
when table.nil?
|
60
|
-
false
|
61
|
-
when ! @tables[tname].fields.include?(field)
|
62
|
-
false # Invalid field.
|
63
|
-
when field
|
64
|
-
res = @sql.query("SELECT #{table.key}, 1 FROM #{table.name} WHERE #{table.key} = '#{Mysql.escape_string(key)}'")
|
65
|
-
res.num_rows > 0
|
66
|
-
end
|
67
|
-
end
|
68
|
-
def can_delete?(path)
|
69
|
-
# This helps editors, but we don't really use it.
|
70
|
-
true
|
71
|
-
end
|
72
|
-
def can_write?(path)
|
73
|
-
# Since this is basically only for editing files,
|
74
|
-
# we just call file?
|
75
|
-
file?(path)
|
76
|
-
end
|
77
|
-
def contents(path)
|
78
|
-
# since this is only called when directory? is true,
|
79
|
-
# We'll assume valid entries.
|
80
|
-
tname, key, field = scan_path(path)
|
81
|
-
table = @tables[tname]
|
82
|
-
case
|
83
|
-
when tname.nil?
|
84
|
-
@tables.keys.sort # Just the tables.
|
85
|
-
when key
|
86
|
-
table.fields.keys.sort
|
87
|
-
else
|
88
|
-
# I limit to 200 so 'ls' doesn't hang all the time :D
|
89
|
-
res = @sql.query("SELECT #{table.key}, 1 FROM #{table.name} ORDER BY #{table.key} LIMIT 100")
|
90
|
-
ret = []
|
91
|
-
res.each do |val,one|
|
92
|
-
ret << val if val.size > 0
|
93
|
-
end
|
94
|
-
ret
|
95
|
-
end
|
96
|
-
end
|
97
|
-
def write_to(path,body)
|
98
|
-
# Since this is only called after can_write?(), we assume
|
99
|
-
# Valid fields.
|
100
|
-
tname, key, field = scan_path(path)
|
101
|
-
table = @tables[tname]
|
102
|
-
res = @sql.query("UPDATE #{table.name} SET #{field} = '#{Mysql.escape_string(body)}' WHERE #{table.key} = '#{key}'")
|
103
|
-
end
|
104
|
-
def read_file(path)
|
105
|
-
# Again, as this is only called after file?, assume valid fields.
|
106
|
-
tname, key, field = scan_path(path)
|
107
|
-
table = @tables[tname]
|
108
|
-
res = @sql.query("SELECT #{field} FROM #{table.name} WHERE #{table.key} = '#{key}'")
|
109
|
-
res.fetch_row[0]
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
if (File.basename($0) == File.basename(__FILE__))
|
114
|
-
if ARGV.size != 5
|
115
|
-
puts "Usage: #{$0} <directory> <host> <user> <pass> <db>"
|
116
|
-
exit
|
117
|
-
end
|
118
|
-
|
119
|
-
dirname, host, user, pass, db = ARGV
|
120
|
-
|
121
|
-
if (! File.directory?(dirname))
|
122
|
-
puts "#{dirname} is not a directory"
|
123
|
-
end
|
124
|
-
|
125
|
-
root = SqlFS.new(host,user,pass,db)
|
126
|
-
|
127
|
-
# Set the root FuseFS
|
128
|
-
FuseFS.set_root(root)
|
129
|
-
|
130
|
-
# root.contents("/quotes")
|
131
|
-
|
132
|
-
FuseFS.mount_under(dirname)
|
133
|
-
FuseFS.run # This doesn't return until we're unmounted.
|
134
|
-
end
|