libarchive-ruby-fs 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ext/rblibarchive/archive_read_support_compression.c +31 -0
- data/ext/rblibarchive/archive_read_support_compression.h +6 -0
- data/ext/rblibarchive/archive_read_support_format.c +32 -0
- data/ext/rblibarchive/archive_read_support_format.h +6 -0
- data/ext/rblibarchive/archive_write_open_rb_str.c +25 -0
- data/ext/rblibarchive/archive_write_open_rb_str.h +6 -0
- data/ext/rblibarchive/archive_write_set_compression.c +32 -0
- data/ext/rblibarchive/archive_write_set_compression.h +6 -0
- data/ext/rblibarchive/extconf.rb +20 -0
- data/ext/rblibarchive/libarchive.c +92 -0
- data/ext/rblibarchive/libarchive_archive.c +84 -0
- data/ext/rblibarchive/libarchive_entry.c +1015 -0
- data/ext/rblibarchive/libarchive_internal.h +134 -0
- data/ext/rblibarchive/libarchive_reader.c +328 -0
- data/ext/rblibarchive/libarchive_writer.c +246 -0
- data/lib/libarchive-ruby-fs/version.rb +3 -0
- data/lib/libarchive-ruby-fs.rb +5 -0
- metadata +77 -0
@@ -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
|
+
}
|