extattr 0.1 → 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.
- checksums.yaml +7 -0
- data/HISTORY.ja.md +49 -0
- data/{LICENSE.txt → LICENSE.md} +5 -0
- data/QUICKREF.ja.md +112 -0
- data/README.md +84 -0
- data/Rakefile +212 -0
- data/ext/extattr-extattr.h +192 -0
- data/ext/extattr-windows.h +724 -0
- data/ext/extattr-xattr.h +229 -0
- data/ext/extattr.c +393 -206
- data/ext/extconf.rb +16 -12
- data/gemstub.rb +22 -0
- data/lib/extattr.rb +274 -0
- data/test/test_extattr.rb +75 -0
- metadata +70 -37
- data/README.txt +0 -53
- data/ext/extattr.bsd +0 -186
- data/ext/extattr.linux +0 -209
- data/ext/extattr.windows +0 -407
- data/rspecs/extattr.rb +0 -53
data/ext/extattr.c
CHANGED
@@ -2,40 +2,52 @@
|
|
2
2
|
|
3
3
|
/*
|
4
4
|
* extattr.c
|
5
|
-
* AUTHOR:: dearblue <dearblue@
|
5
|
+
* AUTHOR:: dearblue <dearblue@users.osdn.me>
|
6
6
|
* LICENSE:: 2-clause BSD License
|
7
|
-
*
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
static VALUE
|
18
|
-
static VALUE
|
19
|
-
static VALUE
|
20
|
-
static VALUE
|
21
|
-
static VALUE
|
22
|
-
static VALUE
|
23
|
-
static VALUE
|
24
|
-
static VALUE
|
25
|
-
static VALUE
|
26
|
-
static VALUE
|
27
|
-
static VALUE
|
28
|
-
static VALUE
|
29
|
-
static VALUE
|
13
|
+
#include <ruby/version.h>
|
14
|
+
#include <ctype.h>
|
15
|
+
|
16
|
+
|
17
|
+
static VALUE file_extattr_list_main(VALUE file, int fd, int namespace1);
|
18
|
+
static VALUE file_extattr_size_main(VALUE file, int fd, int namespace1, VALUE name);
|
19
|
+
static VALUE file_extattr_get_main(VALUE file, int fd, int namespace1, VALUE name);
|
20
|
+
static VALUE file_extattr_set_main(VALUE file, int fd, int namespace1, VALUE name, VALUE data);
|
21
|
+
static VALUE file_extattr_delete_main(VALUE file, int fd, int namespace1, VALUE name);
|
22
|
+
static VALUE file_s_extattr_list_main(VALUE path, int namespace1);
|
23
|
+
static VALUE file_s_extattr_list_link_main(VALUE path, int namespace1);
|
24
|
+
static VALUE file_s_extattr_size_main(VALUE path, int namespace1, VALUE name);
|
25
|
+
static VALUE file_s_extattr_size_link_main(VALUE path, int namespace1, VALUE name);
|
26
|
+
static VALUE file_s_extattr_get_main(VALUE path, int namespace1, VALUE name);
|
27
|
+
static VALUE file_s_extattr_get_link_main(VALUE path, int namespace1, VALUE name);
|
28
|
+
static VALUE file_s_extattr_set_main(VALUE path, int namespace1, VALUE name, VALUE data);
|
29
|
+
static VALUE file_s_extattr_set_link_main(VALUE path, int namespace1, VALUE name, VALUE data);
|
30
|
+
static VALUE file_s_extattr_delete_main(VALUE path, int namespace1, VALUE name);
|
31
|
+
static VALUE file_s_extattr_delete_link_main(VALUE path, int namespace1, VALUE name);
|
30
32
|
|
31
33
|
// Init_extattr から呼び出される、環境ごとの初期設定。
|
32
|
-
static 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
|
|
37
42
|
#define ELEMENTOF(V) (sizeof(V) / sizeof((V)[0]))
|
38
43
|
|
44
|
+
#define LOGF(FORMAT, ...) { fprintf(stderr, "%s:%d:%s: " FORMAT "\n", __FILE__, __LINE__, __func__, __VA_ARGS__); }
|
45
|
+
|
46
|
+
static VALUE mExtAttr;
|
47
|
+
|
48
|
+
static ID id_downcase;
|
49
|
+
static ID id_to_path;
|
50
|
+
|
39
51
|
|
40
52
|
static inline VALUE
|
41
53
|
hash_lookup(VALUE hash, VALUE key, VALUE default_value)
|
@@ -52,294 +64,469 @@ hash_lookup(VALUE hash, VALUE key, VALUE default_value)
|
|
52
64
|
static inline int
|
53
65
|
file2fd(VALUE file)
|
54
66
|
{
|
67
|
+
rb_check_type(file, RUBY_T_FILE);
|
55
68
|
rb_io_t *fptr;
|
56
|
-
// FIXME: ファイルであることを確認すべき
|
57
69
|
GetOpenFile(file, fptr);
|
58
70
|
return fptr->fd;
|
59
71
|
}
|
60
72
|
|
73
|
+
static inline void
|
74
|
+
ext_error_extattr(int err, VALUE filepath, VALUE attrname)
|
75
|
+
{
|
76
|
+
errno = err;
|
77
|
+
if (NIL_P(filepath)) {
|
78
|
+
filepath = rb_str_new_cstr("<?>");
|
79
|
+
} else {
|
80
|
+
filepath = rb_get_path_no_checksafe(filepath);
|
81
|
+
}
|
82
|
+
VALUE mesg = rb_sprintf("%s [%s]", StringValueCStr(filepath), StringValueCStr(attrname));
|
83
|
+
rb_sys_fail(StringValueCStr(mesg));
|
84
|
+
}
|
85
|
+
|
86
|
+
static inline void
|
87
|
+
ext_error_namespace(VALUE path, int namespace1)
|
88
|
+
{
|
89
|
+
ext_error_extattr(EPERM, path, rb_sprintf("namespace=%d", namespace1));
|
90
|
+
}
|
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
|
+
|
61
152
|
|
62
153
|
#if defined(HAVE_SYS_EXTATTR_H)
|
63
|
-
# include "extattr.
|
64
|
-
#elif defined(HAVE_ATTR_XATTR_H)
|
65
|
-
# include "extattr.linux"
|
154
|
+
# include "extattr-extattr.h"
|
66
155
|
#elif defined(HAVE_WINNT_H)
|
67
|
-
# include "extattr.
|
156
|
+
# include "extattr-windows.h"
|
157
|
+
#elif defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H)
|
158
|
+
# include "extattr-xattr.h"
|
68
159
|
#else
|
69
|
-
# error ruby
|
160
|
+
# error ruby-extattr not supported on your system
|
70
161
|
#endif
|
71
162
|
|
72
163
|
|
73
|
-
static VALUE SYMnamespace;
|
74
|
-
|
75
|
-
|
76
|
-
/*
|
77
|
-
* call-seq:
|
78
|
-
* file.extattr_list(namespace: File::EXTATTR_NAMESPACE_USER) -> names array
|
79
|
-
* file.extattr_list(namespace: File::EXTATTR_NAMESPACE_USER) { |name| ... } -> nil
|
80
|
-
*
|
81
|
-
* 開いているファイルの拡張属性名一覧を得ます。
|
82
|
-
*
|
83
|
-
* ブロックが指定された場合、一つ一つの拡張属性名を渡してブロックが評価されます。ブロックの戻り値は無視されます。
|
84
|
-
*/
|
85
164
|
static VALUE
|
86
|
-
|
165
|
+
aux_should_be_string(VALUE obj)
|
87
166
|
{
|
88
|
-
|
89
|
-
|
90
|
-
return file_extattr_list0(file, file2fd(file),
|
91
|
-
NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER))));
|
167
|
+
rb_check_type(obj, RUBY_T_STRING);
|
168
|
+
return obj;
|
92
169
|
}
|
93
170
|
|
94
|
-
|
95
|
-
|
96
|
-
* File.extattr_list(path, namespace: File::EXTATTR_NAMESPACE_USER) -> names array
|
97
|
-
* File.extattr_list(path, namespace: File::EXTATTR_NAMESPACE_USER) { |name| ... } -> nil
|
98
|
-
*
|
99
|
-
* ファイル名を指定すること以外は File#extattr_list と同じです。
|
100
|
-
*/
|
101
|
-
static VALUE
|
102
|
-
file_s_extattr_list(int argc, VALUE argv[], VALUE file)
|
171
|
+
static int
|
172
|
+
convert_namespace_int(VALUE namespace)
|
103
173
|
{
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
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);
|
108
185
|
}
|
109
186
|
|
110
|
-
|
111
|
-
|
112
|
-
* File.extattr_list!(path, namespace: File::EXTATTR_NAMESPACE_USER) -> names array
|
113
|
-
* File.extattr_list!(path, namespace: File::EXTATTR_NAMESPACE_USER) { |name| ... } -> nil
|
114
|
-
*
|
115
|
-
* シンボリックリンクに対する操作という以外は、File.extattr_list と同じです。
|
116
|
-
*/
|
117
|
-
static VALUE
|
118
|
-
file_s_extattr_list_link(int argc, VALUE argv[], VALUE file)
|
187
|
+
static int
|
188
|
+
convert_namespace_str(VALUE namespace)
|
119
189
|
{
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
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
|
+
}
|
124
207
|
}
|
125
208
|
|
209
|
+
static int
|
210
|
+
conv_namespace(VALUE namespace)
|
211
|
+
{
|
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
|
+
}
|
224
|
+
}
|
126
225
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
static VALUE
|
134
|
-
file_extattr_size(int argc, VALUE argv[], VALUE file)
|
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
|
230
|
+
static void
|
231
|
+
ext_check_file_security(VALUE file, VALUE name, VALUE data)
|
135
232
|
{
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
233
|
+
/*
|
234
|
+
* - file が汚染されていない場合、他のオブジェクトも汚染されていてはならない。
|
235
|
+
* - file が汚染されている場合、他のオブジェクトの汚染に左右されない。
|
236
|
+
* - $SAFE が4以上の場合、非汚染オブジェクトがあれば失敗する。
|
237
|
+
*
|
238
|
+
* file name data | list get set delete
|
239
|
+
* - - - | yes yes yes yes
|
240
|
+
* - - T | no
|
241
|
+
* - T - | no no no
|
242
|
+
* - T T | no
|
243
|
+
* T - - | yes yes yes yes
|
244
|
+
* T - T | yes
|
245
|
+
* T T - | yes yes yes
|
246
|
+
* T T T | yes
|
247
|
+
*/
|
248
|
+
|
249
|
+
int safe = rb_safe_level();
|
250
|
+
|
251
|
+
// $SAFE < 1 であれば、常に成功する
|
252
|
+
if (safe < 1) {
|
253
|
+
return;
|
254
|
+
}
|
255
|
+
|
256
|
+
// 0 < $SAFE < 4 であれば、file が汚染されていれば常に成功、
|
257
|
+
// そうでなければ name と data は非汚染状態でなければならない
|
258
|
+
if (safe < 4) {
|
259
|
+
if (OBJ_TAINTED(file)) {
|
260
|
+
return;
|
261
|
+
}
|
262
|
+
if (OBJ_TAINTED(name) || OBJ_TAINTED(data)) {
|
263
|
+
rb_insecure_operation();
|
264
|
+
}
|
265
|
+
return;
|
266
|
+
}
|
267
|
+
|
268
|
+
// $SAFE は 4以上。すべてのオブジェクトが汚染されていなければならない
|
269
|
+
if (!OBJ_TAINTED(file) ||
|
270
|
+
(!NIL_P(name) && !OBJ_TAINTED(name)) ||
|
271
|
+
(!NIL_P(data) && !OBJ_TAINTED(data))) {
|
272
|
+
|
273
|
+
rb_insecure_operation();
|
274
|
+
}
|
141
275
|
}
|
142
276
|
|
143
|
-
|
144
|
-
|
145
|
-
* File.extattr_size(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> size
|
146
|
-
*/
|
147
|
-
static VALUE
|
148
|
-
file_s_extattr_size(int argc, VALUE argv[], VALUE file)
|
277
|
+
static void
|
278
|
+
ext_check_path_security(VALUE path, VALUE name, VALUE data)
|
149
279
|
{
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
280
|
+
/*
|
281
|
+
* - すべてのオブジェクトが汚染されていない状態でなければならない。
|
282
|
+
* - $SAFE が4以上の場合、常に失敗する。
|
283
|
+
*
|
284
|
+
* path name data | list get set delete
|
285
|
+
* - - - | yes yes yes yes
|
286
|
+
* - - T | no
|
287
|
+
* - T - | no no no
|
288
|
+
* - T T | no
|
289
|
+
* T - - | no no no no
|
290
|
+
* T - T | no
|
291
|
+
* T T - | no no no
|
292
|
+
* T T T | no
|
293
|
+
*/
|
294
|
+
|
295
|
+
int safe = rb_safe_level();
|
296
|
+
if (safe < 1) { return; }
|
297
|
+
if (safe < 4) {
|
298
|
+
if (OBJ_TAINTED(path) || OBJ_TAINTED(name) || OBJ_TAINTED(data)) {
|
299
|
+
rb_insecure_operation();
|
300
|
+
}
|
301
|
+
} else {
|
302
|
+
rb_insecure_operation();
|
303
|
+
}
|
155
304
|
}
|
305
|
+
#endif
|
306
|
+
|
156
307
|
|
157
308
|
/*
|
158
309
|
* call-seq:
|
159
|
-
*
|
310
|
+
* list(path, namespace) -> names array
|
311
|
+
* list(path, namespace) { |name| ... } -> nil
|
160
312
|
*/
|
161
313
|
static VALUE
|
162
|
-
|
314
|
+
ext_s_list(VALUE mod, VALUE path, VALUE namespace)
|
163
315
|
{
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
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
|
+
}
|
169
325
|
}
|
170
326
|
|
171
|
-
|
172
327
|
/*
|
173
328
|
* call-seq:
|
174
|
-
*
|
329
|
+
* extattr_list!(path, namespace) -> names array
|
330
|
+
* extattr_list!(path, namespace) { |name| ... } -> nil
|
175
331
|
*/
|
176
332
|
static VALUE
|
177
|
-
|
333
|
+
ext_s_list_link(VALUE mod, VALUE path, VALUE namespace)
|
178
334
|
{
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
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
|
+
}
|
184
344
|
}
|
185
345
|
|
346
|
+
|
186
347
|
/*
|
187
348
|
* call-seq:
|
188
|
-
*
|
349
|
+
* size(path, namespace, name) -> size
|
189
350
|
*/
|
190
351
|
static VALUE
|
191
|
-
|
352
|
+
ext_s_size(VALUE mod, VALUE path, VALUE namespace, VALUE name)
|
192
353
|
{
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
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
|
+
}
|
198
363
|
}
|
199
364
|
|
200
365
|
/*
|
201
366
|
* call-seq:
|
202
|
-
*
|
367
|
+
* size!(path, namespace, name) -> size
|
203
368
|
*/
|
204
369
|
static VALUE
|
205
|
-
|
370
|
+
ext_s_size_link(VALUE mod, VALUE path, VALUE namespace, VALUE name)
|
206
371
|
{
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
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
|
+
}
|
212
381
|
}
|
213
382
|
|
214
383
|
|
215
384
|
/*
|
216
385
|
* call-seq:
|
217
|
-
*
|
386
|
+
* get(path, namespace, name) -> data
|
218
387
|
*/
|
219
388
|
static VALUE
|
220
|
-
|
389
|
+
ext_s_get(VALUE mod, VALUE path, VALUE namespace, VALUE name)
|
221
390
|
{
|
222
|
-
VALUE
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
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
|
+
}
|
401
|
+
|
402
|
+
rb_obj_infect(v, path);
|
403
|
+
return v;
|
228
404
|
}
|
229
405
|
|
230
406
|
/*
|
231
407
|
* call-seq:
|
232
|
-
*
|
408
|
+
* get!(path, namespace, name) -> data
|
233
409
|
*/
|
234
410
|
static VALUE
|
235
|
-
|
411
|
+
ext_s_get_link(VALUE mod, VALUE path, VALUE namespace, VALUE name)
|
236
412
|
{
|
237
|
-
VALUE
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
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);
|
425
|
+
return v;
|
243
426
|
}
|
244
427
|
|
428
|
+
|
245
429
|
/*
|
246
430
|
* call-seq:
|
247
|
-
*
|
431
|
+
* set(path, namespace, name, data) -> nil
|
248
432
|
*/
|
249
433
|
static VALUE
|
250
|
-
|
434
|
+
ext_s_set(VALUE mod, VALUE path, VALUE namespace, VALUE name, VALUE data)
|
251
435
|
{
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
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
|
+
}
|
258
447
|
}
|
259
448
|
|
260
|
-
|
261
449
|
/*
|
262
450
|
* call-seq:
|
263
|
-
*
|
451
|
+
* set!(path, namespace, name, data) -> nil
|
264
452
|
*/
|
265
453
|
static VALUE
|
266
|
-
|
454
|
+
ext_s_set_link(VALUE mod, VALUE path, VALUE namespace, VALUE name, VALUE data)
|
267
455
|
{
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
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
|
+
}
|
273
467
|
}
|
274
468
|
|
469
|
+
|
275
470
|
/*
|
276
471
|
* call-seq:
|
277
|
-
*
|
472
|
+
* delete(path, namespace, name) -> nil
|
278
473
|
*/
|
279
474
|
static VALUE
|
280
|
-
|
475
|
+
ext_s_delete(VALUE mod, VALUE path, VALUE namespace, VALUE name)
|
281
476
|
{
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
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
|
+
}
|
287
486
|
}
|
288
487
|
|
289
488
|
/*
|
290
489
|
* call-seq:
|
291
|
-
*
|
490
|
+
* delete!(path, namespace, name) -> nil
|
292
491
|
*/
|
293
492
|
static VALUE
|
294
|
-
|
493
|
+
ext_s_delete_link(VALUE mod, VALUE path, VALUE namespace, VALUE name)
|
295
494
|
{
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
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
|
+
}
|
301
504
|
}
|
302
505
|
|
303
506
|
|
304
|
-
/*
|
305
|
-
* Document-class: File
|
306
|
-
*
|
307
|
-
* File クラスに拡張属性を操作するメソッドを追加します。
|
308
|
-
*
|
309
|
-
* 感嘆符(『!』)のついたメソッドは、シンボリックリンクに対する操作となります。
|
310
|
-
*
|
311
|
-
* メソッドにキーワード引数として <code>namespace:</code> を与えることにより、拡張属性の名前空間を指定することが出来ます。
|
312
|
-
* 現在の実装においては <code>EXTATTR_NAMESPACE_USER</code> と <code>EXTATTR_NAMESPACE_SYSTEM</code> のみが利用可能です。
|
313
|
-
*/
|
314
|
-
|
315
|
-
|
316
507
|
void
|
317
508
|
Init_extattr(void)
|
318
509
|
{
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
rb_define_singleton_method(
|
330
|
-
rb_define_singleton_method(
|
331
|
-
|
332
|
-
|
333
|
-
rb_define_singleton_method(
|
334
|
-
rb_define_singleton_method(
|
335
|
-
|
336
|
-
|
337
|
-
rb_define_singleton_method(
|
338
|
-
rb_define_singleton_method(
|
339
|
-
|
340
|
-
|
341
|
-
rb_define_singleton_method(rb_cFile, "extattr_delete", RUBY_METHOD_FUNC(file_s_extattr_delete), -1);
|
342
|
-
rb_define_singleton_method(rb_cFile, "extattr_delete!", RUBY_METHOD_FUNC(file_s_extattr_delete_link), -1);
|
343
|
-
|
344
|
-
setup();
|
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();
|
345
532
|
}
|