libarchive-ruby-fs 0.2.0

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.
@@ -0,0 +1,134 @@
1
+ #ifndef _LIBARCHIVE_INTERNAL_H_
2
+ #define _LIBARCHIVE_INTERNAL_H_
3
+
4
+ #include <fcntl.h>
5
+ #include <stdio.h>
6
+ #include <stdlib.h>
7
+ #include <string.h>
8
+ #include <sys/types.h>
9
+ #include <sys/stat.h>
10
+ #include <errno.h>
11
+
12
+ #include <archive.h>
13
+ #include <archive_entry.h>
14
+
15
+ #include <ruby.h>
16
+
17
+ #include "archive_write_open_rb_str.h"
18
+ #include "archive_read_support_compression.h"
19
+ #include "archive_read_support_format.h"
20
+ #include "archive_write_set_compression.h"
21
+
22
+ #ifdef LIBARCHIVE_EXPORTS
23
+ #define DLLEXPORT __declspec(dllexport)
24
+ #else
25
+ #define DLLEXPORT
26
+ #endif
27
+
28
+ #define BLOCK_SIZE 10240
29
+ #define DATA_BUFFER_SIZE 65536
30
+
31
+ #ifndef RSTRING_PTR
32
+ #define RSTRING_PTR(s) (RSTRING(s)->ptr)
33
+ #endif
34
+ #ifndef RSTRING_LEN
35
+ #define RSTRING_LEN(s) (RSTRING(s)->len)
36
+ #endif
37
+
38
+ #ifdef O_NONBLOCK
39
+ #define LIBARCHIVE_O_NONBLOCK O_NONBLOCK
40
+ #elif O_NDELAY
41
+ #define LIBARCHIVE_O_NONBLOCK O_NDELAY
42
+ #else
43
+ #define LIBARCHIVE_O_NONBLOCK 0
44
+ #endif
45
+
46
+ #ifdef O_NOCTTY
47
+ #define LIBARCHIVE_O_NOCTTY O_NOCTTY
48
+ #else
49
+ #define LIBARCHIVE_O_NOCTTY 0
50
+ #endif
51
+
52
+ #ifdef O_BINARY
53
+ #define LIBARCHIVE_O_BINARY O_BINARY
54
+ #else
55
+ #define LIBARCHIVE_O_BINARY 0
56
+ #endif
57
+
58
+ #ifdef O_SYNC
59
+ #define LIBARCHIVE_O_SYNC O_SYNC
60
+ #else
61
+ #define LIBARCHIVE_O_SYNC 0
62
+ #endif
63
+
64
+ #define O_FLAGS (O_RDONLY | O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_EXCL | O_TRUNC | \
65
+ LIBARCHIVE_O_NONBLOCK | LIBARCHIVE_O_NOCTTY | LIBARCHIVE_O_BINARY | LIBARCHIVE_O_SYNC)
66
+
67
+ #define EXTRACT_FLAGS_WITHOUT_ARCHIVE_EXTRACT_SPARSE \
68
+ (ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_TIME | \
69
+ ARCHIVE_EXTRACT_NO_OVERWRITE | ARCHIVE_EXTRACT_UNLINK | ARCHIVE_EXTRACT_ACL | \
70
+ ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR | ARCHIVE_EXTRACT_SECURE_SYMLINKS | \
71
+ ARCHIVE_EXTRACT_SECURE_NODOTDOT | ARCHIVE_EXTRACT_NO_AUTODIR | \
72
+ ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER)
73
+
74
+ #ifdef ARCHIVE_EXTRACT_SPARSE
75
+ #define EXTRACT_FLAGS (EXTRACT_FLAGS_WITHOUT_ARCHIVE_EXTRACT_SPARSE | ARCHIVE_EXTRACT_SPARSE)
76
+ #else
77
+ #define EXTRACT_FLAGS EXTRACT_FLAGS_WITHOUT_ARCHIVE_EXTRACT_SPARSE
78
+ #endif
79
+
80
+ struct rb_libarchive_archive_container {
81
+ struct archive *ar;
82
+ int eof;
83
+ VALUE memory;
84
+ };
85
+
86
+ struct rb_libarchive_entry_container {
87
+ struct archive_entry *ae;
88
+ int must_close;
89
+ };
90
+
91
+ #define Check_Archive(p) do { \
92
+ if ((p)->ar == NULL) { \
93
+ rb_raise(rb_eArchiveError, "Invalid archive"); \
94
+ } \
95
+ } while(0)
96
+
97
+ #define Check_Entry(p) do { \
98
+ if ((p)->ae == NULL) { \
99
+ rb_raise(rb_eArchiveError, "Invalid entry"); \
100
+ } \
101
+ } while(0)
102
+
103
+ #define Check_Class(v, c) do { \
104
+ if (!rb_obj_is_instance_of((v), (c))) { \
105
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)", \
106
+ rb_class2name(CLASS_OF(v)), rb_class2name(c)); \
107
+ } \
108
+ } while(0)
109
+
110
+ #define Check_Class(v, c) do { \
111
+ if (!rb_obj_is_instance_of((v), (c))) { \
112
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)", \
113
+ rb_class2name(CLASS_OF(v)), rb_class2name(c)); \
114
+ } \
115
+ } while(0)
116
+
117
+ #define LONG2TIME(i) rb_funcall(rb_cTime, rb_intern("at"), 1, LONG2NUM(i))
118
+ #define TIME2LONG(v) NUM2LONG(rb_funcall((v), rb_intern("tv_sec"), 0))
119
+
120
+ #define archive_copy_error_string(a, b, n) do { \
121
+ strncpy((b), archive_error_string(a), (n)); \
122
+ (b)[((n) - 1)] = '\0'; \
123
+ } while(0)
124
+
125
+ VALUE rb_libarchive_archive_alloc(VALUE klass);
126
+ VALUE rb_libarchive_entry_new(struct archive_entry *ae, int must_close);
127
+ VALUE rb_libarchive_entry_close(VALUE self);
128
+
129
+ void Init_libarchive_reader();
130
+ void Init_libarchive_writer();
131
+ void Init_libarchive_archive();
132
+ void Init_libarchive_entry();
133
+
134
+ #endif // _LIBARCHIVE_INTERNAL_H_
@@ -0,0 +1,328 @@
1
+ #include "libarchive_internal.h"
2
+
3
+ extern VALUE rb_mArchive;
4
+ VALUE rb_cArchiveReader;
5
+ extern VALUE rb_eArchiveError;
6
+ extern VALUE rb_cArchiveEntry;
7
+
8
+ static void rb_libarchive_reader_close0(struct rb_libarchive_archive_container *p) {
9
+ archive_read_close(p->ar);
10
+ archive_read_finish(p->ar);
11
+ p->ar = NULL;
12
+ }
13
+
14
+ /* */
15
+ static VALUE rb_libarchive_reader_close(VALUE self) {
16
+ struct rb_libarchive_archive_container *p;
17
+ Data_Get_Struct(self, struct rb_libarchive_archive_container, p);
18
+ Check_Archive(p);
19
+ rb_libarchive_reader_close0(p);
20
+ return Qnil;
21
+ }
22
+
23
+ static VALUE rb_libarchive_reader_s_open0(int (*archive_open)(struct rb_libarchive_archive_container *, void *), void *arg, int compression, int format, const char *cmd) {
24
+ VALUE reader;
25
+ struct rb_libarchive_archive_container *p;
26
+ int r;
27
+ reader = rb_funcall(rb_cArchiveReader, rb_intern("new"), 0);
28
+ Data_Get_Struct(reader, struct rb_libarchive_archive_container, p);
29
+
30
+ if ((p->ar = archive_read_new()) == NULL) {
31
+ rb_raise(rb_eArchiveError, "Open reader failed: %s", strerror(errno));
32
+ }
33
+
34
+ if (cmd != NULL) {
35
+ r = archive_read_support_compression_program(p->ar, cmd);
36
+ } else if (compression != -1) {
37
+ r = archive_read_support_compression(p->ar, compression);
38
+ } else {
39
+ r = archive_read_support_compression_all(p->ar);
40
+ }
41
+
42
+ if (r != ARCHIVE_OK) {
43
+ char error_string[BUFSIZ];
44
+ archive_copy_error_string(p->ar, error_string, BUFSIZ);
45
+ rb_libarchive_reader_close0(p);
46
+ rb_raise(rb_eArchiveError, "Support compression failed: %s", error_string);
47
+ }
48
+
49
+ if (format != -1) {
50
+ r = archive_read_support_format(p->ar, format);
51
+ } else {
52
+ r = archive_read_support_format_all(p->ar);
53
+ }
54
+
55
+ if (r != ARCHIVE_OK) {
56
+ char error_string[BUFSIZ];
57
+ archive_copy_error_string(p->ar, error_string, BUFSIZ);
58
+ rb_libarchive_reader_close0(p);
59
+ rb_raise(rb_eArchiveError, "Support format failed: %s", error_string);
60
+ }
61
+
62
+ if (archive_open(p, arg) != ARCHIVE_OK) {
63
+ char error_string[BUFSIZ];
64
+ archive_copy_error_string(p->ar, error_string, BUFSIZ);
65
+ rb_libarchive_reader_close0(p);
66
+ rb_raise(rb_eArchiveError, "Open reader failed: %s", error_string);
67
+ }
68
+
69
+ if (rb_block_given_p()) {
70
+ VALUE retval;
71
+ int status;
72
+ retval = rb_protect(rb_yield, reader, &status);
73
+ rb_libarchive_reader_close0(p);
74
+
75
+ if (status != 0) {
76
+ rb_jump_tag(status);
77
+ }
78
+
79
+ return retval;
80
+ } else {
81
+ return reader;
82
+ }
83
+ }
84
+
85
+ static int rb_libarchive_reader_s_open_filename0(struct rb_libarchive_archive_container *p, void *arg) {
86
+ const char *filename = (const char *) arg;
87
+
88
+ if (filename != NULL) {
89
+ struct stat s;
90
+
91
+ if (stat(filename, &s) != 0) {
92
+ archive_set_error(p->ar, -1, strerror(errno));
93
+ return (ARCHIVE_FATAL);
94
+ }
95
+ }
96
+
97
+ return archive_read_open_filename(p->ar, filename, BLOCK_SIZE);
98
+ }
99
+
100
+ /* */
101
+ static VALUE rb_libarchive_reader_s_open_filename(int argc, VALUE *argv, VALUE self) {
102
+ VALUE v_filename, v_compression, v_format;
103
+ const char *filename = NULL;
104
+ int compression = -1, format = -1;
105
+ const char *cmd = NULL;
106
+ rb_scan_args(argc, argv, "12", &v_filename, &v_compression, &v_format);
107
+ Check_Type(v_filename, T_STRING);
108
+ filename = RSTRING_PTR(v_filename);
109
+
110
+ if (T_STRING == TYPE(v_compression)) {
111
+ compression = -1;
112
+ cmd = RSTRING_PTR(v_compression);
113
+ } else if (!NIL_P(v_compression)) {
114
+ compression = NUM2INT(v_compression);
115
+ }
116
+
117
+ if (!NIL_P(v_format)) {
118
+ format = NUM2INT(v_format);
119
+ }
120
+
121
+ return rb_libarchive_reader_s_open0(rb_libarchive_reader_s_open_filename0, (void *) filename, compression, format, cmd);
122
+ }
123
+
124
+ static int rb_libarchive_reader_s_open_memory0(struct rb_libarchive_archive_container *p, void *arg) {
125
+ VALUE v_buff = (VALUE) arg;
126
+ return archive_read_open_memory(p->ar, RSTRING_PTR(v_buff), RSTRING_LEN(v_buff));
127
+ }
128
+
129
+ /* */
130
+ static VALUE rb_libarchive_reader_s_open_memory(int argc, VALUE *argv, VALUE self) {
131
+ VALUE v_memory, v_compression, v_format;
132
+ int compression = -1, format = -1;
133
+ const char *cmd = NULL;
134
+ rb_scan_args(argc, argv, "12", &v_memory, &v_compression, &v_format);
135
+ Check_Type(v_memory, T_STRING);
136
+
137
+ if (T_STRING == TYPE(v_compression)) {
138
+ compression = -1;
139
+ cmd = RSTRING_PTR(v_compression);
140
+ } else if (!NIL_P(v_compression)) {
141
+ compression = NUM2INT(v_compression);
142
+ }
143
+
144
+ if (!NIL_P(v_format)) {
145
+ format = NUM2INT(v_format);
146
+ }
147
+
148
+ return rb_libarchive_reader_s_open0(rb_libarchive_reader_s_open_memory0, (void *) v_memory, compression, format, cmd);
149
+ }
150
+
151
+ /* */
152
+ static VALUE rb_libarchive_reader_next_header(VALUE self) {
153
+ struct rb_libarchive_archive_container *p;
154
+ struct archive_entry *ae;
155
+ int r;
156
+ Data_Get_Struct(self, struct rb_libarchive_archive_container, p);
157
+ Check_Archive(p);
158
+
159
+ if (p->eof) {
160
+ return Qnil;
161
+ }
162
+
163
+ r = archive_read_next_header(p->ar, &ae);
164
+
165
+ if (r == ARCHIVE_EOF) {
166
+ p->eof = 1;
167
+ return Qnil;
168
+ } else if (r != ARCHIVE_OK) {
169
+ rb_raise(rb_eArchiveError, "Fetch entry failed: %s", archive_error_string(p->ar));
170
+ }
171
+
172
+ return rb_libarchive_entry_new(ae, 0);
173
+ }
174
+
175
+ /* */
176
+ static VALUE rb_libarchive_reader_header_position(VALUE self) {
177
+ struct rb_libarchive_archive_container *p;
178
+ Data_Get_Struct(self, struct rb_libarchive_archive_container, p);
179
+ Check_Archive(p);
180
+ return LONG2NUM((long) archive_read_header_position(p->ar));
181
+ }
182
+
183
+ /* */
184
+ static VALUE rb_libarchive_reader_read_data(int argc, VALUE *argv, VALUE self) {
185
+ VALUE v_size;
186
+ struct rb_libarchive_archive_container *p;
187
+ char *buff;
188
+ size_t size = DATA_BUFFER_SIZE;
189
+ ssize_t n;
190
+ rb_scan_args(argc, argv, "01", &v_size);
191
+
192
+ if (!NIL_P(v_size)) {
193
+ size = NUM2INT(v_size);
194
+ }
195
+
196
+ Data_Get_Struct(self, struct rb_libarchive_archive_container, p);
197
+ Check_Archive(p);
198
+
199
+ if (p->eof) {
200
+ return Qnil;
201
+ }
202
+
203
+ if (rb_block_given_p()) {
204
+ ssize_t len = 0;
205
+ int status = 0;
206
+ buff = xmalloc(size);
207
+
208
+ while ((n = archive_read_data(p->ar, buff, size)) > 0) {
209
+ rb_protect(rb_yield, rb_str_new(buff, n), &status);
210
+
211
+ if (status != 0) {
212
+ break;
213
+ }
214
+
215
+ len += n;
216
+ }
217
+
218
+ xfree(buff);
219
+
220
+ if (status != 0) {
221
+ rb_jump_tag(status);
222
+ }
223
+
224
+ if (n < 0) {
225
+ rb_raise(rb_eArchiveError, "Read data failed: %s", archive_error_string(p->ar));
226
+ }
227
+
228
+ return LONG2NUM(len);
229
+ } else {
230
+ VALUE retval = rb_str_new("", 0);
231
+ buff = xmalloc(size);
232
+
233
+ while ((n = archive_read_data(p->ar, buff, size)) > 0) {
234
+ rb_str_cat(retval, buff, n);
235
+ }
236
+
237
+ xfree(buff);
238
+
239
+ if (n < 0) {
240
+ rb_raise(rb_eArchiveError, "Read data failed: %s", archive_error_string(p->ar));
241
+ }
242
+
243
+ return retval;
244
+ }
245
+ }
246
+
247
+ /* */
248
+ static VALUE rb_libarchive_reader_save_data(int argc, VALUE *argv, VALUE self) {
249
+ VALUE v_filename, v_flags;
250
+ struct rb_libarchive_archive_container *p;
251
+ const char *filename;
252
+ int flags, fd, r;
253
+ rb_scan_args(argc, argv, "11", &v_filename, &v_flags);
254
+ Check_Type(v_filename, T_STRING);
255
+ filename = RSTRING_PTR(v_filename);
256
+
257
+ if (!NIL_P(v_flags)) {
258
+ flags = ((O_WRONLY | NUM2INT(v_flags)) & O_FLAGS);
259
+ } else {
260
+ flags = (O_WRONLY | O_CREAT | O_EXCL
261
+ #ifdef O_BINARY
262
+ | O_BINARY
263
+ #endif
264
+ );
265
+ }
266
+
267
+ Data_Get_Struct(self, struct rb_libarchive_archive_container, p);
268
+ Check_Archive(p);
269
+
270
+ if ((fd = open(filename, flags)) == -1) {
271
+ rb_raise(rb_eArchiveError, "Save data failed: %s", strerror(errno));
272
+ }
273
+
274
+ r = archive_read_data_into_fd(p->ar, fd);
275
+ close(fd);
276
+
277
+ if (r != ARCHIVE_OK) {
278
+ rb_raise(rb_eArchiveError, "Save data failed: %s", archive_error_string(p->ar));
279
+ }
280
+
281
+ return Qnil;
282
+ }
283
+
284
+ /* */
285
+ static VALUE rb_libarchive_reader_extract(int argc, VALUE *argv, VALUE self) {
286
+ VALUE v_entry, v_flags;
287
+ struct rb_libarchive_archive_container *pa;
288
+ struct rb_libarchive_entry_container *pae;
289
+ int flags = 0;
290
+ rb_scan_args(argc, argv, "11", &v_entry, &v_flags);
291
+ Check_Class(v_entry, rb_cArchiveEntry);
292
+
293
+ if (!NIL_P(v_flags)) {
294
+ flags = (NUM2INT(v_flags) & EXTRACT_FLAGS);
295
+ }
296
+
297
+ Data_Get_Struct(self, struct rb_libarchive_archive_container, pa);
298
+ Check_Archive(pa);
299
+
300
+ if (pa->eof) {
301
+ rb_raise(rb_eArchiveError, "Extract archive failed: It has already reached EOF");
302
+ }
303
+
304
+ Data_Get_Struct(v_entry, struct rb_libarchive_entry_container, pae);
305
+ Check_Entry(pae);
306
+
307
+ if (archive_read_extract(pa->ar, pae->ae, flags) != ARCHIVE_OK) {
308
+ rb_raise(rb_eArchiveError, "Extract archive failed: %s", archive_error_string(pa->ar));
309
+ }
310
+
311
+ return Qnil;
312
+ }
313
+
314
+ void Init_libarchive_reader() {
315
+ rb_cArchiveReader = rb_define_class_under(rb_mArchive, "Reader", rb_cObject);
316
+ rb_define_alloc_func(rb_cArchiveReader, rb_libarchive_archive_alloc);
317
+ rb_funcall(rb_cArchiveReader, rb_intern("private_class_method"), 1, ID2SYM(rb_intern("new")));
318
+ rb_define_singleton_method(rb_cArchiveReader, "open_filename", rb_libarchive_reader_s_open_filename, -1);
319
+ rb_define_module_function(rb_mArchive, "read_open_filename", rb_libarchive_reader_s_open_filename, -1);
320
+ rb_define_singleton_method(rb_cArchiveReader, "open_memory", rb_libarchive_reader_s_open_memory, -1);
321
+ rb_define_module_function(rb_mArchive, "read_open_memory", rb_libarchive_reader_s_open_memory, -1);
322
+ rb_define_method(rb_cArchiveReader, "close", rb_libarchive_reader_close, 0);
323
+ rb_define_method(rb_cArchiveReader, "next_header", rb_libarchive_reader_next_header, 0);
324
+ rb_define_method(rb_cArchiveReader, "header_position", rb_libarchive_reader_header_position, 0);
325
+ rb_define_method(rb_cArchiveReader, "read_data", rb_libarchive_reader_read_data, -1);
326
+ rb_define_method(rb_cArchiveReader, "save_data", rb_libarchive_reader_save_data, -1);
327
+ rb_define_method(rb_cArchiveReader, "extract", rb_libarchive_reader_extract, -1);
328
+ }
@@ -0,0 +1,246 @@
1
+ #include "libarchive_internal.h"
2
+
3
+ extern VALUE rb_mArchive;
4
+ VALUE rb_cArchiveWriter;
5
+ extern VALUE rb_eArchiveError;
6
+ extern VALUE rb_cArchiveEntry;
7
+
8
+ static void rb_libarchive_writer_close0(struct rb_libarchive_archive_container *p) {
9
+ archive_write_close(p->ar);
10
+ archive_write_finish(p->ar);
11
+ p->ar = NULL;
12
+ }
13
+
14
+ /* */
15
+ static VALUE rb_libarchive_writer_close(VALUE self) {
16
+ struct rb_libarchive_archive_container *p;
17
+ Data_Get_Struct(self, struct rb_libarchive_archive_container, p);
18
+ Check_Archive(p);
19
+ rb_libarchive_writer_close0(p);
20
+ return Qnil;
21
+ }
22
+
23
+ static VALUE rb_libarchive_writer_s_open0(int (*archive_open)(struct rb_libarchive_archive_container *, void *), void *arg, int compression, int format, const char *cmd) {
24
+ VALUE writer;
25
+ struct rb_libarchive_archive_container *p;
26
+ int r;
27
+ writer = rb_funcall(rb_cArchiveWriter, rb_intern("new"), 0);
28
+ Data_Get_Struct(writer, struct rb_libarchive_archive_container, p);
29
+
30
+ if ((p->ar = archive_write_new()) == NULL) {
31
+ rb_raise(rb_eArchiveError, "Open writer failed: %s", strerror(errno));
32
+ }
33
+
34
+ if (cmd != NULL) {
35
+ r = archive_write_set_compression_program(p->ar, cmd);
36
+ } else {
37
+ r = archive_write_set_compression(p->ar, compression);
38
+ }
39
+
40
+ if (r != ARCHIVE_OK) {
41
+ char error_string[BUFSIZ];
42
+ archive_copy_error_string(p->ar, error_string, BUFSIZ);
43
+ rb_libarchive_writer_close0(p);
44
+ rb_raise(rb_eArchiveError, "Set compression failed: %s", error_string);
45
+ }
46
+
47
+ if (archive_write_set_format(p->ar, format) != ARCHIVE_OK) {
48
+ char error_string[BUFSIZ];
49
+ archive_copy_error_string(p->ar, error_string, BUFSIZ);
50
+ rb_libarchive_writer_close0(p);
51
+ rb_raise(rb_eArchiveError, "Set format failed: %s", error_string);
52
+ }
53
+
54
+ if (archive_open(p, arg) != ARCHIVE_OK) {
55
+ char error_string[BUFSIZ];
56
+ archive_copy_error_string(p->ar, error_string, BUFSIZ);
57
+ rb_libarchive_writer_close0(p);
58
+ rb_raise(rb_eArchiveError, "Open writer failed: %s", error_string);
59
+ }
60
+
61
+ if (rb_block_given_p()) {
62
+ VALUE retval;
63
+ int status;
64
+ retval = rb_protect(rb_yield, writer, &status);
65
+ rb_libarchive_writer_close0(p);
66
+
67
+ if (status != 0) {
68
+ rb_jump_tag(status);
69
+ }
70
+
71
+ return retval;
72
+ } else {
73
+ return writer;
74
+ }
75
+ }
76
+
77
+ static int rb_libarchive_writer_s_open_filename0(struct rb_libarchive_archive_container *p, void *arg) {
78
+ const char *filename = (const char *) arg;
79
+ return archive_write_open_filename(p->ar, filename);
80
+ }
81
+
82
+ /* */
83
+ static VALUE rb_libarchive_writer_s_open_filename(VALUE self, VALUE v_filename, VALUE v_compression, VALUE v_format) {
84
+ const char *filename = NULL;
85
+ int compression, format;
86
+ const char *cmd = NULL;
87
+ Check_Type(v_filename, T_STRING);
88
+
89
+ if (RSTRING_LEN(v_filename) < 1) {
90
+ rb_raise(rb_eArchiveError, "Open writer failed: No such file or directory");
91
+ }
92
+
93
+ filename = RSTRING_PTR(v_filename);
94
+
95
+ if (T_STRING == TYPE(v_compression)) {
96
+ compression = -1;
97
+ cmd = RSTRING_PTR(v_compression);
98
+ } else {
99
+ compression = NUM2INT(v_compression);
100
+ }
101
+
102
+
103
+ format = NUM2INT(v_format);
104
+ return rb_libarchive_writer_s_open0(rb_libarchive_writer_s_open_filename0, (void *) filename, compression, format, cmd);
105
+ }
106
+
107
+ static int rb_libarchive_writer_s_open_memory0(struct rb_libarchive_archive_container *p, void *arg) {
108
+ VALUE str = (VALUE) arg;
109
+ p->memory = str;
110
+ return archive_write_open_rb_str(p->ar, str);
111
+ }
112
+
113
+ /* */
114
+ static VALUE rb_libarchive_writer_s_open_memory(VALUE self, VALUE v_memory, VALUE v_compression, VALUE v_format) {
115
+ int compression, format;
116
+ const char *cmd = NULL;
117
+ Check_Type(v_memory, T_STRING);
118
+
119
+ if (T_STRING == TYPE(v_compression)) {
120
+ compression = -1;
121
+ cmd = RSTRING_PTR(v_compression);
122
+ } else {
123
+ compression = NUM2INT(v_compression);
124
+ }
125
+
126
+ format = NUM2INT(v_format);
127
+ return rb_libarchive_writer_s_open0(rb_libarchive_writer_s_open_memory0, (void *) v_memory, compression, format, cmd);
128
+ }
129
+
130
+ /* */
131
+ static VALUE rb_libarchive_writer_new_entry(VALUE self) {
132
+ VALUE entry;
133
+ struct rb_libarchive_archive_container *p;
134
+ struct archive_entry *ae;
135
+ Data_Get_Struct(self, struct rb_libarchive_archive_container, p);
136
+ Check_Archive(p);
137
+
138
+ if ((ae = archive_entry_new()) == NULL) {
139
+ rb_raise(rb_eArchiveError, "New entry failed: %s", strerror(errno));
140
+ }
141
+
142
+ entry = rb_libarchive_entry_new(ae, 1);
143
+
144
+ if (rb_block_given_p()) {
145
+ VALUE retval;
146
+ int status;
147
+ retval = rb_protect(rb_yield, entry, &status);
148
+ rb_libarchive_entry_close(entry);
149
+
150
+ if (status != 0) {
151
+ rb_jump_tag(status);
152
+ }
153
+
154
+ return retval;
155
+ } else {
156
+ return entry;
157
+ }
158
+ }
159
+
160
+ /* */
161
+ static VALUE rb_libarchive_writer_write_header(VALUE self, VALUE v_entry) {
162
+ struct rb_libarchive_archive_container *pa;
163
+ struct rb_libarchive_entry_container *pae;
164
+ Check_Class(v_entry, rb_cArchiveEntry);
165
+ Data_Get_Struct(self, struct rb_libarchive_archive_container, pa);
166
+ Check_Archive(pa);
167
+ Data_Get_Struct(v_entry, struct rb_libarchive_entry_container, pae);
168
+ Check_Entry(pae);
169
+
170
+ if (archive_write_header(pa->ar, pae->ae) != ARCHIVE_OK) {
171
+ rb_raise(rb_eArchiveError, "Write header failed: %s", archive_error_string(pa->ar));
172
+ }
173
+
174
+ return Qnil;
175
+ }
176
+
177
+ static ssize_t rb_libarchive_writer_write_data0(struct archive *ar, VALUE v_buff) {
178
+ const char *buff;
179
+ size_t size;
180
+ ssize_t n;
181
+
182
+ if (NIL_P(v_buff)) {
183
+ return 0;
184
+ }
185
+
186
+ Check_Type(v_buff, T_STRING);
187
+ buff = RSTRING_PTR(v_buff);
188
+ size = RSTRING_LEN(v_buff);
189
+
190
+ if (size < 1) {
191
+ return 0;
192
+ }
193
+
194
+ if ((n = archive_write_data(ar, buff, size)) < 0) {
195
+ rb_raise(rb_eArchiveError, "Write data failed: %s", archive_error_string(ar));
196
+ }
197
+
198
+ return n;
199
+ }
200
+
201
+ /* */
202
+ static VALUE rb_libarchive_writer_write_data(int argc, VALUE *argv, VALUE self) {
203
+ struct rb_libarchive_archive_container *p;
204
+ Data_Get_Struct(self, struct rb_libarchive_archive_container, p);
205
+ Check_Archive(p);
206
+
207
+ if (rb_block_given_p()) {
208
+ ssize_t len = 0;
209
+
210
+ if (argc > 0) {
211
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
212
+ }
213
+
214
+ while(1) {
215
+ VALUE retval;
216
+ ssize_t n;
217
+ retval = rb_yield(Qnil);
218
+
219
+ if ((n = rb_libarchive_writer_write_data0(p->ar, retval)) < 1) {
220
+ return LONG2NUM(len);
221
+ }
222
+
223
+ len += n;
224
+ }
225
+ } else {
226
+ VALUE v_buff;
227
+ ssize_t n;
228
+ rb_scan_args(argc, argv, "10", &v_buff);
229
+ n = rb_libarchive_writer_write_data0(p->ar, v_buff);
230
+ return LONG2NUM(n);
231
+ }
232
+ }
233
+
234
+ void Init_libarchive_writer() {
235
+ rb_cArchiveWriter = rb_define_class_under(rb_mArchive, "Writer", rb_cObject);
236
+ rb_define_alloc_func(rb_cArchiveWriter, rb_libarchive_archive_alloc);
237
+ rb_funcall(rb_cArchiveWriter, rb_intern("private_class_method"), 1, ID2SYM(rb_intern("new")));
238
+ rb_define_singleton_method(rb_cArchiveWriter, "open_filename", rb_libarchive_writer_s_open_filename, 3);
239
+ rb_define_singleton_method(rb_mArchive, "write_open_filename", rb_libarchive_writer_s_open_filename, 3);
240
+ rb_define_singleton_method(rb_cArchiveWriter, "open_memory", rb_libarchive_writer_s_open_memory, 3);
241
+ rb_define_singleton_method(rb_mArchive, "write_open_memory", rb_libarchive_writer_s_open_memory, 3);
242
+ rb_define_method(rb_cArchiveWriter, "close", rb_libarchive_writer_close, 0);
243
+ rb_define_method(rb_cArchiveWriter, "new_entry", rb_libarchive_writer_new_entry, 0);
244
+ rb_define_method(rb_cArchiveWriter, "write_header", rb_libarchive_writer_write_header, 1);
245
+ rb_define_method(rb_cArchiveWriter, "write_data", rb_libarchive_writer_write_data, -1);
246
+ }
@@ -0,0 +1,3 @@
1
+ module LibArchiveRubyFs
2
+ VERSION = '0.2.0'
3
+ end