Index: utils/OFZIP.m ================================================================== --- utils/OFZIP.m +++ utils/OFZIP.m @@ -76,10 +76,27 @@ { [of_stderr writeFormat: @"Error: -%C and -%C are mutually exclusive!\n", option1, option2]; [OFApplication terminateWithStatus: 1]; } + +static void +setPermissions(OFString *path, OFZIPArchiveEntry *entry) +{ +#ifdef OF_HAVE_CHMOD + if (([entry versionMadeBy] >> 8) == + OF_ZIP_ARCHIVE_ENTRY_ATTR_COMPAT_UNIX) { + uint32_t mode = [entry versionSpecificAttributes] >> 16; + + /* Only allow modes that are safe */ + mode &= (S_IRWXU | S_IRWXG | S_IRWXO); + + [OFFile changePermissionsOfItemAtPath: path + permissions: mode]; + } +#endif +} @implementation OFZIP - (void)applicationDidFinishLaunching { OFOptionsParser *optionsParser = @@ -212,10 +229,20 @@ [of_stdout writeFormat: @"%@: %" PRIu64 @" (%" PRIu64 @") bytes; %08X; %@; " @"%@", [entry fileName], [entry uncompressedSize], [entry compressedSize], [entry CRC32], date, [entry fileComment]]; + + if (_outputLevel >= 2) { + if (([entry versionMadeBy] >> 8) == + OF_ZIP_ARCHIVE_ENTRY_ATTR_COMPAT_UNIX) { + uint32_t mode = [entry + versionSpecificAttributes] >> 16; + [of_stdout writeFormat: @"; %06o", + mode]; + } + } if (_outputLevel >= 3) [of_stdout writeFormat: @"; %@", [entry extraField]]; @@ -279,12 +306,15 @@ [of_stdout writeFormat: @"Extracting %@...", fileName]; if ([fileName hasSuffix: @"/"]) { [OFFile createDirectoryAtPath: outFileName createParents: true]; + setPermissions(outFileName, entry); + if (_outputLevel >= 0) [of_stdout writeLine: @" done"]; + continue; } directory = [outFileName stringByDeletingLastPathComponent]; if (![OFFile directoryExistsAtPath: directory]) @@ -330,10 +360,11 @@ } stream = [archive streamForReadingFile: fileName]; output = [OFFile fileWithPath: outFileName mode: @"wb"]; + setPermissions(outFileName, entry); while (![stream isAtEndOfStream]) { size_t length = [stream readIntoBuffer: buffer length: BUFFER_SIZE]; [output writeBuffer: buffer