extattr 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/ext/extattr.windows +109 -89
  2. data/rspecs/extattr.rb +37 -37
  3. metadata +3 -3
data/ext/extattr.windows CHANGED
@@ -12,9 +12,10 @@
12
12
  #define EXTATTR_NAMESPACE_SYSTEM 1
13
13
 
14
14
  /*
15
- * - TODO: バッファサイズの確保量が結構大きめ。最適化をするべき。
16
- * - TODO: CloseHandle してないところがありすぎ。修正。
17
- * - TODO: Win9X シリーズだとこのライブラリ読み込みすら出来ない。
15
+ * - TODO:
16
+ * バッファサイズの確保量が結構大きめ。最適化をするべき。
17
+ * - TODO:
18
+ * Win9X シリーズだとこのライブラリ読み込みすら出来ない。
18
19
  * メソッド定義だけは行うようにするべき? (実際に呼び出したら NotImplementedError 例外を投げる、とか)
19
20
  * - リパースポイントって、ADSはつけられないのかな? 操作方法がわからない。
20
21
  */
@@ -55,12 +56,11 @@ str2wpath(VALUE str)
55
56
  return str;
56
57
  }
57
58
 
58
- #define STR2WPATH(str) \
59
- ({ \
60
- (str) = str2wpath(str); \
61
- (const wchar_t *)RSTRING_PTR(str); \
62
- }) \
63
-
59
+ #define STR2WPATH(str) \
60
+ ({ \
61
+ (str) = str2wpath(str); \
62
+ (const wchar_t *)RSTRING_PTR(str); \
63
+ }) \
64
64
 
65
65
  static VALUE
66
66
  wcs2str(const wchar_t str[], size_t size)
@@ -91,12 +91,21 @@ wpath2str(const wchar_t path[], size_t size)
91
91
  static VALUE
92
92
  adsname2str(const wchar_t name[], size_t size)
93
93
  {
94
- if (name[0] == L':' && size >= 7 && wcsncmp(name + size - 6, L":$DATA", 6) == 0) {
95
- name += 1;
96
- size -= 7;
94
+ if (name[0] == L':') {
95
+ name ++;
96
+ size --;
97
+ if (size >= 6 && wcsncmp(name + size - 6, L":$DATA", 6) == 0) {
98
+ size -= 6;
99
+ } else {
100
+ size --;
101
+ }
97
102
  }
98
103
 
99
- return wpath2str(name, size);
104
+ if (size > 0) {
105
+ return wpath2str(name, size);
106
+ } else {
107
+ return Qnil;
108
+ }
100
109
  }
101
110
 
102
111
 
@@ -107,22 +116,24 @@ raise_win32_error(DWORD status, VALUE name)
107
116
  VALUE args[] = { INT2NUM(rb_w32_map_errno(status)), };
108
117
  rb_exc_raise(rb_class_new_instance(1, args, rb_eSystemCallError));
109
118
  } else {
119
+ // TODO: name がファイルオブジェクトなのであればパス名を取り出す。パス名がない場合は fd を取り出す。
120
+
110
121
  VALUE args[] = { StringValue(name), INT2NUM(rb_w32_map_errno(status)), };
111
122
  rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemCallError));
112
123
  }
113
124
  }
114
125
 
115
126
  static void
116
- raise_ntstatus_error(NTSTATUS status)
127
+ raise_ntstatus_error(NTSTATUS status, VALUE name)
117
128
  {
118
- rb_raise(rb_eSystemCallError, "NTSTATUS error - %u (%08Xh)", status, status);
129
+ raise_win32_error(RtlNtStatusToDosError(status), name);
119
130
  }
120
131
 
121
132
  static void
122
133
  check_status_error(NTSTATUS status)
123
134
  {
124
135
  if (status != STATUS_SUCCESS) {
125
- raise_ntstatus_error(status);
136
+ raise_ntstatus_error(status, Qnil);
126
137
  }
127
138
  }
128
139
 
@@ -168,14 +179,20 @@ file_close(HANDLE file)
168
179
  * rb_ensure から直接呼びたかったけど、呼び出し規約が違うから無理だよね。
169
180
  */
170
181
  CloseHandle(file);
182
+
183
+ return Qnil;
171
184
  }
172
185
 
173
186
  static void
174
- check_namespace(int namespace)
187
+ check_namespace(int namespace, VALUE path)
175
188
  {
176
189
  if (namespace != EXTATTR_NAMESPACE_USER) {
177
190
  errno = EPERM;
178
- rb_sys_fail(NULL);
191
+ if (NIL_P(path)) {
192
+ rb_sys_fail(NULL);
193
+ } else {
194
+ rb_sys_fail(StringValueCStr(path));
195
+ }
179
196
  }
180
197
  }
181
198
 
@@ -186,7 +203,7 @@ extattr_list_name(const char *ptr, void *(*yield)(void *user, VALUE name), void
186
203
  for (;;) {
187
204
  const FILE_STREAM_INFORMATION *info = (const FILE_STREAM_INFORMATION *)ptr;
188
205
  VALUE name = adsname2str(info->StreamName, info->StreamNameLength / 2);
189
- if (RSTRING_LEN(name) > 0) {
206
+ if (!NIL_P(name) && RSTRING_LEN(name) > 0) {
190
207
  yield(user, name);
191
208
  }
192
209
  size_t size = info->NextEntryOffset;
@@ -196,7 +213,7 @@ extattr_list_name(const char *ptr, void *(*yield)(void *user, VALUE name), void
196
213
  }
197
214
 
198
215
  static VALUE
199
- extattr_list0(HANDLE file)
216
+ extattr_list0_try(HANDLE file)
200
217
  {
201
218
  VALUE iostatusblock = rb_str_buf_new(4096);
202
219
  size_t size = 65536; // TODO: 最適値を見つける
@@ -224,110 +241,83 @@ extattr_list0(HANDLE file)
224
241
  }
225
242
 
226
243
  static VALUE
227
- extattr_size0(HANDLE file)
244
+ extattr_list0(VALUE path, DWORD flags, int namespace)
228
245
  {
229
- return ULL2NUM(get_filesize(file));
246
+ check_namespace(namespace, path);
247
+ VALUE path1 = path;
248
+ HANDLE file = CreateFileW(STR2WPATH(path1), 0,
249
+ FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
250
+ NULL, 3,
251
+ FILE_FLAG_BACKUP_SEMANTICS | flags,
252
+ 0);
253
+ if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError(), path); }
254
+ return rb_ensure(extattr_list0_try, (VALUE)file, file_close, (VALUE)file);
230
255
  }
231
256
 
232
-
233
257
  static VALUE
234
258
  file_extattr_list0(VALUE file, int fd, int namespace)
235
259
  {
236
- check_namespace(namespace);
260
+ check_namespace(namespace, Qnil);
237
261
  HANDLE file1 = (HANDLE)_get_osfhandle(fd);
238
- return extattr_list0(file1);
262
+ return extattr_list0_try(file1);
239
263
  }
240
264
 
241
265
  static VALUE
242
- file_extattr_size0(VALUE file, int fd, int namespace, VALUE name)
266
+ file_s_extattr_list0(VALUE path, int namespace)
243
267
  {
244
- return file_s_extattr_size0(get_filepath((HANDLE)_get_osfhandle(fd)),
245
- namespace, name);
268
+ return extattr_list0(path, 0, namespace);
246
269
  }
247
270
 
248
271
  static VALUE
249
- file_extattr_get0(VALUE file, int fd, int namespace, VALUE name)
272
+ file_s_extattr_list_link0(VALUE path, int namespace)
250
273
  {
251
- return file_s_extattr_get0(get_filepath((HANDLE)_get_osfhandle(fd)),
252
- namespace, name);
274
+ return extattr_list0(path, FILE_FLAG_OPEN_REPARSE_POINT, namespace);
253
275
  }
254
276
 
255
- static VALUE
256
- file_extattr_set0(VALUE file, int fd, int namespace, VALUE name, VALUE data)
257
- {
258
- return file_s_extattr_set0(get_filepath((HANDLE)_get_osfhandle(fd)),
259
- namespace, name, data);
260
- }
261
277
 
262
278
  static VALUE
263
- file_extattr_delete0(VALUE file, int fd, int namespace, VALUE name)
279
+ extattr_size0_try(HANDLE file)
264
280
  {
265
- return file_s_extattr_delete0(get_filepath((HANDLE)_get_osfhandle(fd)),
266
- namespace, name);
281
+ return ULL2NUM(get_filesize(file));
267
282
  }
268
283
 
269
-
270
284
  static VALUE
271
- file_s_extattr_list0(VALUE path, int namespace)
285
+ extattr_size0(VALUE path, DWORD flags, int namespace, VALUE name)
272
286
  {
273
- check_namespace(namespace);
274
- VALUE path1 = path;
287
+ check_namespace(namespace, path);
288
+ VALUE path1 = rb_str_plus(path, rb_str_new(":", 1));
289
+ rb_str_append(path1, name);
275
290
  HANDLE file = CreateFileW(STR2WPATH(path1), 0,
276
291
  FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
277
292
  NULL, 3,
278
- FILE_FLAG_BACKUP_SEMANTICS,
293
+ FILE_FLAG_BACKUP_SEMANTICS | flags,
279
294
  0);
280
295
  if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError(), path); }
281
- return rb_ensure(extattr_list0, (VALUE)file, file_close, (VALUE)file);
296
+ return rb_ensure(extattr_size0_try, (VALUE)file, file_close, (VALUE)file);
282
297
  }
283
298
 
284
299
  static VALUE
285
- file_s_extattr_list_link0(VALUE path, int namespace)
300
+ file_extattr_size0(VALUE file, int fd, int namespace, VALUE name)
286
301
  {
287
- check_namespace(namespace);
288
- VALUE path1 = path;
289
- HANDLE file = CreateFileW(STR2WPATH(path1), 0,
290
- FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
291
- NULL, 3,
292
- FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
293
- 0);
294
- if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError(), path); }
295
- return rb_ensure(extattr_list0, (VALUE)file, file_close, (VALUE)file);
302
+ return file_s_extattr_size0(get_filepath((HANDLE)_get_osfhandle(fd)),
303
+ namespace, name);
296
304
  }
297
305
 
298
306
  static VALUE
299
307
  file_s_extattr_size0(VALUE path, int namespace, VALUE name)
300
308
  {
301
- check_namespace(namespace);
302
- VALUE path1 = rb_str_plus(path, rb_str_new(":", 1));
303
- rb_str_append(path1, name);
304
- HANDLE file = CreateFileW(STR2WPATH(path1), 0,
305
- FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
306
- NULL, 3,
307
- FILE_FLAG_BACKUP_SEMANTICS,
308
- 0);
309
- if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError(), path); }
310
- return rb_ensure(extattr_size0, (VALUE)file, file_close, (VALUE)file);
309
+ return extattr_size0(path, 0, namespace, name);
311
310
  }
312
311
 
313
312
  static VALUE
314
313
  file_s_extattr_size_link0(VALUE path, int namespace, VALUE name)
315
314
  {
316
- check_namespace(namespace);
317
- VALUE path1 = rb_str_plus(path, rb_str_new(":", 1));
318
- rb_str_append(path1, name);
319
- HANDLE file = CreateFileW(STR2WPATH(path1), 0,
320
- FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
321
- NULL, 3,
322
- FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
323
- 0);
324
- if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError(), path); }
325
- return rb_ensure(extattr_size0, (VALUE)file, file_close, (VALUE)file);
315
+ return extattr_size0(path, FILE_FLAG_OPEN_REPARSE_POINT, namespace, name);
326
316
  }
327
317
 
328
318
 
329
319
  static VALUE
330
- extattr_get0(VALUE args[3])
320
+ extattr_get_try(VALUE args[3])
331
321
  {
332
322
  HANDLE file = (HANDLE)args[0];
333
323
  int namespace = (int)args[1];
@@ -344,9 +334,9 @@ extattr_get0(VALUE args[3])
344
334
  }
345
335
 
346
336
  static VALUE
347
- extattr_get1(VALUE path, int flags, int namespace, VALUE name)
337
+ extattr_get0(VALUE path, int flags, int namespace, VALUE name)
348
338
  {
349
- check_namespace(namespace);
339
+ check_namespace(namespace, path);
350
340
  VALUE path1 = rb_str_plus(path, rb_str_new(":", 1));
351
341
  rb_str_append(path1, name);
352
342
  HANDLE file = CreateFileW(STR2WPATH(path1), GENERIC_READ,
@@ -356,23 +346,31 @@ extattr_get1(VALUE path, int flags, int namespace, VALUE name)
356
346
  0);
357
347
  if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError(), path); }
358
348
  VALUE args[] = { (VALUE)file, (VALUE)namespace, name, };
359
- return rb_ensure(extattr_get0, (VALUE)args, file_close, (VALUE)file);
349
+ return rb_ensure(extattr_get_try, (VALUE)args, file_close, (VALUE)file);
350
+ }
351
+
352
+ static VALUE
353
+ file_extattr_get0(VALUE file, int fd, int namespace, VALUE name)
354
+ {
355
+ return file_s_extattr_get0(get_filepath((HANDLE)_get_osfhandle(fd)),
356
+ namespace, name);
360
357
  }
361
358
 
362
359
  static VALUE
363
360
  file_s_extattr_get0(VALUE path, int namespace, VALUE name)
364
361
  {
365
- return extattr_get1(path, 0, namespace, name);
362
+ return extattr_get0(path, 0, namespace, name);
366
363
  }
367
364
 
368
365
  static VALUE
369
366
  file_s_extattr_get_link0(VALUE path, int namespace, VALUE name)
370
367
  {
371
- return extattr_get1(path, FILE_FLAG_OPEN_REPARSE_POINT, namespace, name);
368
+ return extattr_get0(path, FILE_FLAG_OPEN_REPARSE_POINT, namespace, name);
372
369
  }
373
370
 
371
+
374
372
  static VALUE
375
- extattr_set0(VALUE args[])
373
+ extattr_set0_try(VALUE args[])
376
374
  {
377
375
  HANDLE file = (HANDLE)args[0];
378
376
  int namespace = (int)args[1];
@@ -388,31 +386,52 @@ extattr_set0(VALUE args[])
388
386
  }
389
387
 
390
388
  static VALUE
391
- file_s_extattr_set0(VALUE path, int namespace, VALUE name, VALUE data)
389
+ extattr_set0(VALUE path, DWORD flags, int namespace, VALUE name, VALUE data)
392
390
  {
393
- check_namespace(namespace);
391
+ check_namespace(namespace, path);
394
392
  VALUE path1 = rb_str_plus(path, rb_str_new(":", 1));
395
393
  rb_str_append(path1, name);
396
394
  HANDLE file = CreateFileW(STR2WPATH(path1), GENERIC_WRITE,
397
395
  FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
398
396
  NULL, CREATE_ALWAYS,
399
- FILE_FLAG_BACKUP_SEMANTICS,
397
+ FILE_FLAG_BACKUP_SEMANTICS | flags,
400
398
  0);
401
399
  if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError(), path); }
402
400
  VALUE args[] = { (VALUE)file, (VALUE)namespace, name, data };
403
- return rb_ensure(extattr_set0, (VALUE)args, file_close, (VALUE)file);
401
+ return rb_ensure(extattr_set0_try, (VALUE)args, file_close, (VALUE)file);
402
+ }
403
+
404
+ static VALUE
405
+ file_extattr_set0(VALUE file, int fd, int namespace, VALUE name, VALUE data)
406
+ {
407
+ return file_s_extattr_set0(get_filepath((HANDLE)_get_osfhandle(fd)),
408
+ namespace, name, data);
409
+ }
410
+
411
+ static VALUE
412
+ file_s_extattr_set0(VALUE path, int namespace, VALUE name, VALUE data)
413
+ {
414
+ return extattr_set0(path, 0, namespace, name, data);
404
415
  }
405
416
 
406
417
  static VALUE
407
418
  file_s_extattr_set_link0(VALUE path, int namespace, VALUE name, VALUE data)
408
419
  {
409
- return file_s_extattr_set0(path, namespace, name, data);
420
+ return extattr_set0(path, FILE_FLAG_OPEN_REPARSE_POINT, namespace, name, data);
421
+ }
422
+
423
+
424
+ static VALUE
425
+ file_extattr_delete0(VALUE file, int fd, int namespace, VALUE name)
426
+ {
427
+ return file_s_extattr_delete0(get_filepath((HANDLE)_get_osfhandle(fd)),
428
+ namespace, name);
410
429
  }
411
430
 
412
431
  static VALUE
413
432
  file_s_extattr_delete0(VALUE path, int namespace, VALUE name)
414
433
  {
415
- check_namespace(namespace);
434
+ check_namespace(namespace, path);
416
435
  VALUE path1 = rb_str_plus(path, rb_str_new(":", 1));
417
436
  rb_str_append(path1, name);
418
437
  if (!DeleteFileW(STR2WPATH(path1))) {
@@ -427,6 +446,7 @@ file_s_extattr_delete_link0(VALUE path, int namespace, VALUE name)
427
446
  return file_s_extattr_delete0(path, namespace, name);
428
447
  }
429
448
 
449
+
430
450
  static void
431
451
  setup(void)
432
452
  {
data/rspecs/extattr.rb CHANGED
@@ -10,53 +10,53 @@ require "extattr"
10
10
  extdata = "abcdefg"
11
11
 
12
12
  Dir.chdir basedir do
13
- describe "file" do
14
- file = nil
15
- before(:all) do
16
- file = File.open(filepath, "a")
17
- end
13
+ describe "file" do
14
+ file = nil
15
+ before(:all) do
16
+ file = File.open(filepath, "a")
17
+ end
18
18
 
19
- it ".extattr_list" do
20
- file.extattr_list.should eq([])
21
- end
19
+ it ".extattr_list" do
20
+ file.extattr_list.should eq([])
21
+ end
22
22
 
23
- after(:all) do
24
- file.close
25
- file = nil
26
- end
23
+ after(:all) do
24
+ file.close
25
+ file = nil
27
26
  end
27
+ end
28
28
 
29
- describe File do
30
- before(:all) do
31
- File.open(filepath, "a") {}
32
- end
29
+ describe File do
30
+ before(:all) do
31
+ File.open(filepath, "a") {}
32
+ end
33
33
 
34
- it ".extattr_list" do
35
- File.extattr_list(filepath).should eq([])
36
- end
34
+ it ".extattr_list" do
35
+ File.extattr_list(filepath).should eq([])
36
+ end
37
37
 
38
- it ".extattr_set" do
39
- File.extattr_set(filepath, "ext1", extdata).should nil
40
- end
38
+ it ".extattr_set" do
39
+ File.extattr_set(filepath, "ext1", extdata).should nil
40
+ end
41
41
 
42
- it ".extattr_list ((2))" do
43
- File.extattr_list(filepath).should eq(["ext1"])
44
- end
42
+ it ".extattr_list ((2))" do
43
+ File.extattr_list(filepath).should eq(["ext1"])
44
+ end
45
45
 
46
- it ".extattr_get" do
47
- File.extattr_get(filepath, "ext1").should eq(extdata)
48
- end
46
+ it ".extattr_get" do
47
+ File.extattr_get(filepath, "ext1").should eq(extdata)
48
+ end
49
49
 
50
- it ".extattr_delete" do
51
- File.extattr_delete(filepath, "ext1").should nil
52
- end
50
+ it ".extattr_delete" do
51
+ File.extattr_delete(filepath, "ext1").should nil
52
+ end
53
53
 
54
- it ".extattr_list ((3))" do
55
- File.extattr_list(filepath).should eq([])
56
- end
54
+ it ".extattr_list ((3))" do
55
+ File.extattr_list(filepath).should eq([])
56
+ end
57
57
 
58
- after(:all) do
59
- File.unlink filepath
60
- end
58
+ after(:all) do
59
+ File.unlink filepath
61
60
  end
61
+ end
62
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.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-03 00:00:00.000000000 Z
12
+ date: 2013-02-22 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: ! 'extattr is extended attribute operation library for ruby.
15
15
 
16
- Supported for Microsoft Windows and FreeBSD.
16
+ Supported for FreeBSD, Gnu/Linux and Microsoft Windows.
17
17
 
18
18
  '
19
19
  email: dearblue@users.sourceforge.jp