rfusefs 1.0.2.RC1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +2 -0
- data/CHANGES.md +40 -0
- data/LICENSE +24 -0
- data/README.md +83 -0
- data/TODO.md +7 -0
- data/lib/rfusefs.rb +20 -48
- metadata +38 -81
- data/.gitignore +0 -9
- data/.travis.yml +0 -8
- data/Gemfile +0 -4
- data/History.rdoc +0 -28
- data/README.rdoc +0 -106
- data/Rakefile +0 -22
- data/TODO.txt +0 -6
- data/lib/fuse/fusedir.rb +0 -313
- data/lib/fuse/rfusefs-fuse.rb +0 -506
- data/lib/fusefs/dirlink.rb +0 -46
- data/lib/fusefs/metadir.rb +0 -287
- data/lib/fusefs/pathmapper.rb +0 -436
- data/lib/fusefs/sqlitemapper.rb +0 -115
- 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 -364
- data/spec/mount_unmount_spec.rb +0 -21
- data/spec/pathmapper_spec.rb +0 -417
- data/spec/rfusefs_spec.rb +0 -477
- data/spec/sample_spec.rb +0 -30
- data/spec/spec_helper.rb +0 -42
- data/spec/sqlitemapper_spec.rb +0 -135
data/lib/fusefs/sqlitemapper.rb
DELETED
@@ -1,115 +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
|
-
private
|
92
|
-
|
93
|
-
def scan_loop()
|
94
|
-
@mutex.synchronize() do
|
95
|
-
@scan_id = 0
|
96
|
-
while @mounted
|
97
|
-
begin
|
98
|
-
@db = SQLite3::Database.new(@db_path,:readonly => true)
|
99
|
-
@db.results_as_hash = true
|
100
|
-
@db.busy_timeout(10000)
|
101
|
-
@scan_id = @scan_id + 1
|
102
|
-
scan()
|
103
|
-
rescue StandardError => e
|
104
|
-
puts e
|
105
|
-
puts e.backtrace.join("\n")
|
106
|
-
ensure
|
107
|
-
@db.close unless @db.closed?
|
108
|
-
@db = nil
|
109
|
-
end
|
110
|
-
@cv.wait(@mutex)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
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.0.5RC0")
|
24
|
-
s.add_development_dependency("rake")
|
25
|
-
s.add_development_dependency("rspec")
|
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.total_space = 1024*1024
|
10
|
-
root.stats.total_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
|