extattr 0.1.2 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,229 @@
1
+ #include <sys/types.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
+ };
14
+
15
+
16
+ static VALUE NAMESPACE_USER_PREFIX, NAMESPACE_SYSTEM_PREFIX;
17
+
18
+
19
+ static VALUE
20
+ xattr_name(int namespace1, VALUE name)
21
+ {
22
+ switch (namespace1) {
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, "namespace1 error");
29
+ return Qnil;
30
+ }
31
+ }
32
+
33
+
34
+ static inline void
35
+ extattr_list_name(const char *ptr, size_t size, VALUE infection_source, int namespace1, VALUE (*func)(void *, VALUE), void *user)
36
+ {
37
+ const char *end = ptr + size;
38
+ while (ptr < end) {
39
+ int len = strlen(ptr);
40
+ // if (len > (end - ptr)) { ... } // TODO
41
+ if (namespace1 == EXTATTR_NAMESPACE_USER && len > 5 && strncmp(ptr, "user.", 5) == 0) {
42
+ ptr += 5;
43
+ } else if (namespace1 == EXTATTR_NAMESPACE_SYSTEM && len > 7 && strncmp(ptr, "system.", 7) == 0) {
44
+ ptr += 7;
45
+ } else {
46
+ ptr += len + 1;
47
+ continue;
48
+ }
49
+
50
+ VALUE name = rb_str_new_cstr(ptr);
51
+ OBJ_INFECT(name, infection_source);
52
+ func(user, name);
53
+ ptr += RSTRING_LEN(name) + 1; // 最後の『+1』は、ヌルバイトの分。
54
+ }
55
+ }
56
+
57
+ static VALUE
58
+ extattr_list_common(ssize_t (*func)(), void *d, VALUE infection_source, int namespace1)
59
+ {
60
+ ssize_t size = 65536;
61
+ VALUE buf = rb_str_buf_new(size);
62
+ char *ptr = RSTRING_PTR(buf);
63
+ size = func(d, ptr, size);
64
+ if (size < 0) { rb_sys_fail("listxattr call error"); }
65
+
66
+ if (rb_block_given_p()) {
67
+ extattr_list_name(ptr, size, infection_source, namespace1,
68
+ (VALUE (*)(void *, VALUE))rb_yield_values,
69
+ (void *)1);
70
+ return Qnil;
71
+ } else {
72
+ VALUE list = rb_ary_new();
73
+ OBJ_INFECT(list, infection_source);
74
+ extattr_list_name(ptr, size, infection_source, namespace1,
75
+ (VALUE (*)(void *, VALUE))rb_ary_push,
76
+ (void *)list);
77
+ return list;
78
+ }
79
+ }
80
+
81
+ static VALUE
82
+ file_extattr_list_main(VALUE file, int fd, int namespace1)
83
+ {
84
+ return extattr_list_common(flistxattr, (void *)fd,
85
+ file, namespace1);
86
+ }
87
+
88
+ static VALUE
89
+ file_s_extattr_list_main(VALUE path, int namespace1)
90
+ {
91
+ return extattr_list_common(listxattr, StringValueCStr(path),
92
+ path, namespace1);
93
+ }
94
+
95
+ static VALUE
96
+ file_s_extattr_list_link_main(VALUE path, int namespace1)
97
+ {
98
+ return extattr_list_common(llistxattr, StringValueCStr(path),
99
+ path, namespace1);
100
+ }
101
+
102
+
103
+ static VALUE
104
+ extattr_size_common(ssize_t (*func)(), void *d, int namespace1, VALUE name)
105
+ {
106
+ name = xattr_name(namespace1, name);
107
+ ssize_t size = func(d, StringValueCStr(name), NULL, 0);
108
+ if (size < 0) { rb_sys_fail("getxattr call error"); }
109
+ return SSIZET2NUM(size);
110
+ }
111
+
112
+ static VALUE
113
+ file_extattr_size_main(VALUE file, int fd, int namespace1, VALUE name)
114
+ {
115
+ return extattr_size_common(fgetxattr, (void *)fd, namespace1, name);
116
+ }
117
+
118
+ static VALUE
119
+ file_s_extattr_size_main(VALUE path, int namespace1, VALUE name)
120
+ {
121
+ return extattr_size_common(getxattr, StringValueCStr(path), namespace1, name);
122
+ }
123
+
124
+ static VALUE
125
+ file_s_extattr_size_link_main(VALUE path, int namespace1, VALUE name)
126
+ {
127
+ return extattr_size_common(lgetxattr, StringValueCStr(path), namespace1, name);
128
+ }
129
+
130
+
131
+ static VALUE
132
+ extattr_get_common(ssize_t (*func)(), void *d, int namespace1, VALUE name)
133
+ {
134
+ name = xattr_name(namespace1, name);
135
+ ssize_t size = 65536;
136
+ VALUE buf = rb_str_buf_new(size);
137
+ char *ptr = RSTRING_PTR(buf);
138
+ size = func(d, StringValueCStr(name), ptr, size);
139
+ if (size < 0) { rb_sys_fail("getxattr call error"); }
140
+ rb_str_set_len(buf, size);
141
+ return buf;
142
+ }
143
+
144
+ static VALUE
145
+ file_extattr_get_main(VALUE file, int fd, int namespace1, VALUE name)
146
+ {
147
+ return extattr_get_common(fgetxattr, (void *)fd, namespace1, name);
148
+ }
149
+
150
+ static VALUE
151
+ file_s_extattr_get_main(VALUE path, int namespace1, VALUE name)
152
+ {
153
+ return extattr_get_common(getxattr, StringValueCStr(path), namespace1, name);
154
+ }
155
+
156
+ static VALUE
157
+ file_s_extattr_get_link_main(VALUE path, int namespace1, VALUE name)
158
+ {
159
+ return extattr_get_common(lgetxattr, StringValueCStr(path), namespace1, name);
160
+ }
161
+
162
+
163
+ static VALUE
164
+ extattr_set_common(int (*func)(), void *d, int namespace1, VALUE name, VALUE data)
165
+ {
166
+ name = xattr_name(namespace1, name);
167
+ int status = func(d, StringValueCStr(name), RSTRING_PTR(data), RSTRING_LEN(data), 0);
168
+ if (status < 0) { rb_sys_fail("setxattr call error"); }
169
+ return Qnil;
170
+ }
171
+
172
+ static VALUE
173
+ file_extattr_set_main(VALUE file, int fd, int namespace1, VALUE name, VALUE data)
174
+ {
175
+ return extattr_set_common(fsetxattr, (void *)fd, namespace1, name, data);
176
+ }
177
+
178
+ static VALUE
179
+ file_s_extattr_set_main(VALUE path, int namespace1, VALUE name, VALUE data)
180
+ {
181
+ return extattr_set_common(setxattr, StringValueCStr(path), namespace1, name, data);
182
+ }
183
+
184
+ static VALUE
185
+ file_s_extattr_set_link_main(VALUE path, int namespace1, VALUE name, VALUE data)
186
+ {
187
+ return extattr_set_common(lsetxattr, StringValueCStr(path), namespace1, name, data);
188
+ }
189
+
190
+
191
+ static VALUE
192
+ extattr_delete_common(int (*func)(), void *d, int namespace1, VALUE name)
193
+ {
194
+ name = xattr_name(namespace1, name);
195
+ int status = func(d, StringValueCStr(name));
196
+ if (status < 0) { rb_sys_fail("removexattr call error"); }
197
+ return Qnil;
198
+ }
199
+
200
+ static VALUE
201
+ file_extattr_delete_main(VALUE file, int fd, int namespace1, VALUE name)
202
+ {
203
+ return extattr_delete_common(fremovexattr, (void *)fd, namespace1, name);
204
+ }
205
+
206
+ static VALUE
207
+ file_s_extattr_delete_main(VALUE path, int namespace1, VALUE name)
208
+ {
209
+ return extattr_delete_common(removexattr, StringValueCStr(path), namespace1, name);
210
+ }
211
+
212
+ static VALUE
213
+ file_s_extattr_delete_link_main(VALUE path, int namespace1, VALUE name)
214
+ {
215
+ return extattr_delete_common(lremovexattr, StringValueCStr(path), namespace1, name);
216
+ }
217
+
218
+
219
+ static void
220
+ ext_init_implement(void)
221
+ {
222
+ NAMESPACE_USER_PREFIX = rb_str_new_cstr("user.");
223
+ NAMESPACE_SYSTEM_PREFIX = rb_str_new_cstr("system.");
224
+
225
+ rb_gc_register_mark_object(NAMESPACE_USER_PREFIX);
226
+ rb_gc_register_mark_object(NAMESPACE_SYSTEM_PREFIX);
227
+
228
+ rb_define_const(rb_cFile, "EXTATTR_IMPLEMANT", rb_str_freeze(rb_str_new_cstr("xattr")));
229
+ }
@@ -12,30 +12,32 @@
12
12
  #include <ruby/intern.h>
13
13
 
14
14
 
15
- static VALUE file_extattr_list0(VALUE file, int fd, int namespace);
16
- static VALUE file_extattr_size0(VALUE file, int fd, int namespace, VALUE name);
17
- static VALUE file_extattr_get0(VALUE file, int fd, int namespace, VALUE name);
18
- static VALUE file_extattr_set0(VALUE file, int fd, int namespace, VALUE name, VALUE data);
19
- static VALUE file_extattr_delete0(VALUE file, int fd, int namespace, VALUE name);
20
- static VALUE file_s_extattr_list0(VALUE path, int namespace);
21
- static VALUE file_s_extattr_list_link0(VALUE path, int namespace);
22
- static VALUE file_s_extattr_size0(VALUE path, int namespace, VALUE name);
23
- static VALUE file_s_extattr_size_link0(VALUE path, int namespace, VALUE name);
24
- static VALUE file_s_extattr_get0(VALUE path, int namespace, VALUE name);
25
- static VALUE file_s_extattr_get_link0(VALUE path, int namespace, VALUE name);
26
- static VALUE file_s_extattr_set0(VALUE path, int namespace, VALUE name, VALUE data);
27
- static VALUE file_s_extattr_set_link0(VALUE path, int namespace, VALUE name, VALUE data);
28
- static VALUE file_s_extattr_delete0(VALUE path, int namespace, VALUE name);
29
- static VALUE file_s_extattr_delete_link0(VALUE path, int namespace, VALUE name);
15
+ static VALUE file_extattr_list_main(VALUE file, int fd, int namespace1);
16
+ static VALUE file_extattr_size_main(VALUE file, int fd, int namespace1, VALUE name);
17
+ static VALUE file_extattr_get_main(VALUE file, int fd, int namespace1, VALUE name);
18
+ static VALUE file_extattr_set_main(VALUE file, int fd, int namespace1, VALUE name, VALUE data);
19
+ static VALUE file_extattr_delete_main(VALUE file, int fd, int namespace1, VALUE name);
20
+ static VALUE file_s_extattr_list_main(VALUE path, int namespace1);
21
+ static VALUE file_s_extattr_list_link_main(VALUE path, int namespace1);
22
+ static VALUE file_s_extattr_size_main(VALUE path, int namespace1, VALUE name);
23
+ static VALUE file_s_extattr_size_link_main(VALUE path, int namespace1, VALUE name);
24
+ static VALUE file_s_extattr_get_main(VALUE path, int namespace1, VALUE name);
25
+ static VALUE file_s_extattr_get_link_main(VALUE path, int namespace1, VALUE name);
26
+ static VALUE file_s_extattr_set_main(VALUE path, int namespace1, VALUE name, VALUE data);
27
+ static VALUE file_s_extattr_set_link_main(VALUE path, int namespace1, VALUE name, VALUE data);
28
+ static VALUE file_s_extattr_delete_main(VALUE path, int namespace1, VALUE name);
29
+ static VALUE file_s_extattr_delete_link_main(VALUE path, int namespace1, VALUE name);
30
30
 
31
31
  // Init_extattr から呼び出される、環境ごとの初期設定。
32
- static void setup(void);
32
+ static void ext_init_implement(void);
33
33
 
34
34
 
35
35
  #define RDOC(...)
36
36
 
37
37
  #define ELEMENTOF(V) (sizeof(V) / sizeof((V)[0]))
38
38
 
39
+ #define LOGF(FORMAT, ...) { fprintf(stderr, "%s:%d:%s: " FORMAT "\n", __FILE__, __LINE__, __func__, __VA_ARGS__); }
40
+
39
41
 
40
42
  static inline VALUE
41
43
  hash_lookup(VALUE hash, VALUE key, VALUE default_value)
@@ -58,25 +60,126 @@ file2fd(VALUE file)
58
60
  return fptr->fd;
59
61
  }
60
62
 
63
+ static inline void
64
+ ext_error_extattr(int err, VALUE filepath, VALUE attrname)
65
+ {
66
+ errno = err;
67
+ if (NIL_P(filepath)) {
68
+ filepath = rb_str_new_cstr("<?>");
69
+ } else {
70
+ filepath = rb_get_path_no_checksafe(filepath);
71
+ }
72
+ VALUE mesg = rb_sprintf("%s [%s]", StringValueCStr(filepath), StringValueCStr(attrname));
73
+ rb_sys_fail(StringValueCStr(mesg));
74
+ }
75
+
76
+ static inline void
77
+ ext_error_namespace(VALUE path, int namespace1)
78
+ {
79
+ ext_error_extattr(EPERM, path, rb_sprintf("namespace=%d", namespace1));
80
+ }
81
+
61
82
 
62
83
  #if defined(HAVE_SYS_EXTATTR_H)
63
- # include "extattr.bsd"
84
+ # include "extattr-extattr.h"
64
85
  #elif defined(HAVE_WINNT_H)
65
- # include "extattr.windows"
86
+ # include "extattr-windows.h"
66
87
  #elif defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H)
67
- # include "extattr.linux"
88
+ # include "extattr-xattr.h"
68
89
  #else
69
- # error ruby extattr not supported on your system
90
+ # error ruby-extattr not supported on your system
70
91
  #endif
71
92
 
72
93
 
73
94
  static VALUE SYMnamespace;
74
95
 
96
+ static int
97
+ ext_get_namespace(VALUE opts)
98
+ {
99
+ return NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER)));
100
+ }
101
+
102
+ static void
103
+ ext_check_file_security(VALUE file, VALUE name, VALUE data)
104
+ {
105
+ /*
106
+ * - file が汚染されていない場合、他のオブジェクトも汚染されていてはならない。
107
+ * - file が汚染されている場合、他のオブジェクトの汚染に左右されない。
108
+ * - $SAFE が4以上の場合、非汚染オブジェクトがあれば失敗する。
109
+ *
110
+ * file name data | list get set delete
111
+ * - - - | yes yes yes yes
112
+ * - - T | no
113
+ * - T - | no no no
114
+ * - T T | no
115
+ * T - - | yes yes yes yes
116
+ * T - T | yes
117
+ * T T - | yes yes yes
118
+ * T T T | yes
119
+ */
120
+
121
+ int safe = rb_safe_level();
122
+
123
+ // $SAFE < 1 であれば、常に成功する
124
+ if (safe < 1) {
125
+ return;
126
+ }
127
+
128
+ // 0 < $SAFE < 4 であれば、file が汚染されていれば常に成功、
129
+ // そうでなければ name と data は非汚染状態でなければならない
130
+ if (safe < 4) {
131
+ if (OBJ_TAINTED(file)) {
132
+ return;
133
+ }
134
+ if (OBJ_TAINTED(name) || OBJ_TAINTED(data)) {
135
+ rb_insecure_operation();
136
+ }
137
+ return;
138
+ }
139
+
140
+ // $SAFE は 4以上。すべてのオブジェクトが汚染されていなければならない
141
+ if (!OBJ_TAINTED(file) ||
142
+ (!NIL_P(name) && !OBJ_TAINTED(name)) ||
143
+ (!NIL_P(data) && !OBJ_TAINTED(data))) {
144
+
145
+ rb_insecure_operation();
146
+ }
147
+ }
148
+
149
+ static void
150
+ ext_check_path_security(VALUE path, VALUE name, VALUE data)
151
+ {
152
+ /*
153
+ * - すべてのオブジェクトが汚染されていない状態でなければならない。
154
+ * - $SAFE が4以上の場合、常に失敗する。
155
+ *
156
+ * path name data | list get set delete
157
+ * - - - | yes yes yes yes
158
+ * - - T | no
159
+ * - T - | no no no
160
+ * - T T | no
161
+ * T - - | no no no no
162
+ * T - T | no
163
+ * T T - | no no no
164
+ * T T T | no
165
+ */
166
+
167
+ int safe = rb_safe_level();
168
+ if (safe < 1) { return; }
169
+ if (safe < 4) {
170
+ if (OBJ_TAINTED(path) || OBJ_TAINTED(name) || OBJ_TAINTED(data)) {
171
+ rb_insecure_operation();
172
+ }
173
+ } else {
174
+ rb_insecure_operation();
175
+ }
176
+ }
177
+
75
178
 
76
179
  /*
77
180
  * call-seq:
78
- * file.extattr_list(namespace: File::EXTATTR_NAMESPACE_USER) -> names array
79
- * file.extattr_list(namespace: File::EXTATTR_NAMESPACE_USER) { |name| ... } -> nil
181
+ * extattr_list(namespace: File::EXTATTR_NAMESPACE_USER) -> names array
182
+ * extattr_list(namespace: File::EXTATTR_NAMESPACE_USER) { |name| ... } -> nil
80
183
  *
81
184
  * 開いているファイルの拡張属性名一覧を得ます。
82
185
  *
@@ -87,14 +190,15 @@ file_extattr_list(int argc, VALUE argv[], VALUE file)
87
190
  {
88
191
  VALUE opts = Qnil;
89
192
  rb_scan_args(argc, argv, "0:", &opts);
90
- return file_extattr_list0(file, file2fd(file),
91
- NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER))));
193
+ ext_check_file_security(file, Qnil, Qnil);
194
+ return file_extattr_list_main(file, file2fd(file),
195
+ ext_get_namespace(opts));
92
196
  }
93
197
 
94
198
  /*
95
199
  * call-seq:
96
- * File.extattr_list(path, namespace: File::EXTATTR_NAMESPACE_USER) -> names array
97
- * File.extattr_list(path, namespace: File::EXTATTR_NAMESPACE_USER) { |name| ... } -> nil
200
+ * extattr_list(path, namespace: File::EXTATTR_NAMESPACE_USER) -> names array
201
+ * extattr_list(path, namespace: File::EXTATTR_NAMESPACE_USER) { |name| ... } -> nil
98
202
  *
99
203
  * ファイル名を指定すること以外は File#extattr_list と同じです。
100
204
  */
@@ -103,14 +207,15 @@ file_s_extattr_list(int argc, VALUE argv[], VALUE file)
103
207
  {
104
208
  VALUE path, opts = Qnil;
105
209
  rb_scan_args(argc, argv, "1:", &path, &opts);
106
- return file_s_extattr_list0(StringValue(path),
107
- NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER))));
210
+ ext_check_path_security(path, Qnil, Qnil);
211
+ return file_s_extattr_list_main(StringValue(path),
212
+ ext_get_namespace(opts));
108
213
  }
109
214
 
110
215
  /*
111
216
  * call-seq:
112
- * File.extattr_list!(path, namespace: File::EXTATTR_NAMESPACE_USER) -> names array
113
- * File.extattr_list!(path, namespace: File::EXTATTR_NAMESPACE_USER) { |name| ... } -> nil
217
+ * extattr_list!(path, namespace: File::EXTATTR_NAMESPACE_USER) -> names array
218
+ * extattr_list!(path, namespace: File::EXTATTR_NAMESPACE_USER) { |name| ... } -> nil
114
219
  *
115
220
  * シンボリックリンクに対する操作という以外は、File.extattr_list と同じです。
116
221
  */
@@ -119,14 +224,15 @@ file_s_extattr_list_link(int argc, VALUE argv[], VALUE file)
119
224
  {
120
225
  VALUE path, opts = Qnil;
121
226
  rb_scan_args(argc, argv, "1:", &path, &opts);
122
- return file_s_extattr_list_link0(StringValue(path),
123
- NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER))));
227
+ ext_check_path_security(path, Qnil, Qnil);
228
+ return file_s_extattr_list_link_main(StringValue(path),
229
+ ext_get_namespace(opts));
124
230
  }
125
231
 
126
232
 
127
233
  /*
128
234
  * call-seq:
129
- * file.extattr_size(name, namespace: File::EXTATTR_NAMESPACE_USER) -> names array
235
+ * extattr_size(name, namespace: File::EXTATTR_NAMESPACE_USER) -> names array
130
236
  *
131
237
  * 拡張属性の大きさを取得します。
132
238
  */
@@ -135,191 +241,210 @@ file_extattr_size(int argc, VALUE argv[], VALUE file)
135
241
  {
136
242
  VALUE name, opts = Qnil;
137
243
  rb_scan_args(argc, argv, "1:", &name, &opts);
138
- return file_extattr_size0(file, file2fd(file),
139
- NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER))),
140
- StringValue(name));
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));
141
249
  }
142
250
 
143
251
  /*
144
252
  * call-seq:
145
- * File.extattr_size(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> size
253
+ * extattr_size(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> size
146
254
  */
147
255
  static VALUE
148
256
  file_s_extattr_size(int argc, VALUE argv[], VALUE file)
149
257
  {
150
258
  VALUE path, name, opts = Qnil;
151
259
  rb_scan_args(argc, argv, "2:", &path, &name, &opts);
152
- return file_s_extattr_size0(StringValue(path),
153
- NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER))),
154
- StringValue(name));
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));
155
265
  }
156
266
 
157
267
  /*
158
268
  * call-seq:
159
- * File.extattr_size!(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> size
269
+ * extattr_size!(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> size
160
270
  */
161
271
  static VALUE
162
272
  file_s_extattr_size_link(int argc, VALUE argv[], VALUE file)
163
273
  {
164
274
  VALUE path, name, opts = Qnil;
165
275
  rb_scan_args(argc, argv, "2:", &path, &name, &opts);
166
- return file_s_extattr_size_link0(StringValue(path),
167
- NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER))),
168
- StringValue(name));
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));
169
281
  }
170
282
 
171
283
 
172
284
  /*
173
285
  * call-seq:
174
- * file.extattr_get(name, namespace: File::EXTATTR_NAMESPACE_USER) -> data
286
+ * extattr_get(name, namespace: File::EXTATTR_NAMESPACE_USER) -> data
175
287
  */
176
288
  static VALUE
177
289
  file_extattr_get(int argc, VALUE argv[], VALUE file)
178
290
  {
179
291
  VALUE name, opts = Qnil;
180
292
  rb_scan_args(argc, argv, "1:", &name, &opts);
181
- return file_extattr_get0(file, file2fd(file),
182
- NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER))),
183
- StringValue(name));
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;
184
300
  }
185
301
 
186
302
  /*
187
303
  * call-seq:
188
- * File.extattr_get(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> data
304
+ * extattr_get(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> data
189
305
  */
190
306
  static VALUE
191
307
  file_s_extattr_get(int argc, VALUE argv[], VALUE file)
192
308
  {
193
309
  VALUE path, name, opts = Qnil;
194
310
  rb_scan_args(argc, argv, "2:", &path, &name, &opts);
195
- return file_s_extattr_get0(StringValue(path),
196
- NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER))),
197
- StringValue(name));
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);
317
+ return v;
198
318
  }
199
319
 
200
320
  /*
201
321
  * call-seq:
202
- * File.extattr_get!(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> data
322
+ * extattr_get!(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> data
203
323
  */
204
324
  static VALUE
205
325
  file_s_extattr_get_link(int argc, VALUE argv[], VALUE file)
206
326
  {
207
327
  VALUE path, name, opts = Qnil;
208
328
  rb_scan_args(argc, argv, "2:", &path, &name, &opts);
209
- return file_s_extattr_get_link0(StringValue(path),
210
- NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER))),
211
- StringValue(name));
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);
335
+ return v;
212
336
  }
213
337
 
214
338
 
215
339
  /*
216
340
  * call-seq:
217
- * file.extattr_set(name, data, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
341
+ * extattr_set(name, data, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
218
342
  */
219
343
  static VALUE
220
344
  file_extattr_set(int argc, VALUE argv[], VALUE file)
221
345
  {
222
346
  VALUE name, data, opts = Qnil;
223
- rb_scan_args(argc, argv, "11:", &name, &data, &opts);
224
- return file_extattr_set0(file, file2fd(file),
225
- NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER))),
226
- StringValue(name),
227
- StringValue(data));
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));
228
354
  }
229
355
 
230
356
  /*
231
357
  * call-seq:
232
- * File.extattr_set(path, name, data, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
358
+ * extattr_set(path, name, data, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
233
359
  */
234
360
  static VALUE
235
361
  file_s_extattr_set(int argc, VALUE argv[], VALUE file)
236
362
  {
237
363
  VALUE path, name, data, opts = Qnil;
238
- rb_scan_args(argc, argv, "21:", &path, &name, &data, &opts);
239
- return file_s_extattr_set0(StringValue(path),
240
- NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER))),
241
- StringValue(name),
242
- StringValue(data));
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));
243
371
  }
244
372
 
245
373
  /*
246
374
  * call-seq:
247
- * File.extattr_set!(path, name, data, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
375
+ * extattr_set!(path, name, data, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
248
376
  */
249
377
  static VALUE
250
378
  file_s_extattr_set_link(int argc, VALUE argv[], VALUE file)
251
379
  {
252
380
  VALUE path, name, data, opts = Qnil;
253
- rb_scan_args(argc, argv, "21:", &path, &name, &data, &opts);
254
- return file_s_extattr_set_link0(StringValue(path),
255
- NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER))),
256
- StringValue(name),
257
- StringValue(data));
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));
258
388
  }
259
389
 
260
390
 
261
391
  /*
262
392
  * call-seq:
263
- * file.extattr_delete(name, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
393
+ * extattr_delete(name, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
264
394
  */
265
395
  static VALUE
266
396
  file_extattr_delete(int argc, VALUE argv[], VALUE file)
267
397
  {
268
398
  VALUE name, opts = Qnil;
269
399
  rb_scan_args(argc, argv, "1:", &name, &opts);
270
- return file_extattr_delete0(file, file2fd(file),
271
- NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER))),
272
- StringValue(name));
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));
273
405
  }
274
406
 
275
407
  /*
276
408
  * call-seq:
277
- * File.extattr_delete(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
409
+ * extattr_delete(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
278
410
  */
279
411
  static VALUE
280
412
  file_s_extattr_delete(int argc, VALUE argv[], VALUE file)
281
413
  {
282
414
  VALUE path, name, opts = Qnil;
283
415
  rb_scan_args(argc, argv, "2:", &path, &name, &opts);
284
- return file_s_extattr_delete0(StringValue(path),
285
- NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER))),
286
- StringValue(name));
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));
287
421
  }
288
422
 
289
423
  /*
290
424
  * call-seq:
291
- * File.extattr_delete!(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
425
+ * extattr_delete!(path, name, namespace: File::EXTATTR_NAMESPACE_USER) -> nil
292
426
  */
293
427
  static VALUE
294
428
  file_s_extattr_delete_link(int argc, VALUE argv[], VALUE file)
295
429
  {
296
430
  VALUE path, name, opts = Qnil;
297
431
  rb_scan_args(argc, argv, "2:", &path, &name, &opts);
298
- return file_s_extattr_delete_link0(StringValue(path),
299
- NUM2INT(hash_lookup(opts, SYMnamespace, INT2NUM(EXTATTR_NAMESPACE_USER))),
300
- StringValue(name));
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));
301
437
  }
302
438
 
303
439
 
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
440
  void
317
441
  Init_extattr(void)
318
442
  {
319
- SYMnamespace = ID2SYM(rb_intern("namespace"));
443
+ SYMnamespace = ID2SYM(rb_intern_const("namespace"));
320
444
 
321
- rb_const_set(rb_cFile, rb_intern("EXTATTR_NAMESPACE_USER"), INT2NUM(EXTATTR_NAMESPACE_USER));
322
- rb_const_set(rb_cFile, rb_intern("EXTATTR_NAMESPACE_SYSTEM"), INT2NUM(EXTATTR_NAMESPACE_SYSTEM));
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")));
323
448
 
324
449
  rb_define_method(rb_cFile, "extattr_list", RUBY_METHOD_FUNC(file_extattr_list), -1);
325
450
  rb_define_singleton_method(rb_cFile, "extattr_list", RUBY_METHOD_FUNC(file_s_extattr_list), -1);
@@ -341,5 +466,5 @@ Init_extattr(void)
341
466
  rb_define_singleton_method(rb_cFile, "extattr_delete", RUBY_METHOD_FUNC(file_s_extattr_delete), -1);
342
467
  rb_define_singleton_method(rb_cFile, "extattr_delete!", RUBY_METHOD_FUNC(file_s_extattr_delete_link), -1);
343
468
 
344
- setup();
469
+ ext_init_implement();
345
470
  }