Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 32 additions & 30 deletions Source/UZKArchive.h
Original file line number Diff line number Diff line change
Expand Up @@ -593,26 +593,26 @@ compressionMethod:(UZKCompressionMethod)method
error:(NSError **)error __deprecated_msg("Use -writeData:filePath:fileDate:compressionMethod:password:error: instead, and if using the progress block, replace with NSProgress as described in the README");

/**
* Writes the data to the zip file, overwriting only if specified with the overwrite flag. Overwriting
* presents a tradeoff: the whole archive needs to be copied (minus the file to be overwritten) before
* the write begins. For a large archive, this can be slow. On the other hand, when not overwriting,
* the size of the archive will grow each time the file is written.
*
* @param data Data to write into the archive
* @param filePath The full path to the target file in the archive
* @param fileDate The timestamp of the file in the archive. Uses the current time if nil
* @param method The UZKCompressionMethod to use (Default, None, Fastest, Best)
* @param password Override the password associated with the archive (not recommended)
* @param overwrite If YES, and the file exists, delete it before writing. If NO, append
* the data into the archive without removing it first (legacy Objective-Zip
* behavior)
* @param error Contains an NSError object when there was an error writing to the archive
*
* @return YES if successful, NO on error
Writes the data to the zip file, overwriting only if specified with the overwrite flag. Overwriting
presents a tradeoff: the whole archive needs to be copied (minus the file to be overwritten) before
the write begins. For a large archive, this can be slow. On the other hand, when not overwriting,
the size of the archive will grow each time the file is written.

@param data Data to write into the archive
@param filePath The full path to the target file in the archive
@param fileDate The timestamp of the file in the archive. Uses the current time if nil
@param posixPermissions the source posix permissions of the file in the archive
@param method The UZKCompressionMethod to use (Default, None, Fastest, Best)
@param password Override the password associated with the archive (not recommended)
@param overwrite If YES, and the file exists, delete it before writing. If NO,
append the data into the archive without removing it first (legacy Objective-Zip behavior)
@param error Contains an NSError object when there was an error writing to the archive
@return YES if successful, NO on error
*/
- (BOOL)writeData:(NSData *)data
filePath:(NSString *)filePath
fileDate:(nullable NSDate *)fileDate
posixPermissions:(unsigned long)posixPermissions
compressionMethod:(UZKCompressionMethod)method
password:(nullable NSString *)password
overwrite:(BOOL)overwrite
Expand Down Expand Up @@ -800,20 +800,21 @@ compressionMethod:(UZKCompressionMethod)method
* be slow. On the other hand, when not overwriting, the size of the archive will grow each time
* the file is written.
*
* @param filePath The full path to the target file in the archive
* @param fileDate The timestamp of the file in the archive. Uses the current time if nil
* @param method The UZKCompressionMethod to use (Default, None, Fastest, Best)
* @param overwrite If YES, and the file exists, delete it before writing. If NO, append
* the data into the archive without removing it first (legacy Objective-Zip
* behavior)
* @param preCRC The CRC-32 for the data being sent. Only necessary if encrypting the file.
Pass 0 otherwise
* @param password Override the password associated with the archive (not recommended)
* @param error Contains an NSError object when there was an error writing to the archive
* @param action Contains your code to loop through the source bytes and write them to the
* archive. Each time a chunk of data is ready to be written, call writeData,
* passing in a pointer to the bytes and their length. Return YES if successful,
* or NO on error (in which case, you should assign the actionError parameter
* @param filePath The full path to the target file in the archive
* @param fileDate The timestamp of the file in the archive. Uses the current time if nil
* @param posixPermissions the source posix permissions of the file in the archive
* @param method The UZKCompressionMethod to use (Default, None, Fastest, Best)
* @param overwrite If YES, and the file exists, delete it before writing. If NO, append
* the data into the archive without removing it first (legacy Objective-Zip
* behavior)
* @param preCRC The CRC-32 for the data being sent. Only necessary if encrypting the file.
Pass 0 otherwise
* @param password Override the password associated with the archive (not recommended)
* @param error Contains an NSError object when there was an error writing to the archive
* @param action Contains your code to loop through the source bytes and write them to the
* archive. Each time a chunk of data is ready to be written, call writeData,
* passing in a pointer to the bytes and their length. Return YES if successful,
* or NO on error (in which case, you should assign the actionError parameter
*
* - *writeData* Call this block to write some bytes into the archive. It returns NO if the
* write failed. If this happens, you should return from the action block, and
Expand All @@ -824,6 +825,7 @@ compressionMethod:(UZKCompressionMethod)method
*/
- (BOOL)writeIntoBuffer:(NSString *)filePath
fileDate:(nullable NSDate *)fileDate
posixPermissions:(unsigned long)posixPermissions
compressionMethod:(UZKCompressionMethod)method
overwrite:(BOOL)overwrite
CRC:(unsigned long)preCRC
Expand Down
56 changes: 51 additions & 5 deletions Source/UZKArchive.m
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,10 @@ - (BOOL)extractFilesTo:(NSString *)destinationDirectory
UZKLogDebug("Closing file handle");
[deflatedFileHandle closeFile];

NSDictionary* attribs = [NSDictionary dictionaryWithObjectsAndKeys:info.timestamp, NSFileModificationDate, nil];
// Retain the permission attribute of a file
NSDictionary* attribs = @{NSFileModificationDate: info.timestamp,
NSFilePosixPermissions: info.posixPermissions};

[[NSFileManager defaultManager] setAttributes:attribs ofItemAtPath:path error:nil];

if (!extractSuccess) {
Expand Down Expand Up @@ -1058,6 +1061,7 @@ - (BOOL)writeData:(NSData *)data
return [self writeData:data
filePath:filePath
fileDate:nil
posixPermissions:0
compressionMethod:UZKCompressionMethodDefault
password:nil
overwrite:YES
Expand All @@ -1072,6 +1076,7 @@ - (BOOL)writeData:(NSData *)data
return [self writeData:data
filePath:filePath
fileDate:nil
posixPermissions:0
compressionMethod:UZKCompressionMethodDefault
password:nil
overwrite:YES
Expand All @@ -1087,6 +1092,7 @@ - (BOOL)writeData:(NSData *)data
return [self writeData:data
filePath:filePath
fileDate:fileDate
posixPermissions:0
compressionMethod:UZKCompressionMethodDefault
password:nil
overwrite:YES
Expand Down Expand Up @@ -1119,6 +1125,7 @@ - (BOOL)writeData:(NSData *)data
return [self writeData:data
filePath:filePath
fileDate:fileDate
posixPermissions:0
compressionMethod:method
password:password
overwrite:YES
Expand All @@ -1145,18 +1152,20 @@ - (BOOL)writeData:(NSData *)data

- (BOOL)writeData:(NSData *)data
filePath:(NSString *)filePath
fileDate:(NSDate *)fileDate
fileDate:(nullable NSDate *)fileDate
posixPermissions:(unsigned long)posixPermissions
compressionMethod:(UZKCompressionMethod)method
password:(NSString *)password
password:(nullable NSString *)password
overwrite:(BOOL)overwrite
error:(NSError * __autoreleasing*)error
error:(NSError *__autoreleasing*)error
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
return [self writeData:data
filePath:filePath
fileDate:fileDate
compressionMethod:method
posixPermissions:posixPermissions
compressionMethod:UZKCompressionMethodDefault
password:password
overwrite:overwrite
progress:nil
Expand All @@ -1172,6 +1181,27 @@ - (BOOL)writeData:(NSData *)data
overwrite:(BOOL)overwrite
progress:(void (^)(CGFloat percentCompressed))progressBlock
error:(NSError * __autoreleasing*)error
{
return [self writeData:data
filePath:filePath
fileDate:fileDate
posixPermissions:0
compressionMethod:method
password:password
overwrite:overwrite
error:error];
}


- (BOOL)writeData:(NSData *)data
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is also an extra overload.

filePath:(NSString *)filePath
fileDate:(NSDate *)fileDate
posixPermissions:(unsigned long)posixPermissions
compressionMethod:(UZKCompressionMethod)method
password:(NSString *)password
overwrite:(BOOL)overwrite
progress:(void (^)(CGFloat percentCompressed))progressBlock
error:(NSError * __autoreleasing*)error
{
UZKCreateActivity("Writing Data");

Expand Down Expand Up @@ -1228,6 +1258,7 @@ - (BOOL)writeData:(NSData *)data
}
filePath:filePath
fileDate:fileDate
posixPermissions:posixPermissions
compressionMethod:method
password:password
overwrite:overwrite
Expand All @@ -1243,6 +1274,7 @@ - (BOOL)writeIntoBuffer:(NSString *)filePath
{
return [self writeIntoBuffer:filePath
fileDate:nil
posixPermissions:0
compressionMethod:UZKCompressionMethodDefault
overwrite:YES
CRC:0
Expand All @@ -1258,6 +1290,7 @@ - (BOOL)writeIntoBuffer:(NSString *)filePath
{
return [self writeIntoBuffer:filePath
fileDate:fileDate
posixPermissions:0
compressionMethod:UZKCompressionMethodDefault
overwrite:YES
CRC:0
Expand All @@ -1274,6 +1307,7 @@ - (BOOL)writeIntoBuffer:(NSString *)filePath
{
return [self writeIntoBuffer:filePath
fileDate:fileDate
posixPermissions:0
compressionMethod:method
overwrite:YES
CRC:0
Expand All @@ -1291,6 +1325,7 @@ - (BOOL)writeIntoBuffer:(NSString *)filePath
{
return [self writeIntoBuffer:filePath
fileDate:fileDate
posixPermissions:0
compressionMethod:method
overwrite:overwrite
CRC:0
Expand All @@ -1309,6 +1344,7 @@ - (BOOL)writeIntoBuffer:(NSString *)filePath
{
return [self writeIntoBuffer:filePath
fileDate:fileDate
posixPermissions:0
compressionMethod:method
overwrite:overwrite
CRC:preCRC
Expand All @@ -1319,6 +1355,7 @@ - (BOOL)writeIntoBuffer:(NSString *)filePath

- (BOOL)writeIntoBuffer:(NSString *)filePath
fileDate:(NSDate *)fileDate
posixPermissions:(unsigned long)posixPermissions
compressionMethod:(UZKCompressionMethod)method
overwrite:(BOOL)overwrite
CRC:(uLong)preCRC
Expand Down Expand Up @@ -1380,6 +1417,7 @@ - (BOOL)writeIntoBuffer:(NSString *)filePath
}
filePath:filePath
fileDate:fileDate
posixPermissions:posixPermissions
compressionMethod:method
password:password
overwrite:overwrite
Expand Down Expand Up @@ -1922,6 +1960,7 @@ - (BOOL)performActionWithArchiveOpen:(void(^)(NSError * __autoreleasing*innerErr
- (BOOL)performWriteAction:(int(^)(uLong *crc, NSError * __autoreleasing*innerError))write
filePath:(NSString *)filePath
fileDate:(NSDate *)fileDate
posixPermissions:(unsigned long)posixPermissions
compressionMethod:(UZKCompressionMethod)method
password:(NSString *)password
overwrite:(BOOL)overwrite
Expand Down Expand Up @@ -1973,6 +2012,12 @@ - (BOOL)performWriteAction:(int(^)(uLong *crc, NSError * __autoreleasing*innerEr
UZKLogDebug("Making zip_fileinfo struct for date %{time_t}ld", lrint(fileDate.timeIntervalSince1970));
zip_fileinfo zi = [UZKArchive zipFileInfoForDate:fileDate];

if (posixPermissions > 0) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole if block should be refactored into +[UZKArchive zipFileInfoForDate:], adding a permissions: argument to it. You can modify that signature, instead of overloading it, since it's only used privately. Add the octal permissions to the logging output in the line above.


// Revert the value of NSFilePosixPermissions to zip external_fa raw data
zi.external_fa = (posixPermissions + 32768) << 16;
}

const char *passwordStr = NULL;

if (password) {
Expand Down Expand Up @@ -2653,6 +2698,7 @@ + (zip_fileinfo)zipFileInfoForDate:(NSDate *)fileDate
zi.tmz_date.tm_year = (uInt)date.year;
zi.internal_fa = 0;
zi.external_fa = 0;
// zi.external_fa = 2175008768; // default posixPermissions value on zip: 2175008768 (0644U)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this commented code.

zi.dosDate = 0;

return zi;
Expand Down
15 changes: 14 additions & 1 deletion Source/UZKFileInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,24 @@ typedef NS_ENUM(NSInteger, UZKCompressionMethod) {
*/
@property (readonly) BOOL isDirectory;

/**
* YES if the item is a symLink
*/
@property (readonly) BOOL isSymLink;

/**
* YES if the item is a resource fork
*/
@property (readonly) BOOL isResourceFork;

/**
* The type of compression
*/
@property (readonly) UZKCompressionMethod compressionMethod;


/**
@brief posixPermissions (posixPermissions of the file,The value from the file attributes - NSFilePosixPermissions)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I'm not using Doxygen, so please remove the @brief posixPermissions and surrounding parentheses - just format it like the other property comments
  • Give an example value, like 0777U

*/
@property (nonatomic, readonly) NSNumber *posixPermissions;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move this declaration higher up, below timestamp - all the properties below it are always determined by the API instead of by user input


@end
22 changes: 21 additions & 1 deletion Source/UZKFileInfo.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,18 @@ - (instancetype)initWithFileInfo:(unz_file_info64 *)fileInfo filename:(NSString
_zipTMUDate = fileInfo->tmu_date;
_CRC = fileInfo->crc;
_isEncryptedWithPassword = (fileInfo->flag & 1) != 0;
_isDirectory = [filename hasSuffix:@"/"];
// _isDirectory = [filename hasSuffix:@"/"];
_isDirectory = [self isDirectoryWith:fileInfo];
_isSymLink = [self isSymLinkWith:fileInfo->external_fa];

if (_isDirectory) {
_filename = [_filename substringToIndex:_filename.length - 1];
}

_isResourceFork = [[filename pathComponents].firstObject isEqualToString:@"__MACOSX"];
_compressionMethod = [self readCompressionMethod:fileInfo->compression_method
flag:fileInfo->flag];
_posixPermissions = @((fileInfo->external_fa >> 16) ? (fileInfo->external_fa >> 16) : 0755U);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • When reading the permissions out, I think we need to use a bitmask, like in this Stack Overflow answer, since the external_fa header field shares data other than permissions.

  • I also wonder whether it makes sense to return 0755U here, since this is supposed to represent what's actually in the header. I think if it's 0, let's just return 0. I think when it gets written to disk as 755, that's OS default behavior, and possibly subject to change. I think it's also obvious if you see "0" permissions for a file that it's missing, not a file with no permissions, since I don't think that's possible, or at least it shouldn't be

}
return self;
}
Expand Down Expand Up @@ -102,4 +106,20 @@ - (NSDate *)readDate:(tm_unz)date
return [calendar dateFromComponents:components];
}

- (BOOL)isDirectoryWith:(unz_file_info64 *)fileInfo {
// NSLog(@"ISDIR__ %@", S_ISDIR(fileInfo->external_fa)?@"YES":@"NO");
uLong type = fileInfo->external_fa >> 0x1D & 0x1F;
if (0 == (fileInfo->version >> 8)) { //is DOS-archive
type = fileInfo->external_fa >> 4;
return (type == 0x01) && ![self isSymLinkWith:fileInfo->external_fa];
}
return (0x02 == type) && ![self isSymLinkWith:fileInfo->external_fa];
}

- (BOOL)isSymLinkWith:(uLong)externalFileAttributes {

uLong type = externalFileAttributes >> 0x1D & 0x1F;
return 0x05 == type;
}

@end
1 change: 1 addition & 0 deletions Tests/FileDescriptorUsageTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ - (void)testFileDescriptorUsage_WriteIntoArchive
BOOL writeResult = [archive writeData:newFileData
filePath:fileName
fileDate:[NSDate date]
posixPermissions:0
compressionMethod:UZKCompressionMethodDefault
password:nil
overwrite:YES
Expand Down
Loading