Class: Archive
- Inherits:
-
Object
- Object
- Archive
- Includes:
- Enumerable
- Defined in:
- ext/archive.cpp,
ext/entry.cpp,
ext/archive.cpp
Overview
This class represents an archive file. The file may or may not exist, depending on wheather you want to create a new archive or read from an existing one. When instanciating this class, libarchive-ruby will automatically detect the correct file format for you using libarchive’s own detection mechanism if the archive file is already present, otherwise by looking at the archive file’s file extension.
Defined Under Namespace
Constant Summary collapse
- EXTRACT_TIME =
extract the atime and mtime
INT2NUM(ARCHIVE_EXTRACT_TIME)
- EXTRACT_OWNER =
extract the owner
INT2NUM(ARCHIVE_EXTRACT_OWNER)
- EXTRACT_PERM =
extract the permission
INT2NUM(ARCHIVE_EXTRACT_PERM)
- EXTRACT_NO_OVERWRITE =
INT2NUM(ARCHIVE_EXTRACT_NO_OVERWRITE)
- EXTRACT_ACL =
extract the access control list
INT2NUM(ARCHIVE_EXTRACT_ACL)
- EXTRACT_FFLAGS =
extract the fflags
INT2NUM(ARCHIVE_EXTRACT_FFLAGS)
- EXTRACT_XATTR =
extract the extended information
INT2NUM(ARCHIVE_EXTRACT_XATTR)
Instance Method Summary collapse
-
#<<(obj) ⇒ Object
Adds a file to an archive.
-
#[](name) ⇒ Object
Returns an archive entry for the given name.
-
#add ⇒ Object
(VALUE self,VALUE obj,VALUE name).
-
#atime ⇒ Object
:nodoc: call-seq: archive.atime -> Time.
-
#clear ⇒ self
Deletes all files from an archive.
-
#compression ⇒ Object
Returns the archive compression as an integer.
-
#compression_name ⇒ Object
Returns the archive compression’s name as a string.
-
#ctime ⇒ Object
:nodoc: call-seq: archive.ctime -> Time.
-
#delete(name) ⇒ Object
Delete files from an archive.
-
#delete_if ⇒ Object
Yields each entry in the archive to the block and deletes those for which the block evaluates to a truth value.
-
#each ⇒ Object
Iterates through the archive and yields each entry as an Archive::Entry object.
-
#each_data ⇒ Object
Iterates through the archive and yields each entry’s data as a string.
-
#each_entry ⇒ Object
Iterates through the archive and yields each entry as an Archive::Entry object.
-
#exist? ⇒ Boolean
:nodoc: call-seq: archive.exist? -> true or false.
-
#extract([name = nil [, io [ ,opt ] ] ]) ⇒ Object
Extract files to current directory.
-
#extract_if(*args) ⇒ Object
Yields each entry in the archive to the block and extracts only those entries (to the current directory) for which the block evaluates to a truth value.
-
#format ⇒ Object
Returns the archive format as an integer.
-
#format_name ⇒ Object
Returns the archive format’s name as a string.
-
#new(path[, format [, compression ] ]) ⇒ Object
constructor
Makes a new Archive object.
-
#inspect ⇒ String
Human-readable description.
-
#map! ⇒ Object
(also: #collect!)
Iterates through the archive and changes it’s data “on the fly”, i.e.
-
#mtime ⇒ Object
:nodoc: call-seq: archive.mtime -> Time.
-
#path ⇒ Object
Returns the path (filename) of the archive.
-
#stat ⇒ Object
:nodoc: call-seq: archive.stat -> File::Stat.
-
#to_hash ⇒ Object
Iterates through the archive and yields each data of an entry as a string object.
-
#unlink ⇒ Object
:nodoc: call-seq: archive.unlink -> self.
Constructor Details
#new(path[, format [, compression ] ]) ⇒ Object
Makes a new Archive object. If format is given, a new archive is created or
an existing archive will be converted into the given format.
===Parameters
[path] The path to the archive. May or may not exist.
[format] The archive's format as a symbol. If you ommit this, the format will
be guessed from the file extension. Possible formats are:
* :ar
* :tar
* :pax
* :xar
* :zip
[compression] Symbol inidicating the compression you want to use. If
ommited, it will be guessed from the file extension.
Possible formats are:
* :bzip2
* :compress
* :gzip
* :lzma
* :xz
===Raises
[FormatError] Unknown archive format or writing not supported.
[CompressionError] Unknown compression format.
===Examples
See the README for some examples.
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 |
# File 'ext/archive.cpp', line 248
VALUE Archive_initialize(int argc, VALUE *argv,VALUE self)
{
VALUE path,r_format,r_compression;
rb_scan_args(argc, argv, "12", &path,&r_format,&r_compression);
if(rb_obj_is_kind_of(path,rb_cIO)){
_self->fd = NUM2INT(rb_funcall(path,rb_intern("fileno"),0));
_self->type = archive_fd;
rb_scan_args(argc, argv, "21", &path,&r_format,&r_compression);
}else if(rb_obj_is_kind_of(path,rb_cInteger)){
_self->fd = NUM2INT(path);
_self->type = archive_fd;
rb_scan_args(argc, argv, "21", &path,&r_format,&r_compression);
}else if(rb_respond_to(path,rb_intern("read"))){
_self->ruby = path;
_self->type = archive_ruby;
rb_scan_args(argc, argv, "21", &path,&r_format,&r_compression);
}else{
path = rb_file_s_expand_path(1,&path);
_self->path = std::string(rb_string_value_cstr(&path));
_self->type =archive_path;
}
//to set the format the file must convert
if(!NIL_P(r_format)){
char buff[8192];
//std::string selfpath =_self->path;
size_t bytes_read;
struct archive *a = archive_read_new(),*b=archive_write_new();
struct archive_entry *entry;
int format,compression,error=0;
std::vector<struct archive_entry *> entries;
std::vector<std::string> allbuff;
if(rb_obj_is_kind_of(r_format,rb_cSymbol)!=Qtrue)
rb_raise(rb_eTypeError,"exepted Symbol");
if(SYM2ID(r_format) == rb_intern("tar"))
format = ARCHIVE_FORMAT_TAR_GNUTAR;
else if(SYM2ID(r_format) == rb_intern("pax"))
format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
else if(SYM2ID(r_format) == rb_intern("zip"))
format = ARCHIVE_FORMAT_ZIP;
else if(SYM2ID(r_format) == rb_intern("ar"))
format = ARCHIVE_FORMAT_AR_GNU;
else if(SYM2ID(r_format) == rb_intern("xar"))
format = ARCHIVE_FORMAT_XAR;
else
rb_raise(rb_eTypeError,"wrong format");
if(NIL_P(r_compression)){
compression = ARCHIVE_COMPRESSION_NONE;
error = archive_write_set_compression_none(b);
}else if(SYM2ID(r_compression) == rb_intern("gzip")){
compression =ARCHIVE_COMPRESSION_GZIP;
error = archive_write_set_compression_gzip(b);
}else if(SYM2ID(r_compression) == rb_intern("bzip2")){
compression =ARCHIVE_COMPRESSION_BZIP2;
error = archive_write_set_compression_bzip2(b);
}else if(SYM2ID(r_compression) == rb_intern("compress")){
compression =ARCHIVE_COMPRESSION_BZIP2;
error = archive_write_set_compression_compress(b);
}else if(SYM2ID(r_compression) == rb_intern("lzma")){
compression =ARCHIVE_COMPRESSION_LZMA;
error = archive_write_set_compression_lzma(b);
}else if(SYM2ID(r_compression) == rb_intern("xz")){
compression =ARCHIVE_COMPRESSION_XZ;
error = archive_write_set_compression_xz(b);
}else
rb_raise(rb_eTypeError,"unsupported compression");
if(error)
rb_raise(rb_eArchiveError,"error (%d): %s ",archive_errno(b),archive_error_string(b));
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
//autodetect format and compression
error=Archive_read_ruby(self,a);
_self->format = format;
_self->compression = compression;
if(error==ARCHIVE_OK){
while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
if(format==archive_format(a) && compression==archive_compression(a)){
archive_read_finish(a);
return self;
}
entries.push_back(archive_entry_clone(entry));
allbuff.push_back(std::string(""));
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
allbuff.back().append(buff,bytes_read);
}
archive_read_finish(a);
}
//format fix
if(format==ARCHIVE_FORMAT_TAR_GNUTAR)
format=ARCHIVE_FORMAT_TAR_USTAR;
if((error = archive_write_set_format(b,format)) != ARCHIVE_OK)
rb_raise(rb_eArchiveErrorFormat,"error (%d): %s ",error,archive_error_string(b));
error=Archive_write_ruby(self,b);
if(error==ARCHIVE_OK){
//write old data back
for(unsigned int i=0; i<entries.size(); i++){
archive_write_header(b,entries[i]);
archive_write_data(b,allbuff[i].c_str(),allbuff[i].length());
archive_write_finish_entry(b);
}
archive_write_finish(b);
}
}
return self;
}
|
Instance Method Details
#<<(obj) ⇒ Object
Adds a file to an archive. Basicly the same as #add, but you can’t set the path inside the archive.
Parameters
- obj
-
String or File
Return value
self
Raises
- FormatError
-
The archive format is not supported for writing.
1291 1292 1293 1294 |
# File 'ext/archive.cpp', line 1291
VALUE Archive_add_shift(VALUE self,VALUE name)
{
return Archive_add(1,&name,self);
}
|
#[](name) ⇒ Object
Returns an archive entry for the given name.
Parameters
- name
-
could be a String or a Regex.
Return value
If a matching entry is found, it’s returned as an Archive::Entry object. If not, nil is returned.
Example
#Assuming your archive contains file.txt and ruby.txt
a["file.txt"] #=> Archive::Entry
a[/txt/] #=> Archive::Entry
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 |
# File 'ext/archive.cpp', line 690
VALUE Archive_get(VALUE self,VALUE val)
{
struct archive *a = archive_read_new();
struct archive_entry *entry;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
int error=Archive_read_ruby(self,a);
if(error==ARCHIVE_OK){
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
bool find = false;
if(rb_obj_is_kind_of(val,rb_cRegexp)==Qtrue){
find = rb_reg_match(val,rb_str_new2(archive_entry_pathname(entry)))!=Qnil;
}else{
val = rb_funcall(val,rb_intern("to_s"),0);
std::string str1(rb_string_value_cstr(&val)),str2(str1);
str2 += '/'; // dir ends of '/'
const char *cstr = archive_entry_pathname(entry);
find = (str1.compare(cstr)==0 || str2.compare(cstr)==0);
}
if(find){
VALUE result = wrap(entry);
archive_read_finish(a);
return result;
}
}
archive_read_finish(a);
}
return Qnil;
}
|
#add ⇒ Object
(VALUE self,VALUE obj,VALUE name)
1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 |
# File 'ext/archive.cpp', line 1191
VALUE Archive_add(int argc, VALUE *argv, VALUE self)//(VALUE self,VALUE obj,VALUE name)
{
VALUE obj,name;
rb_scan_args(argc, argv, "11", &obj,&name);
if(NIL_P(name)){
if(rb_obj_is_kind_of(obj,rb_cFile))
name = rb_funcall(name,rb_intern("path"),0);
else if(rb_obj_is_kind_of(obj,rb_cIO))
rb_scan_args(argc, argv, "20", &obj,&name);
else if(rb_respond_to(obj,rb_intern("read")))
rb_scan_args(argc, argv, "20", &obj,&name);
else if(rb_obj_is_kind_of(obj,rb_cArray) or rb_obj_is_kind_of(obj,rb_cHash))
rb_scan_args(argc, argv, "10", &obj);
else
name = obj;
}
char buff[8192];
char *path = NULL;
size_t bytes_read;
struct archive *a = archive_read_new(),*b=archive_write_new();
struct archive_entry *entry;
std::vector<struct archive_entry *> entries;
std::vector<std::string> allbuff;
int format= ARCHIVE_FORMAT_EMPTY,compression=ARCHIVE_COMPRESSION_NONE,fd=-1,error=0;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
//autodetect format and compression
if(Archive_read_ruby(self,a)==ARCHIVE_OK){
while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
entries.push_back(archive_entry_clone(entry));
allbuff.push_back(std::string(""));
try{
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
allbuff.back().append(buff,bytes_read);
}catch(...){
rb_raise(rb_eArchiveError,"error:%d:%s",archive_errno(a),archive_error_string(a));
}
}
format = archive_format(a);
compression = archive_compression(a);
archive_read_finish(a);
}
if(rb_obj_is_kind_of(obj,rb_cFile)){
VALUE pathname = rb_funcall(obj,rb_intern("path"),0); //source path
VALUE obj2 = rb_file_s_expand_path(1,&pathname);
path = rb_string_value_cstr(&obj2);
fd = NUM2INT(rb_funcall(obj,rb_intern("fileno"),0));
}else if(rb_obj_is_kind_of(obj,rb_cIO)){
fd = NUM2INT(rb_funcall(obj,rb_intern("fileno"),0));
}else if(rb_respond_to(obj,rb_intern("read")) or rb_obj_is_kind_of(obj,rb_cArray) or rb_obj_is_kind_of(obj,rb_cHash)){
//stringio has neigther path or fileno, so do nothing
}else {
VALUE obj2 = rb_file_s_expand_path(1,&obj);
path = rb_string_value_cstr(&obj2);
fd = open(path, O_RDONLY);
if (fd < 0) //TODO: add error
return self;
}
Archive_format_from_path(self,format,compression);
if((error = archive_write_set_format(b,format)) != ARCHIVE_OK)
rb_raise(rb_eArchiveErrorFormat,"error:%d:%s",archive_errno(b),archive_error_string(b));
Archive_write_set_compression(b,compression);
if(Archive_write_ruby(self,b)==ARCHIVE_OK){
entry = archive_entry_new();
if (path)
archive_entry_copy_sourcepath(entry, path);
if(!NIL_P(name))
archive_entry_copy_pathname(entry, rb_string_value_cstr(&name));
add_obj temp;
temp.archive = b;
temp.file = archive_read_disk_new();
temp.entry = entry;
temp.fd = fd;
temp.obj = obj;
temp.entries = &entries;
temp.allbuff = &allbuff;
RB_ENSURE(Archive_add_block,&temp,Archive_add_block_ensure,&temp);
}
if(fd >= 0 and !rb_obj_is_kind_of(name,rb_cIO))
close(fd);
return self;
}
|
#atime ⇒ Object
:nodoc:
call-seq:
archive.atime -> Time
call the File.atime(path)
1548 1549 1550 1551 |
# File 'ext/archive.cpp', line 1548
VALUE Archive_atime(VALUE self)
{
return rb_funcall(rb_cFile,rb_intern("atime"),1,Archive_path(self));
}
|
#clear ⇒ self
Deletes all files from an archive.
Return value
returns self.
Raises
raise Error if the format has no write support
1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 |
# File 'ext/archive.cpp', line 1466
VALUE Archive_clear(VALUE self)
{
std::string selfpath =_self->path;
struct archive *a = archive_read_new(),*b=archive_write_new();
struct archive_entry *entry;
int format = ARCHIVE_FORMAT_EMPTY,compression = ARCHIVE_COMPRESSION_NONE,error=0;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
error=Archive_read_ruby(self,a);
if(error==ARCHIVE_OK){
archive_read_next_header(a, &entry);
format = archive_format(a);
compression = archive_compression(a);
archive_read_finish(a);
//format fix
if(format==ARCHIVE_FORMAT_TAR_GNUTAR)
format=ARCHIVE_FORMAT_TAR_USTAR;
if((error = archive_write_set_format(b,format)) != ARCHIVE_OK)
rb_raise(rb_eArchiveErrorFormat,"error (%d): %s ",error,archive_error_string(b));
Archive_write_set_compression(b,compression);
error=Archive_write_ruby(self,b);
if(error==ARCHIVE_OK)
archive_write_finish(b);
}
return self;
}
|
#compression ⇒ Object
Returns the archive compression as an integer. You should use #compression_name instead.
Return value
An integer or nil if the compression wasn’t detectable. 0 means no compression.
941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 |
# File 'ext/archive.cpp', line 941
VALUE Archive_compression(VALUE self)
{
struct archive *a = archive_read_new();
struct archive_entry *entry;
VALUE result = Qnil;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
int error=Archive_read_ruby(self,a);
if(error==ARCHIVE_OK){
archive_read_next_header(a, &entry);
result = INT2NUM(archive_compression(a));
archive_read_finish(a);
}
return result;
}
|
#compression_name ⇒ Object
Returns the archive compression’s name as a string.
Return value
A string or nil if the compression format wasn’t detectable. If there is no compression, "none"
is returned.
Example
a.compression_name #=> "gzip"
a.compression_name #=> "none"
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 |
# File 'ext/archive.cpp', line 1001
VALUE Archive_compression_name(VALUE self)
{
struct archive *a = archive_read_new();
struct archive_entry *entry;
const char* name = NULL;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
int error=Archive_read_ruby(self,a);
if(error==ARCHIVE_OK){
archive_read_next_header(a, &entry);
name = archive_compression_name(a);
archive_read_finish(a);
}
return name ? rb_str_new2(name) : Qnil ;
}
|
#ctime ⇒ Object
:nodoc:
call-seq:
archive.ctime -> Time
call the File.ctime(path)
1561 1562 1563 1564 |
# File 'ext/archive.cpp', line 1561
VALUE Archive_ctime(VALUE self)
{
return rb_funcall(rb_cFile,rb_intern("ctime"),1,Archive_path(self));
}
|
#delete(name) ⇒ Object
Delete files from an archive.
Parameters
- name
-
An Archive::Entry, a String or a Regex.
Return value
A list of paths removed from the archive.
Raises
raise TypeError if the parameter is neigther String or File. raise Error if the format has no write support
1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 |
# File 'ext/archive.cpp', line 1310
VALUE Archive_delete(VALUE self,VALUE val)
{
char buff[8192];
size_t bytes_read;
struct archive *a = archive_read_new(),*b=archive_write_new();
struct archive_entry *entry;
int format = ARCHIVE_FORMAT_EMPTY,compression = ARCHIVE_COMPRESSION_NONE,error=0;
std::vector<struct archive_entry *> entries;
std::vector<std::string> allbuff;
VALUE result = rb_ary_new();
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
//autodetect format and compression
error=Archive_read_ruby(self,a);
if(error==ARCHIVE_OK){
while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
format = archive_format(a);
compression = archive_compression(a);
bool del = false;
if(rb_obj_is_kind_of(val,rb_cArchiveEntry)==Qtrue){
del = std::string(archive_entry_pathname(wrap<archive_entry*>(val))).compare(archive_entry_pathname(entry)) == 0;
}else if(rb_obj_is_kind_of(val,rb_cRegexp)==Qtrue){
VALUE str = rb_str_new2(archive_entry_pathname(entry));
del = rb_reg_match(val,str)!=Qnil;
}else {
std::string str1(rb_string_value_cstr(&val)),str2(str1);
str2 += '/'; // dir ends of '/'
const char *cstr = archive_entry_pathname(entry);
del = (str1.compare(cstr)==0 || str2.compare(cstr)==0);
}
if(!del){
entries.push_back(archive_entry_clone(entry));
allbuff.push_back(std::string(""));
try{
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
allbuff.back().append(buff,bytes_read);
}catch(...){
rb_raise(rb_eArchiveError,"error:%d:%s",archive_errno(a),archive_error_string(a));
}
}else
rb_ary_push(result,wrap(archive_entry_clone(entry)));
}
archive_read_finish(a);
//format fix
if(format==ARCHIVE_FORMAT_TAR_GNUTAR)
format=ARCHIVE_FORMAT_TAR_USTAR;
//TODO add archive-error
if((error = archive_write_set_format(b,format)) != ARCHIVE_OK)
rb_raise(rb_eArchiveErrorFormat,"error (%d): %s ",error,archive_error_string(b));
Archive_write_set_compression(b,compression);
error=Archive_write_ruby(self,b);
if(error==ARCHIVE_OK){
//write old data back
for(unsigned int i=0; i<entries.size(); i++){
archive_write_header(b,entries[i]);
archive_write_data(b,allbuff[i].c_str(),allbuff[i].length());
archive_write_finish_entry(b);
}
archive_write_finish(b);
}
}
return result;
}
|
#delete_if {|entry| ... } ⇒ self #delete_if ⇒ Enumerator
Yields each entry in the archive to the block and deletes those for which the block evaluates to a truth value.
Parameters
- name
-
An Archive::Entry, a String or a Regex.
Return value
If a block was given, returns self, otherwise an Enumerator.
Raises
raise Error if the format has no write support
1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 |
# File 'ext/archive.cpp', line 1407
VALUE Archive_delete_if(VALUE self)
{
RETURN_ENUMERATOR(self,0,NULL);
char buff[8192];
std::string selfpath =_self->path;
size_t bytes_read;
struct archive *a = archive_read_new(),*b=archive_write_new();
struct archive_entry *entry;
int format = ARCHIVE_FORMAT_EMPTY,compression = ARCHIVE_COMPRESSION_NONE,error=0;
std::vector<struct archive_entry *> entries;
std::vector<std::string> allbuff;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
error=Archive_read_ruby(self,a);
if(error==ARCHIVE_OK){
while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
format = archive_format(a);
compression = archive_compression(a);
entries.push_back(archive_entry_clone(entry));
allbuff.push_back(std::string(""));
try{
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
allbuff.back().append(buff,bytes_read);
}catch(...){
rb_raise(rb_eArchiveError,"error:%d:%s",archive_errno(a),archive_error_string(a));
}
}
archive_read_finish(a);
//format fix
if(format==ARCHIVE_FORMAT_TAR_GNUTAR)
format=ARCHIVE_FORMAT_TAR_USTAR;
if((error = archive_write_set_format(b,format)) != ARCHIVE_OK)
rb_raise(rb_eArchiveErrorFormat,"error (%d): %s ",error,archive_error_string(b));
Archive_write_set_compression(b,compression);
error=Archive_write_ruby(self,b);
if(error==ARCHIVE_OK){
write_obj obj;
obj.archive = b;
obj.entries = &entries;
obj.allbuff = &allbuff;
return RB_ENSURE(Archive_delete_if_block,&obj,Archive_write_block_ensure,b);
}
}
return Qnil;
}
|
#each ⇒ Object #each ⇒ Object
Iterates through the archive and yields each entry as an Archive::Entry object. The second parameter contains the data of that entry, so you don’t have to extract it only to read what’s in it.
Return value
If a block is given, returns an array of Archive::Entry objects, otherwise an enumerator.
Example
a.each{|entry| p entry.path}
a.each{|entry, data| puts "'#{entry.path}' contains '#{data}'"}
Output:
"file1.txt"
"file2.txt"
'file1.txt' contains 'I am file1!'
'file2.txt' contains 'I am file2!'
421 422 423 424 425 426 427 428 429 430 431 432 433 |
# File 'ext/archive.cpp', line 421
VALUE Archive_each(VALUE self)
{
RETURN_ENUMERATOR(self,0,NULL);
struct archive *a = archive_read_new();
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
int error=Archive_read_ruby(self,a);
if(error==ARCHIVE_OK)
return RB_ENSURE(Archive_each_block,a,Archive_read_block_ensure,a);
return Qnil;
}
|
#each_data ⇒ Object #each_data ⇒ Object
Iterates through the archive and yields each entry’s data as a string. This is the same as #each, but doesn’t allow for the first block parameter.
Return value
If a block is given, returns an array of String objects, otherwise an enumerator.
Example
a.each{|data| puts "This is: '#{data}'"}
Output:
This is: 'I am file1!'
This is: 'I am file2!'
517 518 519 520 521 522 523 524 525 526 527 528 529 |
# File 'ext/archive.cpp', line 517
VALUE Archive_each_data(VALUE self)
{
RETURN_ENUMERATOR(self,0,NULL);
struct archive *a = archive_read_new();
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
int error=Archive_read_ruby(self,a);
if(error==ARCHIVE_OK)
return RB_ENSURE(Archive_each_data_block,a,Archive_read_block_ensure,a);
return Qnil;
}
|
#each_entry ⇒ Object #each_entry ⇒ Object
Iterates through the archive and yields each entry as an Archive::Entry object. This is the same as #each, but doesn’t allow for the second block parameter.
Return value
If a block is given, returns an array of Archive::Entry objects, otherwise an enumerator.
Example
a.each_entry{|entry| p entry.path}
Output:
"file1.txt"
"file2.txt"
465 466 467 468 469 470 471 472 473 474 475 476 477 |
# File 'ext/archive.cpp', line 465
VALUE Archive_each_entry(VALUE self)
{
RETURN_ENUMERATOR(self,0,NULL);
struct archive *a = archive_read_new();
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
int error=Archive_read_ruby(self,a);
if(error==ARCHIVE_OK)
return RB_ENSURE(Archive_each_entry_block,a,Archive_read_block_ensure,a);
return Qnil;
}
|
#exist? ⇒ Boolean
:nodoc:
call-seq:
archive.exist? -> true or false
Same as
File.exist?(archive.path)
. Checks wheather or not the archive file is existant.
===Return value
True or false.
1511 1512 1513 1514 |
# File 'ext/archive.cpp', line 1511
VALUE Archive_exist(VALUE self)
{
return rb_funcall(rb_cFile,rb_intern("exist?"),1,Archive_path(self));
}
|
#extract([name = nil [, io [ ,opt ] ] ]) ⇒ Object
Extract files to current directory.
Parameters
- name
-
(nil) could be an Archive::Entry, a String or an Regex. If given, only this entry is extracted. Otherwise extracts the whole archive.
- io
-
an instance of IO or something with a
write
method like StringIO. If given, the entry specified vianame
will be extracted intoio
instead of a file. - opt
-
is an option hash. See below for possible options.
Parameters for the option hash
- :extract
-
flag, Integer combined of the Archive::Extract_* constants. This tells libarchive-ruby to only extract the file attributes you specify here. Exceptions is Archive::EXTRACT_NO_OVERWRITE which prevents this method from overwrtiting existing files.
Return value
The paths of the extracted entries as an array.
Example
#Simply extract everything into the current directory.
a.extract
#Extract only file1.txt
a.extract("file1.txt")
#Same as above, but extract it to a StringIO
s = StringIO.new
a.extract("file1.txt", s)
#Same as the first example, but only extract information about the
#modification time.
a.extract(nil, nil, extract: Archive::EXTRACT_TIME)
753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 |
# File 'ext/archive.cpp', line 753
VALUE Archive_extract(int argc, VALUE *argv, VALUE self)
{
char buff[8192];
size_t bytes_read;
VALUE result = rb_ary_new(),name,io,opts,temp;
struct archive *a = archive_read_new();
struct archive_entry *entry;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);//add raw, this is not by all
int extract_opt = 0,fd=-1,error=0;
rb_scan_args(argc, argv, "03", &name,&io,&opts);
if(rb_obj_is_kind_of(name,rb_cHash)){
opts = name;name = Qnil;
}
if(rb_obj_is_kind_of(io,rb_cHash)){
opts = io;io = Qnil;
}
if(rb_obj_is_kind_of(io,rb_cIO))
fd = NUM2INT(rb_funcall(io,rb_intern("fileno"),0));
if(rb_obj_is_kind_of(opts,rb_cHash))
if(RTEST(temp=rb_hash_aref(opts,ID2SYM(rb_intern("extract")))))
extract_opt = NUM2INT(temp);
error=Archive_read_ruby(self,a);
if(error==ARCHIVE_OK){
try{
if(NIL_P(name)){
if(!NIL_P(io)){
rb_raise(rb_eArgError,"You can't extract more than 1 entry into an IO-like object!");
}
while(archive_read_next_header(a, &entry) == ARCHIVE_OK){
archive_read_extract(a,entry,extract_opt);
rb_ary_push(result,rb_str_new2(archive_entry_pathname(entry)));
}
}else{
if(rb_obj_is_kind_of(name,rb_cArchiveEntry)==Qtrue){
if(rb_obj_is_kind_of(io,rb_cIO)==Qtrue){
while(archive_read_next_header(a, &entry) == ARCHIVE_OK){
if(std::string(archive_entry_pathname(entry)).compare(archive_entry_pathname(wrap<archive_entry*>(name)))==0)
archive_read_data_into_fd(a,fd);
}
}else if(rb_respond_to(io,rb_intern("write"))){
while(archive_read_next_header(a, &entry) == ARCHIVE_OK){
if(std::string(archive_entry_pathname(entry)).compare(archive_entry_pathname(wrap<archive_entry*>(name)))==0)
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
rb_funcall(io,rb_intern("write"),1,rb_str_new(buff,bytes_read));
}
}else
archive_read_extract(a,wrap<archive_entry*>(name),extract_opt);
rb_ary_push(result,rb_str_new2(archive_entry_pathname(wrap<archive_entry*>(name))));
}else if(rb_obj_is_kind_of(name,rb_cRegexp)==Qtrue){
while(archive_read_next_header(a, &entry) == ARCHIVE_OK){
VALUE str = rb_str_new2(archive_entry_pathname(entry));
if(rb_reg_match(name,str)!=Qnil){
if(rb_obj_is_kind_of(io,rb_cIO)==Qtrue){
archive_read_data_into_fd(a,fd);
}else if(rb_respond_to(io,rb_intern("write"))){
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
rb_funcall(io,rb_intern("write"),1,rb_str_new(buff,bytes_read));
}else
archive_read_extract(a,entry,extract_opt);
rb_ary_push(result,str);
}
}
}else{
name = rb_funcall(name,rb_intern("to_s"),0);
std::string str1(rb_string_value_cstr(&name)),str2(str1);
str2 += '/'; // dir ends of '/'
while(archive_read_next_header(a, &entry) == ARCHIVE_OK){
const char *cstr = archive_entry_pathname(entry);
if(str1.compare(cstr)==0 || str2.compare(cstr)==0){
if(rb_obj_is_kind_of(io,rb_cIO)==Qtrue){
archive_read_data_into_fd(a,fd);
}else if(rb_respond_to(io,rb_intern("write"))){
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
rb_funcall(io,rb_intern("write"),1,rb_str_new(buff,bytes_read));
}else
archive_read_extract(a,entry,extract_opt);
rb_ary_push(result,rb_str_new2(cstr));
}
}
}
}
}catch (...){
rb_raise(rb_eArchiveError,"error:%d:%s",archive_errno(a),archive_error_string(a));
}
archive_read_finish(a);
}
return result;
}
|
#extract_if([ opt ]) ⇒ Object #extract_if([ opt ]) ⇒ Object
Yields each entry in the archive to the block and extracts only those entries (to the current directory) for which the block evaluates to a truth value.
Parameters
- opt
-
is the same option hash that you can pass to #extract.
Parameters for the option hash
See the #extract method for explanation.
Return value
The paths of all extracted entries if a block was given, an Enumerator otherwise.
879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 |
# File 'ext/archive.cpp', line 879
VALUE Archive_extract_if(int argc, VALUE *argv, VALUE self)
{
RETURN_ENUMERATOR(self,argc,argv);
VALUE opts,temp;
struct archive *a = archive_read_new();
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
int extract_opt=0,error=0;
rb_scan_args(argc, argv, "01", &opts);
if(rb_obj_is_kind_of(opts,rb_cHash))
if(RTEST(temp=rb_hash_aref(opts,ID2SYM(rb_intern("extract")))))
extract_opt = NUM2INT(temp);
error=Archive_read_ruby(self,a);
if(error==ARCHIVE_OK){
extract_obj obj;
obj.archive = a;
obj.extract_opt = extract_opt;
return RB_ENSURE(Archive_extract_if_block,&obj,Archive_read_block_ensure,a);
}
return Qnil;
}
|
#format ⇒ Object
Returns the archive format as an integer. You should use #format_name instead.
Return value
An integer or nil if the format wasn’t detectable.
913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 |
# File 'ext/archive.cpp', line 913
VALUE Archive_format(VALUE self)
{
struct archive *a = archive_read_new();
struct archive_entry *entry;
VALUE result = Qnil;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
int error=Archive_read_ruby(self,a);
if(error==ARCHIVE_OK){
archive_read_next_header(a, &entry);
result = INT2NUM(archive_format(a));
archive_read_finish(a);
}
return result;
}
|
#format_name ⇒ Object
Returns the archive format’s name as a string.
Return value
A string or nil if the format wasn’t detectable.
Example
a.format_name #=> "GNU tar format"
969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 |
# File 'ext/archive.cpp', line 969
VALUE Archive_format_name(VALUE self)
{
struct archive *a = archive_read_new();
struct archive_entry *entry;
const char* name = NULL;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
int error=Archive_read_ruby(self,a);
if(error==ARCHIVE_OK){
if(archive_read_next_header(a, &entry)==ARCHIVE_OK){
name = archive_format_name(a);
archive_read_finish(a);
}
}
return name ? rb_str_new2(name) : Qnil ;
}
|
#inspect ⇒ String
Human-readable description.
Return value
String
1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 |
# File 'ext/archive.cpp', line 1587
VALUE Archive_inspect(VALUE self)
{
VALUE array[3];
switch(_self->type){
case archive_path:
array[0]=rb_str_new2("#<%s:%s>");
array[1]=rb_class_of(self);
array[2]=Archive_path(self);
break;
case archive_fd:
array[0]=rb_str_new2("#<%s:%d>");
array[1]=rb_class_of(self);
array[2]=INT2NUM(_self->fd);
break;
case archive_buffer:
break;
case archive_ruby:
array[0]=rb_str_new2("#<%s:%s>");
array[1]=rb_class_of(self);
array[2]=_self->ruby;
break;
}
return rb_f_sprintf(3,array);
}
|
#map! ⇒ Object #map! ⇒ Object Also known as: collect!
Iterates through the archive and changes it’s data “on the fly”, i.e. the value your block returns for each iteration is put for the data in the yielded entry. Your block is expected to return a 2-element array of form
- archive_entry, “data”
-
where
archive_enty
is theentry
yielded to the block (which you may modify via the Archive::Entry methods) and"data"
is a string containing the data you want to set for this entry.The block parameters are the same as for #each.
Return value
The archive itself.
Example
#Double the contents in each file of the archive a.map!{|entry, data| [entry, data * 2]} #Clear all files in the archive a.map!{|entry| [entry, ""]}
623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 |
# File 'ext/archive.cpp', line 623
VALUE Archive_map_self(VALUE self)
{
RETURN_ENUMERATOR(self,0,NULL);
char buff[8192];
std::string selfpath =_self->path;
size_t bytes_read;
struct archive *a = archive_read_new(),*b=archive_write_new();
struct archive_entry *entry;
int format = ARCHIVE_FORMAT_EMPTY,compression = ARCHIVE_COMPRESSION_NONE,error=0;
std::vector<struct archive_entry *> entries;
std::vector<std::string> allbuff;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
//autodetect format and compression
error=Archive_read_ruby(self,a);
if(error==ARCHIVE_OK){
while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
format = archive_format(a);
compression = archive_compression(a);
entries.push_back(archive_entry_clone(entry));
allbuff.push_back(std::string(""));
try{
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
allbuff.back().append(buff,bytes_read);
} catch (...){
rb_raise(rb_eArchiveError,"error:%d:%s",archive_errno(a),archive_error_string(a));
}
}
archive_read_finish(a);
//format fix
if(format==ARCHIVE_FORMAT_TAR_GNUTAR)
format=ARCHIVE_FORMAT_TAR_USTAR;
if((error = archive_write_set_format(b,format)) != ARCHIVE_OK)
rb_raise(rb_eArchiveErrorFormat,"error (%d): %s ",error,archive_error_string(b));
Archive_write_set_compression(b,compression);
error=Archive_write_ruby(self,b);
if(error==ARCHIVE_OK){
write_obj obj;
obj.archive = b;
obj.entries = &entries;
obj.allbuff = &allbuff;
RB_ENSURE(Archive_map_block,&obj,Archive_write_block_ensure,b);
}
}
return self;
}
|
#mtime ⇒ Object
:nodoc:
call-seq:
archive.mtime -> Time
call the File.mtime(path)
1536 1537 1538 1539 |
# File 'ext/archive.cpp', line 1536
VALUE Archive_mtime(VALUE self)
{
return rb_funcall(rb_cFile,rb_intern("mtime"),1,Archive_path(self));
}
|
#path ⇒ Object
Returns the path (filename) of the archive.
Return value
Returns path of the archive. May or may not exist.
Example
a.path #=> /home/freak/myarchive.tar.gz
371 372 373 374 |
# File 'ext/archive.cpp', line 371
VALUE Archive_path(VALUE self)
{
return (_self->type == archive_path) ? rb_str_new2(_self->path.c_str()) : Qnil;
}
|
#stat ⇒ Object
:nodoc:
call-seq:
archive.stat -> File::Stat
call the File.stat(path)
1573 1574 1575 1576 |
# File 'ext/archive.cpp', line 1573
VALUE Archive_stat(VALUE self)
{
return rb_funcall(rb_cFile,rb_intern("stat"),1,Archive_path(self));
}
|
#to_hash ⇒ Object
Iterates through the archive and yields each data of an entry as a string object.
Return value
returns Hash of Archive::Entry => Sring
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 |
# File 'ext/archive.cpp', line 541
VALUE Archive_to_hash(VALUE self)
{
VALUE result = rb_hash_new();
struct archive *a = archive_read_new();
struct archive_entry *entry;
archive_read_support_compression_all(a);
archive_read_support_format_all(a);
archive_read_support_format_raw(a);
int error=Archive_read_ruby(self,a);
if(error==ARCHIVE_OK){
while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
char buff[8192];
std::string str;
size_t bytes_read;
try{
while ((bytes_read=archive_read_data(a,&buff,sizeof(buff)))>0)
str.append(buff,bytes_read);
} catch (...){
rb_raise(rb_eArchiveError,"error:%d:%s",archive_errno(a),archive_error_string(a));
}
rb_hash_aset(result,wrap(entry),rb_str_new2(str.c_str()));
}
archive_read_finish(a);
}
return result;
}
|
#unlink ⇒ Object
:nodoc:
call-seq:
archive.unlink -> self
call the File.unlink(path)
1523 1524 1525 1526 1527 |
# File 'ext/archive.cpp', line 1523
VALUE Archive_unlink(VALUE self)
{
return rb_funcall(rb_cFile,rb_intern("unlink"),1,Archive_path(self));
return self;
}
|