extattr 0.2 → 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.
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")