Index: src/OFTarArchiveEntry.h ================================================================== --- src/OFTarArchiveEntry.h +++ src/OFTarArchiveEntry.h @@ -24,15 +24,25 @@ /*! * @brief The type of the archive entry. */ typedef enum of_tar_archive_entry_type_t { /*! Normal file */ - OF_TAR_ARCHIVE_ENTRY_TYPE_FILE = '0', + OF_TAR_ARCHIVE_ENTRY_TYPE_FILE = '0', /*! Hard link */ - OF_TAR_ARCHIVE_ENTRY_TYPE_LINK = '1', + OF_TAR_ARCHIVE_ENTRY_TYPE_LINK = '1', /*! Symbolic link */ - OF_TAR_ARCHIVE_ENTRY_TYPE_SYMLINK = '2' + OF_TAR_ARCHIVE_ENTRY_TYPE_SYMLINK = '2', + /*! Character device */ + OF_TAR_ARCHIVE_ENTRY_TYPE_CHARACTER_DEVICE = '3', + /*! Block device */ + OF_TAR_ARCHIVE_ENTRY_TYPE_BLOCK_DEVICE = '4', + /*! Directory */ + OF_TAR_ARCHIVE_ENTRY_TYPE_DIRECTORY = '5', + /*! FIFO */ + OF_TAR_ARCHIVE_ENTRY_TYPE_FIFO = '6', + /*! Contiguous file */ + OF_TAR_ARCHIVE_ENTRY_TYPE_CONTIGUOUS_FILE = '7', } of_tar_archive_entry_type_t; /*! * @class OFTarArchiveEntry OFTarArchiveEntry.h ObjFW/OFTarArchiveEntry.h * @@ -46,10 +56,12 @@ uint32_t _mode; uint64_t _size, _toRead; OFDate *_modificationDate; of_tar_archive_entry_type_t _type; OFString *_targetFileName; + OFString *_owner, *_group; + uint32_t _deviceMajor, _deviceMinor; } /*! * The file name of the entry. */ @@ -79,8 +91,28 @@ /*! * The file name of the target (for a hard link or symbolic link). */ @property (readonly, copy) OFString *targetFileName; + +/*! + * The owner of the file. + */ +@property (readonly, copy) OFString *owner; + +/*! + * The group of the file. + */ +@property (readonly, copy) OFString *group; + +/*! + * The device major (if the file is a device). + */ +@property (readonly) uint32_t deviceMajor; + +/*! + * The device major (if the file is a device). + */ +@property (readonly) uint32_t deviceMinor; @end OF_ASSUME_NONNULL_END Index: src/OFTarArchiveEntry.m ================================================================== --- src/OFTarArchiveEntry.m +++ src/OFTarArchiveEntry.m @@ -50,10 +50,12 @@ @implementation OFTarArchiveEntry @synthesize fileName = _fileName, mode = _mode, size = _size; @synthesize modificationDate = _modificationDate, type = _type; @synthesize targetFileName = _targetFileName; +@synthesize owner = _owner, group = _group; +@synthesize deviceMajor = _deviceMajor, deviceMinor = _deviceMinor; - (instancetype)OF_initWithHeader: (char[512])header stream: (OFStream*)stream { self = [super init]; @@ -64,11 +66,11 @@ _stream = [stream retain]; _fileName = [stringFromBuffer(header, 100) copy]; _mode = (uint32_t)octalValueFromBuffer( header + 100, 8, UINT32_MAX); - _size = _toRead = (size_t)octalValueFromBuffer( + _size = _toRead = (uint64_t)octalValueFromBuffer( header + 124, 12, UINT64_MAX); _modificationDate = [[OFDate alloc] initWithTimeIntervalSince1970: (of_time_interval_t)octalValueFromBuffer( header + 136, 12, UINTMAX_MAX)]; @@ -75,10 +77,27 @@ _type = header[156]; _targetFileName = [stringFromBuffer(header + 157, 100) copy]; if (_type == '\0') _type = OF_TAR_ARCHIVE_ENTRY_TYPE_FILE; + + if (memcmp(header + 257, "ustar\0" "00", 8) == 0) { + OFString *fileName; + + _owner = [stringFromBuffer(header + 265, 32) copy]; + _group = [stringFromBuffer(header + 297, 32) copy]; + + _deviceMajor = (uint32_t)octalValueFromBuffer( + header + 329, 8, UINT32_MAX); + _deviceMinor = (uint32_t)octalValueFromBuffer( + header + 337, 8, UINT32_MAX); + + fileName = [OFString stringWithFormat: @"%@/%@", + stringFromBuffer(header + 345, 155), _fileName]; + [_fileName release]; + _fileName = [fileName copy]; + } objc_autoreleasePoolPop(pool); } @catch (id e) { [self release]; @throw e; @@ -91,10 +110,12 @@ { [_stream release]; [_fileName release]; [_modificationDate release]; [_targetFileName release]; + [_owner release]; + [_group release]; [super dealloc]; } - (size_t)lowlevelReadIntoBuffer: (void*)buffer Index: utils/ofzip/TarArchive.m ================================================================== --- utils/ofzip/TarArchive.m +++ utils/ofzip/TarArchive.m @@ -97,10 +97,17 @@ [of_stdout writeFormat: @"\tSize: %" PRIu64 @" bytes\n" @"\tModification date: %@\n", [entry size], date]; + + if ([entry owner] != nil) + [of_stdout writeFormat: @"\tOwner: %@\n", + [entry owner]]; + if ([entry group] != nil) + [of_stdout writeFormat: @"\tGroup: %@\n", + [entry group]]; } if (app->_outputLevel >= 2) { switch ([entry type]) { case OF_TAR_ARCHIVE_ENTRY_TYPE_FILE: @@ -115,10 +122,36 @@ case OF_TAR_ARCHIVE_ENTRY_TYPE_SYMLINK: [of_stdout writeLine: @"\tType: Symbolic link"]; [of_stdout writeFormat: @"\tTarget file name: %@\n", [entry targetFileName]]; + break; + case OF_TAR_ARCHIVE_ENTRY_TYPE_CHARACTER_DEVICE: + [of_stdout writeLine: + @"\tType: Character device"]; + [of_stdout writeFormat: @"\tDevice major: %d\n" + @"\tDevice minor: %d\n", + [entry deviceMajor], + [entry deviceMinor]]; + break; + case OF_TAR_ARCHIVE_ENTRY_TYPE_BLOCK_DEVICE: + [of_stdout writeLine: + @"\tType: Block device"]; + [of_stdout writeFormat: @"\tDevice major: %d\n" + @"\tDevice minor: %d\n", + [entry deviceMajor], + [entry deviceMinor]]; + break; + case OF_TAR_ARCHIVE_ENTRY_TYPE_DIRECTORY: + [of_stdout writeLine: @"\tType: Directory"]; + break; + case OF_TAR_ARCHIVE_ENTRY_TYPE_FIFO: + [of_stdout writeLine: @"\tType: FIFO"]; + break; + case OF_TAR_ARCHIVE_ENTRY_TYPE_CONTIGUOUS_FILE: + [of_stdout writeLine: + @"\tType: Contiguous file"]; break; default: [of_stdout writeLine: @"\tType: Unknown"]; break; }