ObjFW  Diff

Differences From Artifact [e22a0061ae]:

To Artifact [4eb33d5a79]:


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







-
+












-
+







#import "OFStream.h"
#import "OFString.h"

#import "OFOutOfRangeException.h"

static OFString *
stringFromBuffer(const unsigned char *buffer, size_t length,
    of_string_encoding_t encoding)
    OFStringEncoding encoding)
{
	for (size_t i = 0; i < length; i++)
		if (buffer[i] == '\0')
			length = i;

	return [OFString stringWithCString: (const char *)buffer
				  encoding: encoding
				    length: length];
}

static void
stringToBuffer(unsigned char *buffer, OFString *string, size_t length,
    of_string_encoding_t encoding)
    OFStringEncoding encoding)
{
	size_t cStringLength = [string cStringLengthWithEncoding: encoding];

	if (cStringLength > length)
		@throw [OFOutOfRangeException exception];

	memcpy(buffer, [string cStringWithEncoding: encoding], cStringLength);
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
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







-
+



















-
+


















-
+








-
+







		return 0;

	if (buffer[0] == 0x80) {
		for (size_t i = 1; i < length; i++)
			value = (value << 8) | buffer[i];
	} else
		value = [stringFromBuffer(buffer, length,
		    OF_STRING_ENCODING_ASCII) unsignedLongLongValueWithBase: 8];
		    OFStringEncodingASCII) unsignedLongLongValueWithBase: 8];

	if (value > max)
		@throw [OFOutOfRangeException exception];

	return value;
}

@implementation OFTarArchiveEntry
+ (instancetype)entryWithFileName: (OFString *)fileName
{
	return [[[self alloc] initWithFileName: fileName] autorelease];
}

- (instancetype)init
{
	OF_INVALID_INIT_METHOD
}

- (instancetype)of_initWithHeader: (unsigned char [512])header
			 encoding: (of_string_encoding_t)encoding
			 encoding: (OFStringEncoding)encoding
{
	self = [super init];

	@try {
		void *pool = objc_autoreleasePoolPush();
		OFString *targetFileName;

		_fileName = [stringFromBuffer(header, 100, encoding) copy];
		_mode = (unsigned long)octalValueFromBuffer(
		    header + 100, 8, ULONG_MAX);
		_UID = (unsigned long)octalValueFromBuffer(
		    header + 108, 8, ULONG_MAX);
		_GID = (unsigned long)octalValueFromBuffer(
		    header + 116, 8, ULONG_MAX);
		_size = (unsigned long long)octalValueFromBuffer(
		    header + 124, 12, ULLONG_MAX);
		_modificationDate = [[OFDate alloc]
		    initWithTimeIntervalSince1970:
		    (of_time_interval_t)octalValueFromBuffer(
		    (OFTimeInterval)octalValueFromBuffer(
		    header + 136, 12, ULLONG_MAX)];
		_type = header[156];

		targetFileName = stringFromBuffer(header + 157, 100, encoding);
		if (targetFileName.length > 0)
			_targetFileName = [targetFileName copy];

		if (_type == '\0')
			_type = OF_TAR_ARCHIVE_ENTRY_TYPE_FILE;
			_type = OFTarArchiveEntryTypeFile;

		if (memcmp(header + 257, "ustar\0" "00", 8) == 0) {
			OFString *prefix;

			_owner = [stringFromBuffer(header + 265, 32, encoding)
			    copy];
			_group = [stringFromBuffer(header + 297, 32, encoding)
149
150
151
152
153
154
155
156

157
158
159
160
161
162
163
149
150
151
152
153
154
155

156
157
158
159
160
161
162
163







-
+








- (instancetype)initWithFileName: (OFString *)fileName
{
	self = [super init];

	@try {
		_fileName = [fileName copy];
		_type = OF_TAR_ARCHIVE_ENTRY_TYPE_FILE;
		_type = OFTarArchiveEntryTypeFile;
		_mode = 0644;
	} @catch (id e) {
		[self release];
		@throw e;
	}

	return self;
228
229
230
231
232
233
234
235

236
237
238
239
240
241
242
228
229
230
231
232
233
234

235
236
237
238
239
240
241
242







-
+







}

- (OFDate *)modificationDate
{
	return _modificationDate;
}

- (of_tar_archive_entry_type_t)type
- (OFTarArchiveEntryType)type
{
	return _type;
}

- (OFString *)targetFileName
{
	return _targetFileName;
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
324
325
326
327
328
329
330
331
332

333
334
335

336
337
338
339
340
341
342
343

344
345

346
347
348
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
324
325
326
327
328
329
330
331

332
333
334

335
336
337
338
339
340
341
342

343
344

345

346
347







-
+








-
+


-
+


-
+


-
+



-
+
















-
+


-
+







-
+

-
+
-



	objc_autoreleasePoolPop(pool);

	return [ret autorelease];
}

- (void)of_writeToStream: (OFStream *)stream
		encoding: (of_string_encoding_t)encoding
		encoding: (OFStringEncoding)encoding
{
	unsigned char buffer[512];
	unsigned long long modificationDate;
	uint16_t checksum = 0;

	stringToBuffer(buffer, _fileName, 100, encoding);
	stringToBuffer(buffer + 100,
	    [OFString stringWithFormat: @"%06" PRIo16 " ", _mode], 8,
	    OF_STRING_ENCODING_ASCII);
	    OFStringEncodingASCII);
	stringToBuffer(buffer + 108,
	    [OFString stringWithFormat: @"%06" PRIo16 " ", _UID], 8,
	    OF_STRING_ENCODING_ASCII);
	    OFStringEncodingASCII);
	stringToBuffer(buffer + 116,
	    [OFString stringWithFormat: @"%06" PRIo16 " ", _GID], 8,
	    OF_STRING_ENCODING_ASCII);
	    OFStringEncodingASCII);
	stringToBuffer(buffer + 124,
	    [OFString stringWithFormat: @"%011" PRIo64 " ", _size], 12,
	    OF_STRING_ENCODING_ASCII);
	    OFStringEncodingASCII);
	modificationDate = _modificationDate.timeIntervalSince1970;
	stringToBuffer(buffer + 136,
	    [OFString stringWithFormat: @"%011llo", modificationDate],
	    12, OF_STRING_ENCODING_ASCII);
	    12, OFStringEncodingASCII);

	/*
	 * During checksumming, the checksum field is expected to be set to 8
	 * spaces.
	 */
	memset(buffer + 148, ' ', 8);

	buffer[156] = _type;
	stringToBuffer(buffer + 157, _targetFileName, 100, encoding);

	/* ustar */
	memcpy(buffer + 257, "ustar\0" "00", 8);
	stringToBuffer(buffer + 265, _owner, 32, encoding);
	stringToBuffer(buffer + 297, _group, 32, encoding);
	stringToBuffer(buffer + 329,
	    [OFString stringWithFormat: @"%06" PRIo32 " ", _deviceMajor], 8,
	    OF_STRING_ENCODING_ASCII);
	    OFStringEncodingASCII);
	stringToBuffer(buffer + 337,
	    [OFString stringWithFormat: @"%06" PRIo32 " ", _deviceMinor], 8,
	    OF_STRING_ENCODING_ASCII);
	    OFStringEncodingASCII);
	memset(buffer + 345, '\0', 155 + 12);

	/* Fill in the checksum */
	for (size_t i = 0; i < 500; i++)
		checksum += buffer[i];
	stringToBuffer(buffer + 148,
	    [OFString stringWithFormat: @"%06" PRIo16, checksum], 7,
	    OF_STRING_ENCODING_ASCII);
	    OFStringEncodingASCII);

	[stream writeBuffer: buffer
	[stream writeBuffer: buffer length: sizeof(buffer)];
		     length: sizeof(buffer)];
}
@end