extattr 0.1 → 0.4

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 = 1,
10
+ EXTATTR_NAMESPACE_SYSTEM = 2,
11
+ EXTATTR_NAMESPACE_TRUSTED = 3,
12
+ EXTATTR_NAMESPACE_SECURITY = 4,
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
+ extattr_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(mExtAttr, "IMPLEMENT", rb_str_freeze(rb_str_new_cstr("xattr")));
229
+ }