ObjFW  Check-in [2bd117c218]

Overview
Comment:OFZIP: Allow extracting single files.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 2bd117c2187d19e8d8f81f512fc6f2d0f305b94c57d5e9fc3302e97f89352be1
User & Date: js on 2013-11-18 14:09:37
Other Links: manifest | tags
Context
2013-11-18
14:10
OFZIP: Add missing copyright. check-in: 4504d34415 user: js tags: trunk
14:09
OFZIP: Allow extracting single files. check-in: 2bd117c218 user: js tags: trunk
2013-11-10
00:35
objfw-unzip -> ofzip check-in: ab0be1f3f9 user: js tags: trunk
Changes

Modified utils/OFZIP.m from [651abb43b6] to [36d354e8fb].

1
2
3
4
5

6
7
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40




41
42
43
44



45
46
47
48
49
50
51
52
53
54
55
56
57
58


59
60

61
62

63



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

81
82
83
84
85


86
87
88
89
90
91
92
93
94
95
96
97





98
99
100
101
102
103
104
#import "OFApplication.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFFile.h"
#import "OFOptionsParser.h"

#import "OFStdIOStream.h"
#import "OFZIPArchive.h"
#import "OFZIPArchiveEntry.h"

#import "autorelease.h"
#import "macros.h"

#define BUFFER_SIZE 4096

@interface OFZIP: OFObject

- (void)extractAllFilesFromArchive: (OFZIPArchive*)archive;
@end

OF_APPLICATION_DELEGATE(OFZIP)

static void
help(OFStream *stream, int status)
{
	[stream writeFormat: @"Usage: %@ -x archive1.zip [archive2.zip ...]\n",
			     [OFApplication programName]];
	[OFApplication terminateWithStatus: status];
}

@implementation OFZIP
- (void)applicationDidFinishLaunching
{
	OFOptionsParser *optionsParser =
	    [OFOptionsParser parserWithOptions: @"xh"];
	enum {
		NONE,
		EXTRACT
	} mode;
	OFEnumerator *enumerator;
	OFString *file;
	of_unichar_t option;





	while ((option = [optionsParser nextOption]) != '\0') {
		switch (option) {
		case 'x':



			mode = EXTRACT;
			break;
		case 'h':
			help(of_stdout, 0);
			break;
		case '?':
			[of_stderr writeFormat: @"%@: Unknown option: -%c\n",
						[OFApplication programName],
						[optionsParser lastOption]];
			[OFApplication terminateWithStatus: 1];
			break;
		}
	}



	switch (mode) {
	case EXTRACT:

		enumerator =
		    [[optionsParser remainingArguments] objectEnumerator];





		while ((file = [enumerator nextObject]) != nil) {
			void *pool = objc_autoreleasePoolPush();

			[self extractAllFilesFromArchive:
			   [OFZIPArchive archiveWithPath: file]];

			objc_autoreleasePoolPop(pool);
		}
		break;
	default:
		help(of_stderr, 1);
		break;
	}

	[OFApplication terminate];
}


- (void)extractAllFilesFromArchive: (OFZIPArchive*)archive
{
	OFEnumerator *enumerator = [[archive entries] objectEnumerator];
	OFZIPArchiveEntry *entry;
	int_fast8_t override = 0;



	while ((entry = [enumerator nextObject]) != nil) {
		void *pool = objc_autoreleasePoolPush();
		OFString *fileName = [entry fileName];
		OFString *outFileName = [fileName stringByStandardizingPath];
		OFEnumerator *componentEnumerator;
		OFString *component, *directory;
		OFStream *stream;
		OFFile *output;
		char buffer[BUFFER_SIZE];
		off_t written = 0, size = [entry uncompressedSize];
		int_fast8_t percent = -1, newPercent;






#ifndef _WIN32
		if ([outFileName hasPrefix: @"/"]) {
#else
		if ([outFileName hasPrefix: @"/"] ||
		    [outFileName containsString: @":"]) {
#endif





>










>
|







|









<
<
<
<
<
<
|
>
>
>
>




>
>
>
|




|




<



>
>

|
>
|
|
>

>
>
>
|
<

|
|

|
<









>
|




>
>












>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35






36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

74
75
76
77
78

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#import "OFApplication.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFFile.h"
#import "OFOptionsParser.h"
#import "OFSet.h"
#import "OFStdIOStream.h"
#import "OFZIPArchive.h"
#import "OFZIPArchiveEntry.h"

#import "autorelease.h"
#import "macros.h"

#define BUFFER_SIZE 4096

@interface OFZIP: OFObject
- (void)extractFiles: (OFArray*)files
	 fromArchive: (OFZIPArchive*)archive;
@end

OF_APPLICATION_DELEGATE(OFZIP)

static void
help(OFStream *stream, int status)
{
	[stream writeFormat: @"Usage: %@ -x archive1.zip [file1 file2 ...]\n",
			     [OFApplication programName]];
	[OFApplication terminateWithStatus: status];
}

@implementation OFZIP
- (void)applicationDidFinishLaunching
{
	OFOptionsParser *optionsParser =
	    [OFOptionsParser parserWithOptions: @"xh"];






	of_unichar_t option, mode = '\0';
	OFArray *remainingArguments;
	void *pool;
	OFZIPArchive *archive;
	OFArray *files;

	while ((option = [optionsParser nextOption]) != '\0') {
		switch (option) {
		case 'x':
			if (mode != '\0')
				help(of_stdout, 1);

			mode = option;
			break;
		case 'h':
			help(of_stdout, 0);
			break;
		default:
			[of_stderr writeFormat: @"%@: Unknown option: -%c\n",
						[OFApplication programName],
						[optionsParser lastOption]];
			[OFApplication terminateWithStatus: 1];

		}
	}

	remainingArguments = [optionsParser remainingArguments];

	switch (mode) {
	case 'x':
		pool = objc_autoreleasePoolPush();

		if ([remainingArguments count] < 1)
			help(of_stderr, 1);

		files = [remainingArguments objectsInRange:
		    of_range(1, [remainingArguments count] - 1)];
		archive = [OFZIPArchive archiveWithPath:
		    [remainingArguments firstObject]];


		[self extractFiles: files
		       fromArchive: archive];

		objc_autoreleasePoolPop(pool);

		break;
	default:
		help(of_stderr, 1);
		break;
	}

	[OFApplication terminate];
}

- (void)extractFiles: (OFArray*)files
	 fromArchive: (OFZIPArchive*)archive
{
	OFEnumerator *enumerator = [[archive entries] objectEnumerator];
	OFZIPArchiveEntry *entry;
	int_fast8_t override = 0;
	bool all = ([files count] == 0);
	OFMutableSet *missing = [OFMutableSet setWithArray: files];

	while ((entry = [enumerator nextObject]) != nil) {
		void *pool = objc_autoreleasePoolPush();
		OFString *fileName = [entry fileName];
		OFString *outFileName = [fileName stringByStandardizingPath];
		OFEnumerator *componentEnumerator;
		OFString *component, *directory;
		OFStream *stream;
		OFFile *output;
		char buffer[BUFFER_SIZE];
		off_t written = 0, size = [entry uncompressedSize];
		int_fast8_t percent = -1, newPercent;

		if (!all && ![files containsObject: fileName])
			continue;

		[missing removeObject: fileName];

#ifndef _WIN32
		if ([outFileName hasPrefix: @"/"]) {
#else
		if ([outFileName hasPrefix: @"/"] ||
		    [outFileName containsString: @":"]) {
#endif
185
186
187
188
189
190
191
192











193
			}
		}

		[of_stdout writeFormat: @"\rExtracting %@... done\n", fileName];

		objc_autoreleasePoolPop(pool);
	}
}











@end







|
>
>
>
>
>
>
>
>
>
>
>

200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
			}
		}

		[of_stdout writeFormat: @"\rExtracting %@... done\n", fileName];

		objc_autoreleasePoolPop(pool);
	}

	if ([missing count] > 0) {
		OFString *file;

		enumerator = [missing objectEnumerator];
		while ((file = [enumerator nextObject]) != nil)
			[of_stderr writeFormat:
			    @"File %@ is not in the archive!\n", file];

		[OFApplication terminateWithStatus: 1];
	}
}
@end