ffi-libarchive 0.1.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,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