@@ -16,10 +16,11 @@ #include "config.h" #import "OFTarArchiveEntry.h" #import "OFTarArchiveEntry+Private.h" #import "OFDate.h" +#import "OFNumber.h" #import "OFStream.h" #import "OFString.h" #import "OFOutOfRangeException.h" @@ -72,19 +73,36 @@ return value; } @implementation OFTarArchiveEntry -+ (instancetype)entryWithFileName: (OFString *)fileName -{ - return [[[self alloc] initWithFileName: fileName] autorelease]; -} +/* + * The following is optional in OFArchiveEntry, but Apple GCC 4.0.1 is buggy + * and needs this to stop complaining. + */ +@dynamic fileComment; - (instancetype)init { OF_INVALID_INIT_METHOD } + +- (instancetype)of_init +{ + self = [super init]; + + @try { + _type = OFTarArchiveEntryTypeFile; + _POSIXPermissions = + [[OFNumber alloc] initWithUnsignedShort: 0644]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} - (instancetype)of_initWithHeader: (unsigned char [512])header encoding: (OFStringEncoding)encoding { self = [super init]; @@ -92,18 +110,21 @@ @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( + _POSIXPermissions = [[OFNumber alloc] initWithUnsignedLongLong: + octalValueFromBuffer(header + 100, 8, ULONG_MAX)]; + _ownerAccountID = [[OFNumber alloc] initWithUnsignedLongLong: + octalValueFromBuffer(header + 108, 8, ULONG_MAX)]; + _groupOwnerAccountID = [[OFNumber alloc] + initWithUnsignedLongLong: + octalValueFromBuffer(header + 116, 8, ULONG_MAX)]; + _uncompressedSize = (unsigned long long)octalValueFromBuffer( header + 124, 12, ULLONG_MAX); + _compressedSize = + _uncompressedSize + (512 - _uncompressedSize % 512); _modificationDate = [[OFDate alloc] initWithTimeIntervalSince1970: (OFTimeInterval)octalValueFromBuffer( header + 136, 12, ULLONG_MAX)]; _type = header[156]; @@ -116,14 +137,14 @@ _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) - copy]; + _ownerAccountName = + [stringFromBuffer(header + 265, 32, encoding) copy]; + _groupOwnerAccountName = [stringFromBuffer(header + 297, + 32, encoding) copy]; _deviceMajor = (unsigned long)octalValueFromBuffer( header + 329, 8, ULONG_MAX); _deviceMinor = (unsigned long)octalValueFromBuffer( header + 337, 8, ULONG_MAX); @@ -145,33 +166,20 @@ } return self; } -- (instancetype)initWithFileName: (OFString *)fileName -{ - self = [super init]; - - @try { - _fileName = [fileName copy]; - _type = OFTarArchiveEntryTypeFile; - _mode = 0644; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - - (void)dealloc { [_fileName release]; + [_POSIXPermissions release]; + [_ownerAccountID release]; + [_groupOwnerAccountID release]; [_modificationDate release]; [_targetFileName release]; - [_owner release]; - [_group release]; + [_ownerAccountName release]; + [_groupOwnerAccountName release]; [super dealloc]; } - (id)copy @@ -183,17 +191,20 @@ { OFTarArchiveEntry *copy = [[OFMutableTarArchiveEntry alloc] initWithFileName: _fileName]; @try { - copy->_mode = _mode; - copy->_size = _size; + copy->_POSIXPermissions = [_POSIXPermissions retain]; + copy->_ownerAccountID = [_ownerAccountID retain]; + copy->_groupOwnerAccountID = [_groupOwnerAccountID retain]; + copy->_compressedSize = _compressedSize; + copy->_uncompressedSize = _uncompressedSize; copy->_modificationDate = [_modificationDate copy]; copy->_type = _type; copy->_targetFileName = [_targetFileName copy]; - copy->_owner = [_owner copy]; - copy->_group = [_group copy]; + copy->_ownerAccountName = [_ownerAccountName copy]; + copy->_groupOwnerAccountName = [_groupOwnerAccountName copy]; copy->_deviceMajor = _deviceMajor; copy->_deviceMinor = _deviceMinor; } @catch (id e) { [copy release]; @throw e; @@ -205,28 +216,33 @@ - (OFString *)fileName { return _fileName; } -- (unsigned long)mode -{ - return _mode; -} - -- (unsigned long)UID -{ - return _UID; -} - -- (unsigned long)GID -{ - return _GID; -} - -- (unsigned long long)size -{ - return _size; +- (OFNumber *)POSIXPermissions +{ + return _POSIXPermissions; +} + +- (OFNumber *)ownerAccountID +{ + return _ownerAccountID; +} + +- (OFNumber *)groupOwnerAccountID +{ + return _groupOwnerAccountID; +} + +- (unsigned long long)compressedSize +{ + return _compressedSize; +} + +- (unsigned long long)uncompressedSize +{ + return _uncompressedSize; } - (OFDate *)modificationDate { return _modificationDate; @@ -240,18 +256,18 @@ - (OFString *)targetFileName { return _targetFileName; } -- (OFString *)owner +- (OFString *)ownerAccountName { - return _owner; + return _ownerAccountName; } -- (OFString *)group +- (OFString *)groupOwnerAccountName { - return _group; + return _groupOwnerAccountName; } - (unsigned long)deviceMajor { return _deviceMajor; @@ -263,26 +279,36 @@ } - (OFString *)description { void *pool = objc_autoreleasePoolPush(); - OFString *ret = [OFString stringWithFormat: @"<%@:\n" + OFString *POSIXPermissions = nil, *ret; + + if (_POSIXPermissions != nil) + POSIXPermissions = [OFString stringWithFormat: @"%ho", + _POSIXPermissions.unsignedShortValue]; + + ret = [OFString stringWithFormat: @"<%@:\n" @"\tFile name = %@\n" - @"\tMode = %06o\n" - @"\tUID = %u\n" - @"\tGID = %u\n" - @"\tSize = %" PRIu64 @"\n" + @"\tPOSIX permissions = %@\n" + @"\tOwner account ID = %@\n" + @"\tGroup owner account ID = %@\n" + @"\tCompressed size = %llu\n" + @"\tUncompressed size = %llu\n" @"\tModification date = %@\n" @"\tType = %u\n" @"\tTarget file name = %@\n" - @"\tOwner = %@\n" - @"\tGroup = %@\n" + @"\tOwner account name = %@\n" + @"\tGroup owner account name = %@\n" @"\tDevice major = %" PRIu32 @"\n" @"\tDevice minor = %" PRIu32 @"\n" @">", - self.class, _fileName, _mode, _UID, _GID, _size, _modificationDate, - _type, _targetFileName, _owner, _group, _deviceMajor, _deviceMinor]; + self.class, _fileName, POSIXPermissions, _ownerAccountID, + _groupOwnerAccountID, _compressedSize, _uncompressedSize, + _modificationDate, _type, _targetFileName, + _ownerAccountName, _groupOwnerAccountName, _deviceMajor, + _deviceMinor]; [ret retain]; objc_autoreleasePoolPop(pool); @@ -290,26 +316,27 @@ } - (void)of_writeToStream: (OFStream *)stream encoding: (OFStringEncoding)encoding { + void *pool = objc_autoreleasePoolPush(); 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, - OFStringEncodingASCII); + [OFString stringWithFormat: @"%06o ", + _POSIXPermissions.unsignedShortValue], 8, OFStringEncodingASCII); stringToBuffer(buffer + 108, - [OFString stringWithFormat: @"%06" PRIo16 " ", _UID], 8, - OFStringEncodingASCII); + [OFString stringWithFormat: @"%06o ", + _ownerAccountID.unsignedShortValue], 8, OFStringEncodingASCII); stringToBuffer(buffer + 116, - [OFString stringWithFormat: @"%06" PRIo16 " ", _GID], 8, - OFStringEncodingASCII); + [OFString stringWithFormat: @"%06o ", + _groupOwnerAccountID.unsignedShortValue], 8, OFStringEncodingASCII); stringToBuffer(buffer + 124, - [OFString stringWithFormat: @"%011" PRIo64 " ", _size], 12, + [OFString stringWithFormat: @"%011llo ", _uncompressedSize], 12, OFStringEncodingASCII); modificationDate = _modificationDate.timeIntervalSince1970; stringToBuffer(buffer + 136, [OFString stringWithFormat: @"%011llo", modificationDate], 12, OFStringEncodingASCII); @@ -323,12 +350,12 @@ 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 + 265, _ownerAccountName, 32, encoding); + stringToBuffer(buffer + 297, _groupOwnerAccountName, 32, encoding); stringToBuffer(buffer + 329, [OFString stringWithFormat: @"%06" PRIo32 " ", _deviceMajor], 8, OFStringEncodingASCII); stringToBuffer(buffer + 337, [OFString stringWithFormat: @"%06" PRIo32 " ", _deviceMinor], 8, @@ -341,7 +368,9 @@ stringToBuffer(buffer + 148, [OFString stringWithFormat: @"%06" PRIo16, checksum], 7, OFStringEncodingASCII); [stream writeBuffer: buffer length: sizeof(buffer)]; + + objc_autoreleasePoolPop(pool); } @end