rumai 2.0.2 → 2.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.
- data/CREDITS +2 -0
- data/bin/rumai +20 -8
- data/doc/api/classes/IO.html +72 -0
- data/doc/api/classes/Integer.html +110 -0
- data/doc/api/classes/Object.html +60 -0
- data/doc/api/classes/Rumai.html +867 -0
- data/doc/api/classes/Rumai/Area.html +836 -0
- data/doc/api/classes/Rumai/Chain.html +197 -0
- data/doc/api/classes/Rumai/Client.html +865 -0
- data/doc/api/classes/Rumai/ClientContainer.html +191 -0
- data/doc/api/classes/Rumai/ExportInstanceMethods.html +69 -0
- data/doc/api/classes/Rumai/IXP.html +131 -0
- data/doc/api/classes/Rumai/IXP/Agent.html +836 -0
- data/doc/api/classes/Rumai/IXP/Agent/FidStream.html +456 -0
- data/doc/api/classes/Rumai/IXP/Agent/MODES.html +108 -0
- data/doc/api/classes/Rumai/IXP/Agent/RangedPool.html +241 -0
- data/doc/api/classes/Rumai/IXP/Error.html +67 -0
- data/doc/api/classes/Rumai/IXP/Fcall.html +323 -0
- data/doc/api/classes/Rumai/IXP/Qid.html +153 -0
- data/doc/api/classes/Rumai/IXP/Rattach.html +67 -0
- data/doc/api/classes/Rumai/IXP/Rauth.html +67 -0
- data/doc/api/classes/Rumai/IXP/Rclunk.html +67 -0
- data/doc/api/classes/Rumai/IXP/Rcreate.html +67 -0
- data/doc/api/classes/Rumai/IXP/Rerror.html +67 -0
- data/doc/api/classes/Rumai/IXP/Rflush.html +67 -0
- data/doc/api/classes/Rumai/IXP/Ropen.html +67 -0
- data/doc/api/classes/Rumai/IXP/Rread.html +67 -0
- data/doc/api/classes/Rumai/IXP/Rremove.html +67 -0
- data/doc/api/classes/Rumai/IXP/Rstat.html +67 -0
- data/doc/api/classes/Rumai/IXP/Rversion.html +67 -0
- data/doc/api/classes/Rumai/IXP/Rwalk.html +67 -0
- data/doc/api/classes/Rumai/IXP/Rwrite.html +67 -0
- data/doc/api/classes/Rumai/IXP/Rwstat.html +67 -0
- data/doc/api/classes/Rumai/IXP/Stat.html +252 -0
- data/doc/api/classes/Rumai/IXP/Stream.html +131 -0
- data/doc/api/classes/Rumai/IXP/Struct.html +315 -0
- data/doc/api/classes/Rumai/IXP/Struct/Field.html +415 -0
- data/doc/api/classes/Rumai/IXP/Struct/Field/CounteeField.html +153 -0
- data/doc/api/classes/Rumai/IXP/Struct/Field/CounterField.html +104 -0
- data/doc/api/classes/Rumai/IXP/Tattach.html +68 -0
- data/doc/api/classes/Rumai/IXP/Tauth.html +67 -0
- data/doc/api/classes/Rumai/IXP/Tclunk.html +67 -0
- data/doc/api/classes/Rumai/IXP/Tcreate.html +68 -0
- data/doc/api/classes/Rumai/IXP/Terror.html +110 -0
- data/doc/api/classes/Rumai/IXP/Tflush.html +67 -0
- data/doc/api/classes/Rumai/IXP/Topen.html +165 -0
- data/doc/api/classes/Rumai/IXP/Tread.html +67 -0
- data/doc/api/classes/Rumai/IXP/Tremove.html +67 -0
- data/doc/api/classes/Rumai/IXP/Tstat.html +67 -0
- data/doc/api/classes/Rumai/IXP/Tversion.html +86 -0
- data/doc/api/classes/Rumai/IXP/Twalk.html +68 -0
- data/doc/api/classes/Rumai/IXP/Twrite.html +68 -0
- data/doc/api/classes/Rumai/IXP/Twstat.html +67 -0
- data/doc/api/classes/Rumai/Node.html +817 -0
- data/doc/api/classes/Rumai/View.html +818 -0
- data/doc/api/classes/Rumai/WidgetImpl.html +65 -0
- data/doc/api/classes/Rumai/WidgetNode.html +68 -0
- data/doc/api/classes/String.html +163 -0
- data/doc/api/classes/StringIO.html +72 -0
- data/doc/api/classes/Time.html +156 -0
- data/doc/api/created.rid +1 -0
- data/doc/api/css/main.css +263 -0
- data/doc/api/css/panel.css +383 -0
- data/doc/api/css/reset.css +53 -0
- data/doc/api/files/CREDITS.html +64 -0
- data/doc/api/files/LICENSE.html +76 -0
- data/doc/api/files/lib/rumai/fs_rb.html +75 -0
- data/doc/api/files/lib/rumai/ixp/message_rb.html +91 -0
- data/doc/api/files/lib/rumai/ixp/transport_rb.html +75 -0
- data/doc/api/files/lib/rumai/ixp_rb.html +69 -0
- data/doc/api/files/lib/rumai/wm_rb.html +77 -0
- data/doc/api/files/lib/rumai_rb.html +65 -0
- data/doc/api/i/arrows.png +0 -0
- data/doc/api/i/results_bg.png +0 -0
- data/doc/api/i/tree_bg.png +0 -0
- data/doc/api/index.html +14 -18
- data/doc/api/js/jquery-1.3.2.min.js +19 -0
- data/doc/api/js/jquery-effect.js +593 -0
- data/doc/api/js/main.js +22 -0
- data/doc/api/js/searchdoc.js +605 -0
- data/doc/api/panel/index.html +63 -0
- data/doc/api/panel/search_index.js +1 -0
- data/doc/api/panel/tree.js +1 -0
- data/doc/history.erb +41 -16
- data/doc/index.erb +14 -11
- data/doc/index.xhtml +519 -846
- data/doc/intro.erb +33 -32
- data/doc/setup.erb +14 -13
- data/doc/usage.erb +69 -35
- data/lib/rumai.rb +13 -5
- data/lib/rumai/fs.rb +71 -27
- data/lib/rumai/ixp.rb +4 -0
- data/lib/rumai/ixp/message.rb +178 -81
- data/lib/rumai/ixp/transport.rb +144 -91
- data/lib/rumai/wm.rb +717 -593
- data/rakefile +14 -0
- data/test/rumai/ixp/message.rb +42 -54
- metadata +110 -89
- data/Rakefile +0 -8
- data/doc/api/IO.html +0 -53
- data/doc/api/Integer.html +0 -102
- data/doc/api/Object.html +0 -23
- data/doc/api/Rumai.html +0 -1218
- data/doc/api/Rumai/Area.html +0 -1088
- data/doc/api/Rumai/Chain.html +0 -230
- data/doc/api/Rumai/Client.html +0 -1264
- data/doc/api/Rumai/ClientContainer.html +0 -227
- data/doc/api/Rumai/ExportInstMethods.html +0 -115
- data/doc/api/Rumai/IXP.html +0 -23
- data/doc/api/Rumai/IXP/Agent.html +0 -1222
- data/doc/api/Rumai/IXP/Agent/FidStream.html +0 -602
- data/doc/api/Rumai/IXP/Agent/RangedPool.html +0 -263
- data/doc/api/Rumai/IXP/Error.html +0 -32
- data/doc/api/Rumai/IXP/Fcall.html +0 -398
- data/doc/api/Rumai/IXP/Qid.html +0 -99
- data/doc/api/Rumai/IXP/Rattach.html +0 -71
- data/doc/api/Rumai/IXP/Rauth.html +0 -71
- data/doc/api/Rumai/IXP/Rclunk.html +0 -71
- data/doc/api/Rumai/IXP/Rcreate.html +0 -71
- data/doc/api/Rumai/IXP/Rerror.html +0 -71
- data/doc/api/Rumai/IXP/Rflush.html +0 -71
- data/doc/api/Rumai/IXP/Ropen.html +0 -71
- data/doc/api/Rumai/IXP/Rread.html +0 -71
- data/doc/api/Rumai/IXP/Rremove.html +0 -71
- data/doc/api/Rumai/IXP/Rstat.html +0 -71
- data/doc/api/Rumai/IXP/Rversion.html +0 -71
- data/doc/api/Rumai/IXP/Rwalk.html +0 -71
- data/doc/api/Rumai/IXP/Rwrite.html +0 -71
- data/doc/api/Rumai/IXP/Rwstat.html +0 -71
- data/doc/api/Rumai/IXP/Stat.html +0 -188
- data/doc/api/Rumai/IXP/Stream.html +0 -112
- data/doc/api/Rumai/IXP/Struct.html +0 -348
- data/doc/api/Rumai/IXP/Struct/ClassField.html +0 -177
- data/doc/api/Rumai/IXP/Struct/Field.html +0 -549
- data/doc/api/Rumai/IXP/Struct/Field/CounteeField.html +0 -175
- data/doc/api/Rumai/IXP/Struct/Field/CounterField.html +0 -95
- data/doc/api/Rumai/IXP/Struct/Integer8Field.html +0 -181
- data/doc/api/Rumai/IXP/Struct/StringField.html +0 -128
- data/doc/api/Rumai/IXP/Tattach.html +0 -71
- data/doc/api/Rumai/IXP/Tauth.html +0 -71
- data/doc/api/Rumai/IXP/Tclunk.html +0 -71
- data/doc/api/Rumai/IXP/Tcreate.html +0 -71
- data/doc/api/Rumai/IXP/Terror.html +0 -156
- data/doc/api/Rumai/IXP/Tflush.html +0 -71
- data/doc/api/Rumai/IXP/Topen.html +0 -113
- data/doc/api/Rumai/IXP/Tread.html +0 -71
- data/doc/api/Rumai/IXP/Tremove.html +0 -71
- data/doc/api/Rumai/IXP/Tstat.html +0 -71
- data/doc/api/Rumai/IXP/Tversion.html +0 -83
- data/doc/api/Rumai/IXP/Twalk.html +0 -71
- data/doc/api/Rumai/IXP/Twrite.html +0 -71
- data/doc/api/Rumai/IXP/Twstat.html +0 -71
- data/doc/api/Rumai/Node.html +0 -1139
- data/doc/api/Rumai/View.html +0 -1280
- data/doc/api/Rumai/WidgetImpl.html +0 -196
- data/doc/api/Rumai/WidgetNode.html +0 -184
- data/doc/api/String.html +0 -180
- data/doc/api/StringIO.html +0 -53
- data/doc/api/Time.html +0 -175
- data/doc/api/all-methods.html +0 -1436
- data/doc/api/all-namespaces.html +0 -140
- data/doc/api/app.js +0 -18
- data/doc/api/jquery.js +0 -11
- data/doc/api/readme.html +0 -38
- data/doc/api/style.css +0 -68
- data/doc/api/syntax_highlight.css +0 -21
- data/doc/theory.erb +0 -3
data/lib/rumai.rb
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright 2008 Suraj N. Kurapati
|
|
3
|
+
# See the LICENSE file for details.
|
|
4
|
+
#++
|
|
5
|
+
|
|
1
6
|
require 'rubygems'
|
|
2
|
-
gem 'inochi', '~>
|
|
7
|
+
gem 'inochi', '~> 1'
|
|
3
8
|
require 'inochi'
|
|
4
9
|
|
|
5
10
|
Inochi.init :Rumai,
|
|
6
|
-
:version => '2.0
|
|
7
|
-
:release => '2009-
|
|
8
|
-
:website => 'http://snk.tuxfamily.org/lib/rumai',
|
|
9
|
-
:tagline => 'Ruby interface to the wmii window manager'
|
|
11
|
+
:version => '2.1.0',
|
|
12
|
+
:release => '2009-05-09',
|
|
13
|
+
:website => 'http://snk.tuxfamily.org/lib/rumai/',
|
|
14
|
+
:tagline => 'Ruby interface to the wmii window manager',
|
|
15
|
+
:develop => {
|
|
16
|
+
:dfect => nil, # for unit testing
|
|
17
|
+
}
|
|
10
18
|
|
|
11
19
|
require 'rumai/fs'
|
|
12
20
|
require 'rumai/wm'
|
data/lib/rumai/fs.rb
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
# File system abstractions over the 9P2000 protocol.
|
|
2
|
+
#--
|
|
3
|
+
# Copyright 2006 Suraj N. Kurapati
|
|
4
|
+
# See the LICENSE file for details.
|
|
5
|
+
#++
|
|
2
6
|
|
|
3
7
|
require 'rumai/ixp'
|
|
4
8
|
require 'socket'
|
|
@@ -6,6 +10,7 @@ require 'socket'
|
|
|
6
10
|
module Rumai
|
|
7
11
|
# address of the IXP server socket on this machine
|
|
8
12
|
display = ENV['DISPLAY'] || ':0.0'
|
|
13
|
+
|
|
9
14
|
IXP_SOCK_ADDR = ENV['WMII_ADDRESS'].sub(/.*!/, '') rescue
|
|
10
15
|
"/tmp/ns.#{ENV['USER']}.#{display[/:\d+/]}/wmii"
|
|
11
16
|
|
|
@@ -13,33 +18,40 @@ module Rumai
|
|
|
13
18
|
# We use a single, global connection to wmii's IXP server.
|
|
14
19
|
IXP_AGENT = IXP::Agent.new UNIXSocket.new(IXP_SOCK_ADDR)
|
|
15
20
|
|
|
16
|
-
rescue
|
|
17
|
-
|
|
21
|
+
rescue => error
|
|
22
|
+
error.message << %{
|
|
18
23
|
Ensure that (1) the WMII_ADDRESS environment variable is set and that (2)
|
|
19
24
|
it correctly specifies the filesystem path of wmii's IXP socket file,
|
|
20
25
|
which is typically located at "/tmp/ns.$USER.:$DISPLAY/wmii".
|
|
21
26
|
}.gsub(/^ +/, '').gsub(/\A|\z/, "\n")
|
|
22
27
|
|
|
23
|
-
raise
|
|
28
|
+
raise error
|
|
24
29
|
end
|
|
25
30
|
|
|
31
|
+
##
|
|
26
32
|
# An entry in the IXP file system.
|
|
33
|
+
#
|
|
27
34
|
class Node
|
|
28
35
|
@@cache = Hash.new {|h,k| h[k] = Node.new(k) }
|
|
29
36
|
|
|
30
37
|
attr_reader :path
|
|
31
38
|
|
|
32
|
-
def initialize
|
|
33
|
-
@path =
|
|
39
|
+
def initialize path
|
|
40
|
+
@path = path.to_s.squeeze('/')
|
|
34
41
|
end
|
|
35
42
|
|
|
43
|
+
##
|
|
36
44
|
# Returns file statistics about this node.
|
|
45
|
+
#
|
|
37
46
|
# See Rumai::IXP::Client#stat for details.
|
|
47
|
+
#
|
|
38
48
|
def stat
|
|
39
49
|
IXP_AGENT.stat @path
|
|
40
50
|
end
|
|
41
51
|
|
|
52
|
+
##
|
|
42
53
|
# Tests if this node exists on the IXP server.
|
|
54
|
+
#
|
|
43
55
|
def exist?
|
|
44
56
|
begin
|
|
45
57
|
true if stat
|
|
@@ -48,91 +60,122 @@ module Rumai
|
|
|
48
60
|
end
|
|
49
61
|
end
|
|
50
62
|
|
|
63
|
+
##
|
|
51
64
|
# Tests if this node is a directory.
|
|
65
|
+
#
|
|
52
66
|
def directory?
|
|
53
67
|
exist? and stat.directory?
|
|
54
68
|
end
|
|
55
69
|
|
|
70
|
+
##
|
|
56
71
|
# Returns the names of all files in this directory.
|
|
72
|
+
#
|
|
57
73
|
def entries
|
|
58
74
|
IXP_AGENT.entries @path rescue []
|
|
59
75
|
end
|
|
60
76
|
|
|
77
|
+
##
|
|
61
78
|
# Opens this node for I/O access.
|
|
79
|
+
#
|
|
62
80
|
# See Rumai::IXP::Client#open for details.
|
|
63
|
-
|
|
64
|
-
|
|
81
|
+
#
|
|
82
|
+
def open mode = 'r', &block
|
|
83
|
+
IXP_AGENT.open @path, mode, &block
|
|
65
84
|
end
|
|
66
85
|
|
|
86
|
+
##
|
|
67
87
|
# Returns the entire content of this node.
|
|
88
|
+
#
|
|
68
89
|
# See Rumai::IXP::Client#read for details.
|
|
69
|
-
|
|
70
|
-
|
|
90
|
+
#
|
|
91
|
+
def read *args
|
|
92
|
+
IXP_AGENT.read @path, *args
|
|
71
93
|
end
|
|
72
94
|
|
|
95
|
+
##
|
|
73
96
|
# Invokes the given block for every line in the content of this node.
|
|
74
|
-
|
|
97
|
+
#
|
|
98
|
+
def each_line &block #:yields: line
|
|
75
99
|
open do |file|
|
|
76
100
|
until (chunk = file.read(true)).empty?
|
|
77
|
-
chunk.each_line(&
|
|
101
|
+
chunk.each_line(&block)
|
|
78
102
|
end
|
|
79
103
|
end
|
|
80
104
|
end
|
|
81
105
|
|
|
106
|
+
##
|
|
82
107
|
# Writes the given content to this node.
|
|
83
|
-
|
|
84
|
-
|
|
108
|
+
#
|
|
109
|
+
def write content
|
|
110
|
+
IXP_AGENT.write @path, content
|
|
85
111
|
end
|
|
86
112
|
|
|
113
|
+
##
|
|
87
114
|
# Creates a file corresponding to this node on the IXP server.
|
|
115
|
+
#
|
|
88
116
|
# See Rumai::IXP::Client#create for details.
|
|
89
|
-
|
|
90
|
-
|
|
117
|
+
#
|
|
118
|
+
def create *args
|
|
119
|
+
IXP_AGENT.create @path, *args
|
|
91
120
|
end
|
|
92
121
|
|
|
122
|
+
##
|
|
93
123
|
# Deletes the file corresponding to this node on the IXP server.
|
|
124
|
+
#
|
|
94
125
|
def remove
|
|
95
126
|
IXP_AGENT.remove @path
|
|
96
127
|
end
|
|
97
128
|
|
|
129
|
+
##
|
|
98
130
|
# Returns the given sub-path as a Node object.
|
|
99
|
-
|
|
100
|
-
|
|
131
|
+
#
|
|
132
|
+
def [] sub_path
|
|
133
|
+
@@cache[ File.join(@path, sub_path.to_s) ]
|
|
101
134
|
end
|
|
102
135
|
|
|
136
|
+
##
|
|
103
137
|
# Returns the parent node of this node.
|
|
138
|
+
#
|
|
104
139
|
def parent
|
|
105
140
|
@@cache[ File.dirname(@path) ]
|
|
106
141
|
end
|
|
107
142
|
|
|
143
|
+
##
|
|
108
144
|
# Returns all child nodes of this node.
|
|
145
|
+
#
|
|
109
146
|
def children
|
|
110
147
|
entries.map! {|c| self[c] }
|
|
111
148
|
end
|
|
112
149
|
|
|
113
150
|
include Enumerable
|
|
151
|
+
|
|
152
|
+
##
|
|
114
153
|
# Iterates through each child of this directory.
|
|
115
|
-
|
|
116
|
-
|
|
154
|
+
#
|
|
155
|
+
def each &block
|
|
156
|
+
children.each(&block)
|
|
117
157
|
end
|
|
118
158
|
|
|
159
|
+
##
|
|
119
160
|
# Deletes all child nodes.
|
|
161
|
+
#
|
|
120
162
|
def clear
|
|
121
163
|
children.each do |c|
|
|
122
164
|
c.remove
|
|
123
165
|
end
|
|
124
166
|
end
|
|
125
167
|
|
|
168
|
+
##
|
|
126
169
|
# Provides access to child nodes through method calls.
|
|
127
170
|
#
|
|
128
171
|
# :call-seq: node.child -> Node
|
|
129
172
|
#
|
|
130
|
-
def method_missing
|
|
131
|
-
child = self[
|
|
173
|
+
def method_missing meth, *args
|
|
174
|
+
child = self[meth]
|
|
132
175
|
|
|
133
176
|
# speed up future accesses
|
|
134
177
|
(class << self; self; end).instance_eval do
|
|
135
|
-
define_method
|
|
178
|
+
define_method meth do
|
|
136
179
|
child
|
|
137
180
|
end
|
|
138
181
|
end
|
|
@@ -141,6 +184,7 @@ module Rumai
|
|
|
141
184
|
end
|
|
142
185
|
end
|
|
143
186
|
|
|
187
|
+
##
|
|
144
188
|
# Makes instance methods accessible through class
|
|
145
189
|
# methods. This is done to emulate the File class:
|
|
146
190
|
#
|
|
@@ -149,10 +193,10 @@ module Rumai
|
|
|
149
193
|
#
|
|
150
194
|
# Both of the above expressions are equivalent.
|
|
151
195
|
#
|
|
152
|
-
module
|
|
153
|
-
def self.extended
|
|
154
|
-
|
|
155
|
-
(class <<
|
|
196
|
+
module ExportInstanceMethods
|
|
197
|
+
def self.extended target #:nodoc:
|
|
198
|
+
target.instance_methods(false).each do |meth|
|
|
199
|
+
(class << target; self; end).instance_eval do
|
|
156
200
|
define_method meth do |path, *args|
|
|
157
201
|
new(path).__send__(meth, *args)
|
|
158
202
|
end
|
|
@@ -165,5 +209,5 @@ module Rumai
|
|
|
165
209
|
# that the Externalize* module can do its magic. If we include()d
|
|
166
210
|
# the module instead before all methods in the class have been
|
|
167
211
|
# defined, then the magic would only apply to SOME of the methods!
|
|
168
|
-
Node.extend
|
|
212
|
+
Node.extend ExportInstanceMethods
|
|
169
213
|
end
|
data/lib/rumai/ixp.rb
CHANGED
data/lib/rumai/ixp/message.rb
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
# Primitives for the 9P2000 protocol.
|
|
2
2
|
#
|
|
3
3
|
# See http://cm.bell-labs.com/sys/man/5/INDEX.html
|
|
4
|
+
#
|
|
4
5
|
# See http://swtch.com/plan9port/man/man9/
|
|
5
6
|
#
|
|
7
|
+
#--
|
|
8
|
+
# Copyright 2007 Suraj N. Kurapati
|
|
9
|
+
# See the LICENSE file for details.
|
|
10
|
+
#++
|
|
6
11
|
|
|
7
12
|
module Rumai
|
|
8
13
|
module IXP
|
|
@@ -19,49 +24,67 @@ module Rumai
|
|
|
19
24
|
const_set "BYTE#{bytes}_MASK", mask
|
|
20
25
|
end
|
|
21
26
|
|
|
27
|
+
##
|
|
22
28
|
# A 9P2000 byte stream.
|
|
29
|
+
#
|
|
23
30
|
module Stream
|
|
24
31
|
# uchar, ushort, uint32 (all of them little-endian)
|
|
25
32
|
PACKING_FLAGS = { 1 => 'C', 2 => 'v', 4 => 'V' }.freeze
|
|
26
33
|
|
|
34
|
+
##
|
|
27
35
|
# Unpacks the given number of bytes from this 9P2000 byte stream.
|
|
28
|
-
|
|
29
|
-
|
|
36
|
+
#
|
|
37
|
+
def read_9p num_bytes
|
|
38
|
+
read(num_bytes).unpack(PACKING_FLAGS[num_bytes])[0]
|
|
30
39
|
end
|
|
31
40
|
end
|
|
32
41
|
|
|
42
|
+
##
|
|
33
43
|
# A common container for exceptions concerning IXP.
|
|
44
|
+
#
|
|
34
45
|
class Error < StandardError
|
|
35
46
|
end
|
|
36
47
|
|
|
48
|
+
##
|
|
37
49
|
# A serializable 9P2000 data structure.
|
|
50
|
+
#
|
|
38
51
|
module Struct
|
|
39
52
|
attr_reader :fields
|
|
40
53
|
|
|
54
|
+
##
|
|
41
55
|
# Allows field values to be initialized via the constructor.
|
|
42
|
-
#
|
|
43
|
-
|
|
56
|
+
#
|
|
57
|
+
# [field_values]
|
|
58
|
+
# a mapping from field name to field value
|
|
59
|
+
#
|
|
60
|
+
def initialize field_values = {}
|
|
44
61
|
@fields = self.class.fields
|
|
45
|
-
@values =
|
|
62
|
+
@values = field_values
|
|
46
63
|
end
|
|
47
64
|
|
|
65
|
+
##
|
|
48
66
|
# Transforms this object into a string of 9P2000 bytes.
|
|
67
|
+
#
|
|
49
68
|
def to_9p
|
|
50
69
|
@fields.inject('') {|s,f| s << f.to_9p(@values) }
|
|
51
70
|
end
|
|
52
71
|
|
|
72
|
+
##
|
|
53
73
|
# Populates this object with information
|
|
54
74
|
# from the given 9P2000 byte stream.
|
|
55
|
-
|
|
75
|
+
#
|
|
76
|
+
def load_9p stream
|
|
56
77
|
@fields.each do |f|
|
|
57
|
-
f.load_9p
|
|
78
|
+
f.load_9p stream, @values
|
|
58
79
|
end
|
|
59
80
|
end
|
|
60
81
|
|
|
82
|
+
##
|
|
61
83
|
# Provides a convenient DSL (for defining fields)
|
|
62
84
|
# to all objects which *include* this module.
|
|
63
|
-
|
|
64
|
-
|
|
85
|
+
#
|
|
86
|
+
def self.included target
|
|
87
|
+
class << target
|
|
65
88
|
# Returns a list of fields which compose this Struct.
|
|
66
89
|
def fields
|
|
67
90
|
@fields ||=
|
|
@@ -72,11 +95,14 @@ module Rumai
|
|
|
72
95
|
end
|
|
73
96
|
end
|
|
74
97
|
|
|
98
|
+
##
|
|
75
99
|
# Defines a new field in this Struct.
|
|
76
|
-
#
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
100
|
+
#
|
|
101
|
+
# [args] arguments for Field.new()
|
|
102
|
+
#
|
|
103
|
+
def field name, format = nil, *args
|
|
104
|
+
c = Field.factory(format)
|
|
105
|
+
f = c.new(name.to_sym, format, *args)
|
|
80
106
|
fields << f # register field as being part of this structure
|
|
81
107
|
|
|
82
108
|
# provide accessor methods to field values
|
|
@@ -85,19 +111,21 @@ module Rumai
|
|
|
85
111
|
@values[#{f.name.inspect}]
|
|
86
112
|
end
|
|
87
113
|
|
|
88
|
-
def #{f.name}=
|
|
89
|
-
@values[#{f.name.inspect}] =
|
|
114
|
+
def #{f.name}= value
|
|
115
|
+
@values[#{f.name.inspect}] = value
|
|
90
116
|
end
|
|
91
117
|
}
|
|
92
118
|
|
|
93
119
|
return f
|
|
94
120
|
end
|
|
95
121
|
|
|
122
|
+
##
|
|
96
123
|
# Creates a new instance of this class from the
|
|
97
124
|
# given 9P2000 byte stream and returns the instance.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
msg.
|
|
125
|
+
#
|
|
126
|
+
def from_9p stream, msg_class = self
|
|
127
|
+
msg = msg_class.new
|
|
128
|
+
msg.load_9p(stream)
|
|
101
129
|
msg
|
|
102
130
|
end
|
|
103
131
|
end
|
|
@@ -105,48 +133,65 @@ module Rumai
|
|
|
105
133
|
|
|
106
134
|
private
|
|
107
135
|
|
|
108
|
-
|
|
136
|
+
##
|
|
137
|
+
# A field inside a Struct.
|
|
138
|
+
#
|
|
139
|
+
# A field's value is considered to be either:
|
|
109
140
|
# * array of format when <code>counter && format.is_a? Class</code>
|
|
110
141
|
# * raw byte string when <code>counter && format.nil?</code>
|
|
142
|
+
#
|
|
111
143
|
class Field
|
|
112
144
|
attr_reader :name, :format, :counter, :countee
|
|
113
145
|
|
|
114
|
-
|
|
115
|
-
#
|
|
116
|
-
#
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
146
|
+
##
|
|
147
|
+
# [name]
|
|
148
|
+
# unique (among all fields in a struct) name for the field
|
|
149
|
+
#
|
|
150
|
+
# [format]
|
|
151
|
+
# number of bytes, a class, or nil
|
|
152
|
+
#
|
|
153
|
+
# [counter]
|
|
154
|
+
# field which counts the length of this field's value
|
|
155
|
+
#
|
|
156
|
+
def initialize name, format = nil, counter = nil
|
|
157
|
+
@name = name
|
|
158
|
+
@format = format
|
|
120
159
|
@countee = nil
|
|
121
|
-
self.counter =
|
|
160
|
+
self.counter = counter
|
|
122
161
|
end
|
|
123
162
|
|
|
163
|
+
##
|
|
124
164
|
# Sets the counter for this field (implying that the
|
|
125
165
|
# length of this field is counted by the given field).
|
|
126
|
-
|
|
127
|
-
|
|
166
|
+
#
|
|
167
|
+
def counter= field
|
|
168
|
+
if @counter = field
|
|
128
169
|
extend CounteeField
|
|
129
170
|
@counter.countee = self
|
|
130
171
|
end
|
|
131
172
|
end
|
|
132
173
|
|
|
174
|
+
##
|
|
133
175
|
# Sets the countee for this field (implying that
|
|
134
176
|
# this field counts the length of the given field).
|
|
135
|
-
|
|
136
|
-
|
|
177
|
+
#
|
|
178
|
+
def countee= field
|
|
179
|
+
if @countee = field
|
|
137
180
|
extend CounterField
|
|
138
181
|
end
|
|
139
182
|
end
|
|
140
183
|
|
|
184
|
+
##
|
|
141
185
|
# Returns a Field class that best represents the given format.
|
|
142
|
-
|
|
143
|
-
|
|
186
|
+
#
|
|
187
|
+
def self.factory format
|
|
188
|
+
if format == String
|
|
144
189
|
StringField
|
|
145
190
|
|
|
146
|
-
elsif
|
|
191
|
+
elsif format.is_a? Class
|
|
147
192
|
ClassField
|
|
148
193
|
|
|
149
|
-
elsif
|
|
194
|
+
elsif format == 8
|
|
150
195
|
Integer8Field
|
|
151
196
|
|
|
152
197
|
else
|
|
@@ -154,42 +199,54 @@ module Rumai
|
|
|
154
199
|
end
|
|
155
200
|
end
|
|
156
201
|
|
|
202
|
+
##
|
|
157
203
|
# Transforms this object into a string of 9P2000 bytes.
|
|
158
|
-
|
|
159
|
-
|
|
204
|
+
#
|
|
205
|
+
def to_9p field_values
|
|
206
|
+
value_to_9p field_values[@name]
|
|
160
207
|
end
|
|
161
208
|
|
|
209
|
+
##
|
|
162
210
|
# Populates this object with information
|
|
163
211
|
# taken from the given 9P2000 byte stream.
|
|
164
|
-
|
|
165
|
-
|
|
212
|
+
#
|
|
213
|
+
def load_9p stream, field_values
|
|
214
|
+
field_values[@name] = value_from_9p stream
|
|
166
215
|
end
|
|
167
216
|
|
|
168
217
|
private
|
|
169
218
|
|
|
219
|
+
##
|
|
170
220
|
# Converts the given value, according to the format
|
|
171
221
|
# of this field, into a string of 9P2000 bytes.
|
|
172
|
-
|
|
173
|
-
|
|
222
|
+
#
|
|
223
|
+
def value_to_9p value
|
|
224
|
+
value.to_i.to_9p @format.to_i
|
|
174
225
|
end
|
|
175
226
|
|
|
227
|
+
##
|
|
176
228
|
# Parses a value, according to the format of
|
|
177
229
|
# this field, from the given 9P2000 byte stream.
|
|
178
|
-
|
|
179
|
-
|
|
230
|
+
#
|
|
231
|
+
def value_from_9p stream
|
|
232
|
+
stream.read_9p @format.to_i
|
|
180
233
|
end
|
|
181
234
|
|
|
235
|
+
##
|
|
182
236
|
# Methods for a field that counts the length of another field.
|
|
237
|
+
#
|
|
183
238
|
module CounterField
|
|
184
|
-
def to_9p
|
|
185
|
-
value_to_9p
|
|
239
|
+
def to_9p field_values
|
|
240
|
+
value_to_9p field_values[@countee.name].length
|
|
186
241
|
end
|
|
187
242
|
end
|
|
188
243
|
|
|
244
|
+
##
|
|
189
245
|
# Methods for a field whose length is counted by another field.
|
|
246
|
+
#
|
|
190
247
|
module CounteeField
|
|
191
|
-
def to_9p
|
|
192
|
-
value =
|
|
248
|
+
def to_9p field_values
|
|
249
|
+
value = field_values[@name]
|
|
193
250
|
|
|
194
251
|
if @format
|
|
195
252
|
value.map {|v| value_to_9p v}.join
|
|
@@ -198,54 +255,66 @@ module Rumai
|
|
|
198
255
|
end
|
|
199
256
|
end
|
|
200
257
|
|
|
201
|
-
def load_9p
|
|
202
|
-
count =
|
|
258
|
+
def load_9p stream, field_values
|
|
259
|
+
count = field_values[@counter.name].to_i
|
|
203
260
|
|
|
204
|
-
|
|
261
|
+
field_values[@name] =
|
|
205
262
|
if @format
|
|
206
|
-
Array.new(count) { value_from_9p
|
|
263
|
+
Array.new(count) { value_from_9p stream }
|
|
207
264
|
else
|
|
208
|
-
|
|
265
|
+
stream.read(count) # raw byte sequence
|
|
209
266
|
end
|
|
210
267
|
end
|
|
211
268
|
end
|
|
212
269
|
end
|
|
213
270
|
|
|
271
|
+
#:stopdoc:
|
|
272
|
+
|
|
273
|
+
##
|
|
214
274
|
# A field whose value knows how to convert itself to and from 9p.
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
275
|
+
#
|
|
276
|
+
class ClassField < Field
|
|
277
|
+
def value_to_9p value
|
|
278
|
+
value.to_9p
|
|
218
279
|
end
|
|
219
280
|
|
|
220
|
-
def value_from_9p
|
|
221
|
-
@format.from_9p
|
|
281
|
+
def value_from_9p stream
|
|
282
|
+
@format.from_9p stream
|
|
222
283
|
end
|
|
223
284
|
end
|
|
224
285
|
|
|
286
|
+
##
|
|
225
287
|
# A field whose value is a string.
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
288
|
+
#
|
|
289
|
+
class StringField < ClassField
|
|
290
|
+
def value_to_9p value
|
|
291
|
+
value.to_s.to_9p
|
|
229
292
|
end
|
|
230
293
|
end
|
|
231
294
|
|
|
295
|
+
##
|
|
232
296
|
# A field whose value is a 8-byte integer.
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
297
|
+
#
|
|
298
|
+
class Integer8Field < Field
|
|
299
|
+
def value_to_9p value
|
|
300
|
+
v = value.to_i
|
|
236
301
|
(BYTE4_MASK & v).to_9p(4) << # lower bytes
|
|
237
302
|
(BYTE4_MASK & (v >> BYTE4_BITS)).to_9p(4) # higher bytes
|
|
238
303
|
end
|
|
239
304
|
|
|
240
|
-
def value_from_9p
|
|
241
|
-
|
|
305
|
+
def value_from_9p stream
|
|
306
|
+
stream.read_9p(4) | (stream.read_9p(4) << BYTE4_BITS)
|
|
242
307
|
end
|
|
243
308
|
end
|
|
309
|
+
|
|
310
|
+
#:startdoc:
|
|
244
311
|
end
|
|
245
312
|
|
|
313
|
+
##
|
|
246
314
|
# Holds information about a file being accessed on a 9P2000 server.
|
|
247
315
|
#
|
|
248
316
|
# See http://cm.bell-labs.com/magic/man2html/5/intro
|
|
317
|
+
#
|
|
249
318
|
class Qid
|
|
250
319
|
include Struct
|
|
251
320
|
|
|
@@ -265,9 +334,11 @@ module Rumai
|
|
|
265
334
|
QTFILE = 0x00 # type bits for plain file
|
|
266
335
|
end
|
|
267
336
|
|
|
337
|
+
##
|
|
268
338
|
# Holds information about a file on a 9P2000 server.
|
|
269
339
|
#
|
|
270
340
|
# See http://cm.bell-labs.com/magic/man2html/5/stat
|
|
341
|
+
#
|
|
271
342
|
class Stat
|
|
272
343
|
include Struct
|
|
273
344
|
|
|
@@ -301,16 +372,20 @@ module Rumai
|
|
|
301
372
|
DMWRITE = 0x2 # mode bit for write permission
|
|
302
373
|
DMEXEC = 0x1 # mode bit for execute permission
|
|
303
374
|
|
|
375
|
+
##
|
|
304
376
|
# Tests if this file is a directory.
|
|
377
|
+
#
|
|
305
378
|
def directory?
|
|
306
379
|
mode & DMDIR > 0
|
|
307
380
|
end
|
|
308
381
|
end
|
|
309
382
|
|
|
383
|
+
##
|
|
310
384
|
# Fcall is the basic unit of communication in the 9P2000 protocol.
|
|
311
385
|
# It is analogous to a "packet" in the Internetwork Protocol (IP).
|
|
312
386
|
#
|
|
313
387
|
# See http://cm.bell-labs.com/magic/man2html/2/fcall
|
|
388
|
+
#
|
|
314
389
|
class Fcall
|
|
315
390
|
include Struct
|
|
316
391
|
|
|
@@ -322,7 +397,9 @@ module Rumai
|
|
|
322
397
|
#
|
|
323
398
|
field :tag , 2
|
|
324
399
|
|
|
400
|
+
##
|
|
325
401
|
# Transforms this object into a string of 9P2000 bytes.
|
|
402
|
+
#
|
|
326
403
|
def to_9p
|
|
327
404
|
data = type.to_9p(1) << super
|
|
328
405
|
size = (data.length + 4).to_9p(4)
|
|
@@ -331,19 +408,22 @@ module Rumai
|
|
|
331
408
|
|
|
332
409
|
class << self
|
|
333
410
|
alias __from_9p__ from_9p
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
411
|
+
undef from_9p
|
|
412
|
+
|
|
413
|
+
##
|
|
414
|
+
# Creates a new instance of this class from the
|
|
415
|
+
# given 9P2000 byte stream and returns the instance.
|
|
416
|
+
#
|
|
417
|
+
def from_9p stream
|
|
418
|
+
size = stream.read_9p(4)
|
|
419
|
+
type = stream.read_9p(1)
|
|
420
|
+
|
|
421
|
+
unless fcall = TYPE_TO_CLASS[type]
|
|
422
|
+
raise Error, "illegal fcall type: #{type}"
|
|
423
|
+
end
|
|
341
424
|
|
|
342
|
-
|
|
343
|
-
raise Error, "illegal fcall type: #{type}"
|
|
425
|
+
__from_9p__ stream, fcall
|
|
344
426
|
end
|
|
345
|
-
|
|
346
|
-
__from_9p__ aStream, fcall
|
|
347
427
|
end
|
|
348
428
|
|
|
349
429
|
NOTAG = BYTE2_MASK # (ushort)
|
|
@@ -531,6 +611,9 @@ module Rumai
|
|
|
531
611
|
class Rwstat < Fcall
|
|
532
612
|
end
|
|
533
613
|
|
|
614
|
+
##
|
|
615
|
+
# A remote function call (fcall).
|
|
616
|
+
#
|
|
534
617
|
class Fcall
|
|
535
618
|
CLASS_TO_TYPE = {
|
|
536
619
|
Tversion => 100,
|
|
@@ -565,12 +648,16 @@ module Rumai
|
|
|
565
648
|
|
|
566
649
|
TYPE_TO_CLASS = CLASS_TO_TYPE.invert.freeze
|
|
567
650
|
|
|
651
|
+
##
|
|
568
652
|
# Returns the value of the 'type' field for this fcall.
|
|
653
|
+
#
|
|
569
654
|
def self.type
|
|
570
655
|
CLASS_TO_TYPE[self]
|
|
571
656
|
end
|
|
572
657
|
|
|
658
|
+
##
|
|
573
659
|
# Returns the value of the 'type' field for this fcall.
|
|
660
|
+
#
|
|
574
661
|
def type
|
|
575
662
|
self.class.type
|
|
576
663
|
end
|
|
@@ -579,36 +666,46 @@ module Rumai
|
|
|
579
666
|
end
|
|
580
667
|
|
|
581
668
|
class Integer
|
|
669
|
+
##
|
|
582
670
|
# Transforms this object into a string of 9P2000 bytes.
|
|
583
|
-
|
|
584
|
-
|
|
671
|
+
#
|
|
672
|
+
def to_9p num_bytes
|
|
673
|
+
[self].pack Rumai::IXP::Stream::PACKING_FLAGS[num_bytes]
|
|
585
674
|
end
|
|
586
675
|
end
|
|
587
676
|
|
|
588
677
|
# count[2] s[count]
|
|
589
678
|
class String
|
|
679
|
+
##
|
|
590
680
|
# Transforms this object into a string of 9P2000 bytes.
|
|
681
|
+
#
|
|
591
682
|
def to_9p
|
|
592
683
|
length.to_9p(2) << self[0, Rumai::IXP::BYTE2_MASK]
|
|
593
684
|
end
|
|
594
685
|
|
|
686
|
+
##
|
|
595
687
|
# Creates a new instance of this class from the
|
|
596
688
|
# given 9P2000 byte stream and returns the instance.
|
|
597
|
-
|
|
598
|
-
|
|
689
|
+
#
|
|
690
|
+
def self.from_9p stream
|
|
691
|
+
stream.read(stream.read_9p(2))
|
|
599
692
|
end
|
|
600
693
|
end
|
|
601
694
|
|
|
602
695
|
class Time
|
|
696
|
+
##
|
|
603
697
|
# Transforms this object into a string of 9P2000 bytes.
|
|
698
|
+
#
|
|
604
699
|
def to_9p
|
|
605
700
|
to_i.to_9p(4)
|
|
606
701
|
end
|
|
607
702
|
|
|
703
|
+
##
|
|
608
704
|
# Creates a new instance of this class from the
|
|
609
705
|
# given 9P2000 byte stream and returns the instance.
|
|
610
|
-
|
|
611
|
-
|
|
706
|
+
#
|
|
707
|
+
def self.from_9p stream
|
|
708
|
+
at stream.read_9p(4)
|
|
612
709
|
end
|
|
613
710
|
end
|
|
614
711
|
|