libarchive 0.1.0

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