extattr 0.2 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
data/ext/extattr.c CHANGED
@@ -2,14 +2,16 @@
2
2
 
3
3
  /*
4
4
  * extattr.c
5
- * AUTHOR:: dearblue <dearblue@zoho.com>
5
+ * AUTHOR:: dearblue <dearblue@users.osdn.me>
6
6
  * LICENSE:: 2-clause BSD License
7
- * WWW:: http://sourceforge.jp/projects/rutsubo
7
+ * PROJECT-PAGE:: https://github.com/dearblue/ruby-extattr
8
8
  */
9
9
 
10
10
  #include <ruby.h>
11
11
  #include <ruby/io.h>
12
12
  #include <ruby/intern.h>
13
+ #include <ruby/version.h>
14
+ #include <ctype.h>
13
15
 
14
16
 
15
17
  static VALUE file_extattr_list_main(VALUE file, int fd, int namespace1);
@@ -29,8 +31,11 @@ static VALUE file_s_extattr_delete_main(VALUE path, int namespace1, VALUE name);
29
31
  static VALUE file_s_extattr_delete_link_main(VALUE path, int namespace1, VALUE name);
30
32
 
31
33
  // Init_extattr から呼び出される、環境ごとの初期設定。
32
- static void ext_init_implement(void);
34
+ static void extattr_init_implement(void);
33
35
 
36
+ #if RUBY_API_VERSION_CODE >= 20700
37
+ # define rb_obj_infect(OBJ, SRC) ((void)0)
38
+ #endif
34
39
 
35
40
  #define RDOC(...)
36
41
 
@@ -38,6 +43,11 @@ static void ext_init_implement(void);
38
43
 
39
44
  #define LOGF(FORMAT, ...) { fprintf(stderr, "%s:%d:%s: " FORMAT "\n", __FILE__, __LINE__, __func__, __VA_ARGS__); }
40
45
 
46
+ static VALUE mExtAttr;
47
+
48
+ static ID id_downcase;
49
+ static ID id_to_path;
50
+
41
51
 
42
52
  static inline VALUE
43
53
  hash_lookup(VALUE hash, VALUE key, VALUE default_value)
@@ -54,8 +64,8 @@ hash_lookup(VALUE hash, VALUE key, VALUE default_value)
54
64
  static inline int
55
65
  file2fd(VALUE file)
56
66
  {
67
+ rb_check_type(file, RUBY_T_FILE);
57
68
  rb_io_t *fptr;
58
- // FIXME: ファイルであることを確認すべき
59
69
  GetOpenFile(file, fptr);
60
70
  return fptr->fd;
61
71
  }
@@ -79,6 +89,66 @@ ext_error_namespace(VALUE path, int namespace1)
79
89
  ext_error_extattr(EPERM, path, rb_sprintf("namespace=%d", namespace1));
80
90
  }
81
91
 
92
+ static VALUE
93
+ aux_to_path(VALUE path)
94
+ {
95
+ if (rb_respond_to(path, id_to_path)) {
96
+ VALUE args[] = { path };
97
+ path = rb_funcall2(path, id_to_path, 1, args);
98
+ rb_check_type(path, RUBY_T_STRING);
99
+ } else {
100
+ path = StringValue(path);
101
+ }
102
+
103
+ return path;
104
+ }
105
+
106
+ static void
107
+ aux_sys_fail(VALUE filesrc, const char *funcname)
108
+ {
109
+ VALUE tmp;
110
+ filesrc = aux_to_path(filesrc);
111
+ if (funcname) {
112
+ tmp = rb_sprintf("%s (%s error)", StringValueCStr(filesrc), funcname);
113
+ } else {
114
+ tmp = rb_sprintf("%s", StringValueCStr(filesrc));
115
+ }
116
+ rb_sys_fail(StringValueCStr(tmp));
117
+ }
118
+
119
+ static size_t
120
+ aux_str_getmem(VALUE obj, const char **pp)
121
+ {
122
+ switch (rb_type(obj)) {
123
+ case RUBY_T_STRING:
124
+ break;
125
+ case RUBY_T_SYMBOL:
126
+ obj = rb_id2str(rb_sym2id(obj));
127
+ break;
128
+ default:
129
+ rb_raise(rb_eTypeError, "expect string or symbol for namespace");
130
+ }
131
+
132
+ size_t len;
133
+ RSTRING_GETMEM(obj, *pp, len);
134
+ return len;
135
+ }
136
+
137
+ static int
138
+ aux_memcasecmp(const char *a, const char *b, size_t n)
139
+ {
140
+ // MEMO: memicmp() があればそちらを使うべき?
141
+
142
+ for (; n > 0; n--, a++, b++) {
143
+ int c = tolower(*(const unsigned char *)a) - tolower(*(const unsigned char *)b);
144
+ if (c) {
145
+ return (c > 0) ? 1 : -1;
146
+ }
147
+ }
148
+
149
+ return 0;
150
+ }
151
+
82
152
 
83
153
  #if defined(HAVE_SYS_EXTATTR_H)
84
154
  # include "extattr-extattr.h"
@@ -91,14 +161,72 @@ ext_error_namespace(VALUE path, int namespace1)
91
161
  #endif
92
162
 
93
163
 
94
- static VALUE SYMnamespace;
164
+ static VALUE
165
+ aux_should_be_string(VALUE obj)
166
+ {
167
+ rb_check_type(obj, RUBY_T_STRING);
168
+ return obj;
169
+ }
170
+
171
+ static int
172
+ convert_namespace_int(VALUE namespace)
173
+ {
174
+ int n = NUM2INT(namespace);
175
+
176
+ if (n == EXTATTR_NAMESPACE_USER ||
177
+ n == EXTATTR_NAMESPACE_SYSTEM) {
178
+
179
+ return n;
180
+ }
181
+
182
+ rb_raise(rb_eArgError,
183
+ "wrong namespace value - #<%s:%p>",
184
+ rb_obj_classname(namespace), (void *)namespace);
185
+ }
186
+
187
+ static int
188
+ convert_namespace_str(VALUE namespace)
189
+ {
190
+ static const char ns_user[] = "user";
191
+ static const int ns_user_len = sizeof(ns_user) / sizeof(ns_user[0]) - 1;
192
+ static const char ns_system[] = "system";
193
+ static const int ns_system_len = sizeof(ns_system) / sizeof(ns_system[0]) - 1;
194
+
195
+ const char *p;
196
+ size_t len = aux_str_getmem(namespace, &p);
197
+
198
+ if (len == ns_user_len && aux_memcasecmp(p, ns_user, ns_user_len) == 0) {
199
+ return EXTATTR_NAMESPACE_USER;
200
+ } else if (len == ns_system_len && aux_memcasecmp(p, ns_system, ns_system_len) == 0) {
201
+ return EXTATTR_NAMESPACE_SYSTEM;
202
+ } else {
203
+ rb_raise(rb_eArgError,
204
+ "wrong namespace - %s (expected to user or system)",
205
+ StringValueCStr(namespace));
206
+ }
207
+ }
95
208
 
96
209
  static int
97
- ext_get_namespace(VALUE opts)
210
+ conv_namespace(VALUE namespace)
98
211
  {
99
- return NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER)));
212
+ if (NIL_P(namespace)) {
213
+ return EXTATTR_NAMESPACE_USER;
214
+ } else if (rb_obj_is_kind_of(namespace, rb_cNumeric)) {
215
+ return convert_namespace_int(namespace);
216
+ } else if (rb_obj_is_kind_of(namespace, rb_cString) ||
217
+ rb_obj_is_kind_of(namespace, rb_cSymbol)) {
218
+ return convert_namespace_str(rb_String(namespace));
219
+ } else {
220
+ rb_raise(rb_eArgError,
221
+ "wrong namespace object - %p",
222
+ (void *)namespace);
223
+ }
100
224
  }
101
225
 
226
+ #if RUBY_API_VERSION_CODE >= 20700
227
+ static void ext_check_file_security(VALUE file, VALUE name, VALUE data) { }
228
+ static void ext_check_path_security(VALUE path, VALUE name, VALUE data) { }
229
+ #else
102
230
  static void
103
231
  ext_check_file_security(VALUE file, VALUE name, VALUE data)
104
232
  {
@@ -174,297 +302,231 @@ ext_check_path_security(VALUE path, VALUE name, VALUE data)
174
302
  rb_insecure_operation();
175
303
  }
176
304
  }
305
+ #endif
177
306
 
178
307
 
179
308
  /*
180
309
  * call-seq:
181
- * extattr_list(namespace: File::EXTATTR_NAMESPACE_USER) -> names array
182
- * extattr_list(namespace: File::EXTATTR_NAMESPACE_USER) { |name| ... } -> nil
183
- *
184
- * 開いているファイルの拡張属性名一覧を得ます。
185
- *
186
- * ブロックが指定された場合、一つ一つの拡張属性名を渡してブロックが評価されます。ブロックの戻り値は無視されます。
187
- */
188
- static VALUE
189
- file_extattr_list(int argc, VALUE argv[], VALUE file)
190
- {
191
- VALUE opts = Qnil;
192
- rb_scan_args(argc, argv, "0:", &opts);
193
- ext_check_file_security(file, Qnil, Qnil);
194
- return file_extattr_list_main(file, file2fd(file),
195
- ext_get_namespace(opts));
196
- }
197
-
198
- /*
199
- * call-seq:
200
- * extattr_list(path, namespace: File::EXTATTR_NAMESPACE_USER) -> names array
201
- * extattr_list(path, namespace: File::EXTATTR_NAMESPACE_USER) { |name| ... } -> nil
202
- *
203
- * ファイル名を指定すること以外は File#extattr_list と同じです。
310
+ * list(path, namespace) -> names array
311
+ * list(path, namespace) { |name| ... } -> nil
204
312
  */
205
313
  static VALUE
206
- file_s_extattr_list(int argc, VALUE argv[], VALUE file)
314
+ ext_s_list(VALUE mod, VALUE path, VALUE namespace)
207
315
  {
208
- VALUE path, opts = Qnil;
209
- rb_scan_args(argc, argv, "1:", &path, &opts);
210
- ext_check_path_security(path, Qnil, Qnil);
211
- return file_s_extattr_list_main(StringValue(path),
212
- ext_get_namespace(opts));
316
+ if (rb_obj_is_kind_of(path, rb_cFile)) {
317
+ ext_check_file_security(path, Qnil, Qnil);
318
+ return file_extattr_list_main(path, file2fd(path),
319
+ conv_namespace(namespace));
320
+ } else {
321
+ ext_check_path_security(path, Qnil, Qnil);
322
+ return file_s_extattr_list_main(aux_to_path(path),
323
+ conv_namespace(namespace));
324
+ }
213
325
  }
214
326
 
215
327
  /*
216
328
  * call-seq:
217
- * extattr_list!(path, namespace: File::EXTATTR_NAMESPACE_USER) -> names array
218
- * extattr_list!(path, namespace: File::EXTATTR_NAMESPACE_USER) { |name| ... } -> nil
219
- *
220
- * シンボリックリンクに対する操作という以外は、File.extattr_list と同じです。
329
+ * extattr_list!(path, namespace) -> names array
330
+ * extattr_list!(path, namespace) { |name| ... } -> nil
221
331
  */
222
332
  static VALUE
223
- file_s_extattr_list_link(int argc, VALUE argv[], VALUE file)
333
+ ext_s_list_link(VALUE mod, VALUE path, VALUE namespace)
224
334
  {
225
- VALUE path, opts = Qnil;
226
- rb_scan_args(argc, argv, "1:", &path, &opts);
227
- ext_check_path_security(path, Qnil, Qnil);
228
- return file_s_extattr_list_link_main(StringValue(path),
229
- ext_get_namespace(opts));
335
+ if (rb_obj_is_kind_of(path, rb_cFile)) {
336
+ ext_check_file_security(path, Qnil, Qnil);
337
+ return file_extattr_list_main(path, file2fd(path),
338
+ conv_namespace(namespace));
339
+ } else {
340
+ ext_check_path_security(path, Qnil, Qnil);
341
+ return file_s_extattr_list_link_main(aux_to_path(path),
342
+ conv_namespace(namespace));
343
+ }
230
344
  }
231
345
 
232
346
 
233
347
  /*
234
348
  * call-seq:
235
- * extattr_size(name, namespace: File::EXTATTR_NAMESPACE_USER) -> names array
236
- *
237
- * 拡張属性の大きさを取得します。
349
+ * size(path, namespace, name) -> size
238
350
  */
239
351
  static VALUE
240
- file_extattr_size(int argc, VALUE argv[], VALUE file)
352
+ ext_s_size(VALUE mod, VALUE path, VALUE namespace, VALUE name)
241
353
  {
242
- VALUE name, opts = Qnil;
243
- rb_scan_args(argc, argv, "1:", &name, &opts);
244
- ext_check_file_security(file, name, Qnil);
245
- Check_Type(name, RUBY_T_STRING);
246
- return file_extattr_size_main(file, file2fd(file),
247
- ext_get_namespace(opts),
248
- StringValue(name));
249
- }
250
-
251
- /*
252
- * call-seq:
253
- * extattr_size(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> size
254
- */
255
- static VALUE
256
- file_s_extattr_size(int argc, VALUE argv[], VALUE file)
257
- {
258
- VALUE path, name, opts = Qnil;
259
- rb_scan_args(argc, argv, "2:", &path, &name, &opts);
260
- ext_check_path_security(path, name, Qnil);
261
- Check_Type(name, RUBY_T_STRING);
262
- return file_s_extattr_size_main(StringValue(path),
263
- ext_get_namespace(opts),
264
- StringValue(name));
354
+ if (rb_obj_is_kind_of(path, rb_cFile)) {
355
+ ext_check_file_security(path, name, Qnil);
356
+ return file_extattr_size_main(path, file2fd(path), conv_namespace(namespace),
357
+ aux_should_be_string(name));
358
+ } else {
359
+ ext_check_path_security(path, name, Qnil);
360
+ return file_s_extattr_size_main(aux_to_path(path), conv_namespace(namespace),
361
+ aux_should_be_string(name));
362
+ }
265
363
  }
266
364
 
267
365
  /*
268
366
  * call-seq:
269
- * extattr_size!(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> size
367
+ * size!(path, namespace, name) -> size
270
368
  */
271
369
  static VALUE
272
- file_s_extattr_size_link(int argc, VALUE argv[], VALUE file)
370
+ ext_s_size_link(VALUE mod, VALUE path, VALUE namespace, VALUE name)
273
371
  {
274
- VALUE path, name, opts = Qnil;
275
- rb_scan_args(argc, argv, "2:", &path, &name, &opts);
276
- ext_check_path_security(path, name, Qnil);
277
- Check_Type(name, RUBY_T_STRING);
278
- return file_s_extattr_size_link_main(StringValue(path),
279
- ext_get_namespace(opts),
280
- StringValue(name));
372
+ if (rb_obj_is_kind_of(path, rb_cFile)) {
373
+ ext_check_file_security(path, name, Qnil);
374
+ return file_extattr_size_main(path, file2fd(path), conv_namespace(namespace),
375
+ aux_should_be_string(name));
376
+ } else {
377
+ ext_check_path_security(path, name, Qnil);
378
+ return file_s_extattr_size_link_main(aux_to_path(path), conv_namespace(namespace),
379
+ aux_should_be_string(name));
380
+ }
281
381
  }
282
382
 
283
383
 
284
384
  /*
285
385
  * call-seq:
286
- * extattr_get(name, namespace: File::EXTATTR_NAMESPACE_USER) -> data
386
+ * get(path, namespace, name) -> data
287
387
  */
288
388
  static VALUE
289
- file_extattr_get(int argc, VALUE argv[], VALUE file)
389
+ ext_s_get(VALUE mod, VALUE path, VALUE namespace, VALUE name)
290
390
  {
291
- VALUE name, opts = Qnil;
292
- rb_scan_args(argc, argv, "1:", &name, &opts);
293
- ext_check_file_security(file, name, Qnil);
294
- Check_Type(name, RUBY_T_STRING);
295
- VALUE v = file_extattr_get_main(file, file2fd(file),
296
- ext_get_namespace(opts),
297
- StringValue(name));
298
- OBJ_INFECT(v, file);
299
- return v;
300
- }
391
+ VALUE v;
392
+ if (rb_obj_is_kind_of(path, rb_cFile)) {
393
+ ext_check_file_security(path, name, Qnil);
394
+ v = file_extattr_get_main(path, file2fd(path), conv_namespace(namespace),
395
+ aux_should_be_string(name));
396
+ } else {
397
+ ext_check_path_security(path, name, Qnil);
398
+ v = file_s_extattr_get_main(aux_to_path(path), conv_namespace(namespace),
399
+ aux_should_be_string(name));
400
+ }
301
401
 
302
- /*
303
- * call-seq:
304
- * extattr_get(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> data
305
- */
306
- static VALUE
307
- file_s_extattr_get(int argc, VALUE argv[], VALUE file)
308
- {
309
- VALUE path, name, opts = Qnil;
310
- rb_scan_args(argc, argv, "2:", &path, &name, &opts);
311
- ext_check_path_security(path, name, Qnil);
312
- Check_Type(name, RUBY_T_STRING);
313
- VALUE v = file_s_extattr_get_main(StringValue(path),
314
- ext_get_namespace(opts),
315
- StringValue(name));
316
- OBJ_INFECT(v, path);
402
+ rb_obj_infect(v, path);
317
403
  return v;
318
404
  }
319
405
 
320
406
  /*
321
407
  * call-seq:
322
- * extattr_get!(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> data
408
+ * get!(path, namespace, name) -> data
323
409
  */
324
410
  static VALUE
325
- file_s_extattr_get_link(int argc, VALUE argv[], VALUE file)
411
+ ext_s_get_link(VALUE mod, VALUE path, VALUE namespace, VALUE name)
326
412
  {
327
- VALUE path, name, opts = Qnil;
328
- rb_scan_args(argc, argv, "2:", &path, &name, &opts);
329
- ext_check_path_security(path, name, Qnil);
330
- Check_Type(name, RUBY_T_STRING);
331
- VALUE v = file_s_extattr_get_link_main(StringValue(path),
332
- ext_get_namespace(opts),
333
- StringValue(name));
334
- OBJ_INFECT(v, path);
413
+ VALUE v;
414
+ if (rb_obj_is_kind_of(path, rb_cFile)) {
415
+ ext_check_file_security(path, name, Qnil);
416
+ v = file_extattr_get_main(path, file2fd(path), conv_namespace(namespace),
417
+ aux_should_be_string(name));
418
+ } else {
419
+ ext_check_path_security(path, name, Qnil);
420
+ v = file_s_extattr_get_link_main(aux_to_path(path), conv_namespace(namespace),
421
+ aux_should_be_string(name));
422
+ }
423
+
424
+ rb_obj_infect(v, path);
335
425
  return v;
336
426
  }
337
427
 
338
428
 
339
429
  /*
340
430
  * call-seq:
341
- * extattr_set(name, data, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
431
+ * set(path, namespace, name, data) -> nil
342
432
  */
343
433
  static VALUE
344
- file_extattr_set(int argc, VALUE argv[], VALUE file)
434
+ ext_s_set(VALUE mod, VALUE path, VALUE namespace, VALUE name, VALUE data)
345
435
  {
346
- VALUE name, data, opts = Qnil;
347
- rb_scan_args(argc, argv, "2:", &name, &data, &opts);
348
- ext_check_file_security(file, name, data);
349
- Check_Type(name, RUBY_T_STRING);
350
- return file_extattr_set_main(file, file2fd(file),
351
- ext_get_namespace(opts),
352
- StringValue(name),
353
- StringValue(data));
354
- }
355
-
356
- /*
357
- * call-seq:
358
- * extattr_set(path, name, data, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
359
- */
360
- static VALUE
361
- file_s_extattr_set(int argc, VALUE argv[], VALUE file)
362
- {
363
- VALUE path, name, data, opts = Qnil;
364
- rb_scan_args(argc, argv, "3:", &path, &name, &data, &opts);
365
- ext_check_path_security(path, name, data);
366
- Check_Type(name, RUBY_T_STRING);
367
- return file_s_extattr_set_main(StringValue(path),
368
- ext_get_namespace(opts),
369
- StringValue(name),
370
- StringValue(data));
436
+ if (rb_obj_is_kind_of(path, rb_cFile)) {
437
+ ext_check_file_security(path, name, Qnil);
438
+ return file_extattr_set_main(path, file2fd(path),
439
+ conv_namespace(namespace),
440
+ aux_should_be_string(name), aux_should_be_string(data));
441
+ } else {
442
+ ext_check_path_security(path, name, Qnil);
443
+ return file_s_extattr_set_main(aux_to_path(path),
444
+ conv_namespace(namespace),
445
+ aux_should_be_string(name), aux_should_be_string(data));
446
+ }
371
447
  }
372
448
 
373
449
  /*
374
450
  * call-seq:
375
- * extattr_set!(path, name, data, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
451
+ * set!(path, namespace, name, data) -> nil
376
452
  */
377
453
  static VALUE
378
- file_s_extattr_set_link(int argc, VALUE argv[], VALUE file)
454
+ ext_s_set_link(VALUE mod, VALUE path, VALUE namespace, VALUE name, VALUE data)
379
455
  {
380
- VALUE path, name, data, opts = Qnil;
381
- rb_scan_args(argc, argv, "3:", &path, &name, &data, &opts);
382
- ext_check_path_security(path, name, data);
383
- Check_Type(name, RUBY_T_STRING);
384
- return file_s_extattr_set_link_main(StringValue(path),
385
- ext_get_namespace(opts),
386
- StringValue(name),
387
- StringValue(data));
456
+ if (rb_obj_is_kind_of(path, rb_cFile)) {
457
+ ext_check_file_security(path, name, Qnil);
458
+ return file_extattr_set_main(path, file2fd(path),
459
+ conv_namespace(namespace),
460
+ aux_should_be_string(name), aux_should_be_string(data));
461
+ } else {
462
+ ext_check_path_security(path, name, Qnil);
463
+ return file_s_extattr_set_link_main(aux_to_path(path),
464
+ conv_namespace(namespace),
465
+ aux_should_be_string(name), aux_should_be_string(data));
466
+ }
388
467
  }
389
468
 
390
469
 
391
470
  /*
392
471
  * call-seq:
393
- * extattr_delete(name, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
394
- */
395
- static VALUE
396
- file_extattr_delete(int argc, VALUE argv[], VALUE file)
397
- {
398
- VALUE name, opts = Qnil;
399
- rb_scan_args(argc, argv, "1:", &name, &opts);
400
- ext_check_file_security(file, name, Qnil);
401
- Check_Type(name, RUBY_T_STRING);
402
- return file_extattr_delete_main(file, file2fd(file),
403
- ext_get_namespace(opts),
404
- StringValue(name));
405
- }
406
-
407
- /*
408
- * call-seq:
409
- * extattr_delete(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
472
+ * delete(path, namespace, name) -> nil
410
473
  */
411
474
  static VALUE
412
- file_s_extattr_delete(int argc, VALUE argv[], VALUE file)
475
+ ext_s_delete(VALUE mod, VALUE path, VALUE namespace, VALUE name)
413
476
  {
414
- VALUE path, name, opts = Qnil;
415
- rb_scan_args(argc, argv, "2:", &path, &name, &opts);
416
- ext_check_path_security(path, name, Qnil);
417
- Check_Type(name, RUBY_T_STRING);
418
- return file_s_extattr_delete_main(StringValue(path),
419
- ext_get_namespace(opts),
420
- StringValue(name));
477
+ if (rb_obj_is_kind_of(path, rb_cFile)) {
478
+ ext_check_file_security(path, name, Qnil);
479
+ return file_extattr_delete_main(path, file2fd(path), conv_namespace(namespace),
480
+ aux_should_be_string(name));
481
+ } else {
482
+ ext_check_path_security(path, name, Qnil);
483
+ return file_s_extattr_delete_main(aux_to_path(path), conv_namespace(namespace),
484
+ aux_should_be_string(name));
485
+ }
421
486
  }
422
487
 
423
488
  /*
424
489
  * call-seq:
425
- * extattr_delete!(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
490
+ * delete!(path, namespace, name) -> nil
426
491
  */
427
492
  static VALUE
428
- file_s_extattr_delete_link(int argc, VALUE argv[], VALUE file)
493
+ ext_s_delete_link(VALUE mod, VALUE path, VALUE namespace, VALUE name)
429
494
  {
430
- VALUE path, name, opts = Qnil;
431
- rb_scan_args(argc, argv, "2:", &path, &name, &opts);
432
- ext_check_path_security(path, name, Qnil);
433
- Check_Type(name, RUBY_T_STRING);
434
- return file_s_extattr_delete_link_main(StringValue(path),
435
- ext_get_namespace(opts),
436
- StringValue(name));
495
+ if (rb_obj_is_kind_of(path, rb_cFile)) {
496
+ ext_check_file_security(path, name, Qnil);
497
+ return file_extattr_delete_main(path, file2fd(path), conv_namespace(namespace),
498
+ aux_should_be_string(name));
499
+ } else {
500
+ ext_check_path_security(path, name, Qnil);
501
+ return file_s_extattr_delete_link_main(aux_to_path(path), conv_namespace(namespace),
502
+ aux_should_be_string(name));
503
+ }
437
504
  }
438
505
 
439
506
 
440
507
  void
441
508
  Init_extattr(void)
442
509
  {
443
- SYMnamespace = ID2SYM(rb_intern_const("namespace"));
444
-
445
- rb_define_const(rb_cFile, "EXTATTR_NAMESPACE_USER", INT2NUM(EXTATTR_NAMESPACE_USER));
446
- rb_define_const(rb_cFile, "EXTATTR_NAMESPACE_SYSTEM", INT2NUM(EXTATTR_NAMESPACE_SYSTEM));
447
- rb_define_const(rb_cFile, "EXTATTR_VERSION", rb_str_freeze(rb_str_new_cstr("0.2")));
448
-
449
- rb_define_method(rb_cFile, "extattr_list", RUBY_METHOD_FUNC(file_extattr_list), -1);
450
- rb_define_singleton_method(rb_cFile, "extattr_list", RUBY_METHOD_FUNC(file_s_extattr_list), -1);
451
- rb_define_singleton_method(rb_cFile, "extattr_list!", RUBY_METHOD_FUNC(file_s_extattr_list_link), -1);
452
-
453
- rb_define_method(rb_cFile, "extattr_size", RUBY_METHOD_FUNC(file_extattr_size), -1);
454
- rb_define_singleton_method(rb_cFile, "extattr_size", RUBY_METHOD_FUNC(file_s_extattr_size), -1);
455
- rb_define_singleton_method(rb_cFile, "extattr_size!", RUBY_METHOD_FUNC(file_s_extattr_size_link), -1);
456
-
457
- rb_define_method(rb_cFile, "extattr_get", RUBY_METHOD_FUNC(file_extattr_get), -1);
458
- rb_define_singleton_method(rb_cFile, "extattr_get", RUBY_METHOD_FUNC(file_s_extattr_get), -1);
459
- rb_define_singleton_method(rb_cFile, "extattr_get!", RUBY_METHOD_FUNC(file_s_extattr_get_link), -1);
460
-
461
- rb_define_method(rb_cFile, "extattr_set", RUBY_METHOD_FUNC(file_extattr_set), -1);
462
- rb_define_singleton_method(rb_cFile, "extattr_set", RUBY_METHOD_FUNC(file_s_extattr_set), -1);
463
- rb_define_singleton_method(rb_cFile, "extattr_set!", RUBY_METHOD_FUNC(file_s_extattr_set_link), -1);
464
-
465
- rb_define_method(rb_cFile, "extattr_delete", RUBY_METHOD_FUNC(file_extattr_delete), -1);
466
- rb_define_singleton_method(rb_cFile, "extattr_delete", RUBY_METHOD_FUNC(file_s_extattr_delete), -1);
467
- rb_define_singleton_method(rb_cFile, "extattr_delete!", RUBY_METHOD_FUNC(file_s_extattr_delete_link), -1);
468
-
469
- ext_init_implement();
510
+ #if HAVE_RB_EXT_RACTOR_SAFE
511
+ rb_ext_ractor_safe(true);
512
+ #endif
513
+ id_downcase = rb_intern("downcase");
514
+ id_to_path = rb_intern("to_path");
515
+
516
+ mExtAttr = rb_define_module("ExtAttr");
517
+ rb_define_const(mExtAttr, "USER", ID2SYM(rb_intern("user")));
518
+ rb_define_const(mExtAttr, "SYSTEM", ID2SYM(rb_intern("system")));
519
+
520
+ rb_define_singleton_method(mExtAttr, "list", RUBY_METHOD_FUNC(ext_s_list), 2);
521
+ rb_define_singleton_method(mExtAttr, "list!", RUBY_METHOD_FUNC(ext_s_list_link), 2);
522
+ rb_define_singleton_method(mExtAttr, "size", RUBY_METHOD_FUNC(ext_s_size), 3);
523
+ rb_define_singleton_method(mExtAttr, "size!", RUBY_METHOD_FUNC(ext_s_size_link), 3);
524
+ rb_define_singleton_method(mExtAttr, "get", RUBY_METHOD_FUNC(ext_s_get), 3);
525
+ rb_define_singleton_method(mExtAttr, "get!", RUBY_METHOD_FUNC(ext_s_get_link), 3);
526
+ rb_define_singleton_method(mExtAttr, "set", RUBY_METHOD_FUNC(ext_s_set), 4);
527
+ rb_define_singleton_method(mExtAttr, "set!", RUBY_METHOD_FUNC(ext_s_set_link), 4);
528
+ rb_define_singleton_method(mExtAttr, "delete", RUBY_METHOD_FUNC(ext_s_delete), 3);
529
+ rb_define_singleton_method(mExtAttr, "delete!", RUBY_METHOD_FUNC(ext_s_delete_link), 3);
530
+
531
+ extattr_init_implement();
470
532
  }
data/ext/extconf.rb CHANGED
@@ -1,11 +1,8 @@
1
1
  #!ruby
2
- #vim: set fileencoding:utf-8
3
-
4
- raise "require ruby-1.9.3+" unless RUBY_VERSION >= "1.9.3"
5
2
 
6
3
  require "mkmf"
7
4
 
8
- #$CFLAGS << " -std=c99"
5
+ have_func("rb_ext_ractor_safe", "ruby.h")
9
6
 
10
7
  case
11
8
  when have_header("sys/extattr.h")
@@ -19,6 +16,9 @@ when have_header("sys/xattr.h")
19
16
  when have_header("winnt.h") && have_header("ntdef.h") && have_header("psapi.h") &&
20
17
  have_header("ddk/ntifs.h") && have_header("ddk/winddk.h") &&
21
18
  have_library("ntoskrnl") && have_library("ntdll") && have_library("psapi")
19
+ if RbConfig::CONFIG["arch"] =~ /mingw/
20
+ $LDFLAGS << " -static-libgcc -static-libstdc++"
21
+ end
22
22
 
23
23
  else
24
24
  $stderr.puts <<EOM
@@ -28,6 +28,5 @@ EOM
28
28
  exit 1
29
29
  end
30
30
 
31
- #$CFLAGS << " -std=c99"
32
-
33
- create_makefile "extattr"
31
+ ver = RUBY_VERSION.slice(/\d+\.\d+/)
32
+ create_makefile File.join(ver, "extattr")