extattr 0.1 → 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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0a1d94f6586158eb3abf46fb3fc8d43edd251763379f32e57f77ebfaa1db0a6f
4
+ data.tar.gz: 80e8c90ee1e866018f7ddc06d621f733f33276b5beaeac8cd9687da3a086a9a1
5
+ SHA512:
6
+ metadata.gz: ccd9f917160b92b4cc52e02d56505b5824750a73442b8bad7d71041e3e5bd3f0b81dc2a93b5db14312093df65e12fca78085b7f0fc91c2263c53571821ff5679
7
+ data.tar.gz: 0b68f33f665fc50938567a64f8adb3ecdec402c699b3bc26e143a41a73ffd489c6b5d6ffdfc5ee813a82f26bef9ff9b1df4e3850ff2bb853274525fefcb86d74
data/HISTORY.ja.md ADDED
@@ -0,0 +1,49 @@
1
+ # extattr-0.4
2
+
3
+ - Ruby 3 の `Ractor` への対応 (thanks @okeeblow, https://github.com/dearblue/ruby-extattr/pull/1)
4
+ - `bin/extattr` コマンドラインプログラムを削除
5
+
6
+ まだ小さな不具合があり、調整が必要です。
7
+ 独立した gem `extattr-cli` として提供することを計画しています。
8
+
9
+
10
+ # extattr-0.3
11
+
12
+ extattr-0.2 との互換性はありません。
13
+
14
+ - `ExtAttr` モジュールを追加して実装をそちらに移動
15
+ - `File` クラスに対するメソッドの追加は、リファインメント機能によって拡張されます。
16
+ ```ruby
17
+ using ExtAttr
18
+ ```
19
+ - `File::EXTATTR_VERSION` 定数は冗長と判断し削除しました。
20
+ - `ExtAttr::Accessor` クラスの追加
21
+ - 拡張属性の操作に特化したオブジェクトを扱えるようになりました。
22
+ - `bin/extattr` コマンドラインプログラムの追加
23
+ - mingw でライブラリを構築する時 C 実行時ライブラリを静的リンクするように変更
24
+
25
+ # extattr-0.2
26
+
27
+ * セーフレベルに関する改善
28
+ * `$SAFE` と汚染状態を確認するようになりました
29
+ * 汚染状態を伝播させるようになりました
30
+ * バージョン情報と実装 API に関する情報の取得
31
+ * `File::EXTATTR_VERSION` 定数によって、バージョン情報が取得できるようになりました
32
+ * `File::EXTATTR_IMPLEMENT` 定数によって、実装に関する情報が取得できるようになりました
33
+ * 機能の改善
34
+ * `File.extattr_each` / `File#extattr_each` によって、ファイル拡張属性の名前と値を繰り返し取得できるようになりました
35
+ * Windows 版に関する改善
36
+ * `File::EXTATTR_NAMESPACE_SYSTEM` によって、本来の拡張ファイル属性の操作が行えるようになりました
37
+ (NtQueryEaFile / NtSetEaFile)
38
+
39
+ # extattr-0.1.2
40
+
41
+ # extattr-0.1.1
42
+
43
+ # extattr-0.1
44
+
45
+ はじめてのりりーす
46
+
47
+ * 拡張ファイル属性の一覧、取得、設定、削除を行うことが出来ます
48
+ * **セキュリティリスクあり**: `$SAFE` の確認や汚染状態の伝播を行ないません
49
+ * Windows 版では、NTFS ADS に対する操作となります。`File::EXTATTR_NAMESPACE_USER` のみが有効です
@@ -1,3 +1,8 @@
1
+
2
+ extattr license (2-clause BSD License)
3
+
4
+ - - - -
5
+
1
6
  Copyright (c) 2012, dearblue. All rights reserved.
2
7
 
3
8
  Redistribution and use in source and binary forms, with or
data/QUICKREF.ja.md ADDED
@@ -0,0 +1,112 @@
1
+ # Quick Reference
2
+
3
+ メソッド名に『!』がついているものはシンボリックリンクに対する操作となります。
4
+
5
+ キーワード引数の `namespace` を与えると、拡張属性の名前空間を指定できます。
6
+
7
+ 与えられる値:
8
+
9
+ - `ExtAttr::USER`
10
+ - `ExtAttr::SYSTEM`
11
+ - `user` 又は `system` を文字列かシンボルで (大文字小文字は区別されない)
12
+ - `nil` (`ExtAttr::USER` と等価)
13
+
14
+ 規定値は `ExtAttr::USER` です。
15
+
16
+
17
+ ## モジュール `ExtAttr`
18
+
19
+ - `ExtAttr.list(path, namespace) -> array`
20
+ - `ExtAttr.list!(path, namespace) -> array`
21
+ - `ExtAttr.size(path, namespace, name) -> integer`
22
+ - `ExtAttr.size!(path, namespace, name) -> integer`
23
+ - `ExtAttr.get(path, namespace, name) -> string`
24
+ - `ExtAttr.get!(path, namespace, name) -> string`
25
+ - `ExtAttr.set(path, namespace, name, value) -> nil`
26
+ - `ExtAttr.set!(path, namespace, name, value) -> nil`
27
+ - `ExtAttr.delete(path, namespace, name) -> nil`
28
+ - `ExtAttr.delete!(path, namespace, name) -> nil`
29
+ - `ExtAttr.open(path) -> a ExtAttr::Accessor instance`
30
+ - `ExtAttr.open(path) { |ea| ... } -> returned value from yield block`
31
+ - `ExtAttr.each(path, namespace) -> an ExtAttr::Accessor instance`
32
+ - `ExtAttr.each(path, namespace = ExtAttr::USER) -> an enumerator instance`
33
+ - `ExtAttr.each(path, namespace = ExtAttr::USER) { |name, data| ... } -> path`
34
+ - `ExtAttr.each!(path, namespace = ExtAttr::USER) -> an enumerator instance`
35
+ - `ExtAttr.each!(path, namespace = ExtAttr::USER) { |name, data| ... } -> path`
36
+
37
+
38
+ ## クラス `ExtAttr::Accessor`
39
+
40
+ - `ExtAttr::Accessor#each(namespace: ExtAttr::USER) -> an enumerator instance`
41
+ - `ExtAttr::Accessor#each(namespace: ExtAttr::USER) { |name, data| ... } -> path`
42
+ - `ExtAttr::Accessor#list(namespace: ExtAttr::USER) -> array`
43
+ - `ExtAttr::Accessor#size(name, namespace: ExtAttr::USER) -> integer`
44
+ - `ExtAttr::Accessor#get(name, namespace: ExtAttr::USER) -> string`
45
+ - `ExtAttr::Accessor#set(name, data, namespace: ExtAttr::USER) -> nil`
46
+ - `ExtAttr::Accessor#delete(name, namespace: ExtAttr::USER) -> nil`
47
+
48
+
49
+ ## リファインメント `using ExtAttr`
50
+
51
+ リファインメント機能を使うことにより、`File` が拡張されます。
52
+
53
+ ### 拡張属性オブジェクトを生成する
54
+
55
+ ```ruby:ruby
56
+ File.extattr(path) -> an ExtAttr::Accessor instance
57
+ File#extattr -> an ExtAttr::Accessor instance
58
+ ```
59
+
60
+ ### 拡張属性の属性名を取得
61
+
62
+ ```ruby:ruby
63
+ File.extattr_list(path, namespace: ExtAttr::USER) -> array
64
+ File.extattr_list(path, namespace: ExtAttr::USER) { |name| ... } -> nil
65
+ File.extattr_list!(path, namespace: ExtAttr::USER) -> array
66
+ File.extattr_list!(path, namespace: ExtAttr::USER) { |name| ... } -> nil
67
+ File#extattr_list(namespace: ExtAttr::USER) -> array
68
+ File#extattr_list(namespace: ExtAttr::USER) { |name| ... } -> nil
69
+ ```
70
+
71
+ ### 拡張属性の要素の大きさを取得
72
+
73
+ ```ruby:ruby
74
+ File.extattr_size(path, name, namespace: ExtAttr::USER) -> size
75
+ File.extattr_size!(path, name, namespace: ExtAttr::USER) -> size
76
+ File#extattr_size(name, namespace: ExtAttr::USER) -> size
77
+ ```
78
+
79
+ ### 拡張属性の要素を取得
80
+
81
+ ```ruby:ruby
82
+ File.extattr_get(path, name, namespace: ExtAttr::USER) -> data (String)
83
+ File.extattr_get!(path, name, namespace: ExtAttr::USER) -> data (String)
84
+ File#extattr_get(name, namespace: ExtAttr::USER) -> data (String)
85
+ ```
86
+
87
+ ### 拡張属性の要素を設定
88
+
89
+ ```ruby:ruby
90
+ File.extattr_set(path, name, data, namespace: ExtAttr::USER) -> nil
91
+ File.extattr_set!(path, name, data, namespace: ExtAttr::USER) -> nil
92
+ File#extattr_set(name, data, namespace: ExtAttr::USER) -> nil
93
+ ```
94
+
95
+ ### 拡張属性の要素を削除
96
+
97
+ ```ruby:ruby
98
+ File.extattr_delete(path, name, namespace: ExtAttr::USER) -> nil
99
+ File.extattr_delete!(path, name, namespace: ExtAttr::USER) -> nil
100
+ File#extattr_delete(name, namespace: ExtAttr::USER) -> nil
101
+ ```
102
+
103
+ ### 拡張属性の属性名と要素を列挙する
104
+
105
+ ```ruby:ruby
106
+ File.extattr_each(path, namespace: ExtAttr::USER) -> Enumerator
107
+ File.extattr_each(path, namespace: ExtAttr::USER) { |name, data| ... } -> nil
108
+ File.extattr_each!(path, namespace: ExtAttr::USER) -> Enumerator
109
+ File.extattr_each!(path, namespace: ExtAttr::USER) { |name, data| ... } -> nil
110
+ File#extattr_each(namespace: ExtAttr::USER) -> Enumerator
111
+ File#extattr_each(namespace: ExtAttr::USER) { |name, data| ... } -> file
112
+ ```
data/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # extattr - filesystem extended attributes manipurator for Ruby
2
+
3
+ extattr is filesystem extended attributes manipurator for Ruby on FreeBSD, GNU/Linux and Microsoft Windows.
4
+
5
+ - [Quick Reference](QUICKREF.ja.md) (in Japanese)
6
+ - [HISTORY](HISTORY.ja.md) (in Japanese)
7
+
8
+ extattr はファイルシステムの拡張属性を操作するライブラリで、FreeBSD、GNU/Linux、Windows に対応しています。
9
+
10
+ サポートされる環境で、統一的なメソッドを提供します。
11
+
12
+ 実装については、以下のようになっています。
13
+
14
+ * FreeBSD: extattr (`extattr_list`, `extattr_get`, `extattr_set`, `extattr_delete`)
15
+ * GNU/Linux: xattr (`listxattr`, `getxattr`, `setxattr`, `removexattr`)
16
+ * Microsoft Windows: NTFS ADS (代替データストリーム) / 拡張ファイル属性 (`NtQueryEaFile`, `NtSetEaFile`)
17
+
18
+
19
+ ## Tested system
20
+
21
+ * PC-BSD/AMD64 10.0
22
+ * lubuntu 13.10 (i386)
23
+ * Microsoft Windows XP Professional SP3
24
+ * Microsoft Windows 7 Professional SP1
25
+
26
+
27
+ ## GNU/Linux における特記事項
28
+
29
+ * GNU/Linux で利用されている名前空間〈security〉〈trusted〉には未対応です。
30
+
31
+
32
+ ## Microsoft Windows における特記事項
33
+
34
+ * Windows XP 以降を必要とします。Win2k でも動作するかもしれません (未検証)。<br>
35
+ Windows 9x シリーズでは `require "extattr"` の段階で例外が発生すると思われます (未検証)。
36
+ * ``ExtAttr::USER`` は (比較的よく利用される) NTFS ADS に対する操作で、``ExtAttr::SYSTEM`` が本来の (あまり利用されていない) 拡張ファイル属性に対する操作となります。
37
+ * リパースポイント (ジャンクションやシンボリックリンク) に対する NTFS ADS は要素の取得や設定、削除は出来ません。<br>
38
+ 必ずリンク先に対する操作となります (やり方がわかりません)。
39
+ * 64 KiB を超える NTFS ADS は取得も設定も出来ません。<br>
40
+ これは『拡張属性』と捉えた場合、巨大なデータを扱えるべきではないという考えによるためです
41
+ (本当のところは FreeBSD の拡張属性が最大 64KiB 弱であることが由来です)。
42
+ * 巨大な NTFS ADS を扱いたい場合は、``File.open`` でファイルとして扱えるので自由に読み書きできます。<br>
43
+ これは Ruby に限ったことではなく、Windows による仕様です。<br>
44
+ この場合の与えるファイル名は、``path + ":" + name`` という形になります。
45
+
46
+ ``` ruby:ruby
47
+ filepath = "sample.txt"
48
+ extattrname = "category"
49
+ ntfs_ads_name = filepath + ":" + extattrname
50
+ File.open(ntfs_ads_name, "r") do |file|
51
+ ...
52
+ end
53
+ ```
54
+
55
+ ## 既知のバグ
56
+
57
+ * ``extattr_list`` のブロック内で ``extattr_set`` ``extattr_delete`` を行うと正確な列挙がされない場合がある
58
+
59
+ 解決方法: ``extattr_set`` か ``extattr_delete`` のどちらかを同時に利用したい場合、``extattr_list.each`` を用いてください。
60
+
61
+
62
+ ## 参考資料
63
+
64
+ * extattr
65
+ * <https://www.freebsd.org/cgi/man.cgi?query=extattr&sektion=2>
66
+ * xattr
67
+ * <https://linuxjm.osdn.jp/html/LDP_man-pages/man2/listxattr.2.html>
68
+ * windows
69
+ * <https://msdn.microsoft.com/en-us/library/cc232069.aspx>
70
+ * <https://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/FILE_INFORMATION_CLASS.html>
71
+ * <https://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/NtQueryInformationFile.html>
72
+ * <https://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/NtQueryEaFile.html>
73
+ * <https://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/NtSetEaFile.html>
74
+ * FileTest <http://www.zezula.net/en/fstools/filetest.html> <https://github.com/ladislav-zezula/FileTest>
75
+
76
+ ## Specification
77
+
78
+ - package name: [extattr](https://rubygems.org/gems/extattr)
79
+ - Author: dearblue
80
+ - Version: 0.4
81
+ - Product quality: technical preview
82
+ - License: [2-clause BSD License](LICENSE.md)
83
+ - Project page: <https://github.com/dearblue/ruby-extattr>
84
+ - Support Ruby: Ruby 2.5+
data/Rakefile ADDED
@@ -0,0 +1,212 @@
1
+
2
+ require "pathname"
3
+ require "rake/clean"
4
+
5
+ docnames = "{README,LICENSE,CHANGELOG,Changelog,HISTORY}"
6
+ doctypes = "{,.txt,.rd,.rdoc,.md,.markdown}"
7
+ cexttypes = "{c,C,cc,cxx,cpp,h,H,hh}"
8
+
9
+ DOC = FileList["#{docnames}{,.ja}#{doctypes}"] +
10
+ FileList["{contrib,ext}/**/#{docnames}{,.ja}#{doctypes}"] +
11
+ FileList["ext/**/*.#{cexttypes}"]
12
+ EXT = FileList["ext/**/*"]
13
+ BIN = FileList["bin/*"]
14
+ LIB = FileList["lib/**/*.rb"]
15
+ SPEC = FileList["spec/**/*"]
16
+ TEST = FileList["test/**/*"]
17
+ EXAMPLE = FileList["examples/**/*"]
18
+ GEMSTUB_SRC = "gemstub.rb"
19
+ RAKEFILE = [File.basename(__FILE__), GEMSTUB_SRC]
20
+ EXTRA = []
21
+ EXTCONF = FileList["ext/**/extconf.rb"]
22
+ EXTCONF.reject! { |n| !File.file?(n) }
23
+ EXTMAP = {}
24
+
25
+ load GEMSTUB_SRC
26
+
27
+ EXTMAP.dup.each_pair do |dir, name|
28
+ EXTMAP[Pathname.new(dir).cleanpath.to_s] = Pathname.new(name).cleanpath.to_s
29
+ end
30
+
31
+ GEMSTUB.extensions += EXTCONF
32
+ GEMSTUB.executables += FileList["bin/*"].map { |n| File.basename n }
33
+ GEMSTUB.executables.sort!
34
+
35
+ PACKAGENAME = "#{GEMSTUB.name}-#{GEMSTUB.version}"
36
+ GEMFILE = "#{PACKAGENAME}.gem"
37
+ GEMSPEC = "#{PACKAGENAME}.gemspec"
38
+
39
+ GEMSTUB.files += DOC + EXT + EXTCONF + BIN + LIB + SPEC + TEST + EXAMPLE + RAKEFILE + EXTRA
40
+ GEMSTUB.files.sort!
41
+ if GEMSTUB.rdoc_options.nil? || GEMSTUB.rdoc_options.empty?
42
+ readme = %W(.md .markdown .rd .rdoc .txt #{""}).map { |ext| "README#{ext}" }.find { |m| DOC.find { |n| n == m } }
43
+ GEMSTUB.rdoc_options = %w(--charset UTF-8) + (readme ? %W(-m #{readme}) : [])
44
+ end
45
+ GEMSTUB.extra_rdoc_files += DOC + LIB + EXT.reject { |n| n.include?("/externals/") || !%w(.h .hh .c .cc .cpp .cxx).include?(File.extname(n)) }
46
+ GEMSTUB.extra_rdoc_files.sort!
47
+
48
+ GEMSTUB_TRYOUT = GEMSTUB.dup
49
+ GEMSTUB_TRYOUT.version = "#{GEMSTUB.version}#{Time.now.strftime(".TRYOUT.%Y%m%d.%H%M%S")}"
50
+ PACKAGENAME_TRYOUT = "#{GEMSTUB.name}-#{GEMSTUB_TRYOUT.version}"
51
+ GEMFILE_TRYOUT = "#{PACKAGENAME_TRYOUT}.gem"
52
+ GEMSPEC_TRYOUT = "#{PACKAGENAME_TRYOUT}.gemspec"
53
+
54
+ CLEAN << GEMSPEC << GEMSPEC_TRYOUT
55
+ CLOBBER << GEMFILE
56
+
57
+ task :default => :tryout do
58
+ $stderr.puts <<-EOS
59
+ #{__FILE__}:#{__LINE__}:
60
+ \ttype ``rake release'' to build release package.
61
+ EOS
62
+ end
63
+
64
+ desc "build tryout package"
65
+ task :tryout
66
+
67
+ desc "build release package"
68
+ task :release => :all
69
+
70
+ unless EXTCONF.empty?
71
+ RUBYSET ||= (ENV["RUBYSET"] || "").split(",")
72
+
73
+ if RUBYSET.nil? || RUBYSET.empty?
74
+ $stderr.puts <<-EOS
75
+ #{__FILE__}:
76
+ |
77
+ | If you want binary gem package, launch rake with ``RUBYSET`` enviroment
78
+ | variable for set ruby interpreters by comma separated.
79
+ |
80
+ | e.g.) $ rake RUBYSET=ruby
81
+ | or) $ rake RUBYSET=ruby21,ruby22,ruby23
82
+ |
83
+ EOS
84
+ else
85
+ platforms = RUBYSET.map { |ruby| `#{ruby} --disable-gems -e "puts RUBY_PLATFORM"`.chomp }
86
+ platforms1 = platforms.uniq
87
+ unless platforms1.size == 1 && !platforms1[0].empty?
88
+ abort <<-EOS
89
+ #{__FILE__}:#{__LINE__}: different platforms:
90
+ #{RUBYSET.zip(platforms).map { |ruby, platform| "%24s => %s" % [ruby, platform] }.join("\n")}
91
+ ABORTED.
92
+ EOS
93
+ end
94
+ PLATFORM = platforms1[0]
95
+
96
+ RUBY_VERSIONS = RUBYSET.map do |ruby|
97
+ ver = `#{ruby} --disable-gems -e "puts RUBY_VERSION"`.slice(/\d+\.\d+/)
98
+ raise "failed ruby checking - ``#{ruby}''" unless $?.success?
99
+ [ver, ruby]
100
+ end
101
+
102
+ SOFILES_SET = RUBY_VERSIONS.map { |(ver, ruby)|
103
+ EXTCONF.map { |extconf|
104
+ extdir = Pathname.new(extconf).cleanpath.dirname.to_s
105
+ case
106
+ when soname = EXTMAP[extdir.sub(/^ext\//i, "")]
107
+ soname = soname.sub(/\.so$/i, "")
108
+ when extdir == "ext" || extdir == "."
109
+ soname = GEMSTUB.name
110
+ else
111
+ soname = File.basename(extdir)
112
+ end
113
+
114
+ [ruby, File.join("lib", "#{soname.sub(/(?<=\/)|^(?!.*\/)/, "#{ver}/")}.so"), extconf]
115
+ }
116
+ }.flatten(1)
117
+ SOFILES = SOFILES_SET.map { |(ruby, sopath, extconf)| sopath }
118
+
119
+ GEMSTUB_NATIVE = GEMSTUB.dup
120
+ GEMSTUB_NATIVE.files += SOFILES
121
+ GEMSTUB_NATIVE.platform = Gem::Platform.new(PLATFORM).to_s
122
+ GEMSTUB_NATIVE.extensions.clear
123
+ GEMFILE_NATIVE = "#{GEMSTUB_NATIVE.name}-#{GEMSTUB_NATIVE.version}-#{GEMSTUB_NATIVE.platform}.gem"
124
+ GEMSPEC_NATIVE = "#{GEMSTUB_NATIVE.name}-#{GEMSTUB_NATIVE.platform}.gemspec"
125
+
126
+ task :all => ["native-gem", GEMFILE]
127
+
128
+ desc "build binary gem package"
129
+ task "native-gem" => GEMFILE_NATIVE
130
+
131
+ desc "generate binary gemspec"
132
+ task "native-gemspec" => GEMSPEC_NATIVE
133
+
134
+ file GEMFILE_NATIVE => DOC + EXT + EXTCONF + BIN + LIB + SPEC + TEST + EXAMPLE + SOFILES + RAKEFILE + [GEMSPEC_NATIVE] do
135
+ sh "gem build #{GEMSPEC_NATIVE}"
136
+ end
137
+
138
+ file GEMSPEC_NATIVE => RAKEFILE do
139
+ File.write(GEMSPEC_NATIVE, GEMSTUB_NATIVE.to_ruby, mode: "wb")
140
+ end
141
+
142
+ desc "build c-extension libraries"
143
+ task "sofiles" => SOFILES
144
+
145
+ SOFILES_SET.each do |(ruby, soname, extconf)|
146
+ sodir = File.dirname(soname)
147
+ makefile = File.join(sodir, "Makefile")
148
+
149
+ CLEAN << GEMSPEC_NATIVE << sodir
150
+ CLOBBER << GEMFILE_NATIVE
151
+
152
+ directory sodir
153
+
154
+ desc "generate Makefile for binary extension library"
155
+ file makefile => [sodir, extconf] do
156
+ rel_extconf = Pathname.new(extconf).relative_path_from(Pathname.new(sodir)).to_s
157
+ cd sodir do
158
+ sh *%W"#{ruby} #{rel_extconf} --ruby=#{ruby} #{ENV["EXTCONF"]}"
159
+ end
160
+ end
161
+
162
+ desc "build binary extension library"
163
+ file soname => [makefile] + EXT do
164
+ cd sodir do
165
+ sh "make"
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+
173
+ task :all => GEMFILE
174
+ task :tryout => GEMFILE_TRYOUT
175
+
176
+ desc "generate local rdoc"
177
+ task :rdoc => DOC + LIB do
178
+ sh *(%w(rdoc) + GEMSTUB.rdoc_options + DOC + LIB)
179
+ end
180
+
181
+ desc "launch rspec"
182
+ task rspec: :all do
183
+ sh "rspec"
184
+ end
185
+
186
+ desc "build gem package"
187
+ task gem: GEMFILE
188
+
189
+ desc "generate gemspec"
190
+ task gemspec: GEMSPEC
191
+
192
+ desc "print package name"
193
+ task "package-name" do
194
+ puts PACKAGENAME
195
+ end
196
+
197
+ file GEMFILE => DOC + EXT + EXTCONF + BIN + LIB + SPEC + TEST + EXAMPLE + RAKEFILE + [GEMSPEC] do
198
+ sh "gem build #{GEMSPEC}"
199
+ end
200
+
201
+ file GEMFILE_TRYOUT => DOC + EXT + EXTCONF + BIN + LIB + SPEC + TEST + EXAMPLE + RAKEFILE + [GEMSPEC_TRYOUT] do
202
+ #file GEMFILE_TRYOUT do
203
+ sh "gem build #{GEMSPEC_TRYOUT}"
204
+ end
205
+
206
+ file GEMSPEC => RAKEFILE do
207
+ File.write(GEMSPEC, GEMSTUB.to_ruby, mode: "wb")
208
+ end
209
+
210
+ file GEMSPEC_TRYOUT => RAKEFILE do
211
+ File.write(GEMSPEC_TRYOUT, GEMSTUB_TRYOUT.to_ruby, mode: "wb")
212
+ end
@@ -0,0 +1,192 @@
1
+ #include <sys/types.h>
2
+ #include <sys/extattr.h>
3
+
4
+
5
+ static void
6
+ extattr_list_name(const char list[], size_t size, VALUE infection_source, void (*func)(void *, VALUE), void *userdata)
7
+ {
8
+ // Each list entry consists of a single byte containing the length of
9
+ // the attribute name, followed by the attribute name.
10
+ // The attribute name is not terminated by ASCII 0 (nul).
11
+ const char *ptr = list;
12
+ const char *end = list + size;
13
+
14
+ while (ptr < end) {
15
+ size_t len = (uint8_t)*ptr ++;
16
+ if (ptr + len > end) { return; }
17
+ VALUE v = rb_str_new(ptr, len);
18
+ OBJ_INFECT(v, infection_source);
19
+ func(userdata, v);
20
+ ptr += len;
21
+ }
22
+ }
23
+
24
+ static int
25
+ get_extattr_list_size(ssize_t (*extattr_list)(), intptr_t d, VALUE filesrc, int namespace1)
26
+ {
27
+ int size = extattr_list(d, namespace1, NULL, 0);
28
+ if (size < 0) { aux_sys_fail(filesrc, "extattr_list"); }
29
+ return size;
30
+ }
31
+
32
+ static VALUE
33
+ extattr_list_common(ssize_t (*extattr_list)(), intptr_t d, VALUE filesrc, int namespace1)
34
+ {
35
+ size_t size = get_extattr_list_size(extattr_list, d, filesrc, namespace1);
36
+ VALUE buf;
37
+ char *ptr = ALLOCV(buf, size);
38
+
39
+ ssize_t size1 = extattr_list(d, namespace1, ptr, size);
40
+ if (size1 < 0) { aux_sys_fail(filesrc, "extattr_list"); }
41
+
42
+ VALUE list = Qnil;
43
+ if (rb_block_given_p()) {
44
+ extattr_list_name(ptr, size1, filesrc,
45
+ (void (*)(void *, VALUE))rb_yield_values, (void *)(1));
46
+ } else {
47
+ list = rb_ary_new();
48
+ OBJ_INFECT(list, filesrc);
49
+ extattr_list_name(ptr, size1, filesrc,
50
+ (void (*)(void *, VALUE))rb_ary_push, (void *)list);
51
+ }
52
+ ALLOCV_END(buf);
53
+
54
+ return list;
55
+ }
56
+
57
+ static VALUE
58
+ file_extattr_list_main(VALUE file, int fd, int namespace1)
59
+ {
60
+ return extattr_list_common(extattr_list_fd, fd, file, namespace1);
61
+ }
62
+
63
+ static VALUE
64
+ file_s_extattr_list_main(VALUE path, int namespace1)
65
+ {
66
+ return extattr_list_common(extattr_list_file, (intptr_t)StringValueCStr(path), path, namespace1);
67
+ }
68
+
69
+ static VALUE
70
+ file_s_extattr_list_link_main(VALUE path, int namespace1)
71
+ {
72
+ return extattr_list_common(extattr_list_link, (intptr_t)StringValueCStr(path), path, namespace1);
73
+ }
74
+
75
+
76
+ static VALUE
77
+ extattr_size_common(ssize_t (*extattr_get)(), intptr_t d, int namespace1, VALUE name)
78
+ {
79
+ ssize_t size = extattr_get(d, namespace1, StringValueCStr(name), NULL, 0);
80
+ if (size < 0) { rb_sys_fail("extattr_get call error"); }
81
+ return SIZET2NUM(size);
82
+ }
83
+
84
+ static VALUE
85
+ file_extattr_size_main(VALUE file, int fd, int namespace1, VALUE name)
86
+ {
87
+ return extattr_size_common(extattr_get_fd, fd, namespace1, name);
88
+ }
89
+
90
+ static VALUE
91
+ file_s_extattr_size_main(VALUE path, int namespace1, VALUE name)
92
+ {
93
+ return extattr_size_common(extattr_get_file, (intptr_t)StringValueCStr(path), namespace1, name);
94
+ }
95
+
96
+ static VALUE
97
+ file_s_extattr_size_link_main(VALUE path, int namespace1, VALUE name)
98
+ {
99
+ return extattr_size_common(extattr_get_link, (intptr_t)StringValueCStr(path), namespace1, name);
100
+ }
101
+
102
+
103
+ static VALUE
104
+ extattr_get_common(ssize_t (*extattr_get)(), intptr_t d, VALUE path, int namespace1, VALUE name)
105
+ {
106
+ ssize_t size = extattr_get(d, namespace1, StringValueCStr(name), NULL, 0);
107
+ if (size < 0) { rb_sys_fail(StringValueCStr(path)); }
108
+ VALUE buf = rb_str_buf_new(size);
109
+ size = extattr_get(d, namespace1, StringValueCStr(name), StringValueCStr(buf), size);
110
+ if (size < 0) { rb_sys_fail(StringValueCStr(path)); }
111
+ rb_str_set_len(buf, size);
112
+ return buf;
113
+ }
114
+
115
+ static VALUE
116
+ file_extattr_get_main(VALUE file, int fd, int namespace1, VALUE name)
117
+ {
118
+ return extattr_get_common(extattr_get_fd, fd, RFILE(file)->fptr->pathv, namespace1, name);
119
+ }
120
+
121
+ static VALUE
122
+ file_s_extattr_get_main(VALUE path, int namespace1, VALUE name)
123
+ {
124
+ return extattr_get_common(extattr_get_file, (intptr_t)StringValueCStr(path), path, namespace1, name);
125
+ }
126
+
127
+ static VALUE
128
+ file_s_extattr_get_link_main(VALUE path, int namespace1, VALUE name)
129
+ {
130
+ return extattr_get_common(extattr_get_link, (intptr_t)StringValueCStr(path), path, namespace1, name);
131
+ }
132
+
133
+
134
+ static VALUE
135
+ extattr_set_common(ssize_t (*extattr_set)(), intptr_t d, int namespace1, VALUE name, VALUE data)
136
+ {
137
+ int status = extattr_set(d, namespace1, StringValueCStr(name), StringValueCStr(data), RSTRING_LEN(data));
138
+ if (status < 0) { rb_sys_fail("extattr_set call error"); }
139
+ return Qnil;
140
+ }
141
+
142
+ static VALUE
143
+ file_extattr_set_main(VALUE file, int fd, int namespace1, VALUE name, VALUE data)
144
+ {
145
+ return extattr_set_common(extattr_set_fd, fd, namespace1, name, data);
146
+ }
147
+
148
+ static VALUE
149
+ file_s_extattr_set_main(VALUE path, int namespace1, VALUE name, VALUE data)
150
+ {
151
+ return extattr_set_common(extattr_set_file, (intptr_t)StringValueCStr(path), namespace1, name, data);
152
+ }
153
+
154
+ static VALUE
155
+ file_s_extattr_set_link_main(VALUE path, int namespace1, VALUE name, VALUE data)
156
+ {
157
+ return extattr_set_common(extattr_set_link, (intptr_t)StringValueCStr(path), namespace1, name, data);
158
+ }
159
+
160
+
161
+ static VALUE
162
+ extattr_delete_common(int (*extattr_delete)(), intptr_t d, int namespace1, VALUE name)
163
+ {
164
+ int status = extattr_delete(d, namespace1, StringValueCStr(name), NULL, 0);
165
+ if (status < 0) { rb_sys_fail("extattr_delete call error"); }
166
+ return Qnil;
167
+ }
168
+
169
+ static VALUE
170
+ file_extattr_delete_main(VALUE file, int fd, int namespace1, VALUE name)
171
+ {
172
+ return extattr_delete_common(extattr_delete_fd, fd, namespace1, name);
173
+ }
174
+
175
+ static VALUE
176
+ file_s_extattr_delete_main(VALUE path, int namespace1, VALUE name)
177
+ {
178
+ return extattr_delete_common(extattr_delete_file, (intptr_t)StringValueCStr(path), namespace1, name);
179
+ }
180
+
181
+ static VALUE
182
+ file_s_extattr_delete_link_main(VALUE path, int namespace1, VALUE name)
183
+ {
184
+ return extattr_delete_common(extattr_delete_link, (intptr_t)StringValueCStr(path), namespace1, name);
185
+ }
186
+
187
+
188
+ static void
189
+ extattr_init_implement(void)
190
+ {
191
+ rb_define_const(mExtAttr, "IMPLEMENT", rb_str_freeze(rb_str_new_cstr("extattr")));
192
+ }