ffi-xattr 0.0.3 → 0.0.4

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/.gitignore CHANGED
@@ -2,3 +2,4 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
+ /doc/
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - 1.9.3
5
+ before_script:
6
+ - sudo mount / -o remount,user_xattr
data/README.md CHANGED
@@ -3,23 +3,21 @@ ffi-xattr
3
3
 
4
4
  Ruby library to manage extended file attributes.
5
5
 
6
+ [![Build Status](https://secure.travis-ci.org/jarib/ffi-xattr.png)](http://travis-ci.org/jarib/ffi-xattr)
7
+
8
+
6
9
  Example
7
10
  -------
8
11
 
9
12
  xattr = Xattr.new("/path/to/file")
10
13
  xattr['user.foo'] = 'bar'
11
-
14
+
12
15
  xattr['user.foo'] #=> 'bar'
13
16
  xattr.list #=> ["user.foo"]
14
-
17
+
15
18
  xattr.each { |key, value| ... }
16
19
  xattr.as_json #=> {"user.foo" => "bar"}
17
20
 
18
- TODO
19
- ----
20
-
21
- * Handle symlinks
22
-
23
21
 
24
22
  Note on Patches/Pull Requests
25
23
  -----------------------------
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ include Rake::DSL
2
+
1
3
  require 'bundler'
2
4
  Bundler::GemHelper.install_tasks
3
5
 
data/ffi-xattr.gemspec CHANGED
@@ -14,8 +14,10 @@ Gem::Specification.new do |s|
14
14
 
15
15
  s.rubyforge_project = "ffi-xattr"
16
16
 
17
- s.add_development_dependency "rspec", "~> 2.5"
17
+
18
18
  s.add_dependency "ffi"
19
+ s.add_development_dependency "rspec", "~> 2.5"
20
+ s.add_development_dependency "rake", "~> 0.9.2"
19
21
 
20
22
  s.files = `git ls-files`.split("\n")
21
23
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -1,4 +1,4 @@
1
- class Xattr
1
+ class Xattr # :nodoc: all
2
2
  module Lib
3
3
  extend FFI::Library
4
4
 
@@ -9,32 +9,39 @@ class Xattr
9
9
  attach_function :setxattr, [:string, :string, :pointer, :size_t, :uint, :int], :int
10
10
  attach_function :removexattr, [:string, :string, :int], :int
11
11
 
12
+ XATTR_NOFOLLOW = 0x0001
12
13
 
13
- def self.list(path)
14
- size = listxattr(path, nil, 0, 0)
15
- res_ptr = FFI::MemoryPointer.new(:pointer, size)
16
- listxattr(path, res_ptr, size, 0)
14
+ class << self
15
+ def list(path, no_follow)
16
+ options = no_follow ? XATTR_NOFOLLOW : 0
17
+ size = listxattr(path, nil, 0, options)
18
+ res_ptr = FFI::MemoryPointer.new(:pointer, size)
19
+ listxattr(path, res_ptr, size, options)
17
20
 
18
- res_ptr.read_string(size).split("\000")
19
- end
21
+ res_ptr.read_string(size).split("\000")
22
+ end
20
23
 
21
- def self.get(path, key)
22
- size = getxattr(path, key, nil, 0, 0, 0)
23
- return unless size > 0
24
+ def get(path, no_follow, key)
25
+ options = no_follow ? XATTR_NOFOLLOW : 0
26
+ size = getxattr(path, key, nil, 0, 0, options)
27
+ return unless size > 0
24
28
 
25
- str_ptr = FFI::MemoryPointer.new(:char, size);
26
- getxattr(path, key, str_ptr, size, 0, 0)
29
+ str_ptr = FFI::MemoryPointer.new(:char, size)
30
+ getxattr(path, key, str_ptr, size, 0, options)
27
31
 
28
- str_ptr.read_string
29
- end
32
+ str_ptr.read_string
33
+ end
30
34
 
31
- def self.set(path, key, value)
32
- Error.check setxattr(path, key, value, value.bytesize, 0, 0)
33
- end
35
+ def set(path, no_follow, key, value)
36
+ options = no_follow ? XATTR_NOFOLLOW : 0
37
+ Error.check setxattr(path, key, value, value.bytesize, 0, options)
38
+ end
34
39
 
35
- def self.remove(path, key)
36
- Error.check removexattr(path, key, 0)
40
+ def remove(path, no_follow, key)
41
+ options = no_follow ? XATTR_NOFOLLOW : 0
42
+ Error.check removexattr(path, key, options)
43
+ end
37
44
  end
38
45
 
39
46
  end
40
- end
47
+ end
@@ -1,4 +1,4 @@
1
- class Xattr
1
+ class Xattr # :nodoc: all
2
2
  module Error
3
3
  extend FFI::Library
4
4
 
@@ -6,15 +6,17 @@ class Xattr
6
6
 
7
7
  attach_function :strerror_r, [:int, :pointer, :size_t], :int
8
8
 
9
- def self.last
10
- ptr = FFI::MemoryPointer.new(:char, 256)
11
- strerrror_r(FFI.errno, ptr, 256)
9
+ class << self
10
+ def last
11
+ ptr = FFI::MemoryPointer.new(:char, 256)
12
+ strerror_r(FFI.errno, ptr, 256)
12
13
 
13
- ptr.read_string
14
- end
14
+ ptr.read_string
15
+ end
15
16
 
16
- def self.check(int)
17
- raise last if int != 0
17
+ def check(int)
18
+ raise last if int != 0
19
+ end
18
20
  end
19
21
  end
20
- end
22
+ end
@@ -1,4 +1,4 @@
1
- class Xattr
1
+ class Xattr # :nodoc: all
2
2
  module Lib
3
3
  extend FFI::Library
4
4
 
@@ -11,31 +11,42 @@ class Xattr
11
11
  attach_function :getxattr, [:string, :string, :pointer, :size_t], :int
12
12
  attach_function :removexattr, [:string, :string], :int
13
13
 
14
- def self.list(path)
15
- size = listxattr(path, nil, 0)
16
- res_ptr = FFI::MemoryPointer.new(:pointer, size)
17
- listxattr(path, res_ptr, size)
18
-
19
- res_ptr.read_string(size).split("\000")
20
- end
21
-
22
- def self.get(path, key)
23
- size = getxattr(path, key, nil, 0)
24
- return unless size > 0
25
-
26
- str_ptr = FFI::MemoryPointer.new(:char, size);
27
- getxattr(path, key, str_ptr, size)
28
-
29
- str_ptr.read_string
30
- end
31
-
32
- def self.set(path, key, value)
33
- Error.check setxattr(path, key, value, value.bytesize, 0)
34
- end
35
-
36
- def self.remove(path, key)
37
- Error.check removexattr(path, key.to_s)
14
+ attach_function :llistxattr, [:string, :pointer, :size_t], :size_t
15
+ attach_function :lsetxattr, [:string, :string, :pointer, :size_t, :int], :int
16
+ attach_function :lgetxattr, [:string, :string, :pointer, :size_t], :int
17
+ attach_function :lremovexattr, [:string, :string], :int
18
+
19
+ class << self
20
+ def list(path, no_follow)
21
+ method = no_follow ? :llistxattr : :listxattr
22
+ size = send(method, path, nil, 0)
23
+ res_ptr = FFI::MemoryPointer.new(:pointer, size)
24
+ send(method, path, res_ptr, size)
25
+
26
+ res_ptr.read_string(size).split("\000")
27
+ end
28
+
29
+ def get(path, no_follow, key)
30
+ method = no_follow ? :lgetxattr : :getxattr
31
+ size = send(method, path, key, nil, 0)
32
+ return unless size > 0
33
+
34
+ str_ptr = FFI::MemoryPointer.new(:char, size)
35
+ send(method, path, key, str_ptr, size)
36
+
37
+ str_ptr.read_string
38
+ end
39
+
40
+ def set(path, no_follow, key, value)
41
+ method = no_follow ? :lsetxattr : :setxattr
42
+ Error.check send(method, path, key, value, value.bytesize, 0)
43
+ end
44
+
45
+ def remove(path, no_follow, key)
46
+ method = no_follow ? :lremovexattr : :removexattr
47
+ Error.check send(method, path, key)
48
+ end
38
49
  end
39
50
 
40
51
  end
41
- end
52
+ end
@@ -1,5 +1,3 @@
1
1
  class Xattr
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
4
-
5
-
data/lib/ffi-xattr.rb CHANGED
@@ -14,35 +14,44 @@ end
14
14
  class Xattr
15
15
  include Enumerable
16
16
 
17
- def initialize(path)
17
+ # Create a new Xattr instance with path.
18
+ # Use <tt>:no_follow => true</tt> in options to work on symlink itself instead of following it.
19
+ def initialize(path, options = {})
18
20
  raise Errno::ENOENT, path unless File.exist?(path)
19
21
  @path = path
22
+ @no_follow = !!options[:no_follow]
20
23
  end
21
24
 
25
+ # List extended attribute names
22
26
  def list
23
- Lib.list @path
27
+ Lib.list @path, @no_follow
24
28
  end
25
29
 
30
+ # Get an extended attribute value
26
31
  def get(key)
27
- Lib.get @path, key.to_s
32
+ Lib.get @path, @no_follow, key.to_s
28
33
  end
29
34
  alias_method :[], :get
30
35
 
36
+ # Set an extended attribute value
31
37
  def set(key, value)
32
- Lib.set @path, key.to_s, value.to_s
38
+ Lib.set @path, @no_follow, key.to_s, value.to_s
33
39
  end
34
40
  alias_method :[]=, :set
35
41
 
42
+ # Remove an extended attribute value
36
43
  def remove(key)
37
- Lib.remove @path, key.to_s
44
+ Lib.remove @path, @no_follow, key.to_s
38
45
  end
39
46
 
47
+ # Iterates over pairs of extended attribute names and values
40
48
  def each(&blk)
41
49
  list.each do |key|
42
50
  yield key, get(key)
43
51
  end
44
52
  end
45
53
 
54
+ # Returns hash of extended attributes
46
55
  def as_json(*args)
47
56
  res = {}
48
57
  each { |k,v| res[k] = v }
@@ -51,5 +60,3 @@ class Xattr
51
60
  end
52
61
 
53
62
  end
54
-
55
-
data/spec/xattr_spec.rb CHANGED
@@ -35,6 +35,10 @@ describe Xattr do
35
35
  xattr.list.should == []
36
36
  end
37
37
 
38
+ it "raises error when tries to remove inexistent attribute" do
39
+ lambda { xattr.remove("inexisting") }.should raise_error
40
+ end
41
+
38
42
  it "returns nil if the attribute is not set" do
39
43
  xattr.get("hello").should be_nil
40
44
  end
@@ -71,4 +75,66 @@ describe Xattr do
71
75
  lambda { Xattr.new("no-such-file") }.should raise_error(Errno::ENOENT)
72
76
  end
73
77
 
78
+ describe "respecting :no_follow option" do
79
+ let(:link) { "link.txt" }
80
+ let(:xattr_f) { Xattr.new(link, :no_follow => false) }
81
+ let(:xattr_n) { Xattr.new(link, :no_follow => true) }
82
+
83
+ before { File.symlink(path, link) }
84
+ after { File.delete(link) }
85
+
86
+ case RUBY_PLATFORM
87
+ when /linux/
88
+ # http://linux.die.net/man/5/attr
89
+ it "should allow getting extended attributes on any type" do
90
+ xattr['user.a']
91
+ xattr_f['user.b']
92
+ xattr_n['user.c']
93
+ end
94
+
95
+ it "should fail setting extended attributes on symlink" do
96
+ lambda { xattr['user.a'] = 'foo' }.should_not raise_error
97
+ lambda { xattr_f['user.b'] = 'bar' }.should_not raise_error
98
+ lambda { xattr_n['user.c'] = 'baz' }.should raise_error
99
+ end
100
+ when /darwin|bsd/
101
+ it "should set and get attributes" do
102
+ xattr['user.a'] = 'foo'
103
+ xattr_f['user.b'] = 'bar'
104
+ xattr_n['user.c'] = 'baz'
105
+
106
+ xattr.list.sort.should == %w[user.a user.b]
107
+ xattr_f.list.sort.should == %w[user.a user.b]
108
+ xattr_n.list.sort.should == %w[user.c]
109
+
110
+ xattr['user.a'].should == 'foo'
111
+ xattr['user.b'].should == 'bar'
112
+ xattr['user.c'].should be_nil
113
+ xattr_f['user.a'].should == 'foo'
114
+ xattr_f['user.b'].should == 'bar'
115
+ xattr_f['user.c'].should be_nil
116
+ xattr_n['user.a'].should be_nil
117
+ xattr_n['user.b'].should be_nil
118
+ xattr_n['user.c'].should == 'baz'
119
+ end
120
+
121
+ it "should remove attributes" do
122
+ xattr['user.a'] = 'foo'
123
+ xattr_f['user.b'] = 'bar'
124
+ xattr_n['user.c'] = 'baz'
125
+ xattr_n['user.d'] = 'ban'
126
+
127
+ xattr.list.sort.should == %w[user.a user.b]
128
+ xattr_f.list.sort.should == %w[user.a user.b]
129
+ xattr_n.list.sort.should == %w[user.c user.d]
130
+
131
+ xattr_f.remove('user.a')
132
+ xattr_n.remove('user.c')
133
+
134
+ xattr.list.sort.should == %w[user.b]
135
+ xattr_f.list.sort.should == %w[user.b]
136
+ xattr_n.list.sort.should == %w[user.d]
137
+ end
138
+ end
139
+ end
74
140
  end
metadata CHANGED
@@ -1,46 +1,79 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: ffi-xattr
3
- version: !ruby/object:Gem::Version
4
- version: 0.0.3
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 4
10
+ version: 0.0.4
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Jari Bakken
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2011-09-24 00:00:00.000000000Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: rspec
16
- requirement: &2164580140 !ruby/object:Gem::Requirement
17
+
18
+ date: 2011-11-15 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ type: :runtime
22
+ requirement: &id001 !ruby/object:Gem::Requirement
17
23
  none: false
18
- requirements:
19
- - - ~>
20
- - !ruby/object:Gem::Version
21
- version: '2.5'
22
- type: :development
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ hash: 3
28
+ segments:
29
+ - 0
30
+ version: "0"
23
31
  prerelease: false
24
- version_requirements: *2164580140
25
- - !ruby/object:Gem::Dependency
26
32
  name: ffi
27
- requirement: &2164578540 !ruby/object:Gem::Requirement
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ type: :development
36
+ requirement: &id002 !ruby/object:Gem::Requirement
28
37
  none: false
29
- requirements:
30
- - - ! '>='
31
- - !ruby/object:Gem::Version
32
- version: '0'
33
- type: :runtime
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ hash: 9
42
+ segments:
43
+ - 2
44
+ - 5
45
+ version: "2.5"
46
+ prerelease: false
47
+ name: rspec
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ type: :development
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ hash: 63
57
+ segments:
58
+ - 0
59
+ - 9
60
+ - 2
61
+ version: 0.9.2
34
62
  prerelease: false
35
- version_requirements: *2164578540
63
+ name: rake
64
+ version_requirements: *id003
36
65
  description: Manipulate extended file attributes
37
- email:
66
+ email:
38
67
  - jari.bakken@gmail.com
39
68
  executables: []
69
+
40
70
  extensions: []
71
+
41
72
  extra_rdoc_files: []
42
- files:
73
+
74
+ files:
43
75
  - .gitignore
76
+ - .travis.yml
44
77
  - Gemfile
45
78
  - LICENSE
46
79
  - README.md
@@ -54,27 +87,36 @@ files:
54
87
  - spec/xattr_spec.rb
55
88
  homepage: http://github.com/jarib/ffi-xattr
56
89
  licenses: []
90
+
57
91
  post_install_message:
58
92
  rdoc_options: []
59
- require_paths:
93
+
94
+ require_paths:
60
95
  - lib
61
- required_ruby_version: !ruby/object:Gem::Requirement
96
+ required_ruby_version: !ruby/object:Gem::Requirement
62
97
  none: false
63
- requirements:
64
- - - ! '>='
65
- - !ruby/object:Gem::Version
66
- version: '0'
67
- required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ hash: 3
102
+ segments:
103
+ - 0
104
+ version: "0"
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
106
  none: false
69
- requirements:
70
- - - ! '>='
71
- - !ruby/object:Gem::Version
72
- version: '0'
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ hash: 3
111
+ segments:
112
+ - 0
113
+ version: "0"
73
114
  requirements: []
115
+
74
116
  rubyforge_project: ffi-xattr
75
117
  rubygems_version: 1.8.10
76
118
  signing_key:
77
119
  specification_version: 3
78
120
  summary: Manipulate extended file attributes
79
- test_files:
121
+ test_files:
80
122
  - spec/xattr_spec.rb