ObjFW  Check-in [0964e7d687]

Overview
Comment:Add objfw-unzip.

This a small tool to extract ZIP files, using OFZIPArchive.

The idea is that as ObjFW contains a complete ZIP implementation anyway,
it makes sense to add those few extra lines of code to have a very small
tool using ObjFW's ZIP implementation.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 0964e7d6871113e481178885d35b55b62d1256dd3952662913ef1d7ab3143f6d
User & Date: js on 2013-10-20 11:30:22
Other Links: manifest | tags
Context
2013-10-28
15:18
Update Xcode project to 5.0. check-in: ed3a954968 user: js tags: trunk
2013-10-20
11:30
Add objfw-unzip. check-in: 0964e7d687 user: js tags: trunk
2013-10-10
22:18
OFZIPArchive: Correctly handle archive comments. check-in: e2ad3ceacb user: js tags: trunk
Changes

Modified .gitignore from [3a8df09a67] to [130da53fc2].

32
33
34
35
36
37
38

src/ObjFW
tests/tests
tests/tests.exe
tests/EBOOT.PBP
tests/PARAM.SFO
tests/objc_sync/objc_sync
utils/objfw-config








>
32
33
34
35
36
37
38
39
src/ObjFW
tests/tests
tests/tests.exe
tests/EBOOT.PBP
tests/PARAM.SFO
tests/objc_sync/objc_sync
utils/objfw-config
utils/objfw-unzip

Modified utils/Makefile from [dcb4102d42] to [1a6aa46eb0].



1
2
3
4
5
6
7
8
9


include ../buildsys.mk
include ../extra.mk

DISTCLEAN = objfw-config

install-extra: objfw-config objfw-compile
	for i in objfw-config objfw-compile; do \
		${INSTALL_STATUS}; \
		if ${MKDIR_P} ${DESTDIR}${bindir} && ${INSTALL} -m 755 $$i ${DESTDIR}${bindir}/${BIN_PREFIX}$$i; then \
>
>
|
|







1
2
3
4
5
6
7
8
9
10
11
PROG = objfw-unzip
SRCS = objfw-unzip.m

include ../buildsys.mk

DISTCLEAN = objfw-config

install-extra: objfw-config objfw-compile
	for i in objfw-config objfw-compile; do \
		${INSTALL_STATUS}; \
		if ${MKDIR_P} ${DESTDIR}${bindir} && ${INSTALL} -m 755 $$i ${DESTDIR}${bindir}/${BIN_PREFIX}$$i; then \
19
20
21
22
23
24
25




			if rm -f ${DESTDIR}${bindir}/${BIN_PREFIX}$$i; then \
				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi \
	done











>
>
>
>
21
22
23
24
25
26
27
28
29
30
31
			if rm -f ${DESTDIR}${bindir}/${BIN_PREFIX}$$i; then \
				${DELETE_OK}; \
			else \
				${DELETE_FAILED}; \
			fi \
		fi \
	done

CPPFLAGS += -I../src -I../src/runtime -I..
LIBS := -L../src -lobjfw ${LIBS}
LD = ${OBJC}

Added utils/objfw-unzip.m version [b923b772b8].





























































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#import "OFApplication.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFFile.h"
#import "OFStdIOStream.h"
#import "OFZIPArchive.h"
#import "OFZIPArchiveEntry.h"

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

#define BUFFER_SIZE 4096

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

OF_APPLICATION_DELEGATE(UnZIP)

@implementation UnZIP
- (void)applicationDidFinishLaunching
{
	OFEnumerator *enumerator = [[OFApplication arguments] objectEnumerator];
	OFString *file;

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

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

		objc_autoreleasePoolPop(pool);
	}

	[OFApplication terminate];
}

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

	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
			[of_stdout writeFormat: @"Refusing to extract %@!\n",
						fileName];
			[OFApplication terminateWithStatus: 1];
		}

		componentEnumerator =
		    [[outFileName pathComponents] objectEnumerator];
		while ((component = [componentEnumerator nextObject]) != nil) {
			if ([component isEqual: OF_PATH_PARENT_DIRECTORY]) {
				[of_stdout writeFormat:
				    @"Refusing to extract %@!\n", fileName];
				[OFApplication terminateWithStatus: 1];
			}
		}

		[of_stdout writeFormat: @"Extracting %@...", fileName];

		if ([fileName hasSuffix: @"/"]) {
			[OFFile createDirectoryAtPath: outFileName
					createParents: true];
			[of_stdout writeLine: @" done"];
			continue;
		}

		directory = [outFileName stringByDeletingLastPathComponent];
		if (![OFFile directoryExistsAtPath: directory])
			[OFFile createDirectoryAtPath: directory
					createParents: true];

		if ([OFFile fileExistsAtPath: outFileName] && !override) {
			OFString *line;

			do {
				[of_stderr writeFormat:
				    @"\rOverride %@? [ynA] ", fileName];

				line = [of_stdin readLine];
			} while (![line isEqual: @"y"] &&
			    ![line isEqual: @"n"] && ![line isEqual: @"A"]);

			if ([line isEqual: @"n"]) {
				[of_stdout writeFormat: @"Skipping %@...\n",
							fileName];
				continue;
			}

			if ([line isEqual: @"A"])
				override = true;

			[of_stdout writeFormat: @"Extracting %@...", fileName];
		}

		stream = [archive streamForReadingFile: fileName];
		output = [OFFile fileWithPath: outFileName
					 mode: @"w"];

		while (![stream isAtEndOfStream]) {
			size_t length = [stream readIntoBuffer: buffer
							length: BUFFER_SIZE];
			[output writeBuffer: buffer
				     length: length];

			written += length;
			newPercent = (written == size
			    ? 100 : written * 100 / size);

			if (percent != newPercent) {
				percent = newPercent;

				[of_stdout writeFormat:
				    @"\rExtracting %@... %3u%%",
				    fileName, percent];
			}
		}

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

		objc_autoreleasePoolPop(pool);
	}
}
@end