File: sqlfs.rb

package info (click to toggle)
ruby-fusefs 0.7.0-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 296 kB
  • sloc: ansic: 1,137; ruby: 760; sh: 8; makefile: 2
file content (134 lines) | stat: -rw-r--r-- 3,486 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# sqlfs.rb
#
# The SQL-db proof of concept for FuseFS
#
# Author: Greg Millam

require "rubygems"
require 'fusefs'

require 'mysql'

class SqlFS < FuseFS::FuseDir
  class DBTable
    attr_accessor :name, :key, :fields
  end
  def initialize(host,user,pass,db)
    @sql = Mysql.connect(host,user,pass,db)
    @tables = Hash.new(nil)

    tables = @sql.query('show tables')

    tables.each do |i,|
      table = DBTable.new
      table.name = i
      table.fields = {}
      res = @sql.query("describe #{i}")
      res.each do |field,type,null,key,default,extra|
        table.fields[field] = type
        if (key =~ /pri/i)
          table.key = field
        end
      end
      @tables[i] = table if table.key
    end
  end
  def directory?(path)
    tname, key, field = scan_path(path)
    table = @tables[tname]
    case
    when tname.nil?
      true # This means "/"
    when table.nil?
      false
    when field
      false # Always a file
    when key
      res = @sql.query("SELECT #{table.key}, 1 FROM #{table.name} WHERE #{table.key} = '#{Mysql.escape_string(key)}'")
      res.num_rows > 0 # If there was a result, it exists.
    else
      true # It's just a table.
    end
  end
  def file?(path)
    tname, key, field = scan_path(path)
    table = @tables[tname]
    case
    when field.nil?
      false # Only field entries are files.
    when table.nil?
      false
    when ! @tables[tname].fields.include?(field)
      false # Invalid field.
    when field
      res = @sql.query("SELECT #{table.key}, 1 FROM #{table.name} WHERE #{table.key} = '#{Mysql.escape_string(key)}'")
      res.num_rows > 0
    end
  end
  def can_delete?(path)
    # This helps editors, but we don't really use it.
    true
  end
  def can_write?(path)
    # Since this is basically only for editing files,
    # we just call file?
    file?(path)
  end
  def contents(path)
    # since this is only called when directory? is true,
    # We'll assume valid entries.
    tname, key, field = scan_path(path)
    table = @tables[tname]
    case
    when tname.nil?
      @tables.keys.sort # Just the tables.
    when key
      table.fields.keys.sort
    else
      # I limit to 200 so 'ls' doesn't hang all the time :D
      res = @sql.query("SELECT #{table.key}, 1 FROM #{table.name} ORDER BY #{table.key} LIMIT 100")
      ret = []
      res.each do |val,one|
        ret << val if val.size > 0
      end
      ret
    end
  end
  def write_to(path,body)
    # Since this is only called after can_write?(), we assume
    # Valid fields.
    tname, key, field = scan_path(path)
    table = @tables[tname]
    res = @sql.query("UPDATE #{table.name} SET #{field} = '#{Mysql.escape_string(body)}' WHERE #{table.key} = '#{key}'")
  end
  def read_file(path)
    # Again, as this is only called after file?, assume valid fields.
    tname, key, field = scan_path(path)
    table = @tables[tname]
    res = @sql.query("SELECT #{field} FROM #{table.name} WHERE #{table.key} = '#{key}'")
    res.fetch_row[0]
  end
end

if (File.basename($0) == File.basename(__FILE__))
  if ARGV.size != 5
    puts "Usage: #{$0} <directory> <host> <user> <pass> <db>"
    exit
  end

  dirname, host, user, pass, db = ARGV

  if (! File.directory?(dirname))
    puts "#{dirname} is not a directory"
  end

  root = SqlFS.new(host,user,pass,db)

  # Set the root FuseFS
  FuseFS.set_root(root)

  # root.contents("/quotes")

  FuseFS.mount_under(dirname)
  FuseFS.run # This doesn't return until we're unmounted.
end