ffi-libarchive 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,482 @@
1
+ module Archive
2
+
3
+ class Entry
4
+
5
+ S_IFMT = 0170000
6
+ S_IFSOCK = 0140000 # socket
7
+ S_IFLNK = 0120000 # symbolic link
8
+ S_IFREG = 0100000 # regular file
9
+ S_IFBLK = 0060000 # block device
10
+ S_IFDIR = 0040000 # directory
11
+ S_IFCHR = 0020000 # character device
12
+ S_IFIFO = 0010000 # FIFO
13
+
14
+ SOCKET = 0140000 # socket
15
+ SYMBOLIC_LINK = 0120000 # symbolic link
16
+ FILE = 0100000 # regular file
17
+ BLOCK_SPECIAL = 0060000 # block device
18
+ DIRECTORY = 0040000 # directory
19
+ CHARACTER_SPECIAL = 0020000 # character device
20
+ FIFO = 0010000 # FIFO
21
+
22
+ def self.from_pointer entry
23
+ new entry
24
+ end
25
+
26
+ def initialize entry = nil
27
+ @entry_free = [true]
28
+ if entry
29
+ @entry = entry
30
+ yield self if block_given?
31
+ else
32
+ @entry = C::archive_entry_new
33
+ raise Error, @entry unless @entry
34
+
35
+ if block_given?
36
+ result = yield self
37
+ C::archive_entry_free(@entry)
38
+ @entry = nil
39
+ return result
40
+ else
41
+ @entry_free[0] = false
42
+ ObjectSpace.define_finalizer( self, Entry.finalizer(@entry, @entry_free) )
43
+ end
44
+ end
45
+ end
46
+
47
+ def self.finalizer entry, entry_free
48
+ Proc.new do |*args|
49
+ unless entry_free[0]
50
+ C::archive_entry_free(entry)
51
+ end
52
+ end
53
+ end
54
+
55
+ def close
56
+ # TODO: do we need synchronization here?
57
+ if @entry and !@entry_free[0]
58
+ @entry_free[0] = true
59
+ C::archive_entry_free(@entry)
60
+ end
61
+ ensure
62
+ @entry = nil
63
+ end
64
+
65
+ def entry
66
+ raise "No entry object" unless @entry
67
+ @entry
68
+ end
69
+
70
+ def atime
71
+ Time.at C::archive_entry_atime(entry)
72
+ end
73
+
74
+ def atime= time
75
+ set_atime time, 0
76
+ end
77
+
78
+ def set_atime time, nsec
79
+ C::archive_entry_set_atime(entry, time.to_i, nsec)
80
+ end
81
+
82
+ def atime_is_set?
83
+ C::archive_entry_atime_is_set(entry) != 0
84
+ end
85
+
86
+ def atime_nsec
87
+ C::archive_entry_atime_nsec(entry)
88
+ end
89
+
90
+ def birthtime
91
+ Time.at C::archive_entry_birthtime(entry)
92
+ end
93
+
94
+ def birthtime= time
95
+ set_birthtime time, 0
96
+ end
97
+
98
+ def set_birthtime time, nsec
99
+ C::archive_entry_set_birthtime(entry, time.to_i, nsec)
100
+ end
101
+
102
+ def birthtime_is_set?
103
+ C::archive_entry_birthtime_is_set(entry) != 0
104
+ end
105
+
106
+ def birthtime_nsec
107
+ C::archive_entry_birthtime_nsec(entry)
108
+ end
109
+
110
+ def ctime
111
+ Time.at C::archive_entry_ctime(entry)
112
+ end
113
+
114
+ def ctime= time
115
+ set_ctime time, 0
116
+ end
117
+
118
+ def set_ctime time, nsec
119
+ C::archive_entry_set_ctime(entry, time.to_i, nsec)
120
+ end
121
+
122
+ def ctime_is_set?
123
+ C::archive_entry_ctime_is_set(entry) != 0
124
+ end
125
+
126
+ def ctime_nsec
127
+ C::archive_entry_ctime_nsec(entry)
128
+ end
129
+
130
+ def block_special?
131
+ C::archive_entry_filetype(entry) & S_IFMT == S_IFBLK
132
+ end
133
+
134
+ def character_special?
135
+ C::archive_entry_filetype(entry) & S_IFMT == S_IFCHR
136
+ end
137
+
138
+ def directory?
139
+ C::archive_entry_filetype(entry) & S_IFMT == S_IFDIR
140
+ end
141
+
142
+ def fifo?
143
+ C::archive_entry_filetype(entry) & S_IFMT == S_IFIFO
144
+ end
145
+
146
+ def regular?
147
+ C::archive_entry_filetype(entry) & S_IFMT == S_IFREG
148
+ end
149
+ alias :file? :regular?
150
+
151
+ def socket?
152
+ C::archive_entry_filetype(entry) & S_IFMT == S_IFSOCK
153
+ end
154
+
155
+ def symbolic_link?
156
+ C::archive_entry_filetype(entry) & S_IFMT == S_IFLNK
157
+ end
158
+
159
+ def copy_fflags_text fflags_text
160
+ C::archive_entry_copy_fflags_text(entry, fflags_text)
161
+ nil
162
+ end
163
+
164
+ def copy_gname gname
165
+ C::archive_entry_copy_gname(entry, gname)
166
+ nil
167
+ end
168
+
169
+ def copy_hardlink lnk
170
+ C::archive_entry_copy_hardlink(entry, lnk)
171
+ nil
172
+ end
173
+
174
+ def copy_link lnk
175
+ C::archive_entry_copy_link(entry, lnk)
176
+ nil
177
+ end
178
+
179
+ def copy_lstat filename
180
+ # TODO get this work without ffi-inliner
181
+ begin
182
+ require File.join(File.dirname(__FILE__), 'stat.rb')
183
+ rescue => e
184
+ raise "ffi-inliner build for copy_stat failed:\n#{e}"
185
+ end
186
+
187
+ stat = Archive::Stat::ffi_libarchive_create_lstat(filename)
188
+ raise Error, "Copy stat failed: #{LibC::strerror(LibC::errno)}" if stat.null?
189
+ result = C::archive_entry_copy_stat(entry, stat)
190
+ ensure
191
+ Archive::Stat::ffi_libarchive_free_stat(stat)
192
+ end
193
+
194
+ def copy_pathname file_name
195
+ C::archive_entry_copy_pathname(entry, file_name)
196
+ nil
197
+ end
198
+
199
+ def copy_sourcepath path
200
+ C::archive_copy_sourcepath(entry, path)
201
+ nil
202
+ end
203
+
204
+ def copy_stat filename
205
+ # TODO get this work without ffi-inliner
206
+ begin
207
+ require File.join(File.dirname(__FILE__), 'stat.rb')
208
+ rescue => e
209
+ raise "ffi-inliner build for copy_stat failed:\n#{e}"
210
+ end
211
+
212
+ stat = Archive::Stat::ffi_libarchive_create_stat(filename)
213
+ raise Error, "Copy stat failed: #{LibC::strerror(LibC::errno)}" if stat.null?
214
+ result = C::archive_entry_copy_stat(entry, stat)
215
+ ensure
216
+ Archive::Stat::ffi_libarchive_free_stat(stat)
217
+ end
218
+
219
+ def copy_symlink slnk
220
+ C::archive_copy_symlink(entry, slnk)
221
+ nil
222
+ end
223
+
224
+ def copy_uname uname
225
+ C::archive_copy_uname(entry, uname)
226
+ nil
227
+ end
228
+
229
+ def dev
230
+ C::archive_entry_dev(entry)
231
+ end
232
+
233
+ def dev= dev
234
+ C::archive_entry_set_dev(entry, dev)
235
+ end
236
+
237
+ def devmajor
238
+ C::archive_entry_devmajor(entry)
239
+ end
240
+
241
+ def devmajor= dev
242
+ C::archive_entry_set_devmajor(entry, dev)
243
+ end
244
+
245
+ def devminor
246
+ C::archive_entry_devminor(entry)
247
+ end
248
+
249
+ def devminor= dev
250
+ C::archive_entry_set_devminor(entry, dev)
251
+ end
252
+
253
+ def fflags
254
+ set = FFI::MemoryPointer.new :long
255
+ clear = FFI::MemoryPointer.new :long
256
+ C::archive_entry_fflags(entry, set, clear)
257
+ [set.get_long(0), clear.get_long(0)]
258
+ end
259
+
260
+ def fflags_text
261
+ C::archive_entry_fflags_text(entry)
262
+ end
263
+
264
+ def filetype
265
+ C::archive_entry_filetype(entry)
266
+ end
267
+
268
+ def filetype= type
269
+ if type.kind_of? Symbol
270
+ type = Entry.const_get type.to_s.upcase.intern
271
+ end
272
+ C::archive_entry_set_filetype(entry, type)
273
+ end
274
+
275
+ def gid
276
+ C::archive_entry_gid(entry)
277
+ end
278
+
279
+ def gid= gid
280
+ C::archive_entry_set_gid(entry, gid)
281
+ end
282
+
283
+ def gname
284
+ C::archive_entry_gname(entry)
285
+ end
286
+
287
+ def gname= gname
288
+ C::archive_entry_set_gname(entry, gname)
289
+ end
290
+
291
+ def hardlink
292
+ C::archive_entry_hardlink(entry)
293
+ end
294
+
295
+ def hardlink= lnk
296
+ C::archive_entry_set_hardlink(entry, lnk)
297
+ end
298
+
299
+ def ino
300
+ C::archive_entry_ino(entry)
301
+ end
302
+
303
+ def ino= ino
304
+ C::archive_entry_set_ino(entry, ino)
305
+ end
306
+
307
+ def link= lnk
308
+ C::archive_entry_set_link(entry, lnk)
309
+ end
310
+
311
+ def mode
312
+ C::archive_entry_mode(entry)
313
+ end
314
+
315
+ def mode= mode
316
+ C::archive_entry_set_mode(entry, mode)
317
+ end
318
+
319
+ def mtime
320
+ Time.at C::archive_entry_mtime(entry)
321
+ end
322
+
323
+ def mtime= time
324
+ set_mtime time, 0
325
+ end
326
+
327
+ def set_mtime time, nsec
328
+ C::archive_entry_set_mtime(entry, time.to_i, nsec)
329
+ end
330
+
331
+ def mtime_is_set?
332
+ C::archive_entry_mtime_is_set(entry) != 0
333
+ end
334
+
335
+ def mtime_nsec
336
+ C::archive_entry_mtime_nsec(entry)
337
+ end
338
+
339
+ def nlink
340
+ C::archive_entry_nlink(entry)
341
+ end
342
+
343
+ def nlink= nlink
344
+ C::archive_entry_set_nlink(entry, nlink)
345
+ end
346
+
347
+ def pathname
348
+ C::archive_entry_pathname(entry)
349
+ end
350
+
351
+ def pathname= path
352
+ C::archive_entry_set_pathname(entry, path)
353
+ end
354
+
355
+ def perm= perm
356
+ C::archive_entry_set_perm(entry, perm)
357
+ end
358
+
359
+ def rdev
360
+ C::archive_entry_rdev(entry)
361
+ end
362
+
363
+ def rdev= dev
364
+ C::archive_entry_set_rdev(entry, dev)
365
+ end
366
+
367
+ def rdevmajor
368
+ C::archive_entry_rdevmajor(entry)
369
+ end
370
+
371
+ def rdevmajor= dev
372
+ C::archive_entry_set_rdevmajor(entry, dev)
373
+ end
374
+
375
+ def rdevminor
376
+ C::archive_entry_rdevminor(entry)
377
+ end
378
+
379
+ def rdevminor= dev
380
+ C::archive_entry_set_rdevminor(entry, dev)
381
+ end
382
+
383
+ def set_fflags set, clear
384
+ C::archive_entry_set_fflags(entry, set, clear)
385
+ end
386
+
387
+ def size
388
+ C::archive_entry_size(entry)
389
+ end
390
+
391
+ def size= size
392
+ C::archive_entry_set_size(entry, size)
393
+ end
394
+
395
+ def size_is_set?
396
+ C::archive_entry_size_is_set(entry) != 0
397
+ end
398
+
399
+ def sourcepath
400
+ C::archive_entry_sourcepath(entry)
401
+ end
402
+
403
+ def strmode
404
+ C::archive_entry_strmode(entry)
405
+ end
406
+
407
+ def symlink
408
+ C::archive_entry_symlink(entry)
409
+ end
410
+
411
+ def symlink= slnk
412
+ C::archive_entry_set_symlink(entry, slnk)
413
+ end
414
+
415
+ def uid
416
+ C::archive_entry_uid(entry)
417
+ end
418
+
419
+ def uid= uid
420
+ C::archive_entry_set_uid(entry, uid)
421
+ end
422
+
423
+ def uname
424
+ C::archive_entry_uname(entry)
425
+ end
426
+
427
+ def uname= uname
428
+ C::archive_entry_set_uname(entry, uname)
429
+ end
430
+
431
+ def unset_atime
432
+ C::archive_entry_unset_atime(entry)
433
+ end
434
+
435
+ def unset_birthtime
436
+ C::archive_entry_unset_birthtime(entry)
437
+ end
438
+
439
+ def unset_ctime
440
+ C::archive_entry_unset_ctime(entry)
441
+ end
442
+
443
+ def unset_mtime
444
+ C::archive_entry_unset_mtime(entry)
445
+ end
446
+
447
+ def unset_size
448
+ C::archive_entry_unset_size(entry)
449
+ end
450
+
451
+ def xattr_add_entry name, value
452
+ C::archive_entry_xattr_add_entry(entry, name, value, value.size)
453
+ end
454
+
455
+ def xattr_clear
456
+ C::archive_entry_xattr_clear(entry)
457
+ end
458
+
459
+ def xattr_count
460
+ C::archive_entry_xattr_count(entry)
461
+ end
462
+
463
+ def xattr_next
464
+ name = FFI::MemoryPointer.new :pointer
465
+ value = FFI::MemoryPointer.new :pointer
466
+ size = FFI::MemoryPointer.new :size_t
467
+ if C::archive_entry_xattr_next(entry, name, value, size) != C::OK
468
+ return nil
469
+ else
470
+ # TODO: someday size.read_size_t could work
471
+ return [name.null? ? nil : name.read_string,
472
+ value.null? ? nil : value.get_string(0,size.read_ulong)]
473
+ end
474
+ end
475
+
476
+ def xattr_reset
477
+ C::archive_entry_xattr_reset(entry)
478
+ end
479
+
480
+ end
481
+
482
+ end