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
|
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
- (void)extractAllFilesFromArchive: (OFZIPArchive*)archive;
fromArchive: (OFZIPArchive*)archive;
@end
OF_APPLICATION_DELEGATE(OFZIP)
static void
help(OFStream *stream, int status)
{
[stream writeFormat: @"Usage: %@ -x archive1.zip [archive2.zip ...]\n",
[stream writeFormat: @"Usage: %@ -x archive1.zip [file1 file2 ...]\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;
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 = EXTRACT;
mode = option;
break;
case 'h':
help(of_stdout, 0);
break;
case '?':
default:
[of_stderr writeFormat: @"%@: Unknown option: -%c\n",
[OFApplication programName],
[optionsParser lastOption]];
[OFApplication terminateWithStatus: 1];
break;
}
}
remainingArguments = [optionsParser remainingArguments];
switch (mode) {
case EXTRACT:
enumerator =
[[optionsParser remainingArguments] objectEnumerator];
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:
while ((file = [enumerator nextObject]) != nil) {
[remainingArguments firstObject]];
void *pool = objc_autoreleasePoolPush();
[self extractAllFilesFromArchive:
[OFZIPArchive archiveWithPath: file]];
[self extractFiles: files
fromArchive: archive];
objc_autoreleasePoolPop(pool);
objc_autoreleasePoolPop(pool);
}
break;
default:
help(of_stderr, 1);
break;
}
[OFApplication terminate];
}
- (void)extractFiles: (OFArray*)files
- (void)extractAllFilesFromArchive: (OFZIPArchive*)archive
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
|
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
|