ObjFW  Check-in [14b9a27b65]

Overview
Comment:ofzip: Add support for specifying the encoding
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 14b9a27b65df91d87eb47d6cce3397ccfaaddd2e681dc9e83bac3936286b3dd1
User & Date: js on 2018-05-26 08:47:51
Other Links: manifest | tags
Context
2018-05-26
09:03
.travis.yml: Test building without Amiga library check-in: e17f5ee09c user: js tags: trunk
08:47
ofzip: Add support for specifying the encoding check-in: 14b9a27b65 user: js tags: trunk
07:56
OFTarArchive: Allow specifying the encoding check-in: 9db1965939 user: js tags: trunk
Changes

Modified utils/ofzip/Archive.h from [4b94fd1dc8] to [f666c71e45].

17
18
19
20
21
22
23
24

25
26

27
28
29
30
31
32

#import "OFObject.h"
#import "OFFile.h"
#import "OFArray.h"

@protocol Archive <OFObject>
+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream
			     mode: (OFString *)mode;

- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream
			  mode: (OFString *)mode;

- (void)listFiles;
- (void)extractFiles: (OFArray OF_GENERIC(OFString *) *)files;
- (void)printFiles: (OFArray OF_GENERIC(OFString *) *)files;
@optional
- (void)addFiles: (OFArray OF_GENERIC(OFString *) *)files;
@end







|
>

|
>






17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

#import "OFObject.h"
#import "OFFile.h"
#import "OFArray.h"

@protocol Archive <OFObject>
+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream
			     mode: (OFString *)mode
			 encoding: (of_string_encoding_t)encoding;
- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream
			  mode: (OFString *)mode
		      encoding: (of_string_encoding_t)encoding;
- (void)listFiles;
- (void)extractFiles: (OFArray OF_GENERIC(OFString *) *)files;
- (void)printFiles: (OFArray OF_GENERIC(OFString *) *)files;
@optional
- (void)addFiles: (OFArray OF_GENERIC(OFString *) *)files;
@end

Modified utils/ofzip/GZIPArchive.m from [75b73d1fa8] to [e95550219d].

49
50
51
52
53
54
55

56
57
58

59
60
61
62

63
64
65
66
67
68
69
{
	if (self == [GZIPArchive class])
		app = (OFZIP *)[[OFApplication sharedApplication] delegate];
}

+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream
			     mode: (OFString *)mode

{
	return [[[self alloc] initWithStream: stream
					mode: mode] autorelease];

}

- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream
			  mode: (OFString *)mode

{
	self = [super init];

	@try {
		_stream = [[OFGZIPStream alloc] initWithStream: stream
							  mode: mode];
	} @catch (id e) {







>


|
>




>







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
{
	if (self == [GZIPArchive class])
		app = (OFZIP *)[[OFApplication sharedApplication] delegate];
}

+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream
			     mode: (OFString *)mode
			 encoding: (of_string_encoding_t)encoding
{
	return [[[self alloc] initWithStream: stream
					mode: mode
				    encoding: encoding] autorelease];
}

- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream
			  mode: (OFString *)mode
		      encoding: (of_string_encoding_t)encoding
{
	self = [super init];

	@try {
		_stream = [[OFGZIPStream alloc] initWithStream: stream
							  mode: mode];
	} @catch (id e) {

Modified utils/ofzip/OFZIP.h from [922682e77a] to [d234b94864].

36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51
52
	int8_t _outputLevel;
	OFString *_archivePath;
	int _exitStatus;
}

- (id <Archive>)openArchiveWithPath: (OFString *)path
			       type: (OFString *)type
			       mode: (char)mode;

- (bool)shouldExtractFile: (OFString *)fileName
	      outFileName: (OFString *)outFileName;
- (ssize_t)copyBlockFromStream: (OFStream *)input
		      toStream: (OFStream *)output
		      fileName: (OFString *)fileName;
- (nullable OFString *)safeLocalPathForPath: (OFString *)path;
@end

OF_ASSUME_NONNULL_END







|
>









36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
	int8_t _outputLevel;
	OFString *_archivePath;
	int _exitStatus;
}

- (id <Archive>)openArchiveWithPath: (OFString *)path
			       type: (OFString *)type
			       mode: (char)mode
			   encoding: (of_string_encoding_t)encoding;
- (bool)shouldExtractFile: (OFString *)fileName
	      outFileName: (OFString *)outFileName;
- (ssize_t)copyBlockFromStream: (OFStream *)input
		      toStream: (OFStream *)output
		      fileName: (OFString *)fileName;
- (nullable OFString *)safeLocalPathForPath: (OFString *)path;
@end

OF_ASSUME_NONNULL_END

Modified utils/ofzip/OFZIP.m from [3932bfb77d] to [ea3185f976].

32
33
34
35
36
37
38

39
40
41
42
43
44
45
#import "OFZIP.h"
#import "GZIPArchive.h"
#import "TarArchive.h"
#import "ZIPArchive.h"

#import "OFCreateDirectoryFailedException.h"
#import "OFInvalidArgumentException.h"

#import "OFInvalidFormatException.h"
#import "OFNotImplementedException.h"
#import "OFOpenItemFailedException.h"
#import "OFReadFailedException.h"
#import "OFSeekFailedException.h"
#import "OFWriteFailedException.h"








>







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#import "OFZIP.h"
#import "GZIPArchive.h"
#import "TarArchive.h"
#import "ZIPArchive.h"

#import "OFCreateDirectoryFailedException.h"
#import "OFInvalidArgumentException.h"
#import "OFInvalidEncodingException.h"
#import "OFInvalidFormatException.h"
#import "OFNotImplementedException.h"
#import "OFOpenItemFailedException.h"
#import "OFReadFailedException.h"
#import "OFSeekFailedException.h"
#import "OFWriteFailedException.h"

58
59
60
61
62
63
64


65
66
67
68
69
70
71
		[stream writeString: @"\n"];
		[stream writeLine: OF_LOCALIZED(@"full_usage",
		    @"Options:\n"
		    @"    -a  --append      Append to archive\n"
		    @"    -c  --create      Create archive\n"
		    @"    -C  --directory   Extract into the specified "
		    @"directory\n"


		    @"    -f  --force       Force / overwrite files\n"
		    @"    -h  --help        Show this help\n"
		    @"    -l  --list        List all files in the archive\n"
		    @"    -n  --no-clobber  Never overwrite files\n"
		    @"    -p  --print       Print one or more files from the "
		    @"archive\n"
		    @"    -q  --quiet       Quiet mode (no output, except "







>
>







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
		[stream writeString: @"\n"];
		[stream writeLine: OF_LOCALIZED(@"full_usage",
		    @"Options:\n"
		    @"    -a  --append      Append to archive\n"
		    @"    -c  --create      Create archive\n"
		    @"    -C  --directory   Extract into the specified "
		    @"directory\n"
		    @"    -E  --encoding    The encoding used by the archive "
		    "(only tar files)\n"
		    @"    -f  --force       Force / overwrite files\n"
		    @"    -h  --help        Show this help\n"
		    @"    -l  --list        List all files in the archive\n"
		    @"    -n  --no-clobber  Never overwrite files\n"
		    @"    -p  --print       Print one or more files from the "
		    @"archive\n"
		    @"    -q  --quiet       Quiet mode (no output, except "
142
143
144
145
146
147
148
149
150
151
152
153

154
155
156
157
158
159
160
161
162
163
164
165
166

167
168
169
170
171
172
173
	    @"Writing archives of type %[type] is not (yet) supported!",
	    @"type", type)];
}

@implementation OFZIP
- (void)applicationDidFinishLaunching
{
	OFString *outputDir = nil, *type = nil;
	const of_options_parser_option_t options[] = {
		{ 'a', @"append", 0, NULL, NULL },
		{ 'c', @"create", 0, NULL, NULL },
		{ 'C', @"directory", 1, NULL, &outputDir },

		{ 'f', @"force", 0, NULL, NULL },
		{ 'h', @"help", 0, NULL, NULL },
		{ 'l', @"list", 0, NULL, NULL },
		{ 'n', @"no-clobber", 0, NULL, NULL },
		{ 'p', @"print", 0, NULL, NULL },
		{ 'q', @"quiet", 0, NULL, NULL },
		{ 't', @"type", 1, NULL, &type },
		{ 'v', @"verbose", 0, NULL, NULL },
		{ 'x', @"extract", 0, NULL, NULL },
		{ '\0', nil, 0, NULL, NULL }
	};
	OFOptionsParser *optionsParser;
	of_unichar_t option, mode = '\0';

	OFArray OF_GENERIC(OFString *) *remainingArguments, *files;
	id <Archive> archive;

#ifdef OF_HAVE_SANDBOX
	OFSandbox *sandbox = [[OFSandbox alloc] init];
	@try {
		[sandbox setAllowsStdIO: true];







|




>













>







145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
	    @"Writing archives of type %[type] is not (yet) supported!",
	    @"type", type)];
}

@implementation OFZIP
- (void)applicationDidFinishLaunching
{
	OFString *outputDir = nil, *encodingString = nil, *type = nil;
	const of_options_parser_option_t options[] = {
		{ 'a', @"append", 0, NULL, NULL },
		{ 'c', @"create", 0, NULL, NULL },
		{ 'C', @"directory", 1, NULL, &outputDir },
		{ 'E', @"encoding", 1, NULL, &encodingString },
		{ 'f', @"force", 0, NULL, NULL },
		{ 'h', @"help", 0, NULL, NULL },
		{ 'l', @"list", 0, NULL, NULL },
		{ 'n', @"no-clobber", 0, NULL, NULL },
		{ 'p', @"print", 0, NULL, NULL },
		{ 'q', @"quiet", 0, NULL, NULL },
		{ 't', @"type", 1, NULL, &type },
		{ 'v', @"verbose", 0, NULL, NULL },
		{ 'x', @"extract", 0, NULL, NULL },
		{ '\0', nil, 0, NULL, NULL }
	};
	OFOptionsParser *optionsParser;
	of_unichar_t option, mode = '\0';
	of_string_encoding_t encoding = OF_STRING_ENCODING_UTF_8;
	OFArray OF_GENERIC(OFString *) *remainingArguments, *files;
	id <Archive> archive;

#ifdef OF_HAVE_SANDBOX
	OFSandbox *sandbox = [[OFSandbox alloc] init];
	@try {
		[sandbox setAllowsStdIO: true];
243
244
245
246
247
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
			    @"option_takes_no_argument",
			    @"%[prog]: Option --%[opt] takes no argument",
			    @"prog", [OFApplication programName],
			    @"opt", [optionsParser lastLongOption])];

			[OFApplication terminateWithStatus: 1];
			break;






















		case '?':
			if ([optionsParser lastLongOption] != nil)
				[of_stderr writeLine: OF_LOCALIZED(
				    @"unknown_long_option",
				    @"%[prog]: Unknown option: --%[opt]",
				    @"prog", [OFApplication programName],
				    @"opt", [optionsParser lastLongOption])];
			else {
				OFString *optStr = [OFString
				    stringWithFormat: @"%c",
				    [optionsParser lastOption]];
				[of_stderr writeLine: OF_LOCALIZED(
				    @"unknown_option",
				    @"%[prog]: Unknown option: -%[opt]",
				    @"prog", [OFApplication programName],
				    @"opt", optStr)];
			}

			[OFApplication terminateWithStatus: 1];
		}
	}














	remainingArguments = [optionsParser remainingArguments];
	archive = [self openArchiveWithPath: [remainingArguments firstObject]
				       type: type
				       mode: mode];


	if (outputDir != nil)
		[[OFFileManager defaultManager]
		    changeCurrentDirectoryPath: outputDir];

	switch (mode) {
	case 'a':







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









|











>
>
>
>
>
>
>
>
>
>
>
>
>




|
>







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
			    @"option_takes_no_argument",
			    @"%[prog]: Option --%[opt] takes no argument",
			    @"prog", [OFApplication programName],
			    @"opt", [optionsParser lastLongOption])];

			[OFApplication terminateWithStatus: 1];
			break;
		case ':':
			if ([optionsParser lastLongOption] != nil)
				[of_stderr writeLine: OF_LOCALIZED(
				    @"long_option_requires_argument",
				    @"%[prog]: Option --%[opt] requires an "
				    @"argument",
				    @"prog", [OFApplication programName],
				    @"opt", [optionsParser lastLongOption])];
			else {
				OFString *optStr = [OFString
				    stringWithFormat: @"%C",
				    [optionsParser lastOption]];
				[of_stderr writeLine: OF_LOCALIZED(
				    @"option_requires_argument",
				    @"%[prog]: Option -%[opt] requires an "
				    @"argument",
				    @"prog", [OFApplication programName],
				    @"opt", optStr)];
			}

			[OFApplication terminateWithStatus: 1];
			break;
		case '?':
			if ([optionsParser lastLongOption] != nil)
				[of_stderr writeLine: OF_LOCALIZED(
				    @"unknown_long_option",
				    @"%[prog]: Unknown option: --%[opt]",
				    @"prog", [OFApplication programName],
				    @"opt", [optionsParser lastLongOption])];
			else {
				OFString *optStr = [OFString
				    stringWithFormat: @"%C",
				    [optionsParser lastOption]];
				[of_stderr writeLine: OF_LOCALIZED(
				    @"unknown_option",
				    @"%[prog]: Unknown option: -%[opt]",
				    @"prog", [OFApplication programName],
				    @"opt", optStr)];
			}

			[OFApplication terminateWithStatus: 1];
		}
	}

	@try {
		if (encodingString != nil)
			encoding = of_string_parse_encoding(encodingString);
	} @catch (OFInvalidEncodingException *e) {
		[of_stderr writeLine: OF_LOCALIZED(
		    @"invalid_encoding",
		    @"%[prog]: Invalid encoding: %[encoding]",
		    @"prog", [OFApplication programName],
		    @"encoding", encodingString)];

		[OFApplication terminateWithStatus: 1];
	}

	remainingArguments = [optionsParser remainingArguments];
	archive = [self openArchiveWithPath: [remainingArguments firstObject]
				       type: type
				       mode: mode
				   encoding: encoding];

	if (outputDir != nil)
		[[OFFileManager defaultManager]
		    changeCurrentDirectoryPath: outputDir];

	switch (mode) {
	case 'a':
345
346
347
348
349
350
351

352
353
354
355
356
357
358

	[OFApplication terminateWithStatus: _exitStatus];
}

- (id <Archive>)openArchiveWithPath: (OFString *)path
			       type: (OFString *)type
			       mode: (char)mode

{
	OFString *modeString, *fileModeString;
	OFFile *file = nil;
	id <Archive> archive = nil;

	[_archivePath release];
	_archivePath = [path copy];







>







386
387
388
389
390
391
392
393
394
395
396
397
398
399
400

	[OFApplication terminateWithStatus: _exitStatus];
}

- (id <Archive>)openArchiveWithPath: (OFString *)path
			       type: (OFString *)type
			       mode: (char)mode
			   encoding: (of_string_encoding_t)encoding
{
	OFString *modeString, *fileModeString;
	OFFile *file = nil;
	id <Archive> archive = nil;

	[_archivePath release];
	_archivePath = [path copy];
405
406
407
408
409
410
411
412

413
414
415

416
417
418
419
420
421

422
423
424

425
426
427
428
429
430
431
		else
			type = @"zip";
	}

	@try {
		if ([type isEqual: @"gz"])
			archive = [GZIPArchive archiveWithStream: file
							    mode: modeString];

		else if ([type isEqual: @"tar"])
			archive = [TarArchive archiveWithStream: file
							   mode: modeString];

		else if ([type isEqual: @"tgz"]) {
			OFStream *GZIPStream = [OFGZIPStream
			    streamWithStream: file
					mode: modeString];
			archive = [TarArchive archiveWithStream: GZIPStream
							   mode: modeString];

		} else if ([type isEqual: @"zip"])
			archive = [ZIPArchive archiveWithStream: file
							   mode: modeString];

		else {
			[of_stderr writeLine: OF_LOCALIZED(
			    @"unknown_archive_type",
			    @"Unknown archive type: %[type]",
			    @"type", type)];
			goto error;
		}







|
>


|
>





|
>


|
>







447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
		else
			type = @"zip";
	}

	@try {
		if ([type isEqual: @"gz"])
			archive = [GZIPArchive archiveWithStream: file
							    mode: modeString
							encoding: encoding];
		else if ([type isEqual: @"tar"])
			archive = [TarArchive archiveWithStream: file
							   mode: modeString
						       encoding: encoding];
		else if ([type isEqual: @"tgz"]) {
			OFStream *GZIPStream = [OFGZIPStream
			    streamWithStream: file
					mode: modeString];
			archive = [TarArchive archiveWithStream: GZIPStream
							   mode: modeString
						       encoding: encoding];
		} else if ([type isEqual: @"zip"])
			archive = [ZIPArchive archiveWithStream: file
							   mode: modeString
						       encoding: encoding];
		else {
			[of_stderr writeLine: OF_LOCALIZED(
			    @"unknown_archive_type",
			    @"Unknown archive type: %[type]",
			    @"type", type)];
			goto error;
		}

Modified utils/ofzip/TarArchive.m from [154c675e84] to [ce3e6885bb].

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
{
	if (self == [TarArchive class])
		app = (OFZIP *)[[OFApplication sharedApplication] delegate];
}

+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream
			     mode: (OFString *)mode

{
	return [[[self alloc] initWithStream: stream
					mode: mode] autorelease];

}

- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream
			  mode: (OFString *)mode

{
	self = [super init];

	@try {
		_archive = [[OFTarArchive alloc] initWithStream: stream
							   mode: mode];


	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}







>


|
>




>






>
>







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
{
	if (self == [TarArchive class])
		app = (OFZIP *)[[OFApplication sharedApplication] delegate];
}

+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream
			     mode: (OFString *)mode
			 encoding: (of_string_encoding_t)encoding
{
	return [[[self alloc] initWithStream: stream
					mode: mode
				    encoding: encoding] autorelease];
}

- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream
			  mode: (OFString *)mode
		      encoding: (of_string_encoding_t)encoding
{
	self = [super init];

	@try {
		_archive = [[OFTarArchive alloc] initWithStream: stream
							   mode: mode];

		[_archive setEncoding: encoding];
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
}

Modified utils/ofzip/ZIPArchive.m from [5378cae3d0] to [d55c8d68ef].

61
62
63
64
65
66
67

68
69
70

71
72
73
74

75
76
77
78
79
80
81
{
	if (self == [ZIPArchive class])
		app = (OFZIP *)[[OFApplication sharedApplication] delegate];
}

+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream
			     mode: (OFString *)mode

{
	return [[[self alloc] initWithStream: stream
					mode: mode] autorelease];

}

- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream
			  mode: (OFString *)mode

{
	self = [super init];

	@try {
		_archive = [[OFZIPArchive alloc] initWithStream: stream
							   mode: mode];
	} @catch (id e) {







>


|
>




>







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
{
	if (self == [ZIPArchive class])
		app = (OFZIP *)[[OFApplication sharedApplication] delegate];
}

+ (instancetype)archiveWithStream: (OF_KINDOF(OFStream *))stream
			     mode: (OFString *)mode
			 encoding: (of_string_encoding_t)encoding
{
	return [[[self alloc] initWithStream: stream
					mode: mode
				    encoding: encoding] autorelease];
}

- (instancetype)initWithStream: (OF_KINDOF(OFStream *))stream
			  mode: (OFString *)mode
		      encoding: (of_string_encoding_t)encoding
{
	self = [super init];

	@try {
		_archive = [[OFZIPArchive alloc] initWithStream: stream
							   mode: mode];
	} @catch (id e) {

Modified utils/ofzip/lang/de.json from [3f470431d3] to [8e600ce35e].

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
{
    "usage": [
        "Benutzung: %[prog] -[acCfhlnpqtvx] archiv.zip [datei1 datei2 ...]"
    ],
    "full_usage": [
        "Optionen:\n",
        "    -a  --append      Zu Archiv hinzufügen\n",
        "    -c  --create      Archiv erstellen\n",
        "    -C  --directory   In angegebenes Verzeichnis entpacken\n",

        "    -f  --force       Existierende Dateien überschreiben\n",
        "    -h  --help        Diese Hilfe anzeigen\n",
        "    -l  --list        Alle Dateien im Archiv auflisten\n",
        "    -n  --no-clobber  Dateien niemals überschreiben\n",
        "    -p  --print       Eine oder mehr Dateien aus dem Archiv ausgeben",
        "\n",
        "    -q  --quiet       Ruhiger Modus (keine Ausgabe außer Fehler)\n",









>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
    "usage": [
        "Benutzung: %[prog] -[acCfhlnpqtvx] archiv.zip [datei1 datei2 ...]"
    ],
    "full_usage": [
        "Optionen:\n",
        "    -a  --append      Zu Archiv hinzufügen\n",
        "    -c  --create      Archiv erstellen\n",
        "    -C  --directory   In angegebenes Verzeichnis entpacken\n",
        "    -E  --encoding    Das Encoding des Archivs (nur tar-Dateien)\n",
        "    -f  --force       Existierende Dateien überschreiben\n",
        "    -h  --help        Diese Hilfe anzeigen\n",
        "    -l  --list        Alle Dateien im Archiv auflisten\n",
        "    -n  --no-clobber  Dateien niemals überschreiben\n",
        "    -p  --print       Eine oder mehr Dateien aus dem Archiv ausgeben",
        "\n",
        "    -q  --quiet       Ruhiger Modus (keine Ausgabe außer Fehler)\n",
25
26
27
28
29
30
31




32
33

34
35
36
37
38
39
40
    "5_options_mutually_exclusive": [
        "Fehler: -%[shortopt1] / --%[longopt1], -%[shortopt2] / ",
        "--%[longopt2], -%[shortopt3] / --%[longopt3], ",
        "-%[shortopt4] / --%[longopt4] und\n",
        "        -%[shortopt5] / --%[longopt5] schließen sich gegenseitig aus!"
    ],
    "option_takes_no_argument": "%[prog]: Option --%[opt] nimmt kein Argument",




    "unknown_long_option": "%[prog]: Unbekannte Option: --%[opt]",
    "unknown_option": "%[prog]: Unbekannte Option: -%[opt]",

    "writing_not_supported": [
        "Schreiben von Dateien des Typs %[type] wird (noch) nicht unterstützt!"
    ],
    "failed_to_create_directory": [
        "Fehler beim Erstellen des Verzeichnis %[dir]: %[error]"
    ],
    "failed_to_open_file": "Fehler beim Öffnen der Datei %[file]: %[error]",







>
>
>
>


>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    "5_options_mutually_exclusive": [
        "Fehler: -%[shortopt1] / --%[longopt1], -%[shortopt2] / ",
        "--%[longopt2], -%[shortopt3] / --%[longopt3], ",
        "-%[shortopt4] / --%[longopt4] und\n",
        "        -%[shortopt5] / --%[longopt5] schließen sich gegenseitig aus!"
    ],
    "option_takes_no_argument": "%[prog]: Option --%[opt] nimmt kein Argument",
    "long_option_requires_argument": [
        "%[prog]: Option --%[opt] benötigt ein Argument"
    ],
    "option_requires_argument": "%[prog]: Option -%[opt] benötigt ein Argument",
    "unknown_long_option": "%[prog]: Unbekannte Option: --%[opt]",
    "unknown_option": "%[prog]: Unbekannte Option: -%[opt]",
    "invalid_encoding": "%[prog]: Invalid encoding: %[encoding]",
    "writing_not_supported": [
        "Schreiben von Dateien des Typs %[type] wird (noch) nicht unterstützt!"
    ],
    "failed_to_create_directory": [
        "Fehler beim Erstellen des Verzeichnis %[dir]: %[error]"
    ],
    "failed_to_open_file": "Fehler beim Öffnen der Datei %[file]: %[error]",