fiemap 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 707e3fc4c69e0f3cac4ab2a777cabd8e49fb6c7b
4
+ data.tar.gz: 5e4d497661e79e08265ddb13ddef89baac3da0e4
5
+ SHA512:
6
+ metadata.gz: d251a7fd71d97821b17d2cd4f6816a351459df7b935b5e25f4e8d16f879578a3020dc0534178f8e504fcad88a5f8c6d7fc93e8bf64048cd36dd1384e616fe253
7
+ data.tar.gz: 698d3168ea96fa687218829cfab08bc60190cccb9fbbd66f6e8bf6baa6f32bc11d244cac5efed6fe71b85d97732fad15787e849aff5f8594c92b0a8d265986f9
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fiemap.gemspec
4
+ gemspec
5
+ gem "rake-compiler"
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Masaki Matsushita
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # Fiemap
2
+
3
+ FIEMAP ioctl wrapper for Ruby.
4
+ It adds File#extents and File::Extent class.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'fiemap'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install fiemap
21
+
22
+ ## Usage
23
+
24
+ ```ruby
25
+ require "fiemap"
26
+
27
+ f = File.open("something")
28
+ extents = f.extents #=> [#<File::Extent logical:0 physical:0 flags:delalloc>, #<File::Extent logical:8192 physical:0 flags:last,delalloc>]
29
+
30
+ extent = extents.last
31
+ extent.last? #=> true
32
+ extent.delalloc? #=> true
33
+ extent.inline? #=> false
34
+
35
+ extent.flags & File::Extent::FIEMAP_EXTENT_LAST #=> 1
36
+ ```
37
+
38
+ ## File::Extent
39
+
40
+ ### Instance Methods
41
+
42
+ * last?
43
+ * delalloc?
44
+ * encoded?
45
+ * encrypted?
46
+ * not_aligned?
47
+ * inline?
48
+ * tail?
49
+ * unwritten?
50
+ * merged?
51
+
52
+ ### Constants
53
+
54
+ * FIEMAP_EXTENT_LAST
55
+ * FIEMAP_EXTENT_UNKNOWN
56
+ * FIEMAP_EXTENT_DELALLOC
57
+ * FIEMAP_EXTENT_ENCODED
58
+ * FIEMAP_EXTENT_DATA_ENCRYPTED
59
+ * FIEMAP_EXTENT_NOT_ALIGNED
60
+ * FIEMAP_EXTENT_DATA_INLINE
61
+ * FIEMAP_EXTENT_DATA_TAIL
62
+ * FIEMAP_EXTENT_UNWRITTEN
63
+ * FIEMAP_EXTENT_MERGED
64
+
65
+ ## Contributing
66
+
67
+ 1. Fork it ( https://github.com/[my-github-username]/fiemap/fork )
68
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
69
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
70
+ 4. Push to the branch (`git push origin my-new-feature`)
71
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/extensiontask"
3
+
4
+ Rake::ExtensionTask.new "fiemap" do |ext|
5
+ ext.lib_dir = "lib/fiemap"
6
+ end
@@ -0,0 +1,2 @@
1
+ require "mkmf"
2
+ create_makefile("fiemap/fiemap")
@@ -0,0 +1,233 @@
1
+ #include <ruby.h>
2
+ #include <ruby/io.h>
3
+ #include <assert.h>
4
+ #include <sys/ioctl.h>
5
+ #include <linux/fs.h>
6
+ #include <linux/fiemap.h>
7
+
8
+ VALUE cExtent;
9
+ static ID id_flush;
10
+
11
+ enum {
12
+ MAX_EXTENT = 64
13
+ };
14
+
15
+ static size_t
16
+ extent_memsize(const void *p)
17
+ {
18
+ return p ? sizeof(struct fiemap_extent) : 0;
19
+ }
20
+
21
+ static const rb_data_type_t extent_data_type = {
22
+ "stat",
23
+ {NULL, RUBY_TYPED_DEFAULT_FREE, extent_memsize,},
24
+ NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
25
+ };
26
+
27
+ static VALUE
28
+ extent_new(VALUE klass, const struct fiemap_extent *extent)
29
+ {
30
+ struct fiemap_extent *new_extent = NULL;
31
+
32
+ if (extent) {
33
+ new_extent = ALLOC(struct fiemap_extent);
34
+ *new_extent = *extent;
35
+ }
36
+ return TypedData_Wrap_Struct(klass, &extent_data_type, new_extent);
37
+ }
38
+
39
+ static VALUE
40
+ extent_alloc(VALUE klass)
41
+ {
42
+ return extent_new(klass, NULL);
43
+ }
44
+
45
+ static const struct fiemap_extent *
46
+ get_extent(VALUE self)
47
+ {
48
+ const struct fiemap_extent *extent;
49
+ TypedData_Get_Struct(self, struct fiemap_extent, &extent_data_type, extent);
50
+ return extent;
51
+ }
52
+
53
+ static VALUE
54
+ extent_logical_offset(VALUE self)
55
+ {
56
+ return LONG2NUM(get_extent(self)->fe_logical);
57
+ }
58
+
59
+ static VALUE
60
+ extent_physical_offset(VALUE self)
61
+ {
62
+ return LONG2NUM(get_extent(self)->fe_physical);
63
+ }
64
+
65
+ static VALUE
66
+ extent_length(VALUE self)
67
+ {
68
+ return LONG2NUM(get_extent(self)->fe_length);
69
+ }
70
+
71
+ static VALUE
72
+ extent_flags(VALUE self)
73
+ {
74
+ return INT2FIX(get_extent(self)->fe_flags);
75
+ }
76
+
77
+ static VALUE
78
+ extent_test_flag(VALUE self, int flag)
79
+ {
80
+ if (get_extent(self)->fe_flags & flag) {
81
+ return Qtrue;
82
+ }
83
+ return Qfalse;
84
+ }
85
+
86
+ static VALUE
87
+ extent_last_p(VALUE self)
88
+ {
89
+ return extent_test_flag(self, FIEMAP_EXTENT_LAST);
90
+ }
91
+
92
+ static VALUE
93
+ extent_unknown_p(VALUE self)
94
+ {
95
+ return extent_test_flag(self, FIEMAP_EXTENT_UNKNOWN);
96
+ }
97
+
98
+ static VALUE
99
+ extent_delalloc_p(VALUE self)
100
+ {
101
+ return extent_test_flag(self, FIEMAP_EXTENT_DELALLOC);
102
+ }
103
+
104
+ static VALUE
105
+ extent_encoded_p(VALUE self)
106
+ {
107
+ return extent_test_flag(self, FIEMAP_EXTENT_ENCODED);
108
+ }
109
+
110
+ static VALUE
111
+ extent_encrypted_p(VALUE self)
112
+ {
113
+ return extent_test_flag(self, FIEMAP_EXTENT_DATA_ENCRYPTED);
114
+ }
115
+
116
+ static VALUE
117
+ extent_not_aligned_p(VALUE self)
118
+ {
119
+ return extent_test_flag(self, FIEMAP_EXTENT_NOT_ALIGNED);
120
+ }
121
+
122
+ static VALUE
123
+ extent_inline_p(VALUE self)
124
+ {
125
+ return extent_test_flag(self, FIEMAP_EXTENT_DATA_INLINE);
126
+ }
127
+
128
+ static VALUE
129
+ extent_tail_p(VALUE self)
130
+ {
131
+ return extent_test_flag(self, FIEMAP_EXTENT_DATA_TAIL);
132
+ }
133
+
134
+ static VALUE
135
+ extent_unwritten_p(VALUE self)
136
+ {
137
+ return extent_test_flag(self, FIEMAP_EXTENT_UNWRITTEN);
138
+ }
139
+
140
+ static VALUE
141
+ extent_merged_p(VALUE self)
142
+ {
143
+ return extent_test_flag(self, FIEMAP_EXTENT_MERGED);
144
+ }
145
+
146
+ #define rb_sys_fail_path(path) rb_sys_fail(NIL_P(path) ? 0 : RSTRING_PTR(path))
147
+
148
+ static VALUE
149
+ rb_file_extents(VALUE io)
150
+ {
151
+ unsigned int i;
152
+ VALUE temp;
153
+ rb_io_t *fptr;
154
+ __u64 end, start = 0;
155
+ struct stat statinfo;
156
+ VALUE extents = Qnil;
157
+ struct fiemap *p_filemap = (struct fiemap *)xmalloc(offsetof(struct fiemap, fm_extents[0]) + sizeof(struct fiemap_extent) * MAX_EXTENT);
158
+
159
+ temp = rb_io_check_io(io);
160
+ GetOpenFile(temp, fptr);
161
+
162
+ rb_funcall2(io, id_flush, 0, NULL);
163
+
164
+ if (fstat(fptr->fd, &statinfo) < 0) {
165
+ rb_sys_fail_path(fptr->pathv);
166
+ }
167
+
168
+ end = statinfo.st_size;
169
+
170
+ while (start < end) {
171
+ p_filemap->fm_start = start;
172
+ p_filemap->fm_length = end;
173
+ p_filemap->fm_flags = 0;
174
+ p_filemap->fm_extent_count = MAX_EXTENT;
175
+
176
+ if (ioctl(fptr->fd, FS_IOC_FIEMAP, p_filemap) == -1) {
177
+ rb_sys_fail_path(fptr->pathv);
178
+ }
179
+
180
+ if (NIL_P(extents)) {
181
+ extents = rb_ary_new_capa(p_filemap->fm_mapped_extents);
182
+ }
183
+ else {
184
+ rb_ary_resize(extents, RARRAY_LEN(extents) + p_filemap->fm_mapped_extents);
185
+ }
186
+
187
+ for (i=0; i < p_filemap->fm_mapped_extents; i++) {
188
+ struct fiemap_extent extent;
189
+
190
+ extent = p_filemap->fm_extents[i];
191
+ rb_ary_push(extents, extent_new(cExtent, &extent));
192
+ start = extent.fe_logical + extent.fe_length;
193
+ }
194
+ }
195
+
196
+ return extents;
197
+ }
198
+
199
+ void Init_fiemap(void) {
200
+ cExtent = rb_define_class_under(rb_cFile, "Extent", rb_cObject);
201
+ rb_define_alloc_func(cExtent, extent_alloc);
202
+
203
+ rb_define_method(cExtent, "offset", extent_logical_offset, 0);
204
+ rb_define_method(cExtent, "physical_offset", extent_physical_offset, 0);
205
+ rb_define_method(cExtent, "length", extent_length, 0);
206
+ rb_define_method(cExtent, "flags", extent_flags, 0);
207
+ rb_define_alias(cExtent, "size", "length");
208
+
209
+ rb_define_const(cExtent, "FIEMAP_EXTENT_LAST", INT2FIX(FIEMAP_EXTENT_LAST));
210
+ rb_define_const(cExtent, "FIEMAP_EXTENT_UNKNOWN", INT2FIX(FIEMAP_EXTENT_UNKNOWN));
211
+ rb_define_const(cExtent, "FIEMAP_EXTENT_DELALLOC", INT2FIX(FIEMAP_EXTENT_DELALLOC));
212
+ rb_define_const(cExtent, "FIEMAP_EXTENT_ENCODED", INT2FIX(FIEMAP_EXTENT_ENCODED));
213
+ rb_define_const(cExtent, "FIEMAP_EXTENT_DATA_ENCRYPTED", INT2FIX(FIEMAP_EXTENT_DATA_ENCRYPTED));
214
+ rb_define_const(cExtent, "FIEMAP_EXTENT_NOT_ALIGNED", INT2FIX(FIEMAP_EXTENT_NOT_ALIGNED));
215
+ rb_define_const(cExtent, "FIEMAP_EXTENT_DATA_INLINE", INT2FIX(FIEMAP_EXTENT_DATA_INLINE));
216
+ rb_define_const(cExtent, "FIEMAP_EXTENT_DATA_TAIL", INT2FIX(FIEMAP_EXTENT_DATA_TAIL));
217
+ rb_define_const(cExtent, "FIEMAP_EXTENT_UNWRITTEN", INT2FIX(FIEMAP_EXTENT_UNWRITTEN));
218
+ rb_define_const(cExtent, "FIEMAP_EXTENT_MERGED", INT2FIX(FIEMAP_EXTENT_MERGED));
219
+
220
+ rb_define_method(cExtent, "last?", extent_last_p, 0);
221
+ rb_define_method(cExtent, "delalloc?", extent_delalloc_p, 0);
222
+ rb_define_method(cExtent, "encoded?", extent_encoded_p, 0);
223
+ rb_define_method(cExtent, "encrypted?", extent_encrypted_p, 0);
224
+ rb_define_method(cExtent, "not_aligned?", extent_not_aligned_p, 0);
225
+ rb_define_method(cExtent, "inline?", extent_inline_p, 0);
226
+ rb_define_method(cExtent, "tail?", extent_tail_p, 0);
227
+ rb_define_method(cExtent, "unwritten?", extent_unwritten_p, 0);
228
+ rb_define_method(cExtent, "merged?", extent_merged_p, 0);
229
+
230
+ rb_define_method(rb_cFile, "extents", rb_file_extents, 0);
231
+
232
+ id_flush = rb_intern("flush");
233
+ }
data/fiemap.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'fiemap/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "fiemap"
8
+ spec.version = FIEMAP::VERSION
9
+ spec.authors = ["Masaki Matsushita"]
10
+ spec.email = ["glass.saga@gmail.com"]
11
+ spec.summary = %q{fiemap ioctl wrapper}
12
+ spec.description = %q{fiemap ioctl wrapper}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+ spec.extensions = %w[ext/fiemap/extconf.rb]
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.6"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "rake-compiler", "~> 0.9.3"
25
+ end
@@ -0,0 +1,3 @@
1
+ class FIEMAP
2
+ VERSION = "0.0.1"
3
+ end
data/lib/fiemap.rb ADDED
@@ -0,0 +1,30 @@
1
+ require "fiemap/version"
2
+ require "fiemap/fiemap"
3
+
4
+ class File
5
+ class Extent
6
+ private_class_method :new
7
+
8
+ def inspect
9
+ "#<#{self.class} logical:#{self.offset} physical:#{self.physical_offset} flags:#{flags_inspect}>"
10
+ end
11
+
12
+ alias to_s inspect
13
+
14
+ private
15
+
16
+ def flags_inspect
17
+ flags = []
18
+ flags << "last" if last?
19
+ flags << "delalloc" if delalloc?
20
+ flags << "encoded" if encoded?
21
+ flags << "encrypted" if encrypted?
22
+ flags << "not_aligned" if not_aligned?
23
+ flags << "inline?" if inline?
24
+ flags << "tail" if tail?
25
+ flags << "unwritten" if unwritten?
26
+ flags << "merged" if merged?
27
+ flags.join(",")
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,56 @@
1
+ require_relative "spec_helper"
2
+
3
+ describe "File#extents" do
4
+ context "one extent" do
5
+ let(:tempfile) { Tempfile.new("fiemap_spec") }
6
+
7
+ before { tempfile.write("a" * 4096) }
8
+
9
+ subject { tempfile.extents }
10
+
11
+ it { is_expected.to be_a Array }
12
+ it { expect(subject.size).to eq(1) }
13
+
14
+ after do
15
+ tempfile.close unless tempfile.closed?
16
+ end
17
+ end
18
+
19
+ context "two extent" do
20
+ let(:tempfile) { Tempfile.new("fiemap_spec") }
21
+
22
+ before do
23
+ tempfile.write("a" * 4096)
24
+ tempfile.seek(4096, :CUR)
25
+ tempfile.write("a" * 4096)
26
+ end
27
+
28
+ subject { tempfile.extents }
29
+
30
+ it { is_expected.to be_a Array }
31
+ it { expect(subject.size).to eq(2) }
32
+
33
+ after do
34
+ tempfile.close unless tempfile.closed?
35
+ end
36
+ end
37
+ end
38
+
39
+ describe File::Extent do
40
+ let(:tempfile) { Tempfile.new("fiemap_spec") }
41
+
42
+ before { tempfile.write("a" * 4096) }
43
+
44
+ subject { tempfile.extents.first }
45
+
46
+ flag_methods = [:last?, :delalloc?, :encoded?, :encrypted?, :not_aligned?, :inline?, :tail?, :unwritten?, :merged?]
47
+ flag_methods.each do |method|
48
+ it "#{method} doesn't raise error" do
49
+ expect { subject.send(method) }.not_to raise_error
50
+ end
51
+ end
52
+
53
+ after do
54
+ tempfile.close unless tempfile.closed?
55
+ end
56
+ end
@@ -0,0 +1,2 @@
1
+ require "tempfile"
2
+ require_relative "../lib/fiemap"
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fiemap
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Masaki Matsushita
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake-compiler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.9.3
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.9.3
55
+ description: fiemap ioctl wrapper
56
+ email:
57
+ - glass.saga@gmail.com
58
+ executables: []
59
+ extensions:
60
+ - ext/fiemap/extconf.rb
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - Gemfile
65
+ - LICENSE.txt
66
+ - README.md
67
+ - Rakefile
68
+ - ext/fiemap/extconf.rb
69
+ - ext/fiemap/fiemap.c
70
+ - fiemap.gemspec
71
+ - lib/fiemap.rb
72
+ - lib/fiemap/version.rb
73
+ - spec/fiemap_spec.rb
74
+ - spec/spec_helper.rb
75
+ homepage: ''
76
+ licenses:
77
+ - MIT
78
+ metadata: {}
79
+ post_install_message:
80
+ rdoc_options: []
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project:
95
+ rubygems_version: 2.4.1
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: fiemap ioctl wrapper
99
+ test_files:
100
+ - spec/fiemap_spec.rb
101
+ - spec/spec_helper.rb
102
+ has_rdoc: