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 CHANGED
@@ -1,53 +1,73 @@
1
1
  = extattr
2
2
 
3
- extattr is extended attribute operation library for Windows and FreeBSD.
3
+ extattr is filesystem extended attributes operation library for FreeBSD, GNU/Linux and Microsoft Windows.
4
4
 
5
5
  ----
6
6
 
7
- extattr は拡張属性を操作するライブラリで、WindowsFreeBSD に対応しています (GNU/Linux はコードを書いてみただけで、試験がまったくされていません)。
7
+ extattr はファイルシステムの拡張属性を操作するライブラリで、FreeBSD、GNU/Linux、Windows に対応しています。
8
8
 
9
9
  サポートされる環境で、統一的なメソッドを提供します。
10
10
 
11
- クラスメソッドに『!』がついているものはシンボリックリンクに対する操作となります。
12
11
 
13
- キーワード引数の <code>namespace</code> を与えると、拡張属性の名前空間を指定できます。規定値は <code>EXTATTR_NAMESPACE_USER</code> で、ほかの値は <code>EXTATTR_NAMESPACE_SYSTEM</code> のみが指定できます (Windows 版では <code>EXTATTR_NAMESPACE_USER</code> のみが指定可能です)。
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
- - File#extattr_list(namespace: File::EXTATTR_NAMESPACE_USER) -> array
19
- - File.extattr_list(path, namespace: File::EXTATTR_NAMESPACE_USER) -> array
20
- - File.extattr_list!(path, namespace: File::EXTATTR_NAMESPACE_USER) -> array
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
- - File#extattr_size(name, namespace: File::EXTATTR_NAMESPACE_USER) -> size
25
- - File.extattr_size(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> size
26
- - File.extattr_size!(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> size
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
- - File#extattr_get(name, namespace: File::EXTATTR_NAMESPACE_USER) -> data (String)
31
- - File.extattr_get(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> data (String)
32
- - File.extattr_get!(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> data (String)
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
- - File#extattr_set(name, data, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
37
- - File.extattr_set(path, name, data, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
38
- - File.extattr_set!(path, name, data, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
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
- - File#extattr_delete(name, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
43
- - File.extattr_delete(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
44
- - File.extattr_delete!(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
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
- 128 KiB を超える ADS は取得も設定も出来ません。これは『拡張属性』と捉えた場合、巨大なデータを扱えるべきではないという考えによるためです (本当のところは FreeBSD の拡張属性が最大 64KiB 弱であることが由来です)。巨大な ADS を扱いたい場合は、File.open で自由に読み書きできます (これは ruby に限ったことではなく、Windows による仕様です)。この場合の与えるファイル名は、path + ":" + name という形になります。
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
- #include <attr/xattr.h>
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
- extattr_list0(ssize_t (*func)(), void *d, int namespace)
20
+ xattr_name(int namespace, VALUE name)
12
21
  {
13
- ssize_t size = 65536;
14
- VALUE buf = rb_str_buf_new(size);
15
- char *ptr = RSTRING_PTR(buf);
16
- size = func(d, ptr, size);
17
- if (size < 0) { rb_sys_fail("listxattr call error"); }
18
-
19
- VALUE (*reduce)(void *, VALUE);
20
- void *first;
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(first, name);
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
- return list;
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
- * ADS は普通のファイルのように扱えるから、extattr とみなして扱う場合は容量の制限を設けることにする。
15
- * ruby-extattr で不十分な巨大なデータを扱う場合は File.open で開くことが出来るので必要であればそちらで。
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
- * TODO: バッファサイズの確保量が結構大きめ。最適化をするべき。
22
- * TODO: CloseHandle してないところがありすぎ。修正。
23
- * TODO: Win9X シリーズだとこのライブラリ読み込みすら出来ない。
24
- * メソッド定義だけは行うようにするべき? (実際に呼び出したら NotImpError 例外を投げる)
25
- * リパースポイントって、ADSはつけられないのかな? 操作方法がわからない。
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
- rb_raise(rb_eSystemCallError, "Win32 API error - %u (%08Xh)", status, status);
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
- if (status != 0) { raise_ntstatus_error(status); }
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 VALUE
167
- extattr_list0(HANDLE file)
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
- if (NIL_P(list)) {
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
- return list;
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
- HANDLE file = CreateFileW(STR2WPATH(path), 0,
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
- HANDLE file = CreateFileW(STR2WPATH(path), 0,
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
- path = rb_str_plus(path, rb_str_new(":", 1));
272
- rb_str_append(path, name);
273
- HANDLE file = CreateFileW(STR2WPATH(path), 0,
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
- path = rb_str_plus(path, rb_str_new(":", 1));
287
- rb_str_append(path, name);
288
- HANDLE file = CreateFileW(STR2WPATH(path), 0,
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
- path = rb_str_plus(path, rb_str_new(":", 1));
320
- rb_str_append(path, name);
321
- HANDLE file = CreateFileW(STR2WPATH(path), GENERIC_READ,
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
- path = rb_str_plus(path, rb_str_new(":", 1));
364
- rb_str_append(path, name);
365
- HANDLE file = CreateFileW(STR2WPATH(path), GENERIC_WRITE,
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
- path = rb_str_plus(path, rb_str_new(":", 1));
386
- rb_str_append(path, name);
387
- DeleteFileW(STR2WPATH(path));
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("file1", "a")
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("file1").should eq([])
35
+ File.extattr_list(filepath).should eq([])
31
36
  end
32
37
 
33
38
  it ".extattr_set" do
34
- File.extattr_set("file1", "ext1", extdata).should nil
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("file1").should eq(["ext1"])
43
+ File.extattr_list(filepath).should eq(["ext1"])
39
44
  end
40
45
 
41
46
  it ".extattr_get" do
42
- File.extattr_get("file1", "ext1").should eq(extdata)
47
+ File.extattr_get(filepath, "ext1").should eq(extdata)
43
48
  end
44
49
 
45
50
  it ".extattr_delete" do
46
- File.extattr_delete("file1", "ext1").should nil
51
+ File.extattr_delete(filepath, "ext1").should nil
47
52
  end
48
53
 
49
54
  it ".extattr_list ((3))" do
50
- File.extattr_list("file1").should eq([])
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: '0.1'
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-02 00:00:00.000000000 Z
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