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.
- 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
|
+
}
|