Class: Archive

Inherits:
Object
  • Object
show all
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

Classes: Entry, Error

Constant Summary collapse

EXTRACT_OWNER =

extract the owner

INT2NUM(ARCHIVE_EXTRACT_OWNER)
EXTRACT_PERM =

extract the permission

INT2NUM(ARCHIVE_EXTRACT_PERM)
EXTRACT_TIME =

extract the atime and mtime

INT2NUM(ARCHIVE_EXTRACT_TIME)
EXTRACT_NO_OVERWRITE =
INT2NUM(ARCHIVE_EXTRACT_NO_OVERWRITE)
INT2NUM(ARCHIVE_EXTRACT_UNLINK)
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)
INT2NUM(ARCHIVE_EXTRACT_SECURE_SYMLINKS)
EXTRACT_SECURE_NODOTDOT =
INT2NUM(ARCHIVE_EXTRACT_SECURE_NODOTDOT)
EXTRACT_NO_AUTODIR =
INT2NUM(ARCHIVE_EXTRACT_NO_AUTODIR)
EXTRACT_NO_OVERWRITE_NEWER =
INT2NUM(ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER)
EXTRACT_SPARSE =
INT2NUM(ARCHIVE_EXTRACT_SPARSE)
EXTRACT_MAC_METADATA =
INT2NUM(ARCHIVE_EXTRACT_MAC_METADATA)

Instance Method Summary collapse

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.


501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
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
567
568
569
570
571
572
573
574
575
576
577
578
# File 'ext/archive.cpp', line 501

VALUE Archive_initialize(int argc, VALUE *argv,VALUE self)
{
	VALUE path,r_format,r_filter;
	rb_scan_args(argc, argv, "12", &path,&r_format,&r_filter);
	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_filter);
	}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_filter);
	}else if(rb_respond_to(path,rb_intern("read"))){
		_self->type = archive_ruby;
		rb_scan_args(argc, argv, "21", &path,&r_format,&r_filter);
	}else{
		path = rb_file_s_expand_path(1,&path);
		_self->path = std::string(StringValueCStr(path));
		_self->type =archive_path;
	}
	_self->ruby = path;
	//to set the format the file must convert
	if(!NIL_P(r_format)){
	
		//struct archive *a = archive_read_new(),*b=archive_write_new();
		//struct archive_entry *entry;
		int format,filter;
		
		if(SYMBOL_P(r_format)){
			SymToIntType::iterator it = SymToFormat.find(SYM2ID(r_format));
			if(it != SymToFormat.end()) {
				format = it->second;
			}else
				rb_raise(rb_eTypeError,"wrong format");
		}else
			rb_raise(rb_eTypeError,"exepted Symbol");
			
		if(NIL_P(r_filter)){
			filter = ARCHIVE_FILTER_NONE;
		}else if(SYMBOL_P(r_filter)){
			SymToIntType::iterator it = SymToFilter.find(SYM2ID(r_filter));
			if(it != SymToFilter.end()) {
				filter = it->second;
			} else
				rb_raise(rb_eTypeError,"unsupported filter");
		}else
			rb_raise(rb_eTypeError,"exepted Symbol");
		
		//autodetect format and compression

		_self->format = format;
		_self->filter = filter;
		
//		if(Archive_read_ruby(self,a)==ARCHIVE_OK){
//			while(archive_read_next_header(a, &entry)==ARCHIVE_OK){
//				if(format==archive_format(a) && filter==archive_filter_code(a,0)){
//					archive_read_close(a);
//					return self;
//				}
//				entries.push_back(archive_entry_clone(entry));
//				allbuff.push_back(std::string(""));
//				
//				RubyArchive::read_data(a,allbuff.back());
//			}
//			archive_read_close(a);
//			if(Archive_write_ruby(self,b,format,IntVector(filter))==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_close(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.



1364
1365
1366
1367
# File 'ext/archive.cpp', line 1364

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


871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
# File 'ext/archive.cpp', line 871

VALUE Archive_get(VALUE self,VALUE val)
{
	struct archive *a = archive_read_new();
	struct archive_entry *entry;
	
	if(Archive_read_ruby(self,a)==ARCHIVE_OK){
		while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
			if(RubyArchive::match_entry(entry,val)){
				VALUE result = wrap(entry);
				archive_read_close(a);
				return result;
			}
		}
		archive_read_close(a);
	}
	return Qnil;
}

#addObject

(VALUE self,VALUE obj,VALUE name)



1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
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
# File 'ext/archive.cpp', line 1280

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;
	}

	struct archive *a = archive_read_new(),*b=archive_write_new();
	
	DataVector entries;
	IntVector filters;
	

	int format= ARCHIVE_FORMAT_EMPTY;

	
	//autodetect format and compression
	if(Archive_read_ruby(self,a)==ARCHIVE_OK){
		RubyArchive::read_old_data(a, entries, format, filters);
	}
	
//	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 = StringValueCStr(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 {
//		if(RTEST(rb_funcall(rb_cFile,rb_intern("directory?"),1,obj)))
//			obj = rb_funcall(rb_cDir,rb_intern("glob"),1,rb_str_new2("**/**/*"));
//		else{
//			VALUE obj2 = rb_file_s_expand_path(1,&obj);
//			path = StringValueCStr(obj2);
//			fd = open(path, O_RDONLY);
//			if (fd < 0) //TODO: add error
//				return self;
//		}
//	}
//	Archive_format_from_path(self,format,compression);
	
	if(format == ARCHIVE_FORMAT_EMPTY){
		Archive_format_from_path(self,format,filters);
	}
	
	if(Archive_write_ruby(self,b,format,filters)==ARCHIVE_OK){
		
		add_obj temp;
		temp.archive = b;
		temp.obj = obj;
		//temp.path = path;
		temp.name = name;
		temp.data = &entries;
		RB_ENSURE(Archive_add_block,&temp,Archive_add_block_ensure,&temp);
	}
	
	return self;
}

#atimeObject

:nodoc:

call-seq:
archive.atime -> Time

call the File.atime(path)


1551
1552
1553
1554
# File 'ext/archive.cpp', line 1551

VALUE Archive_atime(VALUE self)
{
	return rb_funcall(rb_cFile,rb_intern("atime"),1,Archive_path(self));
}

#clearself

Deletes all files from an archive.

Return value

returns self.

Raises

raise Error if the format has no write support

Returns:

  • (self)


1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
# File 'ext/archive.cpp', line 1482

VALUE Archive_clear(VALUE self)
{

	struct archive *a = archive_read_new(),*b=archive_write_new();
	struct archive_entry *entry;
	int format = ARCHIVE_FORMAT_EMPTY;
	
	if(Archive_read_ruby(self,a)==ARCHIVE_OK){
		archive_read_next_header(a, &entry);
		format = archive_format(a);
		IntVector filters;
		RubyArchive::read_get_filters(a,filters);
		archive_read_close(a);
		
		if(Archive_write_ruby(self,b,format,filters)==ARCHIVE_OK)
			archive_write_close(b);
	}
	
	return self;
}

#ctimeObject

:nodoc:

call-seq:
archive.ctime -> Time

call the File.ctime(path)


1564
1565
1566
1567
# File 'ext/archive.cpp', line 1564

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



1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
# File 'ext/archive.cpp', line 1383

VALUE Archive_delete(VALUE self,VALUE val)
{
	struct archive *a = archive_read_new(),*b=archive_write_new();
	int format = ARCHIVE_FORMAT_EMPTY;
	
	DataVector entries;
	IntVector filters;
	
	VALUE result = rb_ary_new();
	
	//autodetect format and compression
	if(Archive_read_ruby(self,a)==ARCHIVE_OK){
		RubyArchive::read_old_data(a, entries, format, filters);

		for(unsigned int i=0; i<entries.size();){
			if(RubyArchive::match_entry(entries[i].first,val)){
				rb_ary_push(result,rb_str_new2(archive_entry_pathname(entries[i].first)));
				entries.erase(entries.begin() + i);
			}else
				++i;
		}

		if(Archive_write_ruby(self,b,format,filters)==ARCHIVE_OK){
			//write old data back
			for(unsigned int i=0; i<entries.size(); i++){
				archive_write_header(b,entries[i].first);
				archive_write_data(b,&entries[i].second[0],entries[i].second.length());
				archive_write_finish_entry(b);
			}
			archive_write_close(b);
		}
		
	}
	return result;
}

#delete_if {|entry| ... } ⇒ self #delete_ifEnumerator

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

Overloads:

  • #delete_if {|entry| ... } ⇒ self

    Yields:

    • (entry)

    Returns:

    • (self)
  • #delete_ifEnumerator

    Returns:

    • (Enumerator)


1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
# File 'ext/archive.cpp', line 1448

VALUE Archive_delete_if(VALUE self)
{
	RETURN_ENUMERATOR(self,0,NULL);

	struct archive *a = archive_read_new(),*b=archive_write_new();
	int format = ARCHIVE_FORMAT_EMPTY;
	
	DataVector entries;
	IntVector filters;
	
	if(Archive_read_ruby(self,a)==ARCHIVE_OK){
		RubyArchive::read_old_data(a, entries, format, filters);
		
		if(Archive_write_ruby(self,b,format,filters)==ARCHIVE_OK){
			write_obj obj;
			obj.archive = b;
			obj.data = &entries;
			return RB_ENSURE(Archive_delete_if_block,&obj,Archive_write_block_ensure,b);
		}	
	}	
	return Qnil;
}

#eachObject #eachObject

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 self, 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!'


632
633
634
635
636
637
638
639
640
641
642
643
644
# File 'ext/archive.cpp', line 632

VALUE Archive_each(VALUE self)
{
	RETURN_ENUMERATOR(self,0,NULL);
	struct archive *a = archive_read_new();

	
	int error=Archive_read_ruby(self,a);
	if(error==ARCHIVE_OK){
		RB_ENSURE(Archive_each_block,a,Archive_read_block_ensure,a);
		return self;
	}
	return Qnil;
}

#each_dataObject #each_dataObject

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 self, otherwise an enumerator.

Example

a.each{|data| puts "This is: '#{data}'"}

Output:

This is: 'I am file1!'
This is: 'I am file2!'


715
716
717
718
719
720
721
722
723
# File 'ext/archive.cpp', line 715

VALUE Archive_each_data(VALUE self)
{
	RETURN_ENUMERATOR(self,0,NULL);
	struct archive *a = archive_read_new();
	
	if(Archive_read_ruby(self,a)==ARCHIVE_OK)
		RB_ENSURE(Archive_each_data_block,a,Archive_read_block_ensure,a);
	return self;
}

#each_entryObject #each_entryObject

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"


676
677
678
679
680
681
682
683
684
# File 'ext/archive.cpp', line 676

VALUE Archive_each_entry(VALUE self)
{
	RETURN_ENUMERATOR(self,0,NULL);
	struct archive *a = archive_read_new();
	
	if(Archive_read_ruby(self,a)==ARCHIVE_OK)
		return RB_ENSURE(Archive_each_entry_block,a,Archive_read_block_ensure,a);
	return Qnil;
}

#each_filterObject



737
738
739
740
741
742
743
744
745
# File 'ext/archive.cpp', line 737

VALUE Archive_each_filter(VALUE self)
{
	RETURN_ENUMERATOR(self,0,NULL);
	struct archive *a = archive_read_new();
	
	if(Archive_read_ruby(self,a)==ARCHIVE_OK)
		RB_ENSURE(Archive_each_filter_block,a,Archive_read_block_ensure,a);
	return self;
}

#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.

Returns:

  • (Boolean)


1514
1515
1516
1517
# File 'ext/archive.cpp', line 1514

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 via name will be extracted into io 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)


935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
# File 'ext/archive.cpp', line 935

VALUE Archive_extract(int argc, VALUE *argv, VALUE self)
{

	VALUE result = rb_ary_new(),name,io,opts,temp;
	struct archive *a = archive_read_new();
	struct archive_entry *entry;
	//add raw, this is not by all
	int extract_opt = 0,fd=-1;
	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);
			
	if(Archive_read_ruby(self,a)==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{
				while(archive_read_next_header(a, &entry) == ARCHIVE_OK){
					if(RubyArchive::match_entry(entry,name)){
						extract_extract(a,entry,extract_opt,io,fd);
						rb_ary_push(result,rb_str_new2(archive_entry_pathname(entry)));
					}
				}
			}
		}catch (...){
			rb_raise(rb_eArchiveError,"error:%d:%s",archive_errno(a),archive_error_string(a));
		}
		archive_read_close(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.



1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
# File 'ext/archive.cpp', line 1014

VALUE Archive_extract_if(int argc, VALUE *argv, VALUE self)
{
	RETURN_ENUMERATOR(self,argc,argv);
	VALUE opts,temp;
	struct archive *a = archive_read_new();
	
	int extract_opt=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);
	
	if(Archive_read_ruby(self,a)==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;
}

#formatObject

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.



1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
# File 'ext/archive.cpp', line 1046

VALUE Archive_format(VALUE self)
{
	struct archive *a = archive_read_new();
	struct archive_entry *entry;
	VALUE result = Qnil;
	
	if(Archive_read_ruby(self,a)==ARCHIVE_OK){
		archive_read_next_header(a, &entry);
		result = INT2NUM(archive_format(a));
		archive_read_close(a);
	}
	return result;
}

#format_nameObject

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"


1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
# File 'ext/archive.cpp', line 1071

VALUE Archive_format_name(VALUE self)
{
	struct archive *a = archive_read_new();
	struct archive_entry *entry;
	const char* name = NULL;
	
	if(Archive_read_ruby(self,a)==ARCHIVE_OK){
		if(archive_read_next_header(a, &entry)==ARCHIVE_OK){
			name = archive_format_name(a);
			archive_read_close(a);
		}
	}
	return name ? rb_str_new2(name) : Qnil;
}

#inspectString

Human-readable description.

Return value

String

Returns:

  • (String)


1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
# File 'ext/archive.cpp', line 1590

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 the entry 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, ""]}


829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
# File 'ext/archive.cpp', line 829

VALUE Archive_map_self(VALUE self)
{
	RETURN_ENUMERATOR(self,0,NULL);

	struct archive *a = archive_read_new(),*b=archive_write_new();
	int format = ARCHIVE_FORMAT_EMPTY;
	
	DataVector entries;
	IntVector filters;
	
	//autodetect format and filters
	if(Archive_read_ruby(self,a)==ARCHIVE_OK){
		
		RubyArchive::read_old_data(a,entries, format, filters);

		if(Archive_write_ruby(self,b,format,filters)==ARCHIVE_OK){
			write_obj obj;
			obj.archive = b;
			obj.data = &entries;
			RB_ENSURE(Archive_map_block,&obj,Archive_write_block_ensure,b);
		}	
	}	
	return self;
}

#mtimeObject

:nodoc:

call-seq:
archive.mtime -> Time

call the File.mtime(path)


1539
1540
1541
1542
# File 'ext/archive.cpp', line 1539

VALUE Archive_mtime(VALUE self)
{
	return rb_funcall(rb_cFile,rb_intern("mtime"),1,Archive_path(self));
}

#pathObject

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


591
592
593
594
# File 'ext/archive.cpp', line 591

VALUE Archive_path(VALUE self)
{
	return (_self->type == archive_path) ? rb_str_new2(_self->path.c_str()) : Qnil;
}

#statObject

:nodoc:

call-seq:
archive.stat -> File::Stat

call the File.stat(path)


1576
1577
1578
1579
# File 'ext/archive.cpp', line 1576

VALUE Archive_stat(VALUE self)
{
	return rb_funcall(rb_cFile,rb_intern("stat"),1,Archive_path(self));
}

#to_hashObject

Iterates through the archive and yields each data of an entry as a string object.

Return value

returns Hash of Archive::Entry => String



756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
# File 'ext/archive.cpp', line 756

VALUE Archive_to_hash(VALUE self)
{
	VALUE result = rb_hash_new();
	struct archive *a = archive_read_new();
	struct archive_entry *entry;
	
	if(Archive_read_ruby(self,a)==ARCHIVE_OK){
		while (archive_read_next_header(a, &entry) == ARCHIVE_OK) {
			std::string str;
			RubyArchive::read_data(a,str);
			rb_hash_aset(result,wrap(entry),wrap_data(str));
		}
		archive_read_close(a);
	}
	return result;
}

:nodoc:

call-seq:
archive.unlink -> self

call the File.unlink(path)


1526
1527
1528
1529
1530
# File 'ext/archive.cpp', line 1526

VALUE Archive_unlink(VALUE self)
{
	return rb_funcall(rb_cFile,rb_intern("unlink"),1,Archive_path(self));
	return self;
}