homefs 0.3.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/homefs +107 -47
- data/lib/homefs/homefs.rb +17 -31
- data/man/homefs.1 +69 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d24a895d9cbda06b225d6646ec3e04d959b9c85
|
4
|
+
data.tar.gz: c2d59bc728d9dd65f9d4b736d6e54f5a6a74970d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7ebb4625f918fd4a0049517df744df0d681322d42dab5512f640b1f46273dbeab8cab7b350d6ad1307b762d825561b110163edcc669ab34fb7a5162a63fca83
|
7
|
+
data.tar.gz: b161c74a6ee23f2349104926603697fad01f179d747e7131923a2e2d17a380d0632dfd6777e67886ee38480458b9526f85a141e460b16a82f5e823baa9fb517c
|
data/bin/homefs
CHANGED
@@ -1,67 +1,127 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'homefs'
|
4
|
+
require 'etc'
|
5
|
+
require 'optparse'
|
4
6
|
|
5
|
-
|
7
|
+
HELPSTRING = <<EOF
|
8
|
+
Usage: homefs [-h]
|
9
|
+
homefs [OPTION]... relative_directory mountpoint
|
10
|
+
homefs [OPTION]... -r relative_directory mountpoint
|
11
|
+
homefs [OPTION]... -s directory [relative_directory] mountpoint
|
12
|
+
homefs [OPTION]... -s directory [-r relative_directory] mountpoint
|
6
13
|
|
7
|
-
|
8
|
-
|
9
|
-
exit 1
|
10
|
-
end
|
14
|
+
Mount HomeFS on the specified mountpoint, using the specified directory
|
15
|
+
relative to each user's home directory
|
11
16
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
17
|
+
-h print this help string
|
18
|
+
-d enable debug mode
|
19
|
+
-r relative_directory specify the relative directory. If -r is given
|
20
|
+
multiple times, the last given path is taken
|
21
|
+
-s directory instead of using users' home directories, append
|
22
|
+
each user's username to the given directory
|
23
|
+
|
24
|
+
-o no_allow_other disable allow_other, which is default
|
25
|
+
-o debug enable debug mode
|
26
|
+
|
27
|
+
Options accepted by FUSE are also understood.
|
28
|
+
EOF
|
29
|
+
|
30
|
+
def process_arguments(argv)
|
31
|
+
options = []
|
32
|
+
|
33
|
+
parser = OptionParser.new do |opts|
|
34
|
+
opts.on '-d' do
|
35
|
+
@debug = true
|
36
|
+
end
|
37
|
+
opts.on '-oOPTION' do |option|
|
38
|
+
options += option.split(',')
|
39
|
+
end
|
40
|
+
opts.on '-rDIRECTORY' do |directory|
|
41
|
+
@reldir = directory
|
42
|
+
end
|
43
|
+
opts.on '-sDIRECTORY' do |directory|
|
44
|
+
@basedir = directory
|
45
|
+
end
|
46
|
+
opts.on '-h' do
|
47
|
+
print_help
|
48
|
+
exit 0
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
begin
|
53
|
+
args = parser.parse(argv)
|
54
|
+
rescue OptionParser::InvalidOption => e
|
55
|
+
warn "Option '#{e.args.first}' not understood."
|
56
|
+
puts
|
57
|
+
print_help
|
58
|
+
exit 1
|
59
|
+
end
|
60
|
+
|
61
|
+
@reldir = args.shift unless @reldir
|
62
|
+
@mountpoint = args.shift unless @mountpoint
|
63
|
+
|
64
|
+
if !args.empty?
|
65
|
+
warn "Extra arguments '#{args.join("', '")}' not understood."
|
66
|
+
exit 1
|
67
|
+
end
|
68
|
+
|
69
|
+
if !@reldir && !@basedir
|
70
|
+
warn "You must specify a relative directory for HomeFS!"
|
71
|
+
exit 1
|
16
72
|
end
|
17
|
-
end
|
18
73
|
|
19
|
-
|
74
|
+
if !@mountpoint
|
75
|
+
warn "You must specify a mountpoint!"
|
76
|
+
exit 1
|
77
|
+
end
|
20
78
|
|
21
|
-
|
79
|
+
# We use #delete here to prune options that we understand, but
|
80
|
+
# FUSE doesn't.
|
81
|
+
options.unshift 'allow_other' unless options.delete 'no_allow_other'
|
82
|
+
options.unshift 'dev' unless options.delete 'nodev'
|
83
|
+
options.unshift 'suid' unless options.delete 'nosuid'
|
22
84
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
85
|
+
if options.delete('debug')
|
86
|
+
@debug = true
|
87
|
+
end
|
88
|
+
|
89
|
+
options
|
27
90
|
end
|
28
91
|
|
29
|
-
|
30
|
-
|
92
|
+
def print_help
|
93
|
+
puts HELPSTRING
|
31
94
|
end
|
32
95
|
|
33
|
-
|
34
|
-
|
96
|
+
@debug = false
|
97
|
+
|
98
|
+
fuse_options = process_arguments(ARGV)
|
99
|
+
|
100
|
+
# Return immediately
|
101
|
+
unless @debug
|
102
|
+
STDOUT.reopen("/dev/null")
|
103
|
+
STDERR.reopen("/dev/null")
|
104
|
+
|
35
105
|
pid = fork
|
36
106
|
if pid
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
107
|
+
Process.detach(pid)
|
108
|
+
exit 0
|
109
|
+
end
|
110
|
+
end
|
42
111
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
notifier.watch('/etc/passwd', :modify) do
|
47
|
-
# Send a signal to the child process; it will catch USR1 and update
|
48
|
-
# the homedirs hash
|
49
|
-
Process::kill('USR1', pid)
|
50
|
-
end
|
51
|
-
notifier.run
|
52
|
-
else
|
53
|
-
# Here we trap the signal to be sent to us by our parent
|
54
|
-
# when /etc/passwd changes and update our hash accordingly
|
55
|
-
trap 'USR1' do
|
56
|
-
fs.read_passwd
|
57
|
-
end
|
112
|
+
if @basedir
|
113
|
+
fs = HomeFS.new(@reldir || '') do |uid|
|
114
|
+
File.join(@basedir, Etc.getpwuid(uid).name)
|
58
115
|
end
|
59
|
-
|
60
|
-
|
61
|
-
# /etc/passwd
|
116
|
+
else
|
117
|
+
fs = HomeFS.new(@reldir)
|
62
118
|
end
|
63
119
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
120
|
+
if @debug
|
121
|
+
fs = HomeFS::Wrapper.new(fs)
|
122
|
+
end
|
123
|
+
|
124
|
+
optstring = fuse_options.join(',')
|
125
|
+
|
126
|
+
delegator = RFuse::FuseDelegator.new(fs, @mountpoint, '-o', optstring)
|
127
|
+
delegator.run
|
data/lib/homefs/homefs.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rfuse'
|
2
|
+
require 'etc'
|
2
3
|
|
3
4
|
# An instance of HomeFS; this implements all FuseFS methods, and ultimately
|
4
5
|
# handles reading, writing, and inspection of files.
|
@@ -17,41 +18,26 @@ class HomeFS
|
|
17
18
|
# to RFuse, as it does nothing on its own. The path is relative to the
|
18
19
|
# calling user's home directory, that is, the user interacting with the
|
19
20
|
# filesystem through open(2), read(2), write(2), etc.
|
21
|
+
#
|
22
|
+
# This method may accept a block. If a block is given, it is expected to
|
23
|
+
# return the base path for the given UID. If no block is given, this is the
|
24
|
+
# home directory for that UID instead.
|
20
25
|
# @param [String] path the path, relative to $HOME, to use as the root of
|
21
26
|
# the file system.
|
22
|
-
|
27
|
+
# @yieldparam [Integer] uid the user ID of the current caller
|
28
|
+
# @yieldreturn [String] the path to use as the base path for the given user
|
29
|
+
def initialize(path, options = Hash.new, &blk)
|
23
30
|
@relpath = path
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
# Read or re-read /etc/passwd to update the internal table of home
|
28
|
-
# directories for each UID. This method does not try to guess as to which
|
29
|
-
# user IDs are owned by actual users of the system, and which are utility
|
30
|
-
# accounts such as 'lp' or 'pulse'.
|
31
|
-
# @return [void]
|
32
|
-
def read_passwd
|
33
|
-
# Try to read from getent
|
34
|
-
passwd = `getent passwd`
|
35
|
-
if $? != 0
|
36
|
-
passwd = File.read('/etc/passwd')
|
31
|
+
@baseblock = blk || proc do |uid|
|
32
|
+
homedir(uid)
|
37
33
|
end
|
34
|
+
end
|
38
35
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
passwd.each_line.map { |line|
|
45
|
-
next if line.strip.empty?
|
46
|
-
values = line.split(':')
|
47
|
-
# Username, UID, home directory
|
48
|
-
[values[0], Integer(values[2]), values[5]]
|
49
|
-
}.reject { |line|
|
50
|
-
line.nil?
|
51
|
-
}.each { |username, uid, home|
|
52
|
-
@homedirs[uid] = home
|
53
|
-
@usernames[username] = uid
|
54
|
-
}
|
36
|
+
# Get the home directory of the user with the UID _uid_.
|
37
|
+
# @param [Integer] uid the UID of the user
|
38
|
+
# @return [String] the path to the specified user's home directory
|
39
|
+
def homedir(uid)
|
40
|
+
Etc.getpwuid(uid).dir
|
55
41
|
end
|
56
42
|
|
57
43
|
# Return the path to the root of HomeFS relative to the underlying
|
@@ -63,7 +49,7 @@ class HomeFS
|
|
63
49
|
# filesystem, or if _path_ is specified, the path to that resource
|
64
50
|
# relative to the underlying filesystem.
|
65
51
|
def homepath(uid, path = nil)
|
66
|
-
basepath = @
|
52
|
+
basepath = @baseblock[uid]
|
67
53
|
# basepath shouldn't ever be nil, but fail gracefully just
|
68
54
|
# in case.
|
69
55
|
raise Errno::ENOENT if basepath == nil
|
data/man/homefs.1
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
.\" generated with Ronn/v0.7.3
|
2
|
+
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
3
|
+
.
|
4
|
+
.TH "HOMEFS" "1" "November 2015" "" ""
|
5
|
+
.
|
6
|
+
.SH "NAME"
|
7
|
+
\fBhomefs\fR \- FUSE filesystem that redirects filesystem calls to the calling user\'s home directory
|
8
|
+
.
|
9
|
+
.SH "SYNOPSIS"
|
10
|
+
\fBhomefs\fR [\-h]
|
11
|
+
.
|
12
|
+
.br
|
13
|
+
\fBhomefs\fR [OPTION]\.\.\. relative_directory mountpoint
|
14
|
+
.
|
15
|
+
.br
|
16
|
+
\fBhomefs\fR [OPTION]\.\.\. \-r relative_directory mountpoint
|
17
|
+
.
|
18
|
+
.br
|
19
|
+
\fBhomefs\fR [OPTION]\.\.\. \-s directory [relative_directory] mountpoint
|
20
|
+
.
|
21
|
+
.br
|
22
|
+
\fBhomefs\fR [OPTION]\.\.\. \-s directory [\-r relative_directory] mountpoint
|
23
|
+
.
|
24
|
+
.br
|
25
|
+
.
|
26
|
+
.SH "DESCRIPTION"
|
27
|
+
FUSE filesystem currently written in Ruby that directs filesystem calls to a directory relative to the calling user\'s home directory\.
|
28
|
+
.
|
29
|
+
.P
|
30
|
+
If the filesystem is mounted on \fB/mnt/homefs\fR and is linked to the directory \'Documents\' relative to each user\'s home directory, the user Sarah doing ls \fB/mnt/homefs/\fR would see the contents of \fB/home/sarah/Documents,\fR and the user Tyler would see the contents of \fB/home/tyler/Documents\.\fR
|
31
|
+
.
|
32
|
+
.P
|
33
|
+
Since HomeFS only makes sense when it\'s used to display different contents to different users, it by default passes the option \'allow_other\' to FUSE, which allows any user with the appropriate permissions to interact with the filesystem\.
|
34
|
+
.
|
35
|
+
.P
|
36
|
+
Currently we do not support POSIX locking and creation of special device files such as FIFOs (though HomeFS can read and write to and from special device files)\. We do support extended filesystem attributes given that you install the ffi\-xattr gem, but you can use HomeFS without it if you do not need them\.
|
37
|
+
.
|
38
|
+
.SH "OPTIONS"
|
39
|
+
.
|
40
|
+
.TP
|
41
|
+
\fIrelative_directory\fR
|
42
|
+
The directory relative to each user\'s home directory to redirect filesystem calls to\. That is, calls are directed to \fI$HOME\fR/\fIrelative_directory\fR where $HOME is the calling user\'s home directory\.
|
43
|
+
.
|
44
|
+
.TP
|
45
|
+
\fImountpoint\fR
|
46
|
+
The mountpoint where HomeFS is to be mounted
|
47
|
+
.
|
48
|
+
.TP
|
49
|
+
\fB\-h\fR
|
50
|
+
Print a short help string summarizing the options
|
51
|
+
.
|
52
|
+
.TP
|
53
|
+
\fB\-d\fR
|
54
|
+
Enable debug mode\. If debug mode is on, HomeFS will not return immediately, and will report any of its methods that are called\. Note that this does not enable FUSE debug mode\.
|
55
|
+
.
|
56
|
+
.TP
|
57
|
+
\fB\-r\fR \fIrelative_directory\fR
|
58
|
+
Specify the relative directory with a switch instead of a positional argument
|
59
|
+
.
|
60
|
+
.TP
|
61
|
+
\fB\-o\fR \fIno_allow_other\fR
|
62
|
+
Disable allow_other, which is default\. If specified, only the user mounting HomeFS can use it\. Considering the nature of HomeFS, using a symlink would probably be more appropiate\.
|
63
|
+
.
|
64
|
+
.TP
|
65
|
+
\fB\-o\fR \fIdebug\fR
|
66
|
+
Same as \fB\-d\fR\.
|
67
|
+
.
|
68
|
+
.P
|
69
|
+
Options accepted by FUSE are passed onto FUSE\. See \fIfuse(8)\fR for a complete list and explanation of each option\.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: homefs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dylan Frese
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-11-
|
11
|
+
date: 2015-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rfuse
|
@@ -38,6 +38,7 @@ files:
|
|
38
38
|
- lib/homefs.rb
|
39
39
|
- lib/homefs/debug.rb
|
40
40
|
- lib/homefs/homefs.rb
|
41
|
+
- man/homefs.1
|
41
42
|
homepage:
|
42
43
|
licenses:
|
43
44
|
- GPLv2
|