fiemap 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: