extattr 0.1.2-x86-mingw32 → 0.2-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
data/ext/extattr.windows DELETED
@@ -1,460 +0,0 @@
1
- #include <windows.h>
2
- #include <windowsx.h>
3
- #include <winnt.h>
4
- #include <ddk/ntifs.h>
5
- #include <ddk/winddk.h>
6
- #include <ntdef.h>
7
- #include <psapi.h>
8
- #include <wchar.h>
9
- #include <ruby/win32.h>
10
-
11
- #define EXTATTR_NAMESPACE_USER 0
12
- #define EXTATTR_NAMESPACE_SYSTEM 1
13
-
14
- /*
15
- * - TODO:
16
- * バッファサイズの確保量が結構大きめ。最適化をするべき。
17
- * - TODO:
18
- * Win9X シリーズだとこのライブラリ読み込みすら出来ない。
19
- * メソッド定義だけは行うようにするべき? (実際に呼び出したら NotImplementedError 例外を投げる、とか)
20
- * - リパースポイントって、ADSはつけられないのかな? 操作方法がわからない。
21
- */
22
-
23
- /*
24
- * ADS は普通のファイルのように扱えるから、extattr とみなして扱う場合は容量の制限を設けることにする。
25
- *
26
- * ruby-extattr で不十分な巨大なデータを扱う場合は File.open で開くことが出来るので必要であればそちらで。
27
- *
28
- * TODO: 最適値を探すべき
29
- */
30
- static const size_t EXTATTR_MAX = 65536;
31
-
32
-
33
- static rb_encoding *ENCutf8p;
34
- static VALUE ENCutf8;
35
- static rb_encoding *ENCutf16lep;
36
- static VALUE ENCutf16le;
37
-
38
-
39
- static VALUE
40
- str2wcs(VALUE str)
41
- {
42
- str = rb_str_encode(str, ENCutf16le, 0, Qnil);
43
- rb_str_buf_cat(str, "\0", 1);
44
- return str;
45
- }
46
-
47
- static VALUE
48
- str2wpath(VALUE str)
49
- {
50
- str = str2wcs(str);
51
- wchar_t *p = (wchar_t *)RSTRING_PTR(str);
52
- const wchar_t *end = p + RSTRING_LEN(str) / 2;
53
- for (; p < end; p ++) {
54
- if (*p == L'/') { *p = L'\\'; }
55
- }
56
- return str;
57
- }
58
-
59
- #define STR2WPATH(str) \
60
- ({ \
61
- (str) = str2wpath(str); \
62
- (const wchar_t *)RSTRING_PTR(str); \
63
- }) \
64
-
65
- static VALUE
66
- wcs2str(const wchar_t str[], size_t size)
67
- {
68
- if (!str) { return Qnil; }
69
- VALUE v = rb_str_new((const char *)str, size * sizeof(str[0]));
70
- rb_enc_associate(v, ENCutf16lep);
71
-
72
- return rb_str_encode(v, ENCutf8, ECONV_INVALID_REPLACE | ECONV_UNDEF_REPLACE, Qnil);
73
- }
74
-
75
- static VALUE
76
- wpath2str(const wchar_t path[], size_t size)
77
- {
78
- VALUE v = wcs2str(path, size);
79
- if (NIL_P(v)) { return Qnil; }
80
- char *p = RSTRING_PTR(v);
81
- const char *end = p + RSTRING_LEN(v);
82
- for (; p < end; p ++) {
83
- if (*p == '\\') { *p = '/'; }
84
- }
85
- return v;
86
- }
87
-
88
- /*
89
- * ADS 名の先端のコロン『:』と、終端の『:$DATA』を除去してrbuyの文字列を返す。
90
- */
91
- static VALUE
92
- adsname2str(const wchar_t name[], size_t size)
93
- {
94
- if (name[0] == L':') {
95
- name ++;
96
- size --;
97
- if (size >= 6 && wcsncmp(name + size - 6, L":$DATA", 6) == 0) {
98
- size -= 6;
99
- } else {
100
- size --;
101
- }
102
- }
103
-
104
- if (size > 0) {
105
- return wpath2str(name, size);
106
- } else {
107
- return Qnil;
108
- }
109
- }
110
-
111
-
112
- static void
113
- raise_win32_error(DWORD status, VALUE name)
114
- {
115
- if (NIL_P(name)) {
116
- VALUE args[] = { INT2NUM(rb_w32_map_errno(status)), };
117
- rb_exc_raise(rb_class_new_instance(1, args, rb_eSystemCallError));
118
- } else {
119
- // TODO: name がファイルオブジェクトなのであればパス名を取り出す。パス名がない場合は fd を取り出す。
120
-
121
- VALUE args[] = { StringValue(name), INT2NUM(rb_w32_map_errno(status)), };
122
- rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemCallError));
123
- }
124
- }
125
-
126
- static void
127
- raise_ntstatus_error(NTSTATUS status, VALUE name)
128
- {
129
- raise_win32_error(RtlNtStatusToDosError(status), name);
130
- }
131
-
132
- static void
133
- check_status_error(NTSTATUS status)
134
- {
135
- if (status != STATUS_SUCCESS) {
136
- raise_ntstatus_error(status, Qnil);
137
- }
138
- }
139
-
140
-
141
- static VALUE
142
- get_filepath(HANDLE file)
143
- {
144
- DWORD size = 65536;
145
- VALUE buf = rb_str_buf_new(size);
146
- NTSTATUS status = NtQueryObject(file,
147
- ObjectNameInformation,
148
- RSTRING_PTR(buf),
149
- size,
150
- &size);
151
- check_status_error(status);
152
-
153
- const OBJECT_NAME_INFORMATION *info = (const OBJECT_NAME_INFORMATION *)RSTRING_PTR(buf);
154
- if (wcsnicmp(info->Name.Buffer, L"\\Device\\", 8) == 0) {
155
- // 先頭の "/Device/" を "//?/" に置き換える
156
- wcsncpy(info->Name.Buffer + 4, L"\\\\?\\", 4);
157
- return wpath2str(info->Name.Buffer + 4, info->Name.Length / 2 - 4);
158
- } else {
159
- return wpath2str(info->Name.Buffer, info->Name.Length / 2);
160
- }
161
- }
162
-
163
- static uint64_t
164
- get_filesize(HANDLE file)
165
- {
166
- BY_HANDLE_FILE_INFORMATION info;
167
-
168
- if (!GetFileInformationByHandle(file, &info)) {
169
- raise_win32_error(GetLastError(), Qnil);
170
- }
171
-
172
- return ((uint64_t)info.nFileSizeHigh << 32) | info.nFileSizeLow;
173
- }
174
-
175
- static VALUE
176
- file_close(HANDLE file)
177
- {
178
- /*
179
- * rb_ensure から直接呼びたかったけど、呼び出し規約が違うから無理だよね。
180
- */
181
- CloseHandle(file);
182
-
183
- return Qnil;
184
- }
185
-
186
- static void
187
- check_namespace(int namespace, VALUE path)
188
- {
189
- if (namespace != EXTATTR_NAMESPACE_USER) {
190
- errno = EPERM;
191
- if (NIL_P(path)) {
192
- rb_sys_fail(NULL);
193
- } else {
194
- rb_sys_fail(StringValueCStr(path));
195
- }
196
- }
197
- }
198
-
199
-
200
- static void
201
- extattr_list_name(const char *ptr, void *(*yield)(void *user, VALUE name), void *user)
202
- {
203
- for (;;) {
204
- const FILE_STREAM_INFORMATION *info = (const FILE_STREAM_INFORMATION *)ptr;
205
- VALUE name = adsname2str(info->StreamName, info->StreamNameLength / 2);
206
- if (!NIL_P(name) && RSTRING_LEN(name) > 0) {
207
- yield(user, name);
208
- }
209
- size_t size = info->NextEntryOffset;
210
- if (size == 0) { break; }
211
- ptr += size;
212
- }
213
- }
214
-
215
- static VALUE
216
- extattr_list0_try(HANDLE file)
217
- {
218
- VALUE iostatusblock = rb_str_buf_new(4096);
219
- size_t size = 65536; // TODO: 最適値を見つける
220
- VALUE infobuf = rb_str_buf_new(size);
221
- char *ptr = RSTRING_PTR(infobuf);
222
- memset(ptr, 0, sizeof(FILE_STREAM_INFORMATION));
223
- NTSTATUS status = NtQueryInformationFile(file,
224
- (PIO_STATUS_BLOCK)RSTRING_PTR(iostatusblock),
225
- ptr, size,
226
- FileStreamInformation);
227
- check_status_error(status);
228
-
229
- if (rb_block_given_p()) {
230
- extattr_list_name(ptr,
231
- (void *(*)(void *, VALUE))rb_yield_values,
232
- (void *)1);
233
- return Qnil;
234
- } else {
235
- VALUE list = rb_ary_new();
236
- extattr_list_name(ptr,
237
- (void *(*)(void *, VALUE))rb_ary_push,
238
- (void *)list);
239
- return list;
240
- }
241
- }
242
-
243
- static VALUE
244
- extattr_list0(VALUE path, DWORD flags, int namespace)
245
- {
246
- check_namespace(namespace, path);
247
- VALUE path1 = path;
248
- HANDLE file = CreateFileW(STR2WPATH(path1), 0,
249
- FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
250
- NULL, 3,
251
- FILE_FLAG_BACKUP_SEMANTICS | flags,
252
- 0);
253
- if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError(), path); }
254
- return rb_ensure(extattr_list0_try, (VALUE)file, file_close, (VALUE)file);
255
- }
256
-
257
- static VALUE
258
- file_extattr_list0(VALUE file, int fd, int namespace)
259
- {
260
- check_namespace(namespace, Qnil);
261
- HANDLE file1 = (HANDLE)_get_osfhandle(fd);
262
- return extattr_list0_try(file1);
263
- }
264
-
265
- static VALUE
266
- file_s_extattr_list0(VALUE path, int namespace)
267
- {
268
- return extattr_list0(path, 0, namespace);
269
- }
270
-
271
- static VALUE
272
- file_s_extattr_list_link0(VALUE path, int namespace)
273
- {
274
- return extattr_list0(path, FILE_FLAG_OPEN_REPARSE_POINT, namespace);
275
- }
276
-
277
-
278
- static VALUE
279
- extattr_size0_try(HANDLE file)
280
- {
281
- return ULL2NUM(get_filesize(file));
282
- }
283
-
284
- static VALUE
285
- extattr_size0(VALUE path, DWORD flags, int namespace, VALUE name)
286
- {
287
- check_namespace(namespace, path);
288
- VALUE path1 = rb_str_plus(path, rb_str_new(":", 1));
289
- rb_str_append(path1, name);
290
- HANDLE file = CreateFileW(STR2WPATH(path1), 0,
291
- FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
292
- NULL, 3,
293
- FILE_FLAG_BACKUP_SEMANTICS | flags,
294
- 0);
295
- if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError(), path); }
296
- return rb_ensure(extattr_size0_try, (VALUE)file, file_close, (VALUE)file);
297
- }
298
-
299
- static VALUE
300
- file_extattr_size0(VALUE file, int fd, int namespace, VALUE name)
301
- {
302
- return file_s_extattr_size0(get_filepath((HANDLE)_get_osfhandle(fd)),
303
- namespace, name);
304
- }
305
-
306
- static VALUE
307
- file_s_extattr_size0(VALUE path, int namespace, VALUE name)
308
- {
309
- return extattr_size0(path, 0, namespace, name);
310
- }
311
-
312
- static VALUE
313
- file_s_extattr_size_link0(VALUE path, int namespace, VALUE name)
314
- {
315
- return extattr_size0(path, FILE_FLAG_OPEN_REPARSE_POINT, namespace, name);
316
- }
317
-
318
-
319
- static VALUE
320
- extattr_get_try(VALUE args[3])
321
- {
322
- HANDLE file = (HANDLE)args[0];
323
- int namespace = (int)args[1];
324
- VALUE name = args[2];
325
- uint64_t size = get_filesize(file);
326
- if (size > EXTATTR_MAX) { rb_raise(rb_eSystemCallError, "extattr too huge"); }
327
- VALUE buf = rb_str_buf_new(size);
328
- DWORD readsize = 0;
329
- if (!ReadFile(file, RSTRING_PTR(buf), size, &readsize, NULL)) {
330
- raise_win32_error(GetLastError(), Qnil);
331
- }
332
- rb_str_set_len(buf, readsize);
333
- return buf;
334
- }
335
-
336
- static VALUE
337
- extattr_get0(VALUE path, int flags, int namespace, VALUE name)
338
- {
339
- check_namespace(namespace, path);
340
- VALUE path1 = rb_str_plus(path, rb_str_new(":", 1));
341
- rb_str_append(path1, name);
342
- HANDLE file = CreateFileW(STR2WPATH(path1), GENERIC_READ,
343
- FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
344
- NULL, 3,
345
- FILE_FLAG_BACKUP_SEMANTICS | flags,
346
- 0);
347
- if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError(), path); }
348
- VALUE args[] = { (VALUE)file, (VALUE)namespace, name, };
349
- return rb_ensure(extattr_get_try, (VALUE)args, file_close, (VALUE)file);
350
- }
351
-
352
- static VALUE
353
- file_extattr_get0(VALUE file, int fd, int namespace, VALUE name)
354
- {
355
- return file_s_extattr_get0(get_filepath((HANDLE)_get_osfhandle(fd)),
356
- namespace, name);
357
- }
358
-
359
- static VALUE
360
- file_s_extattr_get0(VALUE path, int namespace, VALUE name)
361
- {
362
- return extattr_get0(path, 0, namespace, name);
363
- }
364
-
365
- static VALUE
366
- file_s_extattr_get_link0(VALUE path, int namespace, VALUE name)
367
- {
368
- return extattr_get0(path, FILE_FLAG_OPEN_REPARSE_POINT, namespace, name);
369
- }
370
-
371
-
372
- static VALUE
373
- extattr_set0_try(VALUE args[])
374
- {
375
- HANDLE file = (HANDLE)args[0];
376
- int namespace = (int)args[1];
377
- VALUE name = (VALUE)args[2];
378
- VALUE data = (VALUE)args[3];
379
- uint64_t size = RSTRING_LEN(data);
380
- if (size > EXTATTR_MAX) { rb_raise(rb_eSystemCallError, "extattr too huge"); }
381
- DWORD wrotesize = size;
382
- if (!WriteFile(file, RSTRING_PTR(data), size, &wrotesize, NULL)) {
383
- raise_win32_error(GetLastError(), Qnil);
384
- }
385
- return Qnil;
386
- }
387
-
388
- static VALUE
389
- extattr_set0(VALUE path, DWORD flags, int namespace, VALUE name, VALUE data)
390
- {
391
- check_namespace(namespace, path);
392
- VALUE path1 = rb_str_plus(path, rb_str_new(":", 1));
393
- rb_str_append(path1, name);
394
- HANDLE file = CreateFileW(STR2WPATH(path1), GENERIC_WRITE,
395
- FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
396
- NULL, CREATE_ALWAYS,
397
- FILE_FLAG_BACKUP_SEMANTICS | flags,
398
- 0);
399
- if (file == INVALID_HANDLE_VALUE) { raise_win32_error(GetLastError(), path); }
400
- VALUE args[] = { (VALUE)file, (VALUE)namespace, name, data };
401
- return rb_ensure(extattr_set0_try, (VALUE)args, file_close, (VALUE)file);
402
- }
403
-
404
- static VALUE
405
- file_extattr_set0(VALUE file, int fd, int namespace, VALUE name, VALUE data)
406
- {
407
- return file_s_extattr_set0(get_filepath((HANDLE)_get_osfhandle(fd)),
408
- namespace, name, data);
409
- }
410
-
411
- static VALUE
412
- file_s_extattr_set0(VALUE path, int namespace, VALUE name, VALUE data)
413
- {
414
- return extattr_set0(path, 0, namespace, name, data);
415
- }
416
-
417
- static VALUE
418
- file_s_extattr_set_link0(VALUE path, int namespace, VALUE name, VALUE data)
419
- {
420
- return extattr_set0(path, FILE_FLAG_OPEN_REPARSE_POINT, namespace, name, data);
421
- }
422
-
423
-
424
- static VALUE
425
- file_extattr_delete0(VALUE file, int fd, int namespace, VALUE name)
426
- {
427
- return file_s_extattr_delete0(get_filepath((HANDLE)_get_osfhandle(fd)),
428
- namespace, name);
429
- }
430
-
431
- static VALUE
432
- file_s_extattr_delete0(VALUE path, int namespace, VALUE name)
433
- {
434
- check_namespace(namespace, path);
435
- VALUE path1 = rb_str_plus(path, rb_str_new(":", 1));
436
- rb_str_append(path1, name);
437
- if (!DeleteFileW(STR2WPATH(path1))) {
438
- raise_win32_error(GetLastError(), path);
439
- }
440
- return Qnil;
441
- }
442
-
443
- static VALUE
444
- file_s_extattr_delete_link0(VALUE path, int namespace, VALUE name)
445
- {
446
- return file_s_extattr_delete0(path, namespace, name);
447
- }
448
-
449
-
450
- static void
451
- setup(void)
452
- {
453
- ENCutf8p = rb_enc_find("UTF-8");
454
- ENCutf8 = rb_enc_from_encoding(ENCutf8p);
455
- rb_gc_register_address(&ENCutf8);
456
-
457
- ENCutf16lep = rb_enc_find("UTF-16LE");
458
- ENCutf16le = rb_enc_from_encoding(ENCutf16lep);
459
- rb_gc_register_address(&ENCutf16le);
460
- }