extattr 0.1-x86-mingw32 → 0.1.1-x86-mingw32
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/README.txt +46 -26
- data/ext/extattr.c +2 -2
- data/ext/extattr.linux +50 -37
- data/ext/extattr.windows +93 -60
- data/ext/extconf.rb +4 -1
- data/lib/extattr.so +0 -0
- data/rspecs/extattr.rb +16 -7
- metadata +2 -2
data/README.txt
CHANGED
@@ -1,53 +1,73 @@
|
|
1
1
|
= extattr
|
2
2
|
|
3
|
-
extattr is extended
|
3
|
+
extattr is filesystem extended attributes operation library for FreeBSD, GNU/Linux and Microsoft Windows.
|
4
4
|
|
5
5
|
----
|
6
6
|
|
7
|
-
extattr
|
7
|
+
extattr はファイルシステムの拡張属性を操作するライブラリで、FreeBSD、GNU/Linux、Windows に対応しています。
|
8
8
|
|
9
9
|
サポートされる環境で、統一的なメソッドを提供します。
|
10
10
|
|
11
|
-
クラスメソッドに『!』がついているものはシンボリックリンクに対する操作となります。
|
12
11
|
|
13
|
-
|
12
|
+
== test system
|
13
|
+
|
14
|
+
- Microsoft Windows XP Professional SP3
|
15
|
+
- PC-BSD/AMD64 9.0
|
16
|
+
- lubuntu 12.04
|
17
|
+
|
18
|
+
|
19
|
+
== 簡易リファレンスマニュアル
|
20
|
+
|
21
|
+
クラスメソッドに『!』がついているものはシンボリックリンクに対する操作となります。
|
14
22
|
|
23
|
+
キーワード引数の <code>namespace</code> を与えると、拡張属性の名前空間を指定できます。
|
24
|
+
規定値は <code>EXTATTR_NAMESPACE_USER</code> で、ほかの値は <code>EXTATTR_NAMESPACE_SYSTEM</code> のみが指定できます
|
25
|
+
(Windows 版では <code>EXTATTR_NAMESPACE_USER</code> のみが指定可能です)。
|
15
26
|
|
16
|
-
|
27
|
+
拡張属性の属性名を取得:
|
17
28
|
|
18
|
-
|
19
|
-
|
20
|
-
|
29
|
+
File#extattr_list(namespace: File::EXTATTR_NAMESPACE_USER) -> array
|
30
|
+
File#extattr_list(namespace: File::EXTATTR_NAMESPACE_USER) { |name| ... } -> nil
|
31
|
+
File.extattr_list(path, namespace: File::EXTATTR_NAMESPACE_USER) -> array
|
32
|
+
File.extattr_list(path, namespace: File::EXTATTR_NAMESPACE_USER) { |name| ... } -> nil
|
33
|
+
File.extattr_list!(path, namespace: File::EXTATTR_NAMESPACE_USER) -> array
|
34
|
+
File.extattr_list!(path, namespace: File::EXTATTR_NAMESPACE_USER) { |name| ... } -> nil
|
21
35
|
|
22
|
-
|
36
|
+
拡張属性の要素の大きさを取得:
|
23
37
|
|
24
|
-
|
25
|
-
|
26
|
-
|
38
|
+
File#extattr_size(name, namespace: File::EXTATTR_NAMESPACE_USER) -> size
|
39
|
+
File.extattr_size(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> size
|
40
|
+
File.extattr_size!(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> size
|
27
41
|
|
28
|
-
|
42
|
+
拡張属性の要素を取得:
|
29
43
|
|
30
|
-
|
31
|
-
|
32
|
-
|
44
|
+
File#extattr_get(name, namespace: File::EXTATTR_NAMESPACE_USER) -> data (String)
|
45
|
+
File.extattr_get(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> data (String)
|
46
|
+
File.extattr_get!(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> data (String)
|
33
47
|
|
34
|
-
|
48
|
+
拡張属性の要素を設定:
|
35
49
|
|
36
|
-
|
37
|
-
|
38
|
-
|
50
|
+
File#extattr_set(name, data, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
|
51
|
+
File.extattr_set(path, name, data, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
|
52
|
+
File.extattr_set!(path, name, data, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
|
39
53
|
|
40
|
-
|
54
|
+
拡張属性の要素を削除:
|
41
55
|
|
42
|
-
|
43
|
-
|
44
|
-
|
56
|
+
File#extattr_delete(name, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
|
57
|
+
File.extattr_delete(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
|
58
|
+
File.extattr_delete!(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
|
45
59
|
|
46
60
|
|
47
61
|
== Microsoft Windows における諸注意
|
48
62
|
|
49
63
|
Windows 2000 以降でのみ動作します。Windows 9X シリーズでは <code>require "extattr"</code> の段階で例外が発生するでしょう。
|
50
64
|
|
51
|
-
リパースポイント (ジャンクションやシンボリックリンク) に対する ADS
|
65
|
+
リパースポイント (ジャンクションやシンボリックリンク) に対する ADS は要素の取得や設定、削除は出来ません。
|
66
|
+
必ずリンク先に対する操作となります。
|
52
67
|
|
53
|
-
|
68
|
+
64 KiB を超える ADS は取得も設定も出来ません。
|
69
|
+
これは『拡張属性』と捉えた場合、巨大なデータを扱えるべきではないという考えによるためです
|
70
|
+
(本当のところは FreeBSD の拡張属性が最大 64KiB 弱であることが由来です)。
|
71
|
+
巨大な ADS を扱いたい場合は、<code>File.open</code> でファイルとして扱えるので自由に読み書きできます
|
72
|
+
(これは ruby に限ったことではなく、Windows による仕様です)。
|
73
|
+
この場合の与えるファイル名は、<code>path + ":" + name</code> という形になります。
|
data/ext/extattr.c
CHANGED
@@ -61,10 +61,10 @@ file2fd(VALUE file)
|
|
61
61
|
|
62
62
|
#if defined(HAVE_SYS_EXTATTR_H)
|
63
63
|
# include "extattr.bsd"
|
64
|
-
#elif defined(HAVE_ATTR_XATTR_H)
|
65
|
-
# include "extattr.linux"
|
66
64
|
#elif defined(HAVE_WINNT_H)
|
67
65
|
# include "extattr.windows"
|
66
|
+
#elif defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H)
|
67
|
+
# include "extattr.linux"
|
68
68
|
#else
|
69
69
|
# error ruby extattr not supported on your system
|
70
70
|
#endif
|
data/ext/extattr.linux
CHANGED
@@ -1,33 +1,39 @@
|
|
1
1
|
#include <sys/types.h>
|
2
|
-
#
|
2
|
+
#if HAVE_ATTR_XATTR_H
|
3
|
+
# include <attr/xattr.h>
|
4
|
+
#else
|
5
|
+
# include <sys/xattr.h>
|
6
|
+
#endif
|
7
|
+
|
8
|
+
enum {
|
9
|
+
EXTATTR_NAMESPACE_USER,
|
10
|
+
EXTATTR_NAMESPACE_SYSTEM,
|
11
|
+
EXTATTR_NAMESPACE_TRUSTED,
|
12
|
+
EXTATTR_NAMESPACE_SECURITY,
|
13
|
+
};
|
3
14
|
|
4
|
-
#define EXTATTR_NAMESPACE_USER 0
|
5
|
-
#define EXTATTR_NAMESPACE_SYSTEM 1
|
6
15
|
|
7
16
|
static VALUE NAMESPACE_USER_PREFIX, NAMESPACE_SYSTEM_PREFIX;
|
8
17
|
|
9
18
|
|
10
19
|
static VALUE
|
11
|
-
|
20
|
+
xattr_name(int namespace, VALUE name)
|
12
21
|
{
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
VALUE list;
|
22
|
-
if (rb_block_given_p()) {
|
23
|
-
reduce = (VALUE (*)(void *, VALUE))rb_yield_values;
|
24
|
-
first = (void *)1;
|
25
|
-
list = Qnil;
|
26
|
-
} else {
|
27
|
-
reduce = (VALUE (*)(void *, VALUE))rb_ary_push;
|
28
|
-
first = (void *)(list = rb_ary_new());
|
22
|
+
switch (namespace) {
|
23
|
+
case EXTATTR_NAMESPACE_USER:
|
24
|
+
return rb_str_plus(NAMESPACE_USER_PREFIX, name);
|
25
|
+
case EXTATTR_NAMESPACE_SYSTEM:
|
26
|
+
return rb_str_plus(NAMESPACE_SYSTEM_PREFIX, name);
|
27
|
+
default:
|
28
|
+
rb_raise(rb_eRuntimeError, "namespace error");
|
29
|
+
return Qnil;
|
29
30
|
}
|
31
|
+
}
|
32
|
+
|
30
33
|
|
34
|
+
static inline void
|
35
|
+
extattr_list_name(const char *ptr, size_t size, int namespace, VALUE (*reduce)(void *, VALUE), void *user)
|
36
|
+
{
|
31
37
|
const char *end = ptr + size;
|
32
38
|
while (ptr < end) {
|
33
39
|
int len = strlen(ptr);
|
@@ -42,11 +48,32 @@ extattr_list0(ssize_t (*func)(), void *d, int namespace)
|
|
42
48
|
}
|
43
49
|
|
44
50
|
name = rb_str_new_cstr(ptr);
|
45
|
-
reduce(
|
51
|
+
reduce(user, name);
|
46
52
|
ptr += RSTRING_LEN(name) + 1; // 最後の『+1』は、ヌルバイトの分。
|
47
53
|
}
|
54
|
+
}
|
55
|
+
|
56
|
+
static VALUE
|
57
|
+
extattr_list0(ssize_t (*func)(), void *d, int namespace)
|
58
|
+
{
|
59
|
+
ssize_t size = 65536;
|
60
|
+
VALUE buf = rb_str_buf_new(size);
|
61
|
+
char *ptr = RSTRING_PTR(buf);
|
62
|
+
size = func(d, ptr, size);
|
63
|
+
if (size < 0) { rb_sys_fail("listxattr call error"); }
|
48
64
|
|
49
|
-
|
65
|
+
if (rb_block_given_p()) {
|
66
|
+
extattr_list_name(ptr, size, namespace,
|
67
|
+
(VALUE (*)(void *, VALUE))rb_yield_values,
|
68
|
+
(void *)1);
|
69
|
+
return Qnil;
|
70
|
+
} else {
|
71
|
+
VALUE list = rb_ary_new();
|
72
|
+
extattr_list_name(ptr, size, namespace,
|
73
|
+
(VALUE (*)(void *, VALUE))rb_ary_push,
|
74
|
+
(void *)list);
|
75
|
+
return list;
|
76
|
+
}
|
50
77
|
}
|
51
78
|
|
52
79
|
static VALUE
|
@@ -68,20 +95,6 @@ file_s_extattr_list_link0(VALUE path, int namespace)
|
|
68
95
|
}
|
69
96
|
|
70
97
|
|
71
|
-
static VALUE
|
72
|
-
xattr_name(int namespace, VALUE name)
|
73
|
-
{
|
74
|
-
switch (namespace) {
|
75
|
-
case EXTATTR_NAMESPACE_USER:
|
76
|
-
return rb_str_plus(NAMESPACE_USER_PREFIX, name);
|
77
|
-
case EXTATTR_NAMESPACE_SYSTEM:
|
78
|
-
return rb_str_plus(NAMESPACE_SYSTEM_PREFIX, name);
|
79
|
-
default:
|
80
|
-
rb_raise(rb_eRuntimeError, "namespace error");
|
81
|
-
return Qnil;
|
82
|
-
}
|
83
|
-
}
|
84
|
-
|
85
98
|
static VALUE
|
86
99
|
extattr_size0(ssize_t (*func)(), void *d, int namespace, VALUE name)
|
87
100
|
{
|
@@ -146,7 +159,7 @@ static VALUE
|
|
146
159
|
extattr_set0(int (*func)(), void *d, int namespace, VALUE name, VALUE data)
|
147
160
|
{
|
148
161
|
name = xattr_name(namespace, name);
|
149
|
-
int status = func(d, StringValueCStr(name), RSTRING_PTR(data), RSTRING_LEN(data));
|
162
|
+
int status = func(d, StringValueCStr(name), RSTRING_PTR(data), RSTRING_LEN(data), 0);
|
150
163
|
if (status < 0) { rb_sys_fail("getxattr call error"); }
|
151
164
|
return Qnil;
|
152
165
|
}
|
data/ext/extattr.windows
CHANGED
@@ -6,24 +6,27 @@
|
|
6
6
|
#include <ntdef.h>
|
7
7
|
#include <psapi.h>
|
8
8
|
#include <wchar.h>
|
9
|
+
#include <ruby/win32.h>
|
9
10
|
|
10
11
|
#define EXTATTR_NAMESPACE_USER 0
|
11
12
|
#define EXTATTR_NAMESPACE_SYSTEM 1
|
12
13
|
|
13
14
|
/*
|
14
|
-
*
|
15
|
-
*
|
16
|
-
* TODO:
|
15
|
+
* - TODO: バッファサイズの確保量が結構大きめ。最適化をするべき。
|
16
|
+
* - TODO: CloseHandle してないところがありすぎ。修正。
|
17
|
+
* - TODO: Win9X シリーズだとこのライブラリ読み込みすら出来ない。
|
18
|
+
* メソッド定義だけは行うようにするべき? (実際に呼び出したら NotImplementedError 例外を投げる、とか)
|
19
|
+
* - リパースポイントって、ADSはつけられないのかな? 操作方法がわからない。
|
17
20
|
*/
|
18
|
-
static const size_t EXTATTR_MAX = 131072;
|
19
21
|
|
20
22
|
/*
|
21
|
-
*
|
22
|
-
*
|
23
|
-
*
|
24
|
-
*
|
25
|
-
*
|
23
|
+
* ADS は普通のファイルのように扱えるから、extattr とみなして扱う場合は容量の制限を設けることにする。
|
24
|
+
*
|
25
|
+
* ruby-extattr で不十分な巨大なデータを扱う場合は File.open で開くことが出来るので必要であればそちらで。
|
26
|
+
*
|
27
|
+
* TODO: 最適値を探すべき
|
26
28
|
*/
|
29
|
+
static const size_t EXTATTR_MAX = 65536;
|
27
30
|
|
28
31
|
|
29
32
|
static rb_encoding *ENCutf8p;
|
@@ -32,8 +35,6 @@ static rb_encoding *ENCutf16lep;
|
|
32
35
|
static VALUE ENCutf16le;
|
33
36
|
|
34
37
|
|
35
|
-
|
36
|
-
|
37
38
|
static VALUE
|
38
39
|
str2wcs(VALUE str)
|
39
40
|
{
|
@@ -90,7 +91,7 @@ wpath2str(const wchar_t path[], size_t size)
|
|
90
91
|
static VALUE
|
91
92
|
adsname2str(const wchar_t name[], size_t size)
|
92
93
|
{
|
93
|
-
if (name[0] == L':' && wcsncmp(name + size - 6, L":$DATA", 6) == 0) {
|
94
|
+
if (name[0] == L':' && size >= 7 && wcsncmp(name + size - 6, L":$DATA", 6) == 0) {
|
94
95
|
name += 1;
|
95
96
|
size -= 7;
|
96
97
|
}
|
@@ -100,9 +101,15 @@ adsname2str(const wchar_t name[], size_t size)
|
|
100
101
|
|
101
102
|
|
102
103
|
static void
|
103
|
-
raise_win32_error(DWORD status)
|
104
|
+
raise_win32_error(DWORD status, VALUE name)
|
104
105
|
{
|
105
|
-
|
106
|
+
if (NIL_P(name)) {
|
107
|
+
VALUE args[] = { INT2NUM(rb_w32_map_errno(status)), };
|
108
|
+
rb_exc_raise(rb_class_new_instance(1, args, rb_eSystemCallError));
|
109
|
+
} else {
|
110
|
+
VALUE args[] = { StringValue(name), INT2NUM(rb_w32_map_errno(status)), };
|
111
|
+
rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemCallError));
|
112
|
+
}
|
106
113
|
}
|
107
114
|
|
108
115
|
static void
|
@@ -111,6 +118,15 @@ raise_ntstatus_error(NTSTATUS status)
|
|
111
118
|
rb_raise(rb_eSystemCallError, "NTSTATUS error - %u (%08Xh)", status, status);
|
112
119
|
}
|
113
120
|
|
121
|
+
static void
|
122
|
+
check_status_error(NTSTATUS status)
|
123
|
+
{
|
124
|
+
if (status != STATUS_SUCCESS) {
|
125
|
+
raise_ntstatus_error(status);
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
|
114
130
|
static VALUE
|
115
131
|
get_filepath(HANDLE file)
|
116
132
|
{
|
@@ -121,7 +137,8 @@ get_filepath(HANDLE file)
|
|
121
137
|
RSTRING_PTR(buf),
|
122
138
|
size,
|
123
139
|
&size);
|
124
|
-
|
140
|
+
check_status_error(status);
|
141
|
+
|
125
142
|
const OBJECT_NAME_INFORMATION *info = (const OBJECT_NAME_INFORMATION *)RSTRING_PTR(buf);
|
126
143
|
if (wcsnicmp(info->Name.Buffer, L"\\Device\\", 8) == 0) {
|
127
144
|
// 先頭の "/Device/" を "//?/" に置き換える
|
@@ -138,7 +155,7 @@ get_filesize(HANDLE file)
|
|
138
155
|
BY_HANDLE_FILE_INFORMATION info;
|
139
156
|
|
140
157
|
if (!GetFileInformationByHandle(file, &info)) {
|
141
|
-
raise_win32_error(GetLastError());
|
158
|
+
raise_win32_error(GetLastError(), Qnil);
|
142
159
|
}
|
143
160
|
|
144
161
|
return ((uint64_t)info.nFileSizeHigh << 32) | info.nFileSizeLow;
|
@@ -163,35 +180,47 @@ check_namespace(int namespace)
|
|
163
180
|
}
|
164
181
|
|
165
182
|
|
166
|
-
static
|
167
|
-
|
183
|
+
static void
|
184
|
+
extattr_list_name(const char *ptr, void *(*yield)(void *user, VALUE name), void *user)
|
168
185
|
{
|
169
|
-
VALUE iostatusblock = rb_str_buf_new(4096);
|
170
|
-
VALUE infobuf = rb_str_buf_new(65536);
|
171
|
-
rb_str_set_len(infobuf, 65536);
|
172
|
-
NTSTATUS status = NtQueryInformationFile(file,
|
173
|
-
(PIO_STATUS_BLOCK)RSTRING_PTR(iostatusblock),
|
174
|
-
RSTRING_PTR(infobuf), RSTRING_LEN(infobuf),
|
175
|
-
FileStreamInformation);
|
176
|
-
if (status != 0) { raise_ntstatus_error(status); }
|
177
|
-
const char *ptr = RSTRING_PTR(infobuf);
|
178
|
-
VALUE list = Qnil;
|
179
|
-
if (!rb_block_given_p()) { list = rb_ary_new(); }
|
180
186
|
for (;;) {
|
181
187
|
const FILE_STREAM_INFORMATION *info = (const FILE_STREAM_INFORMATION *)ptr;
|
182
188
|
VALUE name = adsname2str(info->StreamName, info->StreamNameLength / 2);
|
183
189
|
if (RSTRING_LEN(name) > 0) {
|
184
|
-
|
185
|
-
rb_yield(name);
|
186
|
-
} else {
|
187
|
-
rb_ary_push(list, name);
|
188
|
-
}
|
190
|
+
yield(user, name);
|
189
191
|
}
|
190
192
|
size_t size = info->NextEntryOffset;
|
191
193
|
if (size == 0) { break; }
|
192
194
|
ptr += size;
|
193
195
|
}
|
194
|
-
|
196
|
+
}
|
197
|
+
|
198
|
+
static VALUE
|
199
|
+
extattr_list0(HANDLE file)
|
200
|
+
{
|
201
|
+
VALUE iostatusblock = rb_str_buf_new(4096);
|
202
|
+
size_t size = 65536; // TODO: 最適値を見つける
|
203
|
+
VALUE infobuf = rb_str_buf_new(size);
|
204
|
+
char *ptr = RSTRING_PTR(infobuf);
|
205
|
+
memset(ptr, 0, sizeof(FILE_STREAM_INFORMATION));
|
206
|
+
NTSTATUS status = NtQueryInformationFile(file,
|
207
|
+
(PIO_STATUS_BLOCK)RSTRING_PTR(iostatusblock),
|
208
|
+
ptr, size,
|
209
|
+
FileStreamInformation);
|
210
|
+
check_status_error(status);
|
211
|
+
|
212
|
+
if (rb_block_given_p()) {
|
213
|
+
extattr_list_name(ptr,
|
214
|
+
(void *(*)(void *, VALUE))rb_yield_values,
|
215
|
+
(void *)1);
|
216
|
+
return Qnil;
|
217
|
+
} else {
|
218
|
+
VALUE list = rb_ary_new();
|
219
|
+
extattr_list_name(ptr,
|
220
|
+
(void *(*)(void *, VALUE))rb_ary_push,
|
221
|
+
(void *)list);
|
222
|
+
return list;
|
223
|
+
}
|
195
224
|
}
|
196
225
|
|
197
226
|
static VALUE
|
@@ -242,12 +271,13 @@ static VALUE
|
|
242
271
|
file_s_extattr_list0(VALUE path, int namespace)
|
243
272
|
{
|
244
273
|
check_namespace(namespace);
|
245
|
-
|
274
|
+
VALUE path1 = path;
|
275
|
+
HANDLE file = CreateFileW(STR2WPATH(path1), 0,
|
246
276
|
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
247
277
|
NULL, 3,
|
248
278
|
FILE_FLAG_BACKUP_SEMANTICS,
|
249
279
|
0);
|
250
|
-
if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError()); }
|
280
|
+
if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError(), path); }
|
251
281
|
return rb_ensure(extattr_list0, (VALUE)file, file_close, (VALUE)file);
|
252
282
|
}
|
253
283
|
|
@@ -255,12 +285,13 @@ static VALUE
|
|
255
285
|
file_s_extattr_list_link0(VALUE path, int namespace)
|
256
286
|
{
|
257
287
|
check_namespace(namespace);
|
258
|
-
|
288
|
+
VALUE path1 = path;
|
289
|
+
HANDLE file = CreateFileW(STR2WPATH(path1), 0,
|
259
290
|
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
260
291
|
NULL, 3,
|
261
292
|
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
|
262
293
|
0);
|
263
|
-
if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError()); }
|
294
|
+
if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError(), path); }
|
264
295
|
return rb_ensure(extattr_list0, (VALUE)file, file_close, (VALUE)file);
|
265
296
|
}
|
266
297
|
|
@@ -268,14 +299,14 @@ static VALUE
|
|
268
299
|
file_s_extattr_size0(VALUE path, int namespace, VALUE name)
|
269
300
|
{
|
270
301
|
check_namespace(namespace);
|
271
|
-
|
272
|
-
rb_str_append(
|
273
|
-
HANDLE file = CreateFileW(STR2WPATH(
|
302
|
+
VALUE path1 = rb_str_plus(path, rb_str_new(":", 1));
|
303
|
+
rb_str_append(path1, name);
|
304
|
+
HANDLE file = CreateFileW(STR2WPATH(path1), 0,
|
274
305
|
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
275
306
|
NULL, 3,
|
276
307
|
FILE_FLAG_BACKUP_SEMANTICS,
|
277
308
|
0);
|
278
|
-
if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError()); }
|
309
|
+
if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError(), path); }
|
279
310
|
return rb_ensure(extattr_size0, (VALUE)file, file_close, (VALUE)file);
|
280
311
|
}
|
281
312
|
|
@@ -283,14 +314,14 @@ static VALUE
|
|
283
314
|
file_s_extattr_size_link0(VALUE path, int namespace, VALUE name)
|
284
315
|
{
|
285
316
|
check_namespace(namespace);
|
286
|
-
|
287
|
-
rb_str_append(
|
288
|
-
HANDLE file = CreateFileW(STR2WPATH(
|
317
|
+
VALUE path1 = rb_str_plus(path, rb_str_new(":", 1));
|
318
|
+
rb_str_append(path1, name);
|
319
|
+
HANDLE file = CreateFileW(STR2WPATH(path1), 0,
|
289
320
|
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
290
321
|
NULL, 3,
|
291
322
|
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
|
292
323
|
0);
|
293
|
-
if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError()); }
|
324
|
+
if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError(), path); }
|
294
325
|
return rb_ensure(extattr_size0, (VALUE)file, file_close, (VALUE)file);
|
295
326
|
}
|
296
327
|
|
@@ -306,7 +337,7 @@ extattr_get0(VALUE args[3])
|
|
306
337
|
VALUE buf = rb_str_buf_new(size);
|
307
338
|
DWORD readsize = 0;
|
308
339
|
if (!ReadFile(file, RSTRING_PTR(buf), size, &readsize, NULL)) {
|
309
|
-
raise_win32_error(GetLastError());
|
340
|
+
raise_win32_error(GetLastError(), Qnil);
|
310
341
|
}
|
311
342
|
rb_str_set_len(buf, readsize);
|
312
343
|
return buf;
|
@@ -316,14 +347,14 @@ static VALUE
|
|
316
347
|
extattr_get1(VALUE path, int flags, int namespace, VALUE name)
|
317
348
|
{
|
318
349
|
check_namespace(namespace);
|
319
|
-
|
320
|
-
rb_str_append(
|
321
|
-
HANDLE file = CreateFileW(STR2WPATH(
|
350
|
+
VALUE path1 = rb_str_plus(path, rb_str_new(":", 1));
|
351
|
+
rb_str_append(path1, name);
|
352
|
+
HANDLE file = CreateFileW(STR2WPATH(path1), GENERIC_READ,
|
322
353
|
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
323
354
|
NULL, 3,
|
324
355
|
FILE_FLAG_BACKUP_SEMANTICS | flags,
|
325
356
|
0);
|
326
|
-
if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError()); }
|
357
|
+
if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError(), path); }
|
327
358
|
VALUE args[] = { (VALUE)file, (VALUE)namespace, name, };
|
328
359
|
return rb_ensure(extattr_get0, (VALUE)args, file_close, (VALUE)file);
|
329
360
|
}
|
@@ -351,7 +382,7 @@ extattr_set0(VALUE args[])
|
|
351
382
|
if (size > EXTATTR_MAX) { rb_raise(rb_eSystemCallError, "extattr too huge"); }
|
352
383
|
DWORD wrotesize = size;
|
353
384
|
if (!WriteFile(file, RSTRING_PTR(data), size, &wrotesize, NULL)) {
|
354
|
-
raise_win32_error(GetLastError());
|
385
|
+
raise_win32_error(GetLastError(), Qnil);
|
355
386
|
}
|
356
387
|
return Qnil;
|
357
388
|
}
|
@@ -360,14 +391,14 @@ static VALUE
|
|
360
391
|
file_s_extattr_set0(VALUE path, int namespace, VALUE name, VALUE data)
|
361
392
|
{
|
362
393
|
check_namespace(namespace);
|
363
|
-
|
364
|
-
rb_str_append(
|
365
|
-
HANDLE file = CreateFileW(STR2WPATH(
|
394
|
+
VALUE path1 = rb_str_plus(path, rb_str_new(":", 1));
|
395
|
+
rb_str_append(path1, name);
|
396
|
+
HANDLE file = CreateFileW(STR2WPATH(path1), GENERIC_WRITE,
|
366
397
|
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
367
398
|
NULL, CREATE_ALWAYS,
|
368
399
|
FILE_FLAG_BACKUP_SEMANTICS,
|
369
400
|
0);
|
370
|
-
if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError()); }
|
401
|
+
if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError(), path); }
|
371
402
|
VALUE args[] = { (VALUE)file, (VALUE)namespace, name, data };
|
372
403
|
return rb_ensure(extattr_set0, (VALUE)args, file_close, (VALUE)file);
|
373
404
|
}
|
@@ -382,9 +413,11 @@ static VALUE
|
|
382
413
|
file_s_extattr_delete0(VALUE path, int namespace, VALUE name)
|
383
414
|
{
|
384
415
|
check_namespace(namespace);
|
385
|
-
|
386
|
-
rb_str_append(
|
387
|
-
DeleteFileW(STR2WPATH(
|
416
|
+
VALUE path1 = rb_str_plus(path, rb_str_new(":", 1));
|
417
|
+
rb_str_append(path1, name);
|
418
|
+
if (!DeleteFileW(STR2WPATH(path1))) {
|
419
|
+
raise_win32_error(GetLastError(), path);
|
420
|
+
}
|
388
421
|
return Qnil;
|
389
422
|
}
|
390
423
|
|
data/ext/extconf.rb
CHANGED
@@ -9,10 +9,13 @@ require "mkmf"
|
|
9
9
|
|
10
10
|
case
|
11
11
|
when have_header("sys/extattr.h")
|
12
|
-
when have_header("attr/xattr.h")
|
13
12
|
when have_header("winnt.h") && have_header("ntdef.h") && have_header("psapi.h") &&
|
14
13
|
have_header("ddk/ntifs.h") && have_header("ddk/winddk.h") &&
|
15
14
|
have_library("ntoskrnl") && have_library("ntdll") && have_library("psapi")
|
15
|
+
when have_header("attr/xattr.h")
|
16
|
+
$CPPFLAGS << " -DLINUX_XATTR_H=\\<attr/xattr.h\\>"
|
17
|
+
when have_header("sys/xattr.h")
|
18
|
+
$CPPFLAGS << " -DLINUX_XATTR_H=\\<sys/xattr.h\\>"
|
16
19
|
else
|
17
20
|
$stderr.puts <<-EOS
|
18
21
|
#$0: not supported target.
|
data/lib/extattr.so
CHANGED
Binary file
|
data/rspecs/extattr.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require "tmpdir"
|
4
4
|
basedir = File.join(Dir.tmpdir, "ruby-extattr.test-work")
|
5
5
|
Dir.mkdir basedir unless File.directory? basedir
|
6
|
+
filepath = File.join(basedir, "file1")
|
6
7
|
|
7
8
|
require "extattr"
|
8
9
|
|
@@ -12,7 +13,7 @@ Dir.chdir basedir do
|
|
12
13
|
describe "file" do
|
13
14
|
file = nil
|
14
15
|
before(:all) do
|
15
|
-
file = File.open(
|
16
|
+
file = File.open(filepath, "a")
|
16
17
|
end
|
17
18
|
|
18
19
|
it ".extattr_list" do
|
@@ -26,28 +27,36 @@ Dir.chdir basedir do
|
|
26
27
|
end
|
27
28
|
|
28
29
|
describe File do
|
30
|
+
before(:all) do
|
31
|
+
File.open(filepath, "a") {}
|
32
|
+
end
|
33
|
+
|
29
34
|
it ".extattr_list" do
|
30
|
-
File.extattr_list(
|
35
|
+
File.extattr_list(filepath).should eq([])
|
31
36
|
end
|
32
37
|
|
33
38
|
it ".extattr_set" do
|
34
|
-
File.extattr_set(
|
39
|
+
File.extattr_set(filepath, "ext1", extdata).should nil
|
35
40
|
end
|
36
41
|
|
37
42
|
it ".extattr_list ((2))" do
|
38
|
-
File.extattr_list(
|
43
|
+
File.extattr_list(filepath).should eq(["ext1"])
|
39
44
|
end
|
40
45
|
|
41
46
|
it ".extattr_get" do
|
42
|
-
File.extattr_get(
|
47
|
+
File.extattr_get(filepath, "ext1").should eq(extdata)
|
43
48
|
end
|
44
49
|
|
45
50
|
it ".extattr_delete" do
|
46
|
-
File.extattr_delete(
|
51
|
+
File.extattr_delete(filepath, "ext1").should nil
|
47
52
|
end
|
48
53
|
|
49
54
|
it ".extattr_list ((3))" do
|
50
|
-
File.extattr_list(
|
55
|
+
File.extattr_list(filepath).should eq([])
|
56
|
+
end
|
57
|
+
|
58
|
+
after(:all) do
|
59
|
+
File.unlink filepath
|
51
60
|
end
|
52
61
|
end
|
53
62
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: extattr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.1.1
|
5
5
|
segments:
|
6
6
|
hash:
|
7
7
|
platform: x86-mingw32
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-10-
|
13
|
+
date: 2012-10-03 00:00:00.000000000 Z
|
14
14
|
dependencies: []
|
15
15
|
description: ! 'extattr is extended attribute operation library for ruby.
|
16
16
|
|