rfuse_symbolic_fs 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/rfuse_symbolic_fs +15 -0
- data/lib/amaras_fs.rb +144 -0
- data/lib/rfuse_symbolic_fs.rb +88 -0
- data/lib/rfuse_symbolic_fs_opts.rb +72 -0
- data/lib/test_fuse.rb +74 -0
- metadata +86 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rfuse_symbolic_fs'
|
5
|
+
require 'rfuse_symbolic_fs_opts'
|
6
|
+
|
7
|
+
options = RFuseSymbolicFSOpts.parse(ARGV)
|
8
|
+
|
9
|
+
filesystem = RFuseSymbolicFS.new(options)
|
10
|
+
FuseFS.set_root( filesystem )
|
11
|
+
|
12
|
+
# Mount under a directory given on the command line.
|
13
|
+
FuseFS.mount_under options.mountpoint
|
14
|
+
FuseFS.run
|
15
|
+
|
data/lib/amaras_fs.rb
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'pp'
|
2
|
+
|
3
|
+
class AmarasFS
|
4
|
+
|
5
|
+
def initialize(*args)
|
6
|
+
start_time = Time.now
|
7
|
+
begin
|
8
|
+
@root = args[0]
|
9
|
+
|
10
|
+
@partitions = Array.new
|
11
|
+
(1...(args.size)).each_with_index do |x, index|
|
12
|
+
@partitions << args[x]
|
13
|
+
#puts args[x]
|
14
|
+
end
|
15
|
+
puts
|
16
|
+
puts
|
17
|
+
|
18
|
+
puts
|
19
|
+
puts "Starting Linking"
|
20
|
+
@partitions.each do |y|
|
21
|
+
build_links( @root, y )
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
rescue => e
|
27
|
+
puts
|
28
|
+
puts "ERROR caught Exception"
|
29
|
+
puts $!
|
30
|
+
puts e.inspect
|
31
|
+
puts e.backtrace
|
32
|
+
puts
|
33
|
+
end
|
34
|
+
puts "Run Time #{start_time - Time.now}"
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def build_links( root, y , spacer=' ')
|
42
|
+
#puts "build_links( root, y )"
|
43
|
+
puts "#{spacer}build_links( #{root}, #{y})"
|
44
|
+
|
45
|
+
files = Dir.glob(y + '/*')
|
46
|
+
|
47
|
+
pp files
|
48
|
+
|
49
|
+
#puts "Iterating of SubFiles"
|
50
|
+
files.each do |x|
|
51
|
+
|
52
|
+
#TODO validation that link does not already exist
|
53
|
+
|
54
|
+
new_link = x.dup
|
55
|
+
new_link[y] = ""
|
56
|
+
new_link = root + new_link
|
57
|
+
|
58
|
+
puts
|
59
|
+
puts "#{spacer}Thinking about linking #{new_link} "
|
60
|
+
#puts " sub file #{x}"
|
61
|
+
|
62
|
+
#Verify that new_link does not exists
|
63
|
+
if not File.exist?( new_link )
|
64
|
+
puts "#{spacer}Mode :1 INFO : File.symlink(#{x}, #{new_link} )"
|
65
|
+
File.symlink(x, new_link)
|
66
|
+
|
67
|
+
elsif ( ( File.symlink?(new_link)) and ( File.readlink(new_link) == x))
|
68
|
+
#readlink rasies exception if called on non links so check is a link first
|
69
|
+
#Link exists but points to location we tried to set
|
70
|
+
puts "#{spacer}Mode :2 INFO : Link Exists & correct"
|
71
|
+
elsif ( ( File.symlink?(new_link)) and ( not File.readlink(new_link) == x ))
|
72
|
+
test_folder(new_link)
|
73
|
+
|
74
|
+
puts "#{spacer}Mode :3 ERROR : #{new_link} already exists"
|
75
|
+
puts "#{spacer} This section requires programming"
|
76
|
+
|
77
|
+
current_pointer = File.readlink(new_link)
|
78
|
+
|
79
|
+
puts "current_pointer #{current_pointer}"
|
80
|
+
puts " #{root}"
|
81
|
+
puts " #{x}"
|
82
|
+
puts " #{y}"
|
83
|
+
|
84
|
+
pos = current_pointer.rindex(File::SEPARATOR)
|
85
|
+
extra_bit = current_pointer[pos...(current_pointer.size)]
|
86
|
+
|
87
|
+
puts "extra_bit #{extra_bit}"
|
88
|
+
|
89
|
+
#/A/1/x
|
90
|
+
#/A/1/Y
|
91
|
+
#/B/1/z
|
92
|
+
#
|
93
|
+
# current_pointer = /A/1
|
94
|
+
|
95
|
+
#current pointer already has the extra_bit
|
96
|
+
new_root = root + extra_bit
|
97
|
+
next_pointer = x + extra_bit
|
98
|
+
|
99
|
+
puts "File Maintenance"
|
100
|
+
|
101
|
+
FileUtils.rm( new_root )
|
102
|
+
FileUtils.mkdir( new_root )
|
103
|
+
|
104
|
+
build_links(new_root , x, spacer+' ')
|
105
|
+
build_links(new_root , current_pointer, spacer+' ')
|
106
|
+
|
107
|
+
|
108
|
+
elsif File.directory?(new_link)
|
109
|
+
#new_link already exists as folder
|
110
|
+
# this implies it already exists on another drive
|
111
|
+
# just recurse on this lower level
|
112
|
+
puts "#{spacer}Mode :4 INFO : Doing recursive call to build links"
|
113
|
+
|
114
|
+
|
115
|
+
|
116
|
+
new_root = x.dup
|
117
|
+
new_root[y] = ""
|
118
|
+
new_root = root + new_root
|
119
|
+
|
120
|
+
build_links(new_root, x, spacer+' ' )
|
121
|
+
else
|
122
|
+
#Link does exist and points to different Location
|
123
|
+
# What could have caused this?
|
124
|
+
# 1) Data has been completely moved to another Drive
|
125
|
+
# 2) Drive was running out of room and this folder has been split across 2 or more drives
|
126
|
+
#
|
127
|
+
# To resolve this copy current link location if it exists save location for later
|
128
|
+
# Create this folder and link in contnents from new drive then repeat for original location
|
129
|
+
|
130
|
+
puts "#{spacer}Mode :5 ERROR : #{new_link} already exists"
|
131
|
+
puts "#{spacer} This section requires programming"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
def test_folder(path)
|
138
|
+
puts "File #{File.file?(path)}"
|
139
|
+
puts "Folder #{File.directory?(path)}"
|
140
|
+
puts "Symlink #{File.symlink?(path)}"
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require 'fusefs'
|
3
|
+
require 'rfuse_symbolic_fs_opts'
|
4
|
+
|
5
|
+
|
6
|
+
class RFuseSymbolicFS
|
7
|
+
# contents( path )
|
8
|
+
# file?( path )
|
9
|
+
# directory?( path )
|
10
|
+
# read_file( path )
|
11
|
+
# size( path )
|
12
|
+
#
|
13
|
+
# save
|
14
|
+
# touch( path )
|
15
|
+
# can_write?(path)
|
16
|
+
# write_to(path,body)
|
17
|
+
#
|
18
|
+
# can_delete?(path)
|
19
|
+
# delete( path )
|
20
|
+
#
|
21
|
+
# can_mkdir?( path )
|
22
|
+
# mkdir( path )
|
23
|
+
# can_rmdir( path )
|
24
|
+
# rmdir( path )
|
25
|
+
#
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
def initialize( options )
|
30
|
+
@base_dir = options.input
|
31
|
+
end
|
32
|
+
|
33
|
+
def contents(path)
|
34
|
+
n_path = File.expand_path( @base_dir + path )
|
35
|
+
Dir.chdir(n_path)
|
36
|
+
|
37
|
+
files = Dir.glob('*')
|
38
|
+
#Added command to OS X Finder not to index.
|
39
|
+
files << 'metadata_never_index'
|
40
|
+
|
41
|
+
return files
|
42
|
+
end
|
43
|
+
|
44
|
+
def file?(path)
|
45
|
+
#If path ends with metadata_never_index it is a file
|
46
|
+
if path =~ /metadata_never_index$/
|
47
|
+
return true
|
48
|
+
end
|
49
|
+
|
50
|
+
return (not File.directory?( @base_dir + path ))
|
51
|
+
end
|
52
|
+
|
53
|
+
def directory?(path)
|
54
|
+
File.directory?(@base_dir + path)
|
55
|
+
end
|
56
|
+
|
57
|
+
def read_file(path)
|
58
|
+
|
59
|
+
#puts "read file #{path}"
|
60
|
+
if File.exists?( @base_dir + path )
|
61
|
+
return File.new(@base_dir + path , "r").read
|
62
|
+
end
|
63
|
+
return "ERROR, file not found\n"
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def size(path)
|
69
|
+
if File.exists?( @base_dir + path )
|
70
|
+
return File.size( @base_dir + path )
|
71
|
+
else
|
72
|
+
return 16
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
if $0 == __FILE__
|
79
|
+
|
80
|
+
options = RFuseSymbolicFSOpts.parse(ARGV)
|
81
|
+
filesystem = RFuseSymbolicFS.new( options )
|
82
|
+
FuseFS.set_root( filesystem )
|
83
|
+
|
84
|
+
# Mount under a directory given on the command line.
|
85
|
+
FuseFS.mount_under options.mountpoint
|
86
|
+
FuseFS.run
|
87
|
+
end
|
88
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'optparse/time'
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
class RFuseSymbolicFSOpts
|
6
|
+
|
7
|
+
|
8
|
+
#
|
9
|
+
# Return a structure describing the options.
|
10
|
+
#
|
11
|
+
def self.parse(args)
|
12
|
+
@VERSION = "0.0.1"
|
13
|
+
|
14
|
+
# The options specified on the command line will be collected in *options*.
|
15
|
+
# We set default values here.
|
16
|
+
options = OpenStruct.new
|
17
|
+
|
18
|
+
options.verbose = false
|
19
|
+
options.mountpoint = ""
|
20
|
+
options.input = ""
|
21
|
+
|
22
|
+
|
23
|
+
opts = OptionParser.new do |opts|
|
24
|
+
opts.banner = "Usage: #{__FILE__} [options]"
|
25
|
+
opts.separator ""
|
26
|
+
opts.separator "Common options:"
|
27
|
+
|
28
|
+
# No argument, shows at tail. This will print an options summary.
|
29
|
+
opts.on("-h", "--help", "Show this message") do
|
30
|
+
puts opts
|
31
|
+
exit
|
32
|
+
end
|
33
|
+
|
34
|
+
# Another typical switch to print the version.
|
35
|
+
opts.on("--version", "Show version") do
|
36
|
+
#puts OptionParser::Version.join('.')
|
37
|
+
puts "Version #{@VERSION}"
|
38
|
+
exit
|
39
|
+
end
|
40
|
+
|
41
|
+
# Boolean switch.
|
42
|
+
#opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
|
43
|
+
# options.verbose = v
|
44
|
+
#end
|
45
|
+
|
46
|
+
opts.separator ""
|
47
|
+
opts.separator "Specific options:"
|
48
|
+
|
49
|
+
|
50
|
+
# Cast 'delay' argument to a Float.
|
51
|
+
opts.on("--mountpoint path", String, "Root of new Filesystem") do |n|
|
52
|
+
options.mountpoint = n
|
53
|
+
end
|
54
|
+
|
55
|
+
opts.on("--input N", String, "Folder FS will point to") do |n|
|
56
|
+
options.input = n
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
options.leftovers = opts.parse!(args)
|
63
|
+
|
64
|
+
if (options.mountpoint == "") and (options.input == "") and (options.leftovers.size==2)
|
65
|
+
options.mountpoint = options.leftovers[0]
|
66
|
+
options.input = options.leftovers[1]
|
67
|
+
end
|
68
|
+
return options
|
69
|
+
end # parse()
|
70
|
+
|
71
|
+
end # class OptparseExample
|
72
|
+
|
data/lib/test_fuse.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require 'fusefs'
|
3
|
+
|
4
|
+
class HelloDir
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@base_dir = '/Users/morgy/Movies'
|
8
|
+
end
|
9
|
+
|
10
|
+
def contents(path)
|
11
|
+
n_path = File.expand_path( @base_dir + path )
|
12
|
+
Dir.chdir(n_path)
|
13
|
+
|
14
|
+
files = Dir.glob('*')
|
15
|
+
files << 'hello.txt'
|
16
|
+
files << 'metadata_never_index'
|
17
|
+
end
|
18
|
+
|
19
|
+
def file?(path)
|
20
|
+
if path == '/hello.txt'
|
21
|
+
return true
|
22
|
+
end
|
23
|
+
|
24
|
+
if path == '/metadata_never_index'
|
25
|
+
return true
|
26
|
+
end
|
27
|
+
|
28
|
+
if File.exists?(@base_dir + path )
|
29
|
+
#puts "file? #{@base_dir}#{path} "
|
30
|
+
if File.directory?(@base_dir + path )
|
31
|
+
return false
|
32
|
+
else
|
33
|
+
return true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
def directory?(path)
|
40
|
+
File.directory?(@base_dir + path)
|
41
|
+
end
|
42
|
+
|
43
|
+
def read_file(path)
|
44
|
+
puts "read file #{path}"
|
45
|
+
if path == '/hello.txt'
|
46
|
+
return "Hello, World!\n"
|
47
|
+
end
|
48
|
+
puts "exists?"
|
49
|
+
if File.exists?( @base_dir + path )
|
50
|
+
puts " true #{@base_dir}#{path}"
|
51
|
+
return File.new(@base_dir + path , "r").read
|
52
|
+
else
|
53
|
+
puts " fail #{@base_dir}#{path}"
|
54
|
+
end
|
55
|
+
return "ERROR, file not found\n"
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
def size(path)
|
60
|
+
if File.exists?( @base_dir + path )
|
61
|
+
return File.size( @base_dir + path )
|
62
|
+
else
|
63
|
+
return 16
|
64
|
+
end
|
65
|
+
#read_file(path).size
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
hellodir = HelloDir.new
|
70
|
+
FuseFS.set_root( hellodir )
|
71
|
+
|
72
|
+
# Mount under a directory given on the command line.
|
73
|
+
FuseFS.mount_under ARGV.shift
|
74
|
+
FuseFS.run
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rfuse_symbolic_fs
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Morgan Prior
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-07-07 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: fusefs
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 7
|
33
|
+
- 0
|
34
|
+
version: 0.7.0
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
description: Virtual Filesystem Written in Ruby Fuse, which acts like a symbolic link
|
38
|
+
email: rfuse_symbolic_fs_gem@amaras-tech.co.uk
|
39
|
+
executables:
|
40
|
+
- rfuse_symbolic_fs
|
41
|
+
extensions: []
|
42
|
+
|
43
|
+
extra_rdoc_files: []
|
44
|
+
|
45
|
+
files:
|
46
|
+
- bin/rfuse_symbolic_fs
|
47
|
+
- lib/amaras_fs.rb
|
48
|
+
- lib/rfuse_symbolic_fs.rb
|
49
|
+
- lib/rfuse_symbolic_fs_opts.rb
|
50
|
+
- lib/test_fuse.rb
|
51
|
+
has_rdoc: true
|
52
|
+
homepage: http://amaras-tech.co.uk/software/rfuse_symbolic_fs
|
53
|
+
licenses: []
|
54
|
+
|
55
|
+
post_install_message: To use 'rfuse_symbolic_fs' as a standalone application your gems folder must be on your path
|
56
|
+
rdoc_options: []
|
57
|
+
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
hash: 3
|
66
|
+
segments:
|
67
|
+
- 0
|
68
|
+
version: "0"
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
hash: 3
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
version: "0"
|
78
|
+
requirements: []
|
79
|
+
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 1.3.7
|
82
|
+
signing_key:
|
83
|
+
specification_version: 3
|
84
|
+
summary: Ruby Fuse, Filesystem which basically is a soft link on Mac OS X, Linux and Unix.
|
85
|
+
test_files: []
|
86
|
+
|