Skip to content

Commit

Permalink
Collaborate on PR #84 (#87)
Browse files Browse the repository at this point in the history
Adds support for archival and restoration of POSIX permissions, finishing the process that started across PRs #84 and #86
  • Loading branch information
MartinLau7 authored and abbeycode committed Jun 27, 2019
1 parent 8c6f740 commit 8542397
Show file tree
Hide file tree
Showing 8 changed files with 395 additions and 9 deletions.
105 changes: 104 additions & 1 deletion Source/UZKArchive.h
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,34 @@ compressionMethod:(UZKCompressionMethod)method
overwrite:(BOOL)overwrite
error:(NSError **)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 permissions The desired 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:(short)permissions
compressionMethod:(UZKCompressionMethod)method
password:(nullable NSString *)password
overwrite:(BOOL)overwrite
error:(NSError **)error;

/**
* **DEPRECATED:** 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
Expand Down Expand Up @@ -649,6 +677,39 @@ compressionMethod:(UZKCompressionMethod)method
progress:(nullable void (^)(CGFloat percentCompressed))progress
error:(NSError **)error __deprecated_msg("Use -writeData:filePath:fileDate:compressionMethod:password:overwrite:error: instead, and if using the progress block, replace with NSProgress as described in the README");

/**
* **DEPRECATED:** 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 permissions The desired 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 progress Called every so often to report the progress of the compression
*
* - *percentCompressed* The percentage of the file that has been compressed
*
* @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:(short)permissions
compressionMethod:(UZKCompressionMethod)method
password:(nullable NSString *)password
overwrite:(BOOL)overwrite
progress:(nullable void (^)(CGFloat percentCompressed))progress
error:(NSError **)error __deprecated_msg("Use -writeData:filePath:fileDate:permissions:compressionMethod:password:overwrite:error: instead, and if using the progress block, replace with NSProgress as described in the README");

/**
* Writes data to the zip file in pieces, allowing you to stream the write, so the entire contents
* don't need to reside in memory at once. It overwrites an existing file with the same name.
Expand Down Expand Up @@ -807,7 +868,7 @@ compressionMethod:(UZKCompressionMethod)method
* 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
* 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
Expand All @@ -831,6 +892,48 @@ compressionMethod:(UZKCompressionMethod)method
error:(NSError **)error
block:(BOOL(^)(BOOL(^writeData)(const void *bytes, unsigned int length), NSError **actionError))action;


/**
* Writes data to the zip file in pieces, allowing you to stream the write, so the entire contents
* don't need to reside in memory at once. It overwrites an existing file with the same name, 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 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 permissions The desired 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
* handle the NSError returned into the error reference
* - *actionError* Assign to an NSError instance before returning NO
*
* @return YES if successful, NO on error
*/
- (BOOL)writeIntoBuffer:(NSString *)filePath
fileDate:(nullable NSDate *)fileDate
posixPermissions:(short)permissions
compressionMethod:(UZKCompressionMethod)method
overwrite:(BOOL)overwrite
CRC:(unsigned long)preCRC
password:(nullable NSString *)password
error:(NSError **)error
block:(BOOL(^)(BOOL(^writeData)(const void *bytes, unsigned int length), NSError **actionError))action;

/**
* Removes the given file from the archive
*
Expand Down
86 changes: 84 additions & 2 deletions Source/UZKArchive.m
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,9 @@ - (BOOL)extractFilesTo:(NSString *)destinationDirectory
UZKLogDebug("Closing file handle");
[deflatedFileHandle closeFile];

NSDictionary* attribs = [NSDictionary dictionaryWithObjectsAndKeys:info.timestamp, NSFileModificationDate, nil];
// Restore the timestamp and permission attributes of the file
NSDictionary* attribs = @{NSFileModificationDate: info.timestamp,
NSFilePosixPermissions: @(info.posixPermissions)};
[[NSFileManager defaultManager] setAttributes:attribs ofItemAtPath:path error:nil];

if (!extractSuccess) {
Expand Down Expand Up @@ -1172,6 +1174,50 @@ - (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
progress:progressBlock
error:error];
}

- (BOOL)writeData:(NSData *)data
filePath:(NSString *)filePath
fileDate:(nullable NSDate *)fileDate
posixPermissions:(short)permissions
compressionMethod:(UZKCompressionMethod)method
password:(nullable NSString *)password
overwrite:(BOOL)overwrite
error:(NSError * __autoreleasing*)error
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
return [self writeData:data
filePath:filePath
fileDate:fileDate
posixPermissions:permissions
compressionMethod:method
password:password
overwrite:overwrite
progress:nil
error:error];
#pragma clang diagnostic pop
}

- (BOOL)writeData:(NSData *)data
filePath:(NSString *)filePath
fileDate:(NSDate *)fileDate
posixPermissions:(short)permissions
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 +1274,7 @@ - (BOOL)writeData:(NSData *)data
}
filePath:filePath
fileDate:fileDate
posixPermissions:permissions
compressionMethod:method
password:password
overwrite:overwrite
Expand All @@ -1243,6 +1290,7 @@ - (BOOL)writeIntoBuffer:(NSString *)filePath
{
return [self writeIntoBuffer:filePath
fileDate:nil
posixPermissions:0
compressionMethod:UZKCompressionMethodDefault
overwrite:YES
CRC:0
Expand All @@ -1258,6 +1306,7 @@ - (BOOL)writeIntoBuffer:(NSString *)filePath
{
return [self writeIntoBuffer:filePath
fileDate:fileDate
posixPermissions:0
compressionMethod:UZKCompressionMethodDefault
overwrite:YES
CRC:0
Expand All @@ -1274,6 +1323,7 @@ - (BOOL)writeIntoBuffer:(NSString *)filePath
{
return [self writeIntoBuffer:filePath
fileDate:fileDate
posixPermissions:0
compressionMethod:method
overwrite:YES
CRC:0
Expand All @@ -1291,6 +1341,7 @@ - (BOOL)writeIntoBuffer:(NSString *)filePath
{
return [self writeIntoBuffer:filePath
fileDate:fileDate
posixPermissions:0
compressionMethod:method
overwrite:overwrite
CRC:0
Expand All @@ -1309,6 +1360,7 @@ - (BOOL)writeIntoBuffer:(NSString *)filePath
{
return [self writeIntoBuffer:filePath
fileDate:fileDate
posixPermissions:0
compressionMethod:method
overwrite:overwrite
CRC:preCRC
Expand All @@ -1325,6 +1377,27 @@ - (BOOL)writeIntoBuffer:(NSString *)filePath
password:(NSString *)password
error:(NSError *__autoreleasing *)error
block:(BOOL (^)(BOOL (^)(const void *, unsigned int), NSError *__autoreleasing *))action
{
return [self writeIntoBuffer:filePath
fileDate:fileDate
posixPermissions:0
compressionMethod:method
overwrite:overwrite
CRC:preCRC
password:password
error:error
block:action];
}

- (BOOL)writeIntoBuffer:(NSString *)filePath
fileDate:(NSDate *)fileDate
posixPermissions:(short)permissions
compressionMethod:(UZKCompressionMethod)method
overwrite:(BOOL)overwrite
CRC:(uLong)preCRC
password:(NSString *)password
error:(NSError *__autoreleasing *)error
block:(BOOL (^)(BOOL (^)(const void *, unsigned int), NSError *__autoreleasing *))action
{
UZKCreateActivity("Writing Into Buffer");

Expand Down Expand Up @@ -1380,6 +1453,7 @@ - (BOOL)writeIntoBuffer:(NSString *)filePath
}
filePath:filePath
fileDate:fileDate
posixPermissions:permissions
compressionMethod:method
password:password
overwrite:overwrite
Expand Down Expand Up @@ -1922,6 +1996,7 @@ - (BOOL)performActionWithArchiveOpen:(void(^)(NSError * __autoreleasing*innerErr
- (BOOL)performWriteAction:(int(^)(uLong *crc, NSError * __autoreleasing*innerError))write
filePath:(NSString *)filePath
fileDate:(NSDate *)fileDate
posixPermissions:(short)permissions
compressionMethod:(UZKCompressionMethod)method
password:(NSString *)password
overwrite:(BOOL)overwrite
Expand Down Expand Up @@ -1971,7 +2046,8 @@ - (BOOL)performWriteAction:(int(^)(uLong *crc, NSError * __autoreleasing*innerEr
UZKCreateActivity("Performing Write Action");

UZKLogDebug("Making zip_fileinfo struct for date %{time_t}ld", lrint(fileDate.timeIntervalSince1970));
zip_fileinfo zi = [UZKArchive zipFileInfoForDate:fileDate];
zip_fileinfo zi = [UZKArchive zipFileInfoForDate:fileDate
posixPermissions:permissions];

const char *passwordStr = NULL;

Expand Down Expand Up @@ -2623,6 +2699,7 @@ + (NSString *)errorNameForErrorCode:(NSInteger)errorCode
}

+ (zip_fileinfo)zipFileInfoForDate:(NSDate *)fileDate
posixPermissions:(short)permissions
{
NSCalendar *calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];

Expand Down Expand Up @@ -2655,6 +2732,11 @@ + (zip_fileinfo)zipFileInfoForDate:(NSDate *)fileDate
zi.external_fa = 0;
zi.dosDate = 0;

if (permissions > 0) {
unsigned long permissionsMask = (permissions & 0777) << 16;
zi.external_fa |= permissionsMask;
}

return zi;
}

Expand Down
7 changes: 7 additions & 0 deletions Source/UZKFileInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ typedef NS_ENUM(NSInteger, UZKCompressionMethod) {
*/
@property (readonly) UZKCompressionMethod compressionMethod;

/**
* The POSIX permissions of the file, like you would get by retrieving the `NSFilePosixPermissions`
* key from the attributes NSFileManager returns. Assign in octal form, like 0777 in Objective-C or
* 0o777 in Swift
*/
@property (nonatomic, readonly) short posixPermissions;



@end
3 changes: 3 additions & 0 deletions Source/UZKFileInfo.m
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ - (instancetype)initWithFileInfo:(unz_file_info64 *)fileInfo filename:(NSString

_compressionMethod = [self readCompressionMethod:fileInfo->compression_method
flag:fileInfo->flag];

uLong permissions = (fileInfo->external_fa >> 16) & 0777U;
_posixPermissions = permissions ? permissions : 0644U;
}
return self;
}
Expand Down
Loading

0 comments on commit 8542397

Please sign in to comment.